@coinbase/coinbase-cli 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/version.txt CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinbase/coinbase-cli",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Coinbase for agents — CLI and MCP server for trading, wallets, payments, and onchain across the Coinbase platform",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,141 +1,81 @@
1
1
  ---
2
2
  name: coinbase
3
- description: Use this skill when the user wants to trade cryptocurrency on Coinbase Advanced Trade — check prices, place market or limit orders, manage portfolios, view balances, convert currencies, or query brokerage data. Execute commands with the `coinbase` binary.
3
+ description: Umbrella skill for the coinbase CLI — the agent-first interface to the Coinbase Advanced Trade brokerage. Use when the user mentions Coinbase trading, spot orders, crypto prices, balances, portfolios, converting currencies, or wants to know which coinbase tool/lane to use. Indexes the granular journey skills (trading, market-data, watch, convert, portfolios) and explains auth, env, and MCP-vs-CLI selection.
4
4
  ---
5
5
 
6
6
  # coinbase CLI
7
7
 
8
8
  `coinbase` is an agent-first CLI for the Coinbase Advanced Trade brokerage API. All commands output JSON to stdout by default. Errors are JSON to stderr with non-zero exit codes.
9
9
 
10
- ## Prerequisites
10
+ These are REAL orders against a live brokerage. Confirm the full plan with the user before placing or arming anything.
11
+
12
+ ## Auth & env
11
13
 
12
14
  Authenticated commands need a CDP API key configured per environment.
13
15
 
14
- 1. Go to https://portal.cdp.coinbase.com/projects/api-keys → Click **Create API Key**
15
- 2. In the Create API Key modal:
16
- - Under **API restrictions → Coinbase App & Advanced Trade**:
17
- - Select the **Portfolio** this key will be scoped to (e.g. "Primary"). The key can only trade within this portfolio.
18
- - Enable **Trade** and **Transfer** permissions (View is on by default).
19
- - Under **Advanced Settings** (bottom of modal):
20
- - Select **ECDSA** signature algorithm. The brokerage SDK rejects Ed25519.
21
- 3. Download the key file and configure:
16
+ 1. https://portal.cdp.coinbase.com/projects/api-keys → **Create API Key**
17
+ 2. Under **API restrictions → Coinbase App & Advanced Trade**: pick the **Portfolio** to scope the key to, enable **Trade** and **Transfer** (View is default).
18
+ 3. Under **Advanced Settings**: select **ECDSA** (the brokerage SDK rejects Ed25519).
19
+ 4. Download the key file, then:
22
20
  ```sh
23
21
  coinbase env live --key-file path/to/cdp_api_key.json
22
+ coinbase balance # verify
24
23
  ```
25
- 4. Verify: `coinbase balance`
26
-
27
- ### Multiple portfolios
28
24
 
29
- Each CDP key is scoped to one portfolio. To operate across portfolios, create a key per portfolio and register each as a separate environment using the `live-<portfolio>` convention:
30
-
31
- ```sh
32
- coinbase env live-primary --key-file primary-key.json
33
- coinbase env live-trading --key-file trading-key.json
34
- ```
25
+ Each CDP key is scoped to one portfolio. To operate across portfolios, register one env per portfolio (`live-primary`, `live-trading`) and switch with `coinbase env live-trading` or per-command `-e live-primary`. See `coinbase-portfolios`.
35
26
 
36
- Switch with `coinbase env live-trading` or per-command with `-e live-primary`. Moving funds between portfolios requires switching to the source portfolio's key first.
27
+ ## Permissions
37
28
 
29
+ By default agents prompt before each `coinbase` command. To reduce or remove those prompts, allow-list commands in your agent's permission settings. Offer the user two tiers:
38
30
 
39
- ## Discovery
31
+ - **Read-only** — never prompted for safe reads (prices, balances, history); still prompted before any order or transfer. Good default.
32
+ - **Everything** — never prompted at all, including orders and transfers. Confirm explicitly before enabling.
40
33
 
41
- ```sh
42
- coinbase --help # All resources + commands
43
- coinbase orders --help # Actions in a resource
44
- coinbase orders create --template # Request body template
45
- ```
34
+ Allow-list rules for each tier:
46
35
 
47
- ## Common workflows
36
+ | Tier | Rules |
37
+ | :--- | :--- |
38
+ | Read-only | `coinbase balance`, `coinbase products *`, `coinbase orders list`, `coinbase orders get *`, `coinbase orders fills`, `coinbase fees`, `coinbase env`, `coinbase portfolios list`, `coinbase portfolios get *` |
39
+ | Everything | `coinbase *` |
48
40
 
49
- ### Check a price (authenticated)
41
+ How to apply depends on the agent. For Claude Code, add the rules to `permissions.allow` in settings.json (e.g. `Bash(coinbase products *)`) — `~/.claude/settings.json` for all projects or `.claude/settings.json` to share with a team. Other agents have their own allow-list mechanism.
50
42
 
51
- ```sh
52
- coinbase products get BTC-USD # Current BTC product info
53
- coinbase products candles BTC-USD --jq '.candles[0]'
54
- coinbase products book BTC-USD --jq '.pricebook'
55
- ```
43
+ ## MCP vs CLI — which lane
56
44
 
57
- ### List balances
45
+ Both surfaces wrap the same API. Pick by the shape of the task:
58
46
 
59
- ```sh
60
- coinbase balance # All account balances
61
- coinbase balance show_zero==true # Include zero-balance accounts
62
- ```
47
+ - **MCP** (`coinbase_<resource>_<action>` tools) — for **atomic, structured calls**: place one order, fetch a ticker, list portfolios. Typed args, structured result, no shell needed.
48
+ - **CLI** (`coinbase ...` in Bash) — for **composition and streaming**: `--until` conditional watchers, piping (`| jq`), chaining with `&&`, `--paginate`, scripting multi-step flows. Anything MCP can't express as a single call.
63
49
 
64
- ### Funding a fresh account
50
+ Rule of thumb: one structured action → MCP; a pipeline, a stream, or a conditional → CLI.
65
51
 
66
- The brokerage API does not support buying crypto with a payment method directly. To fund an account for trading:
52
+ Add MCP with: `claude mcp add --scope user --transport stdio coinbase -- coinbase mcp`
67
53
 
68
- 1. Deposit USD or crypto via [coinbase.com](https://www.coinbase.com) or the Coinbase mobile app. Deposits land in the **default portfolio**.
69
- 2. If trading from a non-default portfolio, transfer funds from default using:
70
- ```sh
71
- coinbase transfer \
72
- amount=100 currency=USD \
73
- from=<default_portfolio_uuid> \
74
- to=<trading_portfolio_uuid>
75
- ```
76
- 3. Verify: `coinbase balance`
54
+ ## Install agent skills
77
55
 
78
- ### Place a market order
56
+ Skills give your agent step-by-step guidance for common Coinbase workflows (trading, market data, watch, convert, portfolios).
79
57
 
80
58
  ```sh
81
- # Buy $100 of BTC at market
82
- coinbase orders create \
83
- client_order_id=$(uuidgen) \
84
- product_id=BTC-USD \
85
- side=BUY \
86
- type=market \
87
- quote_size=100
88
-
89
- # Sell 0.5 ETH at market
90
- coinbase orders create \
91
- client_order_id=$(uuidgen) \
92
- product_id=ETH-USD \
93
- side=SELL \
94
- type=market \
95
- base_size=0.5
96
-
97
- # Preview before sending
98
- coinbase orders preview \
99
- product_id=BTC-USD \
100
- side=BUY \
101
- type=market \
102
- quote_size=100
59
+ coinbase skills add
103
60
  ```
104
61
 
105
- SELL market orders use `base_size` (amount of asset to sell). BUY market orders use `quote_size` (amount of USD to spend).
106
-
107
- ### Manage orders
62
+ If non-interactive, pass the directory explicitly:
108
63
 
109
64
  ```sh
110
- coinbase orders list status==OPEN
111
- coinbase orders get <order_id>
112
- coinbase orders cancel order_ids:='["id-1","id-2"]'
113
- coinbase orders edit <order_id> limit_price=50000
65
+ coinbase skills add --dir ~/.claude/skills
114
66
  ```
115
67
 
116
- ### Portfolios
68
+ Skills auto-update on future `npm i -g @coinbase/coinbase-cli` upgrades.
117
69
 
118
- ```sh
119
- coinbase portfolios list
120
- coinbase portfolios get <portfolio_uuid>
121
- coinbase portfolios create name="Day Trading"
122
- ```
123
-
124
- ### Convert (USDC ↔ USD, etc.)
125
-
126
- ```sh
127
- coinbase convert quote from=USD to=USDC amount=100
128
- coinbase convert execute <quote_id> from=USD to=USDC
129
- coinbase convert get <quote_id>
130
- ```
131
-
132
- ### Transfer funds between portfolios
70
+ ## Discovery
133
71
 
134
72
  ```sh
135
- coinbase transfer amount=1000 currency=USD from=<src_uuid> to=<dst_uuid>
73
+ coinbase --help # all resources + commands
74
+ coinbase orders --help # actions in a resource
75
+ coinbase orders create --template # request body schema
136
76
  ```
137
77
 
138
- ## Field syntax
78
+ ## Field & flag syntax
139
79
 
140
80
  | Syntax | Meaning |
141
81
  | :---- | :---- |
@@ -143,35 +83,25 @@ coinbase transfer amount=1000 currency=USD from=<src_uuid> to=<dst_uuid>
143
83
  | `key:=value` | Raw JSON body field |
144
84
  | `key==value` | Query parameter |
145
85
  | `a.b.c=value` | Nested body field |
146
- | `@file.json` | Body from file |
147
- | `-` | Body from stdin |
148
-
149
- ## Flags
86
+ | `@file.json` / `-` | Body from file / stdin |
150
87
 
151
88
  | Flag | Behavior |
152
89
  | :---- | :---- |
153
- | `--template` | Print request body schema, don't send |
90
+ | `--template` | Print body schema, don't send |
154
91
  | `--dry-run` | Assemble + print request, don't send |
155
- | `--edit` | Open body in `$EDITOR` |
156
92
  | `--jq <expr>` | Filter JSON response |
157
93
  | `--paginate` | Auto-follow `cursor` until exhausted |
158
94
  | `-e <env>` | Override active environment |
159
- | `-v` | Verbose; print headers (sensitive redacted) |
95
+ | `-v` | Verbose; print headers (redacted) |
160
96
 
161
- ## Output
97
+ Output: `stdout` = raw JSON (parseable), `stderr` = human status/errors. Exit `0` success, `1` error.
162
98
 
163
- - `stdout`: raw JSON response (default), parseable.
164
- - `stderr`: human status, errors, warnings.
165
- - Exit codes: `0` success, `1` error.
99
+ ## Journey skills (index)
166
100
 
167
- ## Portfolio ID for spot orders (CDP-key auth)
168
-
169
- CDP API keys derive portfolio scope from the key itself — no `retail_portfolio_id` needed in the body.
170
-
171
- ## MCP
172
-
173
- ```sh
174
- claude mcp add --scope user --transport stdio coinbase -- coinbase mcp
175
- ```
176
-
177
- 29 tools generated from the spec: `coinbase_<resource>_<action>` (e.g. `coinbase_orders_create`) and top-level actions (e.g. `coinbase_balance`, `coinbase_transfer`, `coinbase_fees`), plus meta tools `coinbase_env`, `coinbase_set_env`, `coinbase_template`, `coinbase_help`.
101
+ | Skill | Use when the user wants to… |
102
+ | :---- | :---- |
103
+ | `coinbase-trading` | place / preview / cancel / edit spot orders, market & limit, stop-loss |
104
+ | `coinbase-market-data` | check prices, candles, order book, best bid/ask, ticker |
105
+ | `coinbase-watch` | trigger an action on a live condition (`--until` watchers) |
106
+ | `coinbase-convert` | convert between currencies (USDC ↔ USD, etc.) |
107
+ | `coinbase-portfolios` | list / create / manage portfolios, move funds between them |
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: coinbase-convert
3
+ description: Converts between currencies on Coinbase (e.g. USDC ↔ USD, USD ↔ a stablecoin) using the quote-then-execute flow. Use when the user wants to convert, swap stablecoins, or move between fiat and USDC. Not for buying/selling crypto assets — use `coinbase-trading` (a spot order) for that.
4
+ requires: coinbase env configured with Trade permission (see `coinbase` skill)
5
+ ---
6
+
7
+ # coinbase-convert
8
+
9
+ Convert between supported currency pairs (commonly USDC ↔ USD). Convert is a distinct flow from trading — for buying/selling a crypto asset, place a spot order via `coinbase-trading` instead of converting.
10
+
11
+ ## Flow: quote → execute
12
+
13
+ ```sh
14
+ # 1. Get a quote (returns a quote_id)
15
+ coinbase convert quote from=USD to=USDC amount=100
16
+
17
+ # 2. Execute the quote
18
+ coinbase convert execute <quote_id> from=USD to=USDC
19
+
20
+ # 3. Inspect a quote/trade
21
+ coinbase convert get <quote_id>
22
+ ```
23
+
24
+ Always quote first, surface the rate/fees to the user, and confirm before executing — `execute` is a real conversion.
25
+
26
+ ## Notes
27
+
28
+ - `from` / `to` are currency codes (e.g. `USD`, `USDC`).
29
+ - `amount` is denominated in the `from` currency.
30
+ - This is the conversion product, not a market order. "Buy N USDC worth of BTC" is a spot order (`coinbase-trading`), not a convert.
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: coinbase-market-data
3
+ description: Reads market data from Coinbase Advanced Trade — current prices, candles/OHLCV, order book depth, best bid/ask, ticker, and product metadata. Use when the user wants to check a price, look at a chart, see the order book, get the spread, or list tradable products. Read-only.
4
+ requires: coinbase env configured (see `coinbase` skill)
5
+ ---
6
+
7
+ # coinbase-market-data
8
+
9
+ Read-only market data. All commands return JSON to stdout.
10
+
11
+ ## Current price / product info
12
+
13
+ ```sh
14
+ coinbase products get BTC-USD
15
+ coinbase products ticker BTC-USD # latest trades
16
+ coinbase products ticker BTC-USD --jq '.trades[0].price' # just the last price
17
+ ```
18
+
19
+ Extract a bare spot price (useful when resolving relative targets):
20
+
21
+ ```sh
22
+ SPOT=$(coinbase products ticker BTC-USD --jq '.trades[0].price' | tr -d '"')
23
+ ```
24
+
25
+ ## Candles (OHLCV)
26
+
27
+ ```sh
28
+ coinbase products candles BTC-USD
29
+ coinbase products candles BTC-USD --jq '.candles[0]'
30
+ # narrow with query params, e.g. granularity / time range
31
+ coinbase products candles BTC-USD granularity==ONE_HOUR
32
+ ```
33
+
34
+ ## Order book & spread
35
+
36
+ ```sh
37
+ coinbase products book BTC-USD --jq '.pricebook'
38
+ coinbase products best_bid_ask product_ids==BTC-USD
39
+ ```
40
+
41
+ ## List / discover products
42
+
43
+ ```sh
44
+ coinbase products list
45
+ coinbase products list --jq '.products[].product_id' --paginate
46
+ ```
47
+
48
+ ## Notes
49
+
50
+ - For streaming/conditional reads ("tell me when BTC > 65k"), use `coinbase-watch` (`--until`), not polling loops.
51
+ - Market data is read-only and does not place orders. To act on a price, hand off to `coinbase-trading`.
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: coinbase-portfolios
3
+ description: Manages Coinbase Advanced Trade portfolios — list, get, create, edit, delete portfolios, view balances, and move funds between portfolios. Use when the user wants to see their portfolios, create a new one (e.g. "day trading"), check balances, or transfer funds between portfolios. Covers the per-portfolio API-key scoping model.
4
+ requires: coinbase env configured (see `coinbase` skill); transfers need Transfer permission
5
+ ---
6
+
7
+ # coinbase-portfolios
8
+
9
+ Manage portfolios and move funds between them.
10
+
11
+ ## Balances
12
+
13
+ ```sh
14
+ coinbase balance # all account balances (active portfolio)
15
+ coinbase balance show_zero==true # include zero-balance accounts
16
+ ```
17
+
18
+ ## Portfolios
19
+
20
+ ```sh
21
+ coinbase portfolios list
22
+ coinbase portfolios get <portfolio_uuid>
23
+ coinbase portfolios create name="Day Trading"
24
+ coinbase portfolios edit <portfolio_uuid> name="Renamed"
25
+ coinbase portfolios delete <portfolio_uuid>
26
+ ```
27
+
28
+ ## The per-key scoping model
29
+
30
+ Each CDP API key is scoped to ONE portfolio — the key can only trade within it. To operate across portfolios, register one env per portfolio using the `live-<portfolio>` convention:
31
+
32
+ ```sh
33
+ coinbase env live-primary --key-file primary-key.json
34
+ coinbase env live-trading --key-file trading-key.json
35
+ ```
36
+
37
+ Switch with `coinbase env live-trading`, or per-command with `-e live-primary`.
38
+
39
+ ## Move funds between portfolios
40
+
41
+ Switch to the SOURCE portfolio's key first, then transfer:
42
+
43
+ ```sh
44
+ coinbase transfer amount=1000 currency=USD from=<src_uuid> to=<dst_uuid>
45
+ ```
46
+
47
+ ## Funding a fresh account
48
+
49
+ The brokerage API does not buy crypto with a payment method directly. To fund for trading:
50
+
51
+ 1. Deposit USD or crypto via coinbase.com or the mobile app — deposits land in the **default portfolio**.
52
+ 2. If trading from a non-default portfolio, transfer from default (see above).
53
+ 3. Verify: `coinbase balance`
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: coinbase-trading
3
+ description: Places, previews, edits, and cancels spot orders on Coinbase Advanced Trade — market buys/sells, limit orders, stop-loss / take-profit, and order management. Use when the user wants to buy or sell crypto, place an order, set a limit or stop, or check/cancel existing orders. These are real orders.
4
+ requires: coinbase env configured with Trade permission (see `coinbase` skill)
5
+ ---
6
+
7
+ # coinbase-trading
8
+
9
+ Place and manage spot orders. **These are REAL orders.** Confirm the full plan (product, side, size) with the user before placing.
10
+
11
+ ## Market orders
12
+
13
+ Side determines which size field you use:
14
+ - **Market BUY uses `quote_size`** (amount of quote currency, e.g. USD/USDC, to spend).
15
+ - **Market SELL uses `base_size`** (amount of the asset to sell).
16
+
17
+ `client_order_id` is auto-generated — omit it. Place market orders directly in one call; preview only for large or limit/stop orders.
18
+
19
+ ```sh
20
+ # Buy $100 of BTC at market
21
+ coinbase orders create product_id=BTC-USD side=BUY type=market quote_size=100
22
+
23
+ # "Buy N USDC worth of <ASSET>" → BUY on <ASSET>-USDC with quote_size=N
24
+ coinbase orders create product_id=BTC-USDC side=BUY type=market quote_size=1
25
+
26
+ # Sell 0.5 ETH at market
27
+ coinbase orders create product_id=ETH-USD side=SELL type=market base_size=0.5
28
+ ```
29
+
30
+ **Report the result from the create response.** Do NOT automatically run `coinbase orders get <order_id>` afterward — check back with the user first; only run the confirmation `get` if they ask.
31
+
32
+ ## Preview (large or limit/stop orders)
33
+
34
+ Skip preview for small market buys — place directly. For a large order, or any limit/stop, preview first to check fees, fill price, and slippage:
35
+
36
+ ```sh
37
+ coinbase orders preview product_id=BTC-USD side=BUY type=limit base_size=0.5 limit_price=50000
38
+ ```
39
+
40
+ ## Limit orders (resting, server-side)
41
+
42
+ ```sh
43
+ # Resting buy at a price
44
+ coinbase orders create product_id=BTC-USD side=BUY type=limit base_size=0.01 limit_price=50000
45
+
46
+ # Take-profit / sell-at-price
47
+ coinbase orders create product_id=ETH-USD side=SELL type=limit base_size=0.5 limit_price=4000
48
+ ```
49
+
50
+ ## Stop orders (server-side, durable)
51
+
52
+ ```sh
53
+ # Stop-loss sell
54
+ coinbase orders create product_id=BTC-USD side=SELL type=stop_limit \
55
+ base_size=0.01 limit_price=48000 stop_price=49000 stop_direction=down
56
+ ```
57
+
58
+ Prefer native order types — they are durable and server-side. Only use a `--until` watcher (see `coinbase-watch`) when the trigger is something a single resting order cannot express (cross-product price, spread/volume, fill sequencing).
59
+
60
+ ## Manage orders
61
+
62
+ ```sh
63
+ coinbase orders list status==OPEN
64
+ coinbase orders get <order_id>
65
+ coinbase orders cancel order_ids:='["id-1","id-2"]'
66
+ coinbase orders edit <order_id> limit_price=50000
67
+ coinbase orders fills order_id==<order_id>
68
+ coinbase orders close_position product_id=BTC-USD
69
+ ```
70
+
71
+ ## Portfolio scope
72
+
73
+ CDP API keys derive portfolio scope from the key itself — no `retail_portfolio_id` needed in the body. To trade in a different portfolio, switch envs (`-e live-trading`); see `coinbase-portfolios`.
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: coinbase-watch
3
+ description: Watches a live Coinbase data stream and triggers an action when a condition becomes true, via the CLI's `--until` flag. Use when the user wants to "do X when price hits Y", "buy on a dip", "wait until my order fills then…", or any cross-product / spread / volume trigger that a single resting order cannot express. Places real orders when chained.
4
+ requires: coinbase env configured with Trade permission (see `coinbase` skill); CLI lane only (not MCP)
5
+ ---
6
+
7
+ # coinbase-watch (`--until`)
8
+
9
+ `coinbase products ticker|book | orders list <ARGS> --until "<predicate>"` watches a live stream, blocks until the predicate is true, prints the matching event as JSON to stdout, and exits 0 (timeout → 124, permanent failure → 2). Chain an action onto it with `&&`.
10
+
11
+ **Use `--until` ONLY for triggers native `orders` cannot express.** It does not replace native order types — those are durable and server-side; a `--until` watcher is a monitored, session-lived process (see Safety).
12
+
13
+ ## Use native `orders` (see `coinbase-trading`) for — do NOT rebuild with `--until`
14
+
15
+ - Stop-loss → `type=stop_limit` sell, `stop_direction=down`
16
+ - Take-profit / sell-at-price → `type=limit` (or `stop_limit`)
17
+ - Triggered / breakout / dip entry on the *same* product's price → `type=stop_limit`
18
+ - Resting buy/sell at a price → `type=limit`
19
+ - Price ladder → several `type=limit` orders
20
+
21
+ ## Reach for `--until` only when a single resting order can't watch the trigger
22
+
23
+ Cross-product (act on one product based on ANOTHER's price):
24
+ ```sh
25
+ coinbase products ticker BTC-USDC ETH-USDC --until "price BTC-USDC >= 65000" --until-timeout 3600 \
26
+ && coinbase orders create client_order_id=$(uuidgen) product_id=ETH-USDC side=BUY type=market quote_size=50
27
+ ```
28
+
29
+ Compound, multi-field / multi-product:
30
+ ```sh
31
+ coinbase products ticker BTC-USDC ETH-USDC --until "price BTC-USDC >= 65k && price ETH-USDC <= 1500" --until-timeout 3600 \
32
+ && coinbase orders create client_order_id=$(uuidgen) product_id=ETH-USDC side=BUY type=market quote_size=50
33
+ ```
34
+
35
+ Non-price trigger — spread / volume / 24h move:
36
+ ```sh
37
+ # only execute when the book is tight (low slippage)
38
+ coinbase products book BTC-USDC --until "spread <= 1" --until-timeout 600 \
39
+ && coinbase orders create client_order_id=$(uuidgen) product_id=BTC-USDC side=BUY type=market quote_size=50
40
+ # enter only after a sharp 24h drawdown
41
+ coinbase products ticker SOL-USDC --until "pct_24h <= -8" --until-timeout 86400 \
42
+ && coinbase orders create client_order_id=$(uuidgen) product_id=SOL-USDC side=BUY type=market quote_size=25
43
+ ```
44
+
45
+ Fill / state sequencing — run the next leg only AFTER another order fills:
46
+ ```sh
47
+ coinbase orders list --until "status == FILLED" --until-timeout 86400 \
48
+ && coinbase orders create client_order_id=$(uuidgen) product_id=ETH-USDC side=BUY type=market quote_size=50
49
+ ```
50
+
51
+ Arbitrary "then" — the matched event is JSON on stdout; the chained action can be anything (notify, call another tool, place a *different* order), not just an order.
52
+
53
+ ## Predicate syntax
54
+
55
+ Form: `field [product] op value`. Operators `== != > < >= <=`, combined with `&& || ( )`; numeric suffixes `k m b`. Scope to a product when watching several: `price BTC-USDC >= 65k`.
56
+
57
+ **Don't memorize the fields — they're per-stream and authoritative in `--help`** (generated from the spec). Run `coinbase products ticker --help` (or `products book` / `orders list`) for the valid fields, types, and ready examples for that surface.
58
+
59
+ ## Safety rules
60
+
61
+ - Gate every action on a match: chain with `&&` (runs only on exit 0). A timeout (124) or failure (2) must NOT trade. Always set `--until-timeout`.
62
+ - Resolve relative targets ("3% below") from LIVE spot at arm time, and confirm the resolved absolute number with the user before arming:
63
+ `SPOT=$(coinbase products ticker BTC-USDC --jq '.trades[0].price' | tr -d '"')`
64
+ - These are REAL orders. Confirm the full plan before arming; do NOT auto-run `orders get` afterward.
65
+ - A `--until` watcher is MONITORED and session-lived, not a resting server-side order — if it stops, the trigger is gone. For anything that must survive, use a native `limit` / `stop_limit`.