playmaker-cli 0.5.1__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.
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/CHANGELOG.md +42 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/PKG-INFO +55 -12
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/README.md +52 -9
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/pyproject.toml +4 -2
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/skills/playmaker-coach/SKILL.md +12 -7
- playmaker_cli-0.6.0/src/playmaker/agents/opencode.py +461 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/cli.py +36 -6
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/quotas.py +160 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/registry.py +2 -0
- playmaker_cli-0.6.0/tests/test_opencode.py +430 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/tests/test_permissions.py +18 -0
- playmaker_cli-0.6.0/tests/test_quotas_zai.py +165 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/tests/test_registry.py +2 -2
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/.gitignore +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/LICENSE +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/__init__.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/__main__.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/agents/__init__.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/agents/agy.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/agents/base.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/agents/claude.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/agents/codex.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/agents/gemini.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/config.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/notify.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/state.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/src/playmaker/watcher.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/tests/__init__.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/tests/test_agy.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/tests/test_claude.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/tests/test_codex.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/tests/test_quotas_antigravity.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/tests/test_skill.py +0 -0
- {playmaker_cli-0.5.1 → playmaker_cli-0.6.0}/tests/test_state.py +0 -0
|
@@ -5,6 +5,48 @@ 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
|
+
|
|
8
50
|
## [0.5.1] - 2026-07-27
|
|
9
51
|
|
|
10
52
|
### Fixed
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: playmaker-cli
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Playing-coach CLI for orchestrating Claude Code, Codex and
|
|
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
|
[](https://github.com/vladsafedev/playmaker/actions/workflows/ci.yml)
|
|
31
|
-
[](https://pypi.org/project/playmaker-cli/)
|
|
32
|
-
[](https://pypi.org/project/playmaker-cli/)
|
|
31
|
+
[](https://pypi.org/project/playmaker-cli/)
|
|
32
|
+
[](https://pypi.org/project/playmaker-cli/)
|
|
33
33
|
[](LICENSE)
|
|
34
34
|
|
|
35
|
-
**Run Claude Code, Codex and
|
|
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,
|
|
@@ -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
|
|
78
|
-
pools from your Anthropic plan. Every slice you hand them is
|
|
79
|
-
main session never spends — and Antigravity's roster includes
|
|
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
|
|
@@ -170,6 +182,7 @@ playmaker agents # which agent CLIs are reachable
|
|
|
170
182
|
| **Claude Code** | `npm i -g @anthropic-ai/claude-code` | `--model sonnet` / `opus` / `haiku` |
|
|
171
183
|
| **Codex CLI** | `npm i -g @openai/codex` | the model roster depends on your plan; omit `--model` to use the account default |
|
|
172
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
|
|
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
|
[](https://github.com/vladsafedev/playmaker/actions/workflows/ci.yml)
|
|
4
|
-
[](https://pypi.org/project/playmaker-cli/)
|
|
5
|
-
[](https://pypi.org/project/playmaker-cli/)
|
|
4
|
+
[](https://pypi.org/project/playmaker-cli/)
|
|
5
|
+
[](https://pypi.org/project/playmaker-cli/)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
**Run Claude Code, Codex and
|
|
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,
|
|
@@ -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
|
|
51
|
-
pools from your Anthropic plan. Every slice you hand them is
|
|
52
|
-
main session never spends — and Antigravity's roster includes
|
|
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
|
|
@@ -143,6 +155,7 @@ playmaker agents # which agent CLIs are reachable
|
|
|
143
155
|
| **Claude Code** | `npm i -g @anthropic-ai/claude-code` | `--model sonnet` / `opus` / `haiku` |
|
|
144
156
|
| **Codex CLI** | `npm i -g @openai/codex` | the model roster depends on your plan; omit `--model` to use the account default |
|
|
145
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
|
|
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.
|
|
4
|
-
description = "Playing-coach CLI for orchestrating Claude Code, Codex and
|
|
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,11 +1,11 @@
|
|
|
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
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
11
|
>
|
|
@@ -23,7 +23,7 @@ All Claude work — coach, internal sub-agents, external `claude -p` — draws f
|
|
|
23
23
|
|
|
24
24
|
3. **External dispatch — `playmaker dispatch <agent>`.** Separate OS processes, tracked in playmaker (`list`/`watch`/`thread`/`continue`):
|
|
25
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.
|
|
26
|
-
- **`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.
|
|
27
27
|
|
|
28
28
|
**Routing cheat-sheet for Claude-side work:**
|
|
29
29
|
|
|
@@ -32,8 +32,10 @@ All Claude work — coach, internal sub-agents, external `claude -p` — draws f
|
|
|
32
32
|
| writes files and the coach integrates the result directly | **internal sub-agent** (Task tool) | in-session, write-capable, returns into context |
|
|
33
33
|
| is an independent stream you'll monitor / continue separately | **external `dispatch claude --model sonnet`** | tracked & detached; Sonnet's own weekly bucket spares Opus |
|
|
34
34
|
| is heavy reasoning only the coach can do | **coach** | top-tier Opus, serial |
|
|
35
|
-
| is write-heavy and can leave Claude | **codex / agy** | their own quotas |
|
|
35
|
+
| is write-heavy and can leave Claude | **codex / agy / opencode** | their own quotas |
|
|
36
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 |
|
|
37
39
|
|
|
38
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.
|
|
39
41
|
|
|
@@ -61,6 +63,7 @@ playmaker quotas --refresh # current capacity, broken out per model
|
|
|
61
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.
|
|
62
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.)
|
|
63
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.
|
|
64
67
|
|
|
65
68
|
If `quotas.json` is more than 1h old (or shows errors), say so before relying on the numbers.
|
|
66
69
|
|
|
@@ -159,6 +162,8 @@ Two exceptions to "always pass `--model`":
|
|
|
159
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.
|
|
160
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.
|
|
161
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`.
|
|
166
|
+
|
|
162
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".
|
|
163
168
|
|
|
164
169
|
**Bad-model handling (playmaker ≥0.4 does this for you):** a wrong `--model` is the classic silent failure. Codex returns a `turn.failed` while exiting 0 with empty output; agy silently runs its *default* model instead of erroring. playmaker catches both — a codex model/auth failure raises `codex turn failed: …`, and an unknown agy model raises with the valid roster before dispatch. So a dispatch that comes back **failed** with a model message means: fix the `--model` string (for agy, copy it exactly from `agy models`) and re-dispatch. Don't retry the same string.
|
|
@@ -230,7 +235,7 @@ If `playmaker dispatch` returns an error (binary missing, auth bad, agent unavai
|
|
|
230
235
|
Both Claude lanes are on the subscription, so pick by **where the work lives**, not cost:
|
|
231
236
|
- **Coach folds the result in directly → internal sub-agent (Task tool).** In-session, write-capable, returns into context. Default choice for "more Claude."
|
|
232
237
|
- **Independent stream you'll monitor / continue separately → `playmaker dispatch claude --model sonnet`.** Tracked, detached; Sonnet's separate weekly bucket spares Opus.
|
|
233
|
-
- **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).
|
|
234
239
|
|
|
235
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.
|
|
236
241
|
|
|
@@ -244,7 +249,7 @@ If a dispatch comes back with zero file changes, check `playmaker summary <id>`.
|
|
|
244
249
|
## Quota awareness
|
|
245
250
|
|
|
246
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.
|
|
247
|
-
- 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.
|
|
248
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.
|
|
249
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.
|
|
250
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.
|
|
@@ -269,7 +274,7 @@ playmaker watch # Rich live TUI of sessions
|
|
|
269
274
|
|
|
270
275
|
Every command takes `--json` for machine-readable output.
|
|
271
276
|
|
|
272
|
-
`--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
|
|
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.
|
|
273
278
|
|
|
274
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.
|
|
275
280
|
|