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.
@@ -0,0 +1,12 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .venv/
4
+ venv/
5
+ *.egg-info/
6
+ .ruff_cache/
7
+ .pytest_cache/
8
+ .DS_Store
9
+ dist/
10
+ build/
11
+ .claude/
12
+ .smoke/
@@ -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
+ [![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/)
33
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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).