playmaker-cli 0.5.0__tar.gz → 0.6.0__tar.gz

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.
Files changed (34) hide show
  1. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/CHANGELOG.md +57 -0
  2. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/PKG-INFO +59 -16
  3. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/README.md +56 -13
  4. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/pyproject.toml +4 -2
  5. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/skills/playmaker-coach/SKILL.md +31 -20
  6. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/agents/agy.py +7 -4
  7. playmaker_cli-0.6.0/src/playmaker/agents/opencode.py +461 -0
  8. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/cli.py +39 -8
  9. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/quotas.py +160 -0
  10. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/registry.py +2 -0
  11. playmaker_cli-0.6.0/tests/test_opencode.py +430 -0
  12. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/tests/test_permissions.py +18 -0
  13. playmaker_cli-0.6.0/tests/test_quotas_zai.py +165 -0
  14. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/tests/test_registry.py +2 -2
  15. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/.gitignore +0 -0
  16. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/LICENSE +0 -0
  17. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/__init__.py +0 -0
  18. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/__main__.py +0 -0
  19. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/agents/__init__.py +0 -0
  20. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/agents/base.py +0 -0
  21. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/agents/claude.py +0 -0
  22. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/agents/codex.py +0 -0
  23. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/agents/gemini.py +0 -0
  24. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/config.py +0 -0
  25. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/notify.py +0 -0
  26. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/state.py +0 -0
  27. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/src/playmaker/watcher.py +0 -0
  28. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/tests/__init__.py +0 -0
  29. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/tests/test_agy.py +0 -0
  30. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/tests/test_claude.py +0 -0
  31. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/tests/test_codex.py +0 -0
  32. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/tests/test_quotas_antigravity.py +0 -0
  33. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/tests/test_skill.py +0 -0
  34. {playmaker_cli-0.5.0 → playmaker_cli-0.6.0}/tests/test_state.py +0 -0
@@ -5,6 +5,63 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.6.0] - 2026-07-27
9
+
10
+ ### Added
11
+
12
+ - **`opencode` agent handler — one lane, ~75 providers.** The ask was z.ai GLM
13
+ support, but playmaker never talks to a model API: it drives agent CLIs. So
14
+ rather than teach the claude handler an `ANTHROPIC_BASE_URL` override — which
15
+ would have *replaced* the Anthropic lane rather than added one — the handler
16
+ wraps [opencode](https://opencode.ai), whose `--model provider/model` already
17
+ reaches GLM (`zai-coding-plan/glm-5.2`), local LMStudio/MLX models, and
18
+ everything else on models.dev. Oneshot via `opencode run --format json`,
19
+ resume via `-s <id>`; every JSONL event carries `sessionID`, so a detached
20
+ dispatch records the id from the first line rather than at completion.
21
+
22
+ Four behaviours worth knowing. opencode resolves its working directory from
23
+ `process.env.PWD`, which `subprocess.Popen(cwd=…)` does not update — left
24
+ alone it ignores `--cwd` and writes into whatever directory the coach was
25
+ sitting in, so the handler passes `--dir` and corrects `PWD`.
26
+ opencode ≥1.18 keeps transcripts in SQLite
27
+ (`opencode.db`), not one file per session, so playmaker writes a pointer at
28
+ `~/.playmaker/opencode/<id>.session` and reads the `session`/`message`/`part`
29
+ tables live — which keeps `thread --follow` current rather than frozen.
30
+ Cost comes from opencode's own per-session accounting rather than the stream,
31
+ because `run --format json` can exit before its final `step_finish`
32
+ ([opencode#26855](https://github.com/anomalyco/opencode/issues/26855)).
33
+ And `[agents.opencode] model` matters more than the usual `--model` default:
34
+ left unset, opencode falls back to whatever its own `opencode.json` says,
35
+ which is typically the model you last picked interactively rather than the
36
+ one you meant to dispatch to.
37
+
38
+ Permissions follow agy, for the same reason: `--auto` is opencode's only
39
+ lever, so a detached run either auto-approves or comes back having done
40
+ nothing. `yolo` defaults to `true`; narrow it with the `permission` block in
41
+ your own opencode.json, which `--auto` still honours for denies.
42
+ - **`zai` quota probe** — GLM Coding Plan windows (5-hour, weekly, and the
43
+ monthly MCP tool pool) from `api.z.ai/api/monitor/usage/quota/limit`, keyed
44
+ off the credential opencode already wrote to its `auth.json`, so playmaker
45
+ still stores no secret of its own. Reported as its own provider rather than
46
+ under `opencode`, because the quota belongs to the plan — an opencode lane
47
+ pointed at a local model spends nothing here. Degrades to *unsupported*, not
48
+ an error row, when no Z.ai credential exists.
49
+
50
+ ## [0.5.1] - 2026-07-27
51
+
52
+ ### Fixed
53
+
54
+ - **The bundled coach skill taught agy model names agy no longer accepts.**
55
+ `agy models` switched from quoted display strings (`"Claude Opus 4.6
56
+ (Thinking)"`) to bare slugs (`claude-opus-4-6-thinking`), so every agy
57
+ dispatch the skill proposed failed model validation. The skill now says to
58
+ read the live roster from `agy models` instead of spelling names from
59
+ memory. It also recommended `codex -m gpt-5-codex`, which fails on accounts
60
+ whose plan lacks that model; codex dispatches now default to the account's
61
+ own default model. Both fixes landed on main just after v0.5.0 was tagged —
62
+ this release exists because the skill ships inside the wheel, so doc fixes
63
+ are not live until published.
64
+
8
65
  ## [0.5.0] - 2026-07-27
9
66
 
10
67
  ### Changed
@@ -1,14 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: playmaker-cli
3
- Version: 0.5.0
4
- Summary: Playing-coach CLI for orchestrating Claude Code, Codex and Antigravity sub-agents in parallel.
3
+ Version: 0.6.0
4
+ Summary: Playing-coach CLI for orchestrating Claude Code, Codex, Antigravity and opencode sub-agents in parallel.
5
5
  Project-URL: Homepage, https://github.com/vladsafedev/playmaker
6
6
  Project-URL: Repository, https://github.com/vladsafedev/playmaker
7
7
  Project-URL: Issues, https://github.com/vladsafedev/playmaker/issues
8
8
  Author-email: Vladislav Shulyugin <vladislav.shulyugin@gmail.com>
9
9
  License-Expression: MIT
10
10
  License-File: LICENSE
11
- Keywords: agents,ai,antigravity,claude,claude-code,cli,codex,gemini,orchestration,subagents
11
+ Keywords: agents,ai,antigravity,claude,claude-code,cli,codex,gemini,glm,opencode,orchestration,subagents
12
12
  Classifier: Development Status :: 3 - Alpha
13
13
  Classifier: Environment :: Console
14
14
  Classifier: Intended Audience :: Developers
@@ -28,11 +28,11 @@ Description-Content-Type: text/markdown
28
28
  # playmaker
29
29
 
30
30
  [![CI](https://github.com/vladsafedev/playmaker/actions/workflows/ci.yml/badge.svg)](https://github.com/vladsafedev/playmaker/actions/workflows/ci.yml)
31
- [![PyPI](https://img.shields.io/pypi/v/playmaker-cli.svg)](https://pypi.org/project/playmaker-cli/)
32
- [![Python](https://img.shields.io/pypi/pyversions/playmaker-cli.svg)](https://pypi.org/project/playmaker-cli/)
31
+ [![PyPI](https://img.shields.io/pypi/v/playmaker-cli.svg?cacheSeconds=3600)](https://pypi.org/project/playmaker-cli/)
32
+ [![Python](https://img.shields.io/pypi/pyversions/playmaker-cli.svg?cacheSeconds=3600)](https://pypi.org/project/playmaker-cli/)
33
33
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
34
34
 
35
- **Run Claude Code, Codex and Antigravity as parallel sub-agents from one terminal — and spend three separate quotas instead of one.**
35
+ **Run Claude Code, Codex, Antigravity and opencode as parallel sub-agents from one terminal — and spend separate quotas instead of one.**
36
36
 
37
37
  You stay in your Claude Code session doing the part only you can do. `playmaker`
38
38
  fans the rest out to other agent CLIs as detached processes, tracks them,
@@ -41,9 +41,9 @@ parses their native session files, and pings you when they land.
41
41
  ```console
42
42
  $ B=dashboard # one label for the whole fan-out
43
43
 
44
- $ playmaker dispatch codex --batch $B --model gpt-5-codex -p "Add PATCH /users/:id …"
44
+ $ playmaker dispatch codex --batch $B -p "Add PATCH /users/:id …"
45
45
  session: 9f2c1a4e-… pid: 48211 (detached)
46
- $ playmaker dispatch agy --batch $B --model "Gemini 3.5 Flash (High)" -p "pytest coverage for …"
46
+ $ playmaker dispatch agy --batch $B --model gemini-3.6-flash-high -p "pytest coverage for …"
47
47
  session: 4b1f9c02-… pid: 48219 (detached)
48
48
  $ playmaker dispatch claude --batch $B --model sonnet -p "Update the API docs for …"
49
49
  session: c07d5511-… pid: 48244 (detached)
@@ -74,10 +74,12 @@ in one serial session:
74
74
  1. **Wall-clock speed.** A task that decomposes into 3–5 independent
75
75
  work-streams (schema, backend, frontend, tests, docs) finishes 2–4× faster
76
76
  when each stream runs as its own parallel agent.
77
- 2. **Provider arbitrage.** Codex and Antigravity quotas are entirely separate
78
- pools from your Anthropic plan. Every slice you hand them is capacity your
79
- main session never spends — and Antigravity's roster includes Claude
80
- Sonnet/Opus, so even Claude-quality work can run on Google's pool.
77
+ 2. **Provider arbitrage.** Codex, Antigravity and opencode quotas are entirely
78
+ separate pools from your Anthropic plan. Every slice you hand them is
79
+ capacity your main session never spends — and Antigravity's roster includes
80
+ Claude Sonnet/Opus, so even Claude-quality work can run on Google's pool.
81
+ `opencode` widens this the most: one CLI fronting ~75 providers, from a z.ai
82
+ GLM coding plan to models running locally on your own machine.
81
83
  3. **Bucket arbitrage inside one plan.** Headless `claude -p` draws on the same
82
84
  subscription as your interactive session, but per-model weekly buckets are
83
85
  separate — dispatching `--model sonnet` spends Sonnet's usually-idle bucket
@@ -134,6 +136,16 @@ The other agents differ, because their CLIs do:
134
136
  either auto-approves or comes back having done nothing. It therefore
135
137
  defaults to `yolo = true`; layer `sandbox = true` on top for agy's own
136
138
  terminal restrictions.
139
+ - **opencode** is the same story: its only lever is `--auto`, so it also
140
+ defaults to `yolo = true`. The granular control lives in opencode's own
141
+ config rather than in playmaker — and `--auto` still honours it, because it
142
+ auto-approves only what you have not explicitly denied:
143
+
144
+ ```jsonc
145
+ // ~/.config/opencode/opencode.json
146
+ { "permission": { "edit": "allow", "bash": "allow", "webfetch": "deny" } }
147
+ ```
148
+
137
149
  - **gemini** (legacy) runs with `--yolo`.
138
150
 
139
151
  ## Install
@@ -168,8 +180,9 @@ playmaker agents # which agent CLIs are reachable
168
180
  | Agent | Install | Notes |
169
181
  |---|---|---|
170
182
  | **Claude Code** | `npm i -g @anthropic-ai/claude-code` | `--model sonnet` / `opus` / `haiku` |
171
- | **Codex CLI** | `npm i -g @openai/codex` | `--model gpt-5-codex` |
172
- | **Antigravity (`agy`)** | bundled with [Antigravity](https://antigravity.google) | models are display names: `--model "Claude Opus 4.6 (Thinking)"` see `agy models` |
183
+ | **Codex CLI** | `npm i -g @openai/codex` | the model roster depends on your plan; omit `--model` to use the account default |
184
+ | **Antigravity (`agy`)** | bundled with [Antigravity](https://antigravity.google) | `--model claude-opus-4-6-thinking` the roster moves, so read it from `agy models` |
185
+ | **opencode** | `brew install sst/tap/opencode` (or see [opencode.ai](https://opencode.ai)) | `--model provider/model`, e.g. `zai-coding-plan/glm-5.2`; roster from `opencode models`, providers from `opencode auth login` |
173
186
  | **Gemini CLI** (legacy) | `npm i -g @google/gemini-cli` | still supported, superseded by `agy` |
174
187
 
175
188
  At least one is required; `playmaker agents` tells you which it can see.
@@ -233,9 +246,11 @@ flowchart LR
233
246
  P --> A1["claude -p<br/>--model sonnet"]
234
247
  P --> A2["codex exec"]
235
248
  P --> A3["agy -p"]
249
+ P --> A4["opencode run<br/>-m zai-coding-plan/glm-5.2"]
236
250
  A1 --> S[("state.db<br/>outputs/ + logs/")]
237
251
  A2 --> S
238
252
  A3 --> S
253
+ A4 --> S
239
254
  S -->|"list / thread / summary"| C
240
255
  S -.->|"batch drained"| N["one ping"]
241
256
  ```
@@ -250,6 +265,7 @@ bookkeeping in between.
250
265
  ├── agents/ optional agent profile markdown (claude.md, codex.md, agy.md…)
251
266
  ├── outputs/ final output per session — .md, or .json if the agent returned JSON
252
267
  ├── logs/ subprocess stdout for detached runs
268
+ ├── opencode/ pointer per opencode session (its transcript lives in SQLite)
253
269
  └── quotas.json latest capacity snapshot
254
270
  ```
255
271
 
@@ -261,6 +277,7 @@ and locates the session file the tool writes locally. Empirically:
261
277
  | Claude | `~/.claude/projects/<cwd-with-slashes-as-dashes>/<id>.jsonl` |
262
278
  | Codex | `~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-<ts>-<thread_id>.jsonl` |
263
279
  | Antigravity | `~/.gemini/antigravity-cli/brain/<conversation-id>/.system_generated/logs/transcript_full.jsonl` |
280
+ | opencode | SQLite — `~/.local/share/opencode/opencode.db` (`session` / `message` / `part`); playmaker keeps a pointer at `~/.playmaker/opencode/<id>.session` |
264
281
  | Gemini | `~/.gemini/tmp/<cwd-basename>/chats/session-<ts>-<short_id>.{json,jsonl}` |
265
282
 
266
283
  `thread` and `summary` normalize all of them into the same turn list, so every
@@ -276,6 +293,21 @@ dispatch; and a wrong `--model` is a silent failure on both **codex** (reports
276
293
  `turn.failed` while exiting 0) and **agy** (runs its default model instead) —
277
294
  playmaker turns both into real errors.
278
295
 
296
+ **opencode** deserves its own note, because one CLI is many providers. Models
297
+ are `provider/model` strings from `opencode models`, and if you don't pass
298
+ `--model` opencode falls back to the default in *its* config — often whatever
299
+ you last picked interactively. Set the lane's default once:
300
+
301
+ ```toml
302
+ [agents.opencode]
303
+ model = "zai-coding-plan/glm-5.2"
304
+ ```
305
+
306
+ It also has agy's working-directory problem in a different costume: opencode
307
+ reads `process.env.PWD`, which a subprocess `cwd` does not update, so left
308
+ alone it would ignore `--cwd` and write into the directory *you* were standing
309
+ in. playmaker passes `--dir` and fixes up `PWD`, so `--cwd` means what it says.
310
+
279
311
  ## Notifications
280
312
 
281
313
  Every detached dispatch pings when it finishes. With
@@ -321,11 +353,16 @@ Antigravity (agy)
321
353
  Gemini weekly ███████████████████░ 95% left
322
354
  Claude/GPT 5h ██████████████████░░ 90% left resets in 2h 05m
323
355
  Claude/GPT weekly ██████████████░░░░░░ 70% left resets in 5d 1h
356
+
357
+ Z.ai (GLM, via opencode) Max
358
+ Session ████████████████████ 100% left
359
+ Weekly ███████████████████░ 95% left resets in 1d 11h
360
+ MCP tools ███████████████████░ 99% left resets in 25d 11h
324
361
  ```
325
362
 
326
363
  The `Weekly` and `Sonnet` rows above are the point: they are **separate
327
- buckets**. So is every agy row. Routing a subtask is choosing which of them to
328
- spend.
364
+ buckets**. So is every agy row, and so is the whole Z.ai block. Routing a
365
+ subtask is choosing which of them to spend.
329
366
 
330
367
  - **Claude** — OAuth usage API; token from the Claude Code Keychain entry.
331
368
  - **Codex** — ChatGPT `wham/usage` API; token from `~/.codex/auth.json`.
@@ -336,6 +373,12 @@ spend.
336
373
  `retrieveUserQuota` on the Antigravity backend, which surfaces only coarse
337
374
  Gemini buckets and is flagged *daemon offline*. Approach ported from
338
375
  [steipete/CodexBar](https://github.com/steipete/CodexBar).
376
+ - **Z.ai** — GLM Coding Plan usage API; key from opencode's
377
+ `~/.local/share/opencode/auth.json` (or `$ZAI_API_KEY`). Reported as its own
378
+ provider because the quota belongs to the plan, not to opencode — an opencode
379
+ lane pointed at a local model spends nothing here. Shows *unsupported* rather
380
+ than an error when no Z.ai credential exists. `MCP tools` is the monthly
381
+ web-search/reader pool, not inference.
339
382
 
340
383
  Reading these at *model* granularity is the point: they are the load-balancing
341
384
  input the coach skill uses to route each subtask.
@@ -1,11 +1,11 @@
1
1
  # playmaker
2
2
 
3
3
  [![CI](https://github.com/vladsafedev/playmaker/actions/workflows/ci.yml/badge.svg)](https://github.com/vladsafedev/playmaker/actions/workflows/ci.yml)
4
- [![PyPI](https://img.shields.io/pypi/v/playmaker-cli.svg)](https://pypi.org/project/playmaker-cli/)
5
- [![Python](https://img.shields.io/pypi/pyversions/playmaker-cli.svg)](https://pypi.org/project/playmaker-cli/)
4
+ [![PyPI](https://img.shields.io/pypi/v/playmaker-cli.svg?cacheSeconds=3600)](https://pypi.org/project/playmaker-cli/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/playmaker-cli.svg?cacheSeconds=3600)](https://pypi.org/project/playmaker-cli/)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
7
 
8
- **Run Claude Code, Codex and Antigravity as parallel sub-agents from one terminal — and spend three separate quotas instead of one.**
8
+ **Run Claude Code, Codex, Antigravity and opencode as parallel sub-agents from one terminal — and spend separate quotas instead of one.**
9
9
 
10
10
  You stay in your Claude Code session doing the part only you can do. `playmaker`
11
11
  fans the rest out to other agent CLIs as detached processes, tracks them,
@@ -14,9 +14,9 @@ parses their native session files, and pings you when they land.
14
14
  ```console
15
15
  $ B=dashboard # one label for the whole fan-out
16
16
 
17
- $ playmaker dispatch codex --batch $B --model gpt-5-codex -p "Add PATCH /users/:id …"
17
+ $ playmaker dispatch codex --batch $B -p "Add PATCH /users/:id …"
18
18
  session: 9f2c1a4e-… pid: 48211 (detached)
19
- $ playmaker dispatch agy --batch $B --model "Gemini 3.5 Flash (High)" -p "pytest coverage for …"
19
+ $ playmaker dispatch agy --batch $B --model gemini-3.6-flash-high -p "pytest coverage for …"
20
20
  session: 4b1f9c02-… pid: 48219 (detached)
21
21
  $ playmaker dispatch claude --batch $B --model sonnet -p "Update the API docs for …"
22
22
  session: c07d5511-… pid: 48244 (detached)
@@ -47,10 +47,12 @@ in one serial session:
47
47
  1. **Wall-clock speed.** A task that decomposes into 3–5 independent
48
48
  work-streams (schema, backend, frontend, tests, docs) finishes 2–4× faster
49
49
  when each stream runs as its own parallel agent.
50
- 2. **Provider arbitrage.** Codex and Antigravity quotas are entirely separate
51
- pools from your Anthropic plan. Every slice you hand them is capacity your
52
- main session never spends — and Antigravity's roster includes Claude
53
- Sonnet/Opus, so even Claude-quality work can run on Google's pool.
50
+ 2. **Provider arbitrage.** Codex, Antigravity and opencode quotas are entirely
51
+ separate pools from your Anthropic plan. Every slice you hand them is
52
+ capacity your main session never spends — and Antigravity's roster includes
53
+ Claude Sonnet/Opus, so even Claude-quality work can run on Google's pool.
54
+ `opencode` widens this the most: one CLI fronting ~75 providers, from a z.ai
55
+ GLM coding plan to models running locally on your own machine.
54
56
  3. **Bucket arbitrage inside one plan.** Headless `claude -p` draws on the same
55
57
  subscription as your interactive session, but per-model weekly buckets are
56
58
  separate — dispatching `--model sonnet` spends Sonnet's usually-idle bucket
@@ -107,6 +109,16 @@ The other agents differ, because their CLIs do:
107
109
  either auto-approves or comes back having done nothing. It therefore
108
110
  defaults to `yolo = true`; layer `sandbox = true` on top for agy's own
109
111
  terminal restrictions.
112
+ - **opencode** is the same story: its only lever is `--auto`, so it also
113
+ defaults to `yolo = true`. The granular control lives in opencode's own
114
+ config rather than in playmaker — and `--auto` still honours it, because it
115
+ auto-approves only what you have not explicitly denied:
116
+
117
+ ```jsonc
118
+ // ~/.config/opencode/opencode.json
119
+ { "permission": { "edit": "allow", "bash": "allow", "webfetch": "deny" } }
120
+ ```
121
+
110
122
  - **gemini** (legacy) runs with `--yolo`.
111
123
 
112
124
  ## Install
@@ -141,8 +153,9 @@ playmaker agents # which agent CLIs are reachable
141
153
  | Agent | Install | Notes |
142
154
  |---|---|---|
143
155
  | **Claude Code** | `npm i -g @anthropic-ai/claude-code` | `--model sonnet` / `opus` / `haiku` |
144
- | **Codex CLI** | `npm i -g @openai/codex` | `--model gpt-5-codex` |
145
- | **Antigravity (`agy`)** | bundled with [Antigravity](https://antigravity.google) | models are display names: `--model "Claude Opus 4.6 (Thinking)"` see `agy models` |
156
+ | **Codex CLI** | `npm i -g @openai/codex` | the model roster depends on your plan; omit `--model` to use the account default |
157
+ | **Antigravity (`agy`)** | bundled with [Antigravity](https://antigravity.google) | `--model claude-opus-4-6-thinking` the roster moves, so read it from `agy models` |
158
+ | **opencode** | `brew install sst/tap/opencode` (or see [opencode.ai](https://opencode.ai)) | `--model provider/model`, e.g. `zai-coding-plan/glm-5.2`; roster from `opencode models`, providers from `opencode auth login` |
146
159
  | **Gemini CLI** (legacy) | `npm i -g @google/gemini-cli` | still supported, superseded by `agy` |
147
160
 
148
161
  At least one is required; `playmaker agents` tells you which it can see.
@@ -206,9 +219,11 @@ flowchart LR
206
219
  P --> A1["claude -p<br/>--model sonnet"]
207
220
  P --> A2["codex exec"]
208
221
  P --> A3["agy -p"]
222
+ P --> A4["opencode run<br/>-m zai-coding-plan/glm-5.2"]
209
223
  A1 --> S[("state.db<br/>outputs/ + logs/")]
210
224
  A2 --> S
211
225
  A3 --> S
226
+ A4 --> S
212
227
  S -->|"list / thread / summary"| C
213
228
  S -.->|"batch drained"| N["one ping"]
214
229
  ```
@@ -223,6 +238,7 @@ bookkeeping in between.
223
238
  ├── agents/ optional agent profile markdown (claude.md, codex.md, agy.md…)
224
239
  ├── outputs/ final output per session — .md, or .json if the agent returned JSON
225
240
  ├── logs/ subprocess stdout for detached runs
241
+ ├── opencode/ pointer per opencode session (its transcript lives in SQLite)
226
242
  └── quotas.json latest capacity snapshot
227
243
  ```
228
244
 
@@ -234,6 +250,7 @@ and locates the session file the tool writes locally. Empirically:
234
250
  | Claude | `~/.claude/projects/<cwd-with-slashes-as-dashes>/<id>.jsonl` |
235
251
  | Codex | `~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-<ts>-<thread_id>.jsonl` |
236
252
  | Antigravity | `~/.gemini/antigravity-cli/brain/<conversation-id>/.system_generated/logs/transcript_full.jsonl` |
253
+ | opencode | SQLite — `~/.local/share/opencode/opencode.db` (`session` / `message` / `part`); playmaker keeps a pointer at `~/.playmaker/opencode/<id>.session` |
237
254
  | Gemini | `~/.gemini/tmp/<cwd-basename>/chats/session-<ts>-<short_id>.{json,jsonl}` |
238
255
 
239
256
  `thread` and `summary` normalize all of them into the same turn list, so every
@@ -249,6 +266,21 @@ dispatch; and a wrong `--model` is a silent failure on both **codex** (reports
249
266
  `turn.failed` while exiting 0) and **agy** (runs its default model instead) —
250
267
  playmaker turns both into real errors.
251
268
 
269
+ **opencode** deserves its own note, because one CLI is many providers. Models
270
+ are `provider/model` strings from `opencode models`, and if you don't pass
271
+ `--model` opencode falls back to the default in *its* config — often whatever
272
+ you last picked interactively. Set the lane's default once:
273
+
274
+ ```toml
275
+ [agents.opencode]
276
+ model = "zai-coding-plan/glm-5.2"
277
+ ```
278
+
279
+ It also has agy's working-directory problem in a different costume: opencode
280
+ reads `process.env.PWD`, which a subprocess `cwd` does not update, so left
281
+ alone it would ignore `--cwd` and write into the directory *you* were standing
282
+ in. playmaker passes `--dir` and fixes up `PWD`, so `--cwd` means what it says.
283
+
252
284
  ## Notifications
253
285
 
254
286
  Every detached dispatch pings when it finishes. With
@@ -294,11 +326,16 @@ Antigravity (agy)
294
326
  Gemini weekly ███████████████████░ 95% left
295
327
  Claude/GPT 5h ██████████████████░░ 90% left resets in 2h 05m
296
328
  Claude/GPT weekly ██████████████░░░░░░ 70% left resets in 5d 1h
329
+
330
+ Z.ai (GLM, via opencode) Max
331
+ Session ████████████████████ 100% left
332
+ Weekly ███████████████████░ 95% left resets in 1d 11h
333
+ MCP tools ███████████████████░ 99% left resets in 25d 11h
297
334
  ```
298
335
 
299
336
  The `Weekly` and `Sonnet` rows above are the point: they are **separate
300
- buckets**. So is every agy row. Routing a subtask is choosing which of them to
301
- spend.
337
+ buckets**. So is every agy row, and so is the whole Z.ai block. Routing a
338
+ subtask is choosing which of them to spend.
302
339
 
303
340
  - **Claude** — OAuth usage API; token from the Claude Code Keychain entry.
304
341
  - **Codex** — ChatGPT `wham/usage` API; token from `~/.codex/auth.json`.
@@ -309,6 +346,12 @@ spend.
309
346
  `retrieveUserQuota` on the Antigravity backend, which surfaces only coarse
310
347
  Gemini buckets and is flagged *daemon offline*. Approach ported from
311
348
  [steipete/CodexBar](https://github.com/steipete/CodexBar).
349
+ - **Z.ai** — GLM Coding Plan usage API; key from opencode's
350
+ `~/.local/share/opencode/auth.json` (or `$ZAI_API_KEY`). Reported as its own
351
+ provider because the quota belongs to the plan, not to opencode — an opencode
352
+ lane pointed at a local model spends nothing here. Shows *unsupported* rather
353
+ than an error when no Z.ai credential exists. `MCP tools` is the monthly
354
+ web-search/reader pool, not inference.
312
355
 
313
356
  Reading these at *model* granularity is the point: they are the load-balancing
314
357
  input the coach skill uses to route each subtask.
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "playmaker-cli"
3
- version = "0.5.0"
4
- description = "Playing-coach CLI for orchestrating Claude Code, Codex and Antigravity sub-agents in parallel."
3
+ version = "0.6.0"
4
+ description = "Playing-coach CLI for orchestrating Claude Code, Codex, Antigravity and opencode sub-agents in parallel."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
7
7
  license = "MIT"
@@ -19,6 +19,8 @@ keywords = [
19
19
  "codex",
20
20
  "antigravity",
21
21
  "gemini",
22
+ "opencode",
23
+ "glm",
22
24
  "subagents",
23
25
  ]
24
26
  classifiers = [
@@ -1,13 +1,15 @@
1
1
  ---
2
2
  name: playmaker-coach
3
- description: Playing-coach orchestration of Claude/Codex/Antigravity (agy) sub-agents via the `playmaker` CLI and in-session Task sub-agents. Triggered when the user gives a complex multi-component task where decomposition gives >2x parallel speedup (e.g. "build admin dashboard with schema, backend, FE, tests, docs"). NOT triggered for single-file refactor, single bug fix, single component, or simple Q&A — those stay in this thread without delegation.
3
+ description: Playing-coach orchestration of Claude/Codex/Antigravity (agy)/opencode sub-agents via the `playmaker` CLI and in-session Task sub-agents. Triggered when the user gives a complex multi-component task where decomposition gives >2x parallel speedup (e.g. "build admin dashboard with schema, backend, FE, tests, docs"). NOT triggered for single-file refactor, single bug fix, single component, or simple Q&A — those stay in this thread without delegation.
4
4
  ---
5
5
 
6
6
  # playmaker-coach — playing-coach orchestration
7
7
 
8
- Use the `playmaker` CLI as a facade to dispatch sub-tasks to Codex / Antigravity (`agy`) / a sibling Claude, monitor them, read their threads, review their diffs, and feed back. The coach (this thread) does its own portion of the work in parallel.
8
+ Use the `playmaker` CLI as a facade to dispatch sub-tasks to Codex / Antigravity (`agy`) / opencode / a sibling Claude, monitor them, read their threads, review their diffs, and feed back. The coach (this thread) does its own portion of the work in parallel.
9
9
 
10
- > **`agy` (Antigravity CLI)** does not only serve Google models: `agy models` exposes **Gemini 3.5 Flash (Low/Medium/High)**, **Gemini 3.1 Pro (Low/High)**, **Claude Sonnet 4.6 (Thinking)**, **Claude Opus 4.6 (Thinking)**, and **GPT-OSS 120B (Medium)**. Opus via agy runs on *Google's* quota pool — top-tier Claude work that does not touch the Anthropic subscription's scarce Opus weekly bucket. Model names are the exact display strings (quote them in bash): `--model "Claude Opus 4.6 (Thinking)"`.
10
+ > **`agy` (Antigravity CLI)** does not only serve Google models: alongside the Gemini Flash and Pro tiers, `agy models` carries **Claude Sonnet and Opus** and a **GPT-OSS** mid-tier. Opus via agy runs on *Google's* quota pool — top-tier Claude work that does not touch the Anthropic subscription's scarce Opus weekly bucket: `--model claude-opus-4-6-thinking`.
11
+ >
12
+ > **Never write an agy model name from memory — run `agy models` and copy a line.** Both the roster *and its spelling* move with Antigravity releases: names used to be quoted display strings like `"Claude Opus 4.6 (Thinking)"` and are now bare slugs. playmaker validates `--model` against the live roster and fails the dispatch on a stale name, so a wrong guess costs you a round-trip.
11
13
 
12
14
  **The point of the coach pattern:** all available models do useful work in parallel under your direction. The coach's job is *orchestration*, not *production*. A coach that does its own implementation, runs its own codebase recon, and reviews everything line by line burns the same budget delegation was meant to save. Treat your own context window as the most expensive resource on the table — every byte you read or generate yourself is a byte that could have come from a cheaper model. Push out as much as you can: implementation, recon, summarization, even drafting the per-subtask prompts when the task is large enough.
13
15
 
@@ -21,7 +23,7 @@ All Claude work — coach, internal sub-agents, external `claude -p` — draws f
21
23
 
22
24
  3. **External dispatch — `playmaker dispatch <agent>`.** Separate OS processes, tracked in playmaker (`list`/`watch`/`thread`/`continue`):
23
25
  - **`claude -p` (sibling Claude):** same subscription. Its key lever is the model bucket — **Sonnet is a separate weekly bucket from Opus**, usually idle while Opus depletes, so default **`--model sonnet`** to spare the scarce Opus bucket (**`--model haiku`** for trivial mechanical work). It **can write files** — playmaker runs it in `acceptEdits`, so it edits and runs commands freely inside `--cwd` and is refused outside it (see §10). Use it over an internal sub-agent when you want a **tracked, detached work-stream** you can monitor/continue independently of the coach's turn.
24
- - **`codex` / `agy`:** each on its own subscription/quota — the right home for **write-heavy** parallel implementation that can leave the Anthropic subscription. `agy` is special: besides Gemini tiers it carries **Claude Sonnet/Opus 4.6 (Thinking)** on Google's pool, so even "must be Claude-quality" work can leave the Anthropic quota.
26
+ - **`codex` / `agy` / `opencode`:** each on its own subscription/quota — the right home for **write-heavy** parallel implementation that can leave the Anthropic subscription. `agy` is special: besides Gemini tiers it carries **Claude Sonnet/Opus 4.6 (Thinking)** on Google's pool, so even "must be Claude-quality" work can leave the Anthropic quota. `opencode` is the widest lane: one CLI over ~75 providers, addressed as `provider/model` — a GLM coding plan (`zai-coding-plan/glm-5.2`), or a model running locally on this machine, which spends **no** subscription quota at all.
25
27
 
26
28
  **Routing cheat-sheet for Claude-side work:**
27
29
 
@@ -30,8 +32,10 @@ All Claude work — coach, internal sub-agents, external `claude -p` — draws f
30
32
  | writes files and the coach integrates the result directly | **internal sub-agent** (Task tool) | in-session, write-capable, returns into context |
31
33
  | is an independent stream you'll monitor / continue separately | **external `dispatch claude --model sonnet`** | tracked & detached; Sonnet's own weekly bucket spares Opus |
32
34
  | is heavy reasoning only the coach can do | **coach** | top-tier Opus, serial |
33
- | is write-heavy and can leave Claude | **codex / agy** | their own quotas |
34
- | needs top-tier Claude but the Anthropic Opus weekly is precious | **`dispatch agy --model "Claude Opus 4.6 (Thinking)"`** | Opus quality on Google's pool |
35
+ | is write-heavy and can leave Claude | **codex / agy / opencode** | their own quotas |
36
+ | needs top-tier Claude but the Anthropic Opus weekly is precious | **`dispatch agy --model claude-opus-4-6-thinking`** | Opus quality on Google's pool |
37
+ | is bulk work and every subscription is running low | **`dispatch opencode --model zai-coding-plan/glm-5.2`** | a separate GLM plan, untouched by the others |
38
+ | is mechanical and privacy-sensitive, or all quotas are spent | **`dispatch opencode --model <local provider>/<model>`** | runs on this machine; costs no quota, just wall-clock |
35
39
 
36
40
  **Sonnet is your cheap parallel Claude worker** — a separate weekly bucket that usually sits idle while Opus depletes. Reach for it (via `dispatch claude --model sonnet`, or by pointing an internal sub-agent at Sonnet) instead of burning Opus on mid-tier work.
37
41
 
@@ -59,6 +63,7 @@ playmaker quotas --refresh # current capacity, broken out per model
59
63
  - Claude: two non-coach ways to run it — an **internal sub-agent** (Task tool; in-session, write-capable, result returns to the coach) and an **external `claude -p` dispatch** (tracked, detached stream). Both draw on the subscription; the difference is where results land, not cost. See "Execution lanes". Default external Claude to `--model sonnet` — its weekly bucket is separate from Opus and usually idle, so it spares the scarce coach (Opus) bucket.
60
64
  - Antigravity (`agy`): one Google pool split across model families — Gemini Flash tiers for cheap bulk work, Gemini 3.1 Pro for hard Gemini work, **Claude Sonnet/Opus 4.6 (Thinking)** as Anthropic-quality capacity that spends *Google's* quota, GPT-OSS 120B as a spare mid-tier. `playmaker quotas` shows the **full categorized breakdown** — `Gemini 5h` / `Gemini weekly` and `Claude/GPT 5h` / `Claude/GPT weekly`. Two things share a bucket: all Gemini models draw the Gemini bucket, and Claude *and* GPT-OSS share the Claude/GPT bucket. So dispatching Opus 4.6 via agy spends the same `Claude/GPT` bucket as Sonnet or GPT-OSS — watch the `Claude/GPT 5h` window when fanning out several agy-Claude jobs. (This needs agy's local daemon up — normally true when any agy process is running; if `playmaker quotas` tags agy "daemon offline" it fell back to a coarse Gemini-only view.)
61
65
  - Codex: top-tier vs lighter modes (where applicable).
66
+ - Z.ai (GLM): shown as its own provider because the plan is what has the quota, not the CLI — `Session` (5h) and `Weekly` windows plus a monthly `MCP tools` pool that only web-search/reader calls touch. It appears whenever `opencode auth login` has a Z.AI credential, and reads *unsupported* when it doesn't. An `opencode` dispatch pointed at a **local** model spends none of it, so local lanes never show up in this table at all.
62
67
 
63
68
  If `quotas.json` is more than 1h old (or shows errors), say so before relying on the numbers.
64
69
 
@@ -69,7 +74,7 @@ Codebase exploration ("find where the User entity lives, list its existing field
69
74
  Pattern: dispatch a recon subtask with an explicit deliverable.
70
75
 
71
76
  ```bash
72
- playmaker dispatch agy --model "Gemini 3.5 Flash (Low)" --cwd $(pwd) --sync \
77
+ playmaker dispatch agy --model gemini-3.6-flash-low --cwd $(pwd) --sync \
73
78
  --prompt "Recon only — do not edit any files. In apps/backend/, locate: (a) the User entity/schema and the migration tooling used (Prisma vs TypeORM vs other), (b) the auth middleware that resolves the current user, (c) where DTOs are defined for user PATCH endpoints if any. Report under 200 words as a numbered list with file paths and line ranges."
74
79
  ```
75
80
 
@@ -89,9 +94,9 @@ Break the task into 2-5 subtasks (don't go finer-grained than that on first run
89
94
 
90
95
  1. Sort *models* (not agents) by remaining capacity — freshest at the top. A provider with one fresh model and one depleted model is two separate buckets.
91
96
  2. **Tier-match each subtask to the cheapest model that can finish it cleanly:**
92
- - **Architectural / spec judgment / cross-module integration:** top tier (Opus, agy "Claude Opus 4.6 (Thinking)" / "Gemini 3.1 Pro (High)", Codex top-tier). The coach lives here; agy-Opus is the overflow lane when the Anthropic Opus weekly is precious.
93
- - **Pattern-following implementation, well-scoped CRUD, mechanical refactor, test scaffolding, writing inside an existing convention:** mid tier (Claude Sonnet, agy "Claude Sonnet 4.6 (Thinking)" / "Gemini 3.5 Flash (High)" / "Gemini 3.1 Pro (Low)", mid-tier Codex). This is where the bulk of delegated implementation goes.
94
- - **Recon, summarization, mechanical loops over many files, name normalization:** cheap tier (agy "Gemini 3.5 Flash (Low)"/"(Medium)", **Claude Haiku**, Sonnet for recon-with-judgment).
97
+ - **Architectural / spec judgment / cross-module integration:** top tier (Opus, agy `claude-opus-4-6-thinking` / `gemini-3.1-pro-high`, Codex top-tier). The coach lives here; agy-Opus is the overflow lane when the Anthropic Opus weekly is precious.
98
+ - **Pattern-following implementation, well-scoped CRUD, mechanical refactor, test scaffolding, writing inside an existing convention:** mid tier (Claude Sonnet, agy `claude-sonnet-4-6` / `gemini-3.5-flash-high` / `gemini-3.1-pro-low`, mid-tier Codex). This is where the bulk of delegated implementation goes.
99
+ - **Recon, summarization, mechanical loops over many files, name normalization:** cheap tier (agy's lowest Flash tiers, **Claude Haiku**, Sonnet for recon-with-judgment).
95
100
 
96
101
  For Claude specifically, tier is orthogonal to **lane** (see "Execution lanes"): pick the model tier here, then decide *internal sub-agent* (coach integrates the result) vs *external `-p`* (tracked detached stream).
97
102
  3. Pass the model explicitly: `playmaker dispatch <agent> --model <name> ...`. Without `--model`, the agent CLI uses its default — which is usually fine but means the coach gives up control over tier-matching. **For sibling Claude, default to `--model sonnet`** (Haiku for trivial mechanical work); never omit it and let the CLI pick Opus — that burns the scarce shared Opus weekly bucket.
@@ -112,7 +117,7 @@ To make a subtask finishable, every dispatch must carry:
112
117
  2. **Acceptance criteria as a check the agent runs itself.** A green command — `npx prisma validate`, `pnpm test users.spec.ts`, `tsc --noEmit`, an `eslint` pass on a specific file. The agent is told to keep iterating until that command exits 0 and to surface its output in the final answer. This replaces coach-side review for ~80% of the work.
113
118
  3. **Done definition in one sentence**, written so the coach can confirm it in seconds without reading the diff line by line. "Column added, migration generated, prisma validate green." If the coach can't write such a sentence, the subtask isn't sized right yet — split or specify further before dispatching.
114
119
  4. **Context the agent needs but doesn't have.** Spec section excerpts, naming conventions, the one related file it should mirror. Paste these into the prompt; don't make the agent find them by reading half the repo. If your team keeps durable notes (a docs folder, a wiki, a notes vault), pass the *exact* paths worth reading rather than asking the agent to go looking.
115
- 5. **Match to capability.** Codex / agy-Gemini do well on pattern-following, well-scoped CRUD, test scaffolding, mechanical refactors, and writing within an existing convention. They do poorly on architectural decisions across files they haven't been pointed at, novel API design, and judging whether a spec rule applies. Keep those for the coach — or for agy's "Claude Opus 4.6 (Thinking)" when the subtask genuinely needs top-tier judgment but should not burn the Anthropic Opus weekly. If a profile in `.playmaker/agents/<name>.md` exists, trust its guidance over these defaults.
120
+ 5. **Match to capability.** Codex / agy-Gemini do well on pattern-following, well-scoped CRUD, test scaffolding, mechanical refactors, and writing within an existing convention. They do poorly on architectural decisions across files they haven't been pointed at, novel API design, and judging whether a spec rule applies. Keep those for the coach — or for agy's `claude-opus-4-6-thinking` when the subtask genuinely needs top-tier judgment but should not burn the Anthropic Opus weekly. If a profile in `.playmaker/agents/<name>.md` exists, trust its guidance over these defaults.
116
121
 
117
122
  A useful smell test before dispatching: *"If this came back done, would I review by running one command and reading one paragraph — or would I need to read the whole diff and think hard about whether it's right?"* If the latter, re-scope before sending.
118
123
 
@@ -121,7 +126,7 @@ Output the plan as a short proposal:
121
126
  Plan:
122
127
  - Coach (me): schema design + integration glue
123
128
  - Codex: FastAPI handlers in apps/api/
124
- - agy (Gemini 3.5 Flash High): pytest tests + README
129
+ - agy (gemini-3.6-flash-high): pytest tests + README
125
130
 
126
131
  Quotas: Claude session 93% / weekly 80%, Codex 100%,
127
132
  agy Gemini 5h 100% / weekly 96%, Claude/GPT 5h 88% / weekly 71%.
@@ -151,7 +156,13 @@ playmaker dispatch <agent> --model <name> --prompt "<scoped prompt>" --cwd $(pwd
151
156
 
152
157
  Always pass `--cwd $(pwd)` — `playmaker`'s default is the *coach process's* current dir, which is not always what you want.
153
158
 
154
- Always pass `--model` when you've made a tier-matching decision in step 3. Without it, the agent CLI uses its own default (which may be its top-tier model, defeating the load-distribution effort). Model name is what the agent's native CLI accepts: `claude --model sonnet`, `codex exec -m gpt-5-codex`, `agy --model "Gemini 3.5 Flash (High)"` — agy takes the exact display names from `agy models` and they contain spaces, so **always quote them**. Note: agy's own default is a top-tier model, another reason never to omit `--model` on agy dispatches meant to be cheap.
159
+ Always pass `--model` when you've made a tier-matching decision in step 3. Without it, the agent CLI uses its own default (which may be its top-tier model, defeating the load-distribution effort). Model name is what the agent's native CLI accepts: `claude --model sonnet`, `agy --model gemini-3.6-flash-high` — for agy, copy the line from `agy models` rather than typing it.
160
+
161
+ Two exceptions to "always pass `--model`":
162
+ - **codex** — its model roster depends on the account plan, and an unavailable name fails the whole dispatch (`codex turn failed: … not supported when using Codex with a ChatGPT account`). Omitting `--model` uses whatever that account actually has, which is usually what you want.
163
+ - **agy** — its own default is a top-tier model, so omitting `--model` on a dispatch meant to be cheap silently spends the expensive bucket. Always pass it here.
164
+
165
+ **opencode is `provider/model`, and the default is a trap.** Names look like `zai-coding-plan/glm-5.2` or `lmstudio/qwen/qwen3-coder-30b` — **run `opencode models` and copy a line** rather than writing one from memory; playmaker validates against that roster and fails the dispatch on a name it doesn't contain. Omitting `--model` does *not* fall back to something sensible: it uses whatever is set in the user's own `~/.config/opencode/opencode.json`, which is typically the last model they picked interactively — often a small local one. So for opencode, always pass `--model` unless `[agents.opencode] model` is already set in `~/.playmaker/config.toml`.
155
166
 
156
167
  **agy prompt discipline:** the agy agent's shell lives in a private scratch directory, not the workspace. playmaker automatically prepends a workspace preamble to every agy dispatch, but reinforce it: word file instructions with paths relative to the workspace root or absolute paths, never "in the current directory".
157
168
 
@@ -163,8 +174,8 @@ Always pass `--model` when you've made a tier-matching decision in step 3. Witho
163
174
 
164
175
  ```bash
165
176
  B=admin-dashboard # any short label shared across this fan-out
166
- playmaker dispatch codex --batch "$B" --model gpt-5-codex --prompt "..." --cwd $(pwd)
167
- playmaker dispatch agy --batch "$B" --model "Gemini 3.5 Flash (High)" --prompt "..." --cwd $(pwd)
177
+ playmaker dispatch codex --batch "$B" --prompt "..." --cwd $(pwd)
178
+ playmaker dispatch agy --batch "$B" --model gemini-3.6-flash-high --prompt "..." --cwd $(pwd)
168
179
  ```
169
180
 
170
181
  `playmaker continue <id> --model <name>` overrides the model for one follow-up turn while keeping the live session; without `--model` it inherits the parent session's model.
@@ -173,7 +184,7 @@ For sequential delegation (e.g. "I'll do schema first, then Codex builds on top"
173
184
 
174
185
  ```bash
175
186
  git commit -am "checkpoint: schema before backend dispatch"
176
- playmaker dispatch codex --model gpt-5-codex --prompt "..." --cwd $(pwd) --sync # blocks, prints output
187
+ playmaker dispatch codex --prompt "..." --cwd $(pwd) --sync # blocks, prints output
177
188
  ```
178
189
 
179
190
  ### 6. Coach's own work
@@ -224,7 +235,7 @@ If `playmaker dispatch` returns an error (binary missing, auth bad, agent unavai
224
235
  Both Claude lanes are on the subscription, so pick by **where the work lives**, not cost:
225
236
  - **Coach folds the result in directly → internal sub-agent (Task tool).** In-session, write-capable, returns into context. Default choice for "more Claude."
226
237
  - **Independent stream you'll monitor / continue separately → `playmaker dispatch claude --model sonnet`.** Tracked, detached; Sonnet's separate weekly bucket spares Opus.
227
- - **Work that can leave the Claude family → Codex / agy** (their own quotas).
238
+ - **Work that can leave the Claude family → Codex / agy / opencode** (their own quotas, or none at all for a local model).
228
239
 
229
240
  If a dispatch comes back with zero file changes, check `playmaker summary <id>`. Two common causes for Claude: the subtask tried to write outside `--cwd` and was refused (re-dispatch with the right `--cwd`), or the run needed a permission the configured mode doesn't grant — a "I need your permission" answer, not a crash. For **agy** specifically, a "done" with no file changes usually means the files landed in agy's private scratch dir (`~/.gemini/antigravity-cli/scratch/`) — the prompt referred to "the current directory" instead of workspace paths; re-dispatch with explicit paths.
230
241
 
@@ -238,7 +249,7 @@ If a dispatch comes back with zero file changes, check `playmaker summary <id>`.
238
249
  ## Quota awareness
239
250
 
240
251
  - **Read Claude quota at model granularity:** Sonnet weekly and Opus weekly are **independent buckets**. Coach and internal sub-agents on Opus spend the scarce one; Sonnet usually sits idle. Push mid-tier work to Sonnet (an internal sub-agent set to Sonnet, or `dispatch claude --model sonnet`) to spare Opus.
241
- - Read quotas at *model* granularity, not *agent* granularity. For agy, the probe reports four windows — `Gemini 5h/weekly` and `Claude/GPT 5h/weekly`; for Codex, top-tier vs lighter modes.
252
+ - Read quotas at *model* granularity, not *agent* granularity. For agy, the probe reports four windows — `Gemini 5h/weekly` and `Claude/GPT 5h/weekly`; for Codex, top-tier vs lighter modes; for opencode, the quota is reported under the **provider** it is pointed at (`Z.ai`), and a local model reports nothing because it spends nothing.
242
253
  - Skip a *model* if its `*_left` is below ~10%; reroute the subtask to the same agent with a different model, or to a different agent entirely.
243
254
  - If a top-tier `weekly_*_left` is degrading toward the deadline, push as much work as possible to mid- and cheap-tier models on the same provider (which are often nowhere near depleted), instead of switching providers blindly.
244
255
  - agy's **5-hour** window is the one that bites during a fan-out: it "smooths aggregate demand", so a burst of agy dispatches drains `Gemini 5h` or `Claude/GPT 5h` well before the weekly. If a 5h window is low, spread the burst or move some slices to Codex/coach.
@@ -263,9 +274,9 @@ playmaker watch # Rich live TUI of sessions
263
274
 
264
275
  Every command takes `--json` for machine-readable output.
265
276
 
266
- `--model NAME` is forwarded to the agent's native CLI: `claude --model sonnet`, `codex exec -m gpt-5-codex`, `agy --model "Claude Opus 4.6 (Thinking)"` (display names from `agy models`, always quoted). Without it the agent CLI uses its own default. Model is stored on the session row, so detached re-runs and `continue` inherit it; `continue --model X` overrides for that one turn.
277
+ `--model NAME` is forwarded to the agent's native CLI: `claude --model sonnet`, `agy --model claude-opus-4-6-thinking`, `codex -m <whatever that account has>`, `opencode -m zai-coding-plan/glm-5.2`. Without it the agent CLI uses its own default. Model is stored on the session row, so detached re-runs and `continue` inherit it; `continue --model X` overrides for that one turn.
267
278
 
268
- agy model roster (from `agy models`): `Gemini 3.5 Flash (Low)` / `(Medium)` / `(High)`, `Gemini 3.1 Pro (Low)` / `(High)`, `Claude Sonnet 4.6 (Thinking)`, `Claude Opus 4.6 (Thinking)`, `GPT-OSS 120B (Medium)`. Re-check the roster with `agy models` when in doubt it changes with Antigravity releases.
279
+ **The agy roster is not documented here on purpose** — it changes with Antigravity releases, and so does the spelling convention. Run `agy models` and copy a line. At the time of writing it returns bare slugs in the shape `gemini-3.6-flash-{low,medium,high}`, `gemini-3.1-pro-{low,high}`, `claude-sonnet-4-6`, `claude-opus-4-6-thinking`, `gpt-oss-120b-medium` but treat that as an example of the *shape*, not a list to copy from.
269
280
 
270
281
  ## Anti-patterns
271
282
 
@@ -1,12 +1,15 @@
1
1
  """Antigravity CLI (`agy`) handler.
2
2
 
3
3
  Empirically (agy 1.1.1):
4
- - oneshot: `agy -p "<prompt>" [--model "<display name>"] [--dangerously-skip-permissions]
4
+ - oneshot: `agy -p "<prompt>" [--model <name>] [--dangerously-skip-permissions]
5
5
  [--print-timeout 60m] [--log-file <path>]`; stdout is the final response as
6
6
  plain text (no JSON envelope).
7
7
  - resume: `agy --conversation <uuid> -p "..."` — keeps the same conversation id.
8
- - models are addressed by *display name* from `agy models`, e.g.
9
- "Claude Opus 4.6 (Thinking)", "Gemini 3.5 Flash (Low)".
8
+ - `--model` takes a name from `agy models` verbatim, e.g.
9
+ "claude-opus-4-6-thinking", "gemini-3.6-flash-high". Both the roster and its
10
+ *spelling* move with Antigravity releases — earlier builds took display names
11
+ like "Claude Opus 4.6 (Thinking)" — which is why _validate_model() reads the
12
+ live list instead of trusting a hardcoded one.
10
13
  - the conversation id is NOT printed to stdout; it is recovered from the CLI
11
14
  debug log (`--log-file`) via the `Created conversation <uuid>` line, which
12
15
  appears a few seconds in — that is our early on_session_started signal.
@@ -53,7 +56,7 @@ class AgyHandler:
53
56
  @staticmethod
54
57
  @functools.lru_cache(maxsize=1)
55
58
  def available_models() -> tuple[str, ...]:
56
- """Exact model display names agy accepts, from `agy models`.
59
+ """Exact model names agy accepts, from `agy models`.
57
60
 
58
61
  agy resolves an unknown `--model` to its default *silently* (no error,
59
62
  wrong model runs), so we validate against this list before dispatch.