playmaker-cli 0.4.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.4.0/.gitignore +12 -0
- playmaker_cli-0.4.0/CHANGELOG.md +93 -0
- playmaker_cli-0.4.0/LICENSE +21 -0
- playmaker_cli-0.4.0/PKG-INFO +335 -0
- playmaker_cli-0.4.0/README.md +308 -0
- playmaker_cli-0.4.0/pyproject.toml +90 -0
- playmaker_cli-0.4.0/skills/playmaker-coach/SKILL.md +282 -0
- playmaker_cli-0.4.0/src/playmaker/__init__.py +10 -0
- playmaker_cli-0.4.0/src/playmaker/__main__.py +4 -0
- playmaker_cli-0.4.0/src/playmaker/agents/__init__.py +0 -0
- playmaker_cli-0.4.0/src/playmaker/agents/agy.py +342 -0
- playmaker_cli-0.4.0/src/playmaker/agents/base.py +96 -0
- playmaker_cli-0.4.0/src/playmaker/agents/claude.py +307 -0
- playmaker_cli-0.4.0/src/playmaker/agents/codex.py +387 -0
- playmaker_cli-0.4.0/src/playmaker/agents/gemini.py +352 -0
- playmaker_cli-0.4.0/src/playmaker/cli.py +978 -0
- playmaker_cli-0.4.0/src/playmaker/config.py +30 -0
- playmaker_cli-0.4.0/src/playmaker/notify.py +82 -0
- playmaker_cli-0.4.0/src/playmaker/quotas.py +940 -0
- playmaker_cli-0.4.0/src/playmaker/registry.py +41 -0
- playmaker_cli-0.4.0/src/playmaker/state.py +173 -0
- playmaker_cli-0.4.0/src/playmaker/watcher.py +145 -0
- playmaker_cli-0.4.0/tests/__init__.py +1 -0
- playmaker_cli-0.4.0/tests/test_agy.py +125 -0
- playmaker_cli-0.4.0/tests/test_codex.py +144 -0
- playmaker_cli-0.4.0/tests/test_quotas_antigravity.py +100 -0
- playmaker_cli-0.4.0/tests/test_registry.py +28 -0
- playmaker_cli-0.4.0/tests/test_skill.py +48 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.4.0] - 2026-07-27
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `playmaker skill install` — the `playmaker-coach` Claude Code skill now ships
|
|
13
|
+
with the package (`skills/playmaker-coach/SKILL.md`) and installs itself into
|
|
14
|
+
`~/.claude/skills/`. It was previously documented as a separate repository
|
|
15
|
+
that was never published.
|
|
16
|
+
- `playmaker --version`. `__version__` is read from installed package metadata
|
|
17
|
+
rather than a hand-maintained literal, which had drifted to 0.1.0.
|
|
18
|
+
- `[notifications] editor` in `config.toml` — the app a clicked notification
|
|
19
|
+
opens the output in was hardcoded to Zed.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- `claude`: a failing `claude -p` run reports the error in its final
|
|
24
|
+
stream-json event with an empty stderr, so failures surfaced as a blank
|
|
25
|
+
`claude failed (exit 1):`. The error text is now captured and raised.
|
|
26
|
+
- `codex`: a non-zero exit no longer discards an answer the CLI had already
|
|
27
|
+
written. The last-message file is consumed before the exit-code check, so
|
|
28
|
+
testing the file at that point always failed — codex's harmless
|
|
29
|
+
"failed to record rollout items" shutdown warning would have lost the result.
|
|
30
|
+
- `codex`: invalid-model / auth / upstream failures are now surfaced. Codex
|
|
31
|
+
reports these via a `turn.failed`/`error` stream event while still exiting 0
|
|
32
|
+
and writing an empty last-message file, so a bad `--model` used to look "done"
|
|
33
|
+
with no output. The handler now inspects those events (unwrapping the nested
|
|
34
|
+
JSON error) and raises, so the coach reroutes instead of silently getting
|
|
35
|
+
nothing back.
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- `agy`: `--model` is validated against `agy models` before dispatch. agy
|
|
40
|
+
resolves an unknown model name to its default *silently* (wrong model runs, no
|
|
41
|
+
error); a typo'd or stale name now raises with the available roster. Skipped
|
|
42
|
+
when the roster can't be read, so a probe hiccup never blocks a dispatch.
|
|
43
|
+
- Antigravity quota probe now prefers agy's **local daemon** (`RetrieveUser
|
|
44
|
+
QuotaSummary` over the embedded self-signed-TLS gRPC-web endpoint), giving the
|
|
45
|
+
full categorized breakdown — Gemini and Claude/GPT, each split 5-hour vs
|
|
46
|
+
weekly — matching Antigravity's own UI and CodexBar. Works whenever any agy or
|
|
47
|
+
CodexBar daemon is running. Falls back to the coarse OAuth `retrieveUserQuota`
|
|
48
|
+
(Gemini daily buckets only) with a "daemon offline" note when none is up.
|
|
49
|
+
Ported from steipete/CodexBar's `AntigravityStatusProbe`.
|
|
50
|
+
- Quota render: adaptive name column so longer categorized labels keep bar
|
|
51
|
+
alignment.
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- Packaging: PEP 639 license metadata, accurate description/keywords, sdist now
|
|
56
|
+
ships tests and the skill.
|
|
57
|
+
- Lint: ruff `select = E,F,I,UP,B` (minus B008, which flags Typer's own API) and
|
|
58
|
+
linting covers `tests/` too.
|
|
59
|
+
- Removed `packaging/homebrew/playmaker.rb` — it targeted a tap that was never
|
|
60
|
+
published, under an org name no longer in use.
|
|
61
|
+
|
|
62
|
+
## [0.3.0] - 2026-07-12
|
|
63
|
+
|
|
64
|
+
### Added
|
|
65
|
+
|
|
66
|
+
- `agy` agent handler — Antigravity CLI (Google AI Pro): Gemini 3.5 Flash / 3.1 Pro,
|
|
67
|
+
Claude Sonnet/Opus 4.6 (Thinking), GPT-OSS 120B, addressed by display name from
|
|
68
|
+
`agy models`. Oneshot via `agy -p`, resume via `--conversation <id>`; the
|
|
69
|
+
conversation id is recovered early from the CLI debug log (`--log-file`), and
|
|
70
|
+
threads are parsed from the plain-JSONL brain transcript
|
|
71
|
+
(`~/.gemini/antigravity-cli/brain/<id>/.system_generated/logs/transcript_full.jsonl`).
|
|
72
|
+
Dispatch prepends a workspace preamble because the agy agent's shell cwd is a
|
|
73
|
+
private scratch dir — without it, relative file writes never reach the workspace.
|
|
74
|
+
- `antigravity_probe` quota probe (daily-cloudcode-pa, ideType ANTIGRAVITY) —
|
|
75
|
+
replaces the gemini probe in the default set; surfaces Gemini buckets only
|
|
76
|
+
(Antigravity's Claude/GPT windows are not exposed to plain OAuth tokens).
|
|
77
|
+
|
|
78
|
+
### Changed
|
|
79
|
+
|
|
80
|
+
- Default probe set is now codex / claude / agy; gemini-cli's handler and probe
|
|
81
|
+
remain in the codebase but the CLI is retired locally.
|
|
82
|
+
|
|
83
|
+
## [0.2.0] - 2026-06-10
|
|
84
|
+
|
|
85
|
+
### Removed
|
|
86
|
+
|
|
87
|
+
- ACP/Zed integration layer — project is now a dispatch-only core with no Zed or ACP dependencies.
|
|
88
|
+
|
|
89
|
+
### Changed
|
|
90
|
+
|
|
91
|
+
- `claude`: headless dispatch and resume now pass `--dangerously-skip-permissions` so unattended runs are not blocked by permission prompts.
|
|
92
|
+
- `quotas`: CLI renders the Extra usage pool (metered overage) alongside standard quota display.
|
|
93
|
+
- `gemini`: falls back to session-file parse when the stream or JSON response body is empty, preventing silent failures on partial responses.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vladislav Shulyugin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: playmaker-cli
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Playing-coach CLI for orchestrating Claude Code, Codex and Antigravity sub-agents in parallel.
|
|
5
|
+
Project-URL: Homepage, https://github.com/vladsafedev/playmaker
|
|
6
|
+
Project-URL: Repository, https://github.com/vladsafedev/playmaker
|
|
7
|
+
Project-URL: Issues, https://github.com/vladsafedev/playmaker/issues
|
|
8
|
+
Author-email: Vladislav Shulyugin <vladislav.shulyugin@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agents,ai,antigravity,claude,claude-code,cli,codex,gemini,orchestration,subagents
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: MacOS
|
|
16
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development
|
|
22
|
+
Classifier: Topic :: Utilities
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Requires-Dist: rich>=13.7
|
|
25
|
+
Requires-Dist: typer>=0.12
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# playmaker
|
|
29
|
+
|
|
30
|
+
[](https://github.com/vladsafedev/playmaker/actions/workflows/ci.yml)
|
|
31
|
+
[](https://pypi.org/project/playmaker-cli/)
|
|
32
|
+
[](https://pypi.org/project/playmaker-cli/)
|
|
33
|
+
[](LICENSE)
|
|
34
|
+
|
|
35
|
+
**Run Claude Code, Codex and Antigravity as parallel sub-agents from one terminal — and spend three separate quotas instead of one.**
|
|
36
|
+
|
|
37
|
+
You stay in your Claude Code session doing the part only you can do. `playmaker`
|
|
38
|
+
fans the rest out to other agent CLIs as detached processes, tracks them,
|
|
39
|
+
parses their native session files, and pings you when they land.
|
|
40
|
+
|
|
41
|
+
```console
|
|
42
|
+
$ B=dashboard # one label for the whole fan-out
|
|
43
|
+
|
|
44
|
+
$ playmaker dispatch codex --batch $B --model gpt-5-codex -p "Add PATCH /users/:id …"
|
|
45
|
+
session: 9f2c1a4e-… pid: 48211 (detached)
|
|
46
|
+
$ playmaker dispatch agy --batch $B --model "Gemini 3.5 Flash (High)" -p "pytest coverage for …"
|
|
47
|
+
session: 4b1f9c02-… pid: 48219 (detached)
|
|
48
|
+
$ playmaker dispatch claude --batch $B --model sonnet -p "Update the API docs for …"
|
|
49
|
+
session: c07d5511-… pid: 48244 (detached)
|
|
50
|
+
|
|
51
|
+
# …you keep working in your own session while those three run
|
|
52
|
+
|
|
53
|
+
$ playmaker list
|
|
54
|
+
┏━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
55
|
+
┃ id ┃ agent ┃ status ┃ started ┃ prompt ┃
|
|
56
|
+
┡━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
|
|
57
|
+
│ 9f2c1a4e │ codex │ running │ 2026-07-27T18:02:09 │ Add PATCH /users/:id … │
|
|
58
|
+
│ 4b1f9c02 │ agy │ done │ 2026-07-27T18:02:11 │ pytest coverage for … │
|
|
59
|
+
│ c07d5511 │ claude │ done │ 2026-07-27T18:02:14 │ Update the API docs … │
|
|
60
|
+
└──────────┴────────┴─────────┴─────────────────────┴────────────────────────┘
|
|
61
|
+
|
|
62
|
+
🔔 playmaker — batch done # one ping for the whole fan-out…
|
|
63
|
+
3/3 done · codex ✓ · agy ✓ · claude ✓ # …click it to open every output
|
|
64
|
+
|
|
65
|
+
$ playmaker summary 9f2c1a4e # what codex says it did
|
|
66
|
+
$ playmaker continue 9f2c1a4e -p "the 404 branch is missing a test"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Why
|
|
70
|
+
|
|
71
|
+
Three reasons to fan work out across agent CLIs instead of grinding through it
|
|
72
|
+
in one serial session:
|
|
73
|
+
|
|
74
|
+
1. **Wall-clock speed.** A task that decomposes into 3–5 independent
|
|
75
|
+
work-streams (schema, backend, frontend, tests, docs) finishes 2–4× faster
|
|
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.
|
|
81
|
+
3. **Bucket arbitrage inside one plan.** Headless `claude -p` draws on the same
|
|
82
|
+
subscription as your interactive session, but per-model weekly buckets are
|
|
83
|
+
separate — dispatching `--model sonnet` spends Sonnet's usually-idle bucket
|
|
84
|
+
instead of the scarce Opus one.
|
|
85
|
+
|
|
86
|
+
The catch: doing this by hand — terminal tabs, jumping between tools,
|
|
87
|
+
copy-pasting context — is friction. `playmaker` removes the friction; the
|
|
88
|
+
[coach skill](#the-coach-skill) provides the discipline.
|
|
89
|
+
|
|
90
|
+
## ⚠️ Sub-agents skip permission prompts by default
|
|
91
|
+
|
|
92
|
+
By default, playmaker launches Claude and Antigravity sub-agents with
|
|
93
|
+
`--dangerously-skip-permissions` (and Gemini with `--yolo`). This is
|
|
94
|
+
deliberate: a headless agent has no human at the keyboard, so without these
|
|
95
|
+
flags a detached run stalls at the first tool-approval prompt and finishes
|
|
96
|
+
having written nothing.
|
|
97
|
+
|
|
98
|
+
It also means a dispatched agent can run commands and edit files **without
|
|
99
|
+
asking**. Only dispatch prompts you'd be comfortable running unattended, in
|
|
100
|
+
working directories you trust.
|
|
101
|
+
|
|
102
|
+
To opt out for Claude, set this in `~/.playmaker/config.toml`:
|
|
103
|
+
|
|
104
|
+
```toml
|
|
105
|
+
[agents.claude]
|
|
106
|
+
skip_permissions = false
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
— with the caveat above: detached runs will then stall on the first permission
|
|
110
|
+
prompt, so this only really makes sense alongside `--sync` workflows or
|
|
111
|
+
allowlist rules you've configured in Claude Code itself.
|
|
112
|
+
|
|
113
|
+
## Install
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
uv tool install playmaker-cli # or: pipx install playmaker-cli
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
<details>
|
|
120
|
+
<summary>From source</summary>
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
git clone https://github.com/vladsafedev/playmaker
|
|
124
|
+
cd playmaker
|
|
125
|
+
uv tool install --editable .
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
</details>
|
|
129
|
+
|
|
130
|
+
Then set up the data directory and install the coach skill:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
playmaker init # creates ~/.playmaker/ (state.db, logs/, outputs/, config.toml)
|
|
134
|
+
playmaker skill install # drops playmaker-coach into ~/.claude/skills/
|
|
135
|
+
playmaker agents # which agent CLIs are reachable
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Prerequisites
|
|
139
|
+
|
|
140
|
+
`playmaker` orchestrates external CLIs — install whichever you have access to:
|
|
141
|
+
|
|
142
|
+
| Agent | Install | Notes |
|
|
143
|
+
|---|---|---|
|
|
144
|
+
| **Claude Code** | `npm i -g @anthropic-ai/claude-code` | `--model sonnet` / `opus` / `haiku` |
|
|
145
|
+
| **Codex CLI** | `npm i -g @openai/codex` | `--model gpt-5-codex` |
|
|
146
|
+
| **Antigravity (`agy`)** | bundled with [Antigravity](https://antigravity.google) | models are display names: `--model "Claude Opus 4.6 (Thinking)"` — see `agy models` |
|
|
147
|
+
| **Gemini CLI** (legacy) | `npm i -g @google/gemini-cli` | still supported, superseded by `agy` |
|
|
148
|
+
|
|
149
|
+
At least one is required; `playmaker agents` tells you which it can see.
|
|
150
|
+
|
|
151
|
+
## The coach skill
|
|
152
|
+
|
|
153
|
+
`playmaker` is the runner. The decision-making — *when* delegation beats doing
|
|
154
|
+
it yourself, *which* agent gets *which* slice, how to size a subtask so
|
|
155
|
+
reviewing it is cheap — lives in
|
|
156
|
+
[**playmaker-coach**](skills/playmaker-coach/SKILL.md), a Claude Code skill
|
|
157
|
+
that ships with the package:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
playmaker skill install # ~/.claude/skills/playmaker-coach/SKILL.md
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Then give any Claude Code session a multi-component task and it activates:
|
|
164
|
+
proposes a split with per-model quota rationale, waits for your approval, fans
|
|
165
|
+
out, and reviews what comes back.
|
|
166
|
+
|
|
167
|
+
## Commands
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
playmaker agents # who's installed
|
|
171
|
+
playmaker quotas [--refresh] # capacity per provider, per model
|
|
172
|
+
|
|
173
|
+
playmaker dispatch <agent> --prompt "..." # detached by default
|
|
174
|
+
[--model NAME] # forwarded to the agent's own CLI
|
|
175
|
+
[--cwd DIR]
|
|
176
|
+
[--files PATH...]
|
|
177
|
+
[--sync] # block and print the final answer
|
|
178
|
+
[--parent ID] # link lineage to an earlier session
|
|
179
|
+
[--batch LABEL] # group a fan-out; one summary ping
|
|
180
|
+
playmaker continue <id> --prompt "..." # follow-up inside the live session
|
|
181
|
+
[--model NAME] [--files PATH...] [--sync]
|
|
182
|
+
|
|
183
|
+
playmaker list [--status running|done|failed] [--agent NAME] [--limit N]
|
|
184
|
+
playmaker get <id> [--wait] [--poll SECONDS]
|
|
185
|
+
playmaker summary <id> # last 2 assistant messages
|
|
186
|
+
playmaker thread <id> [--last N] [--all] [--role assistant|user|tool]
|
|
187
|
+
[--include-tools] [--max-bytes N] [--follow]
|
|
188
|
+
playmaker logs <id> [--follow] # subprocess stdout for detached runs
|
|
189
|
+
playmaker kill <id>
|
|
190
|
+
playmaker watch # live TUI of sessions
|
|
191
|
+
playmaker skill install [--dir PATH] [--force]
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
`dispatch`, `continue`, `list`, `get`, `thread` and `quotas` all take `--json`
|
|
195
|
+
for scripting.
|
|
196
|
+
|
|
197
|
+
**`continue` vs a fresh `dispatch`.** `continue` sends a follow-up into the
|
|
198
|
+
agent's existing session, so its reasoning, tool history and file context are
|
|
199
|
+
still live — that's the cheap path for "almost right, fix Y". Start fresh with
|
|
200
|
+
`--parent <id>` only when the old context has become a liability.
|
|
201
|
+
|
|
202
|
+
## How it works
|
|
203
|
+
|
|
204
|
+
```mermaid
|
|
205
|
+
flowchart LR
|
|
206
|
+
C["🧑🏫 coach<br/>your Claude Code session"] -->|dispatch| P(("playmaker"))
|
|
207
|
+
P --> A1["claude -p<br/><i>--model sonnet</i>"]
|
|
208
|
+
P --> A2["codex exec"]
|
|
209
|
+
P --> A3["agy -p"]
|
|
210
|
+
A1 & A2 & A3 --> S[("state.db<br/>outputs/ · logs/")]
|
|
211
|
+
S -->|list · thread · summary| C
|
|
212
|
+
S -.->|batch drained| N["🔔 one ping"]
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Each dispatch is a detached OS process with its own quota; playmaker owns the
|
|
216
|
+
bookkeeping in between.
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
~/.playmaker/
|
|
220
|
+
├── state.db SQLite — sessions, status, pids, models, output paths
|
|
221
|
+
├── config.toml
|
|
222
|
+
├── agents/ optional agent profile markdown (claude.md, codex.md, agy.md…)
|
|
223
|
+
├── outputs/ final output per session — .md, or .json if the agent returned JSON
|
|
224
|
+
├── logs/ subprocess stdout for detached runs
|
|
225
|
+
└── quotas.json latest capacity snapshot
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
`dispatch` runs the agent's CLI non-interactively, parses its native output,
|
|
229
|
+
and locates the session file the tool writes locally. Empirically:
|
|
230
|
+
|
|
231
|
+
| Agent | Session transcript |
|
|
232
|
+
|---|---|
|
|
233
|
+
| Claude | `~/.claude/projects/<cwd-with-slashes-as-dashes>/<id>.jsonl` |
|
|
234
|
+
| Codex | `~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-<ts>-<thread_id>.jsonl` |
|
|
235
|
+
| Antigravity | `~/.gemini/antigravity-cli/brain/<conversation-id>/.system_generated/logs/transcript_full.jsonl` |
|
|
236
|
+
| Gemini | `~/.gemini/tmp/<cwd-basename>/chats/session-<ts>-<short_id>.{json,jsonl}` |
|
|
237
|
+
|
|
238
|
+
`thread` and `summary` normalize all of them into the same turn list, so every
|
|
239
|
+
agent reads back in one shape.
|
|
240
|
+
|
|
241
|
+
Profiles are optional and discovered, not shipped: drop
|
|
242
|
+
`~/.playmaker/agents/<name>.md` (or `./.playmaker/agents/<name>.md` next to a
|
|
243
|
+
repo, which wins) and it is prepended to every dispatch for that agent.
|
|
244
|
+
|
|
245
|
+
Two quirks worth knowing: **agy**'s shell cwd is a private scratch dir rather
|
|
246
|
+
than your workspace, so playmaker prepends a workspace preamble to every agy
|
|
247
|
+
dispatch; and a wrong `--model` is a silent failure on both **codex** (reports
|
|
248
|
+
`turn.failed` while exiting 0) and **agy** (runs its default model instead) —
|
|
249
|
+
playmaker turns both into real errors.
|
|
250
|
+
|
|
251
|
+
## Notifications
|
|
252
|
+
|
|
253
|
+
Every detached dispatch pings when it finishes. With
|
|
254
|
+
[`terminal-notifier`](https://github.com/julienXX/terminal-notifier) installed
|
|
255
|
+
(`brew install terminal-notifier`), the notification is **clickable** and opens
|
|
256
|
+
the agent's output file in your editor:
|
|
257
|
+
|
|
258
|
+
```toml
|
|
259
|
+
[notifications]
|
|
260
|
+
editor = "Zed" # any app name `open -a` accepts
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Without terminal-notifier, playmaker falls back to plain `osascript` banners,
|
|
264
|
+
which can't be clicked.
|
|
265
|
+
|
|
266
|
+
**Batches.** Pass the same `--batch <label>` to every dispatch in a fan-out and
|
|
267
|
+
per-dispatch success pings are suppressed — one "N/N done" summary fires when
|
|
268
|
+
the whole batch drains. Failures are the actionable event, so they still ping
|
|
269
|
+
immediately, with a distinct sound (Basso vs. the usual Blow).
|
|
270
|
+
|
|
271
|
+
Each session's final output lands in `~/.playmaker/outputs/<id>.md` (or `.json`
|
|
272
|
+
when the agent returned genuine JSON), so the notification click — and
|
|
273
|
+
`playmaker get` — always have a stable file to open.
|
|
274
|
+
|
|
275
|
+
## Quotas
|
|
276
|
+
|
|
277
|
+
`playmaker quotas` is token-based: it reads the credentials each CLI already
|
|
278
|
+
stores, no scraping and no browser.
|
|
279
|
+
|
|
280
|
+
```console
|
|
281
|
+
$ playmaker quotas --refresh
|
|
282
|
+
Claude Max 20x
|
|
283
|
+
Session ████████████████░░░░ 80% left resets in 3h 12m
|
|
284
|
+
Weekly ███████████░░░░░░░░░ 55% left resets in 4d 6h
|
|
285
|
+
Sonnet ███████████████████░ 95% left resets in 4d 6h
|
|
286
|
+
|
|
287
|
+
Codex Plus
|
|
288
|
+
Session ██████████████████░░ 90% left resets in 1h 40m
|
|
289
|
+
Weekly █████████████░░░░░░░ 65% left resets in 2d 9h
|
|
290
|
+
|
|
291
|
+
Antigravity (agy)
|
|
292
|
+
Gemini 5h ████████████████████ 100% left
|
|
293
|
+
Gemini weekly ███████████████████░ 95% left
|
|
294
|
+
Claude/GPT 5h ██████████████████░░ 90% left resets in 2h 05m
|
|
295
|
+
Claude/GPT weekly ██████████████░░░░░░ 70% left resets in 5d 1h
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
The `Weekly` and `Sonnet` rows above are the point: they are **separate
|
|
299
|
+
buckets**. So is every agy row. Routing a subtask is choosing which of them to
|
|
300
|
+
spend.
|
|
301
|
+
|
|
302
|
+
- **Claude** — OAuth usage API; token from the Claude Code Keychain entry.
|
|
303
|
+
- **Codex** — ChatGPT `wham/usage` API; token from `~/.codex/auth.json`.
|
|
304
|
+
- **Antigravity** — prefers agy's **local daemon**
|
|
305
|
+
(`RetrieveUserQuotaSummary` over its embedded gRPC-web endpoint), which is
|
|
306
|
+
the only source for the full categorized breakdown above. Works whenever any
|
|
307
|
+
agy process has the singleton daemon up. Falls back to the OAuth
|
|
308
|
+
`retrieveUserQuota` on the Antigravity backend, which surfaces only coarse
|
|
309
|
+
Gemini buckets and is flagged *daemon offline*. Approach ported from
|
|
310
|
+
[steipete/CodexBar](https://github.com/steipete/CodexBar).
|
|
311
|
+
|
|
312
|
+
Reading these at *model* granularity is the point: they are the load-balancing
|
|
313
|
+
input the coach skill uses to route each subtask.
|
|
314
|
+
|
|
315
|
+
## Limitations
|
|
316
|
+
|
|
317
|
+
- macOS-only for the Claude quota probe (reads the Claude Code Keychain entry)
|
|
318
|
+
and for notifications. Everything else works on Linux.
|
|
319
|
+
- No remote agents — everything runs as a local subprocess on your machine.
|
|
320
|
+
- Quota probes read undocumented endpoints the vendors can change at any time.
|
|
321
|
+
|
|
322
|
+
## Contributing
|
|
323
|
+
|
|
324
|
+
Handlers for other agent CLIs are especially welcome — see
|
|
325
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) for the `AgentHandler` contract and what you
|
|
326
|
+
need to know about a CLI before writing one.
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
uv run pytest
|
|
330
|
+
uv run ruff check .
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## License
|
|
334
|
+
|
|
335
|
+
MIT. See [LICENSE](LICENSE).
|