{"skill":{"slug":"looper-golf","displayName":"Looper Golf","summary":"Play a round of golf using CLI tools — autonomously or with a human caddy.","description":"---\nname: looper-golf\ndescription: Play a round of golf using CLI tools — autonomously or with a human caddy.\nmetadata: {\"openclaw\":{\"requires\":{\"bins\":[\"node\"]}}}\n---\n\n# Looper Golf\n\nYou are an AI golfer. You can play autonomously or collaborate with a human caddy, and switch between styles at any point during a round.\n\n## CRITICAL RULES\n\n1. **ONLY use the CLI commands listed below.** Never make direct HTTP requests, curl calls, or try to access API endpoints. The CLI handles all server communication internally.\n2. ALWAYS run `look` at the start of every hole.\n3. ALWAYS run `bearing` before every `hit`. Never guess an aim angle — calculate it.\n4. Never use aim 0 or aim 180 unless `bearing` actually returned that value.\n5. Read your target's coordinates directly from the map — every cell shows `symbol(right)` and the row label is the ahead value.\n\n## Available Commands\n\nThese are the ONLY commands you use. Each one is a subcommand of the CLI tool:\n\n| Command | Usage |\n|---------|-------|\n| **register** | `node \"{baseDir}/cli.js\" register --inviteCode <code> --name \"Name\"` |\n| **courses** | `node \"{baseDir}/cli.js\" courses` |\n| **start** | `node \"{baseDir}/cli.js\" start --courseId <id>` |\n| **look** | `node \"{baseDir}/cli.js\" look` |\n| **bearing** | `node \"{baseDir}/cli.js\" bearing --ahead <yards> --right <yards>` |\n| **hit** | `node \"{baseDir}/cli.js\" hit --club <name> --aim <degrees> --power <1-100>` |\n| **view** | `node \"{baseDir}/cli.js\" view` |\n| **scorecard** | `node \"{baseDir}/cli.js\" scorecard` |\n| **prepare-round** | `node \"{baseDir}/cli.js\" prepare-round --courseId <id>` |\n\n## Setup\n\nRounds require an on-chain transaction before you can play. You cannot start a round from the CLI alone.\n\n### Step 1: Get an invite code\n\nAsk the course owner to generate an invite code from the web app. They click \"Generate Agent Invite\" and give you the code (format: `GOLF-XXXXXXXX`). Codes expire after 1 hour.\n\n### Step 2: Register (one-time)\n\n```\nnode \"{baseDir}/cli.js\" register --inviteCode <code> --name \"Your Name\"\n```\n\nThis creates your agent identity, binds it to the owner's course, and saves credentials to `agent.json`.\n\n### Step 3: Start a round (on-chain)\n\nThere are two ways to start a round:\n\n**Option A — Agent Play (course owner starts from web app):**\nThe course owner clicks \"Play via Agent\" in the web app. This calls `GameContract.startRound(playerCourseId, hostCourseId, 2)` on-chain. The game server picks up the event and creates a round for your agent automatically. No wallet needed on your end.\n\n**Option B — Start on-chain yourself (requires a wallet skill):**\nIf the course owner has added your wallet as an approved signer on the course's TBA (Token Bound Account), you can start rounds yourself using the `prepare-round` command:\n\n```\nnode \"{baseDir}/cli.js\" prepare-round --courseId <hostCourseId>\n```\n\nThis outputs a JSON transaction object (`{to, data, value, chainId}`) that you submit via your wallet. The transaction calls `CourseTBA.execute()` which invokes `GameContract.startRound()` with mode 2 (agent play). After the transaction confirms, the game server's indexer picks up the event and creates the round.\n\n**Security note:** The `prepare-round` command generates raw EVM calldata. Before submitting, verify that the `to` address matches your known Course TBA and the `chainId` matches Base Sepolia (84532). The `value` should always be `\"0\"`. Never submit transaction data from this command to addresses you don't recognize.\n\n**Wallet requirement:** Option B requires a wallet skill that can submit arbitrary EVM transactions. [Bankr](https://github.com/BankrBot/openclaw-skills/blob/main/bankr/SKILL.md) is a known compatible wallet skill. Any wallet skill that can submit a raw transaction (`{to, data, value, chainId}`) will work.\n\n### Step 4: Resume and play\n\nOnce a round is started on-chain (via either option), use `start` to pick it up:\n\n```\nnode \"{baseDir}/cli.js\" courses\nnode \"{baseDir}/cli.js\" start --courseId <id>\n```\n\nThe `start` command finds your active round on the course and resumes it. If no round exists, it will tell you.\n\nStart options: `--teeColor <color>`, `--yardsPerCell <2-20>`, `--mapFormat <grid|ascii>`.\n\n## Play Modes\n\nYou support two play modes. The user can switch between them at any time — even mid-hole. **Default to caddy mode unless the user asks you to play autonomously.**\n\n### Caddy Mode (default)\n\nYou are the golfer. The human is your caddy. Before each shot:\n\n1. Run `look` and share the map with the user\n2. Analyze the hole — identify hazards, suggest a target, recommend club and power\n3. **Ask your caddy for their read** before hitting. They may agree, suggest adjustments, or offer a different perspective\n4. Consider their advice, then make your call — run `bearing` and `hit`\n\nYou make the final decision on every shot, but your caddy knows the course. Listen to their advice and factor it into your thinking.\n\n### Autonomous Mode\n\nYou make all decisions yourself. Use the shot workflow below without pausing for input. This is efficient for playing many holes quickly.\n\n**Per-hole subagents (recommended for multiple holes):** When playing more than 1-2 holes autonomously, spawn a fresh subagent for each hole to keep context clean. Each subagent plays one hole, reports the score, then you spawn the next. Key rules:\n- **One hole per subagent** — spawn with clean context (`contextMessages: 0`)\n- **Sequential only** — never play holes in parallel (server state is sequential)\n- **Include the shot workflow and map-reading instructions** in each subagent's task prompt\n- Round state persists server-side, so a new subagent picks up exactly where the last left off\n\n### Switching Modes\n\nThe user can say things like:\n- \"Play the front 9 on your own, then let's do the back 9 together\" → autonomous for holes 1-9, caddy mode for 10-18\n- \"Go ahead and finish this hole\" → switch to autonomous for the current hole\n- \"Hold on, let me see this shot\" → switch to caddy mode immediately\n- \"Play the next 3 holes, then check back in\" → autonomous for 3 holes, then caddy mode\n\nAlways respect the user's request. When finishing an autonomous stretch, show the scorecard and ask the user how they'd like to continue.\n\n## Shot Workflow (repeat for every shot)\n\n1. **look** — `node \"{baseDir}/cli.js\" look`\n2. **Read coordinates** — Find your target on the map. Read `ahead` from the row label, `right` from the parentheses.\n3. **bearing** — `node \"{baseDir}/cli.js\" bearing --ahead <yards> --right <yards>` to get the exact aim angle and distance.\n4. **hit** — `node \"{baseDir}/cli.js\" hit --club <name> --aim <degrees> --power <percent>` using the aim from bearing.\n\n## Reading the Map\n\nThe `look` command shows each row labeled with yards AHEAD of your ball (positive = toward green, negative = behind). Cells use two formats:\n- `TYPE(X)` — single cell at X yards right of ball\n- `TYPE(START:END)` — consecutive cells of same type spanning START to END yards right\n\nFlag `F` and ball `O` are always shown as single cells.\n\nConsecutive rows with identical terrain may be merged into Y-ranges (e.g., `10-20y:` means rows from 10y to 20y ahead all share the same terrain). This does not apply on the green, where every row is shown individually.\n\nExample:\n```\n   200y: .(-20) F(-15) G(-15:0) g(5)\n90-148y: .(-25:10)\n    50y: T(-15:-10) .(-5:5)\n     0y: .(-10:-5) O(0) .(5:10)\n```\n\nTo find a target's coordinates:\n1. Find the symbol (e.g., `F(-15)` on the `200y` row)\n2. The row label is the `ahead` value → 200 (for merged rows like `90-148y`, use any value in that range)\n3. The number in parentheses is the `right` value → -15\n4. Run `bearing --ahead 200 --right -15`\n\nFor ranges like `G(-15:0)`, the green spans from 15y left to center — pick any value in that range as `right`.\n\nYour ball is `O(0)` at row `0y`.\n\nOn tee shots, the map trims boring fairway rows near the tee. On the green, only green-area rows are shown and distance is in feet.\n\n## Worked Examples\n\n### Example 1 — Approach to the flag\n\nMap shows `F(-15)` on the `200y` row.\n\nRun: `bearing --ahead 200 --right -15` → `Bearing: 356 deg | Distance: 201 yards`\n\nYour 5-iron has 210y total stock. Power = 201/210 * 100 = 96%.\nRun: `hit --club 5-iron --aim 356 --power 96`\n\n### Example 2 — Tee shot to fairway bend\n\nYou want to hit the fairway bend, not the flag. On the `230y` row you see `.(-5:15)`.\nAim at the center of the range: `bearing --ahead 230 --right 5` → `Bearing: 1 deg | Distance: 230 yards`\nRun: `hit --club driver --aim 1 --power 85`\n\n## Map Symbols\n\n- `F` = Flag, `G` = Green, `g` = Collar, `.` = Fairway, `;` = Rough\n- `S` = Bunker, `s` = Greenside bunker, `W` = Water, `T` = Tee, `O` = Your ball\n\nHigher row values = closer to the green. Lower/negative = behind your ball.\n\n## Your Bag\n\nYour stock yardages are shown once when you `start` a round. Distance scales linearly:\n- `carry = stockCarry * (power / 100)`\n- `power = (desiredDistance / stockTotal) * 100`\n\n## Aim System (for reference — let bearing calculate this for you)\n\n- 0 = toward green (up on map)\n- 90 = right\n- 180 = backward\n- 270 = left\n\n## Wind\n\nThe `look` output includes a **Wind** line describing the current conditions, e.g.:\n\n```\nWind: 10 mph from NW (headwind-left)\n```\n\nWind affects every full shot. Putts are immune.\n\n### How wind affects shots\n\n- **Headwind** reduces carry distance. A 10 mph headwind on a 200y shot loses ~6 yards.\n- **Tailwind** adds carry distance. Same shot gains ~6 yards downwind.\n- **Crosswind** pushes the ball sideways. A 10 mph crosswind drifts a 200y shot ~10 yards.\n- Longer shots are affected more. A driver in wind drifts much further than a wedge.\n\n### Adjusting for wind\n\n- **Headwind**: Club up (e.g., 5-iron instead of 6-iron) or increase power.\n- **Tailwind**: Club down or reduce power to avoid overshooting.\n- **Crosswind**: Aim upwind of your target. If the wind pushes right, aim left. Use `bearing` to get aim to an offset target.\n- **Strong wind (12+ mph)**: Favor lower-lofted clubs that keep the ball down. Consider laying up rather than attacking a pin near hazards.\n- **Calm (<3 mph)**: Wind is negligible — play normally.\n\n## Strategy Tips\n\n- Off the tee: Aim at the widest part of the fairway, not always the flag.\n- Doglegs: Aim at the bend, not the green.\n- Lay up short of water/bunkers rather than trying to carry them.\n- Putting: Use putter at low power. Read distance carefully.\n- Factor wind into every club and aim decision — check the wind line in `look` output.\n- A bogey beats a double. Play safe when unsure.\n","tags":{"latest":"1.0.2"},"stats":{"comments":0,"downloads":1550,"installsAllTime":1,"installsCurrent":1,"stars":2,"versions":3},"createdAt":1770767338598,"updatedAt":1778486994957},"latestVersion":{"version":"1.0.2","createdAt":1771944011995,"changelog":"- Registration now requires a short-lived invite code from the course owner (`--inviteCode`), replacing the previous `--registrationKey` and course linking workflow.\n- The `caddy-code` command and corresponding steps have been removed; agent registration is managed entirely via the invite system.\n- Added a security note for on-chain play: users should verify `prepare-round` transaction details before sending.\n- Updated CLI usage examples and documentation to reflect the new onboarding process.\n- No changes to gameplay flow or available play modes.","license":null},"metadata":{"setup":[],"os":null,"systems":null},"owner":{"handle":"sbauch","userId":"s179q58vdpa3x525ma30kwfac9885e8g","displayName":"sbauch","image":"https://avatars.githubusercontent.com/u/923033?v=4"},"moderation":null}