patchbai 0.1.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 (76) hide show
  1. patchbai-0.1.0/.gitignore +11 -0
  2. patchbai-0.1.0/LICENSE +21 -0
  3. patchbai-0.1.0/PKG-INFO +573 -0
  4. patchbai-0.1.0/README.md +538 -0
  5. patchbai-0.1.0/patchbai/__init__.py +1 -0
  6. patchbai-0.1.0/patchbai/__main__.py +10 -0
  7. patchbai-0.1.0/patchbai/actions.py +34 -0
  8. patchbai-0.1.0/patchbai/activity/__init__.py +0 -0
  9. patchbai-0.1.0/patchbai/activity/log.py +237 -0
  10. patchbai-0.1.0/patchbai/agents/__init__.py +0 -0
  11. patchbai-0.1.0/patchbai/agents/child_tools.py +66 -0
  12. patchbai-0.1.0/patchbai/agents/fake_sdk_adapter.py +45 -0
  13. patchbai-0.1.0/patchbai/agents/manager.py +272 -0
  14. patchbai-0.1.0/patchbai/agents/request_inbox.py +65 -0
  15. patchbai-0.1.0/patchbai/agents/sdk_adapter.py +49 -0
  16. patchbai-0.1.0/patchbai/agents/session.py +224 -0
  17. patchbai-0.1.0/patchbai/agents/sort.py +66 -0
  18. patchbai-0.1.0/patchbai/agents/state.py +80 -0
  19. patchbai-0.1.0/patchbai/app.py +1288 -0
  20. patchbai-0.1.0/patchbai/config.py +128 -0
  21. patchbai-0.1.0/patchbai/events.py +236 -0
  22. patchbai-0.1.0/patchbai/layout/__init__.py +0 -0
  23. patchbai-0.1.0/patchbai/layout/custom_widgets.py +82 -0
  24. patchbai-0.1.0/patchbai/layout/defaults.py +33 -0
  25. patchbai-0.1.0/patchbai/layout/engine.py +241 -0
  26. patchbai-0.1.0/patchbai/layout/local_widgets.py +188 -0
  27. patchbai-0.1.0/patchbai/layout/registry.py +69 -0
  28. patchbai-0.1.0/patchbai/layout/spec.py +104 -0
  29. patchbai-0.1.0/patchbai/layout/splitter.py +170 -0
  30. patchbai-0.1.0/patchbai/layout/titles.py +70 -0
  31. patchbai-0.1.0/patchbai/orchestrator/__init__.py +0 -0
  32. patchbai-0.1.0/patchbai/orchestrator/formatting.py +15 -0
  33. patchbai-0.1.0/patchbai/orchestrator/session.py +644 -0
  34. patchbai-0.1.0/patchbai/orchestrator/tabs_tools.py +149 -0
  35. patchbai-0.1.0/patchbai/orchestrator/tools.py +976 -0
  36. patchbai-0.1.0/patchbai/persistence/__init__.py +0 -0
  37. patchbai-0.1.0/patchbai/persistence/agents_index.py +68 -0
  38. patchbai-0.1.0/patchbai/persistence/atomic.py +47 -0
  39. patchbai-0.1.0/patchbai/persistence/layout_store.py +25 -0
  40. patchbai-0.1.0/patchbai/persistence/layouts_store.py +61 -0
  41. patchbai-0.1.0/patchbai/persistence/orchestrator_sessions.py +127 -0
  42. patchbai-0.1.0/patchbai/persistence/paths.py +48 -0
  43. patchbai-0.1.0/patchbai/persistence/themes_store.py +44 -0
  44. patchbai-0.1.0/patchbai/persistence/transcript_store.py +64 -0
  45. patchbai-0.1.0/patchbai/persistence/workspace_store.py +25 -0
  46. patchbai-0.1.0/patchbai/theme/__init__.py +0 -0
  47. patchbai-0.1.0/patchbai/theme/engine.py +75 -0
  48. patchbai-0.1.0/patchbai/theme/spec.py +31 -0
  49. patchbai-0.1.0/patchbai/widgets/__init__.py +0 -0
  50. patchbai-0.1.0/patchbai/widgets/_file_lang.py +36 -0
  51. patchbai-0.1.0/patchbai/widgets/_terminal_keys.py +89 -0
  52. patchbai-0.1.0/patchbai/widgets/_terminal_render.py +147 -0
  53. patchbai-0.1.0/patchbai/widgets/activity_feed.py +365 -0
  54. patchbai-0.1.0/patchbai/widgets/agent_table.py +235 -0
  55. patchbai-0.1.0/patchbai/widgets/agent_transcript.py +58 -0
  56. patchbai-0.1.0/patchbai/widgets/change_cwd_screen.py +39 -0
  57. patchbai-0.1.0/patchbai/widgets/chrome.py +210 -0
  58. patchbai-0.1.0/patchbai/widgets/diff_viewer.py +52 -0
  59. patchbai-0.1.0/patchbai/widgets/file_editor.py +258 -0
  60. patchbai-0.1.0/patchbai/widgets/file_tree.py +33 -0
  61. patchbai-0.1.0/patchbai/widgets/file_viewer.py +77 -0
  62. patchbai-0.1.0/patchbai/widgets/history_screen.py +58 -0
  63. patchbai-0.1.0/patchbai/widgets/layout_switcher.py +126 -0
  64. patchbai-0.1.0/patchbai/widgets/log_tail.py +113 -0
  65. patchbai-0.1.0/patchbai/widgets/markdown.py +65 -0
  66. patchbai-0.1.0/patchbai/widgets/new_tab_screen.py +31 -0
  67. patchbai-0.1.0/patchbai/widgets/notebook.py +45 -0
  68. patchbai-0.1.0/patchbai/widgets/orchestrator_chat.py +73 -0
  69. patchbai-0.1.0/patchbai/widgets/resume_screen.py +179 -0
  70. patchbai-0.1.0/patchbai/widgets/rich_transcript.py +606 -0
  71. patchbai-0.1.0/patchbai/widgets/terminal.py +251 -0
  72. patchbai-0.1.0/patchbai/widgets/theme_switcher.py +63 -0
  73. patchbai-0.1.0/patchbai/widgets/transcript_screen.py +39 -0
  74. patchbai-0.1.0/patchbai/workspace/__init__.py +3 -0
  75. patchbai-0.1.0/patchbai/workspace/spec.py +72 -0
  76. patchbai-0.1.0/pyproject.toml +77 -0
@@ -0,0 +1,11 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ .uv/
5
+ dist/
6
+ *.egg-info/
7
+ .pytest_cache/
8
+ .patchbai/
9
+ .superpowers/
10
+ docs/superpowers/
11
+ .DS_Store
patchbai-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jimmy Mills
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,573 @@
1
+ Metadata-Version: 2.4
2
+ Name: patchbai
3
+ Version: 0.1.0
4
+ Summary: A Textual TUI for managing multiple Claude Code agent sessions
5
+ Project-URL: Homepage, https://github.com/jimmymills/patchbai
6
+ Project-URL: Repository, https://github.com/jimmymills/patchbai
7
+ Project-URL: Issues, https://github.com/jimmymills/patchbai/issues
8
+ Author: Jimmy Mills
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agents,claude,claude-code,orchestrator,textual,tui
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console :: Curses
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Operating System :: POSIX
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 :: Terminals
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: claude-agent-sdk>=0.1
25
+ Requires-Dist: ptyprocess>=0.7
26
+ Requires-Dist: pydantic>=2.6
27
+ Requires-Dist: pyte>=0.8
28
+ Requires-Dist: textual>=0.80
29
+ Requires-Dist: tomli-w>=1.0
30
+ Provides-Extra: dev
31
+ Requires-Dist: pyright<1.2,>=1.1.395; extra == 'dev'
32
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
33
+ Requires-Dist: pytest>=8.0; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # Patchbai
37
+
38
+ **A Textual TUI that turns N parallel Claude Code sessions into one
39
+ orchestrator-managed workspace — and lets the agent reshape the UI to fit
40
+ the work.**
41
+
42
+ ![patchbai — orchestrator chat on the left, agent table and activity feed on the right](https://raw.githubusercontent.com/jimmymills/patchbai/main/docs/images/screenshot.png)
43
+
44
+ ## The pitch
45
+
46
+ You're running three Claude Code sessions at once. One's refactoring auth,
47
+ one's writing tests, one's doing a security pass. They live in three
48
+ terminal tabs with three scrollbacks, and you're the one mentally juggling
49
+ which is waiting on what.
50
+
51
+ **Patchbai is the room you wish you had.** One TUI. One top-level Claude —
52
+ the *orchestrator* — runs the show. You tell it what you want done in
53
+ plain English; it spawns the right children with the right tool
54
+ allowlists, watches their progress, and pulls them onscreen when they
55
+ need you. Tell it *"give me the file tree on the left and the diff viewer
56
+ on the right"* and the layout actually changes — the orchestrator emits a
57
+ declarative spec and the engine swaps panels in place, atomically, with
58
+ rollback on failure.
59
+
60
+ You get this without giving anything up. Children are real Claude Code
61
+ sessions running through the official Agent SDK, with your
62
+ `~/.claude/settings.json` permissions. No screen-scraping, no fragile
63
+ regex over PTY output — the orchestrator reads transcripts, sends
64
+ messages, interrupts, and kills via structured in-process MCP tools. When
65
+ you're tired of being orchestrator-mediated, the `Terminal` widget drops
66
+ you into the actual `claude` CLI in any panel.
67
+
68
+ It's conversational the whole way down. You spawn:
69
+
70
+ > *"Spawn three agents in parallel: `tests` running pytest, `lint` running ruff + pyright, `format` running ruff format. Notify me when any of them fail."*
71
+
72
+ You arrange:
73
+
74
+ > *"Open a **Review** tab: orchestrator on top, FileTree next to a DiffViewer below it. Save it as `review`."*
75
+
76
+ You react:
77
+
78
+ > *"Interrupt migrator — I want to change its instructions."*<br>
79
+ > *"Re-run the last failed agent with `--cov` added."*<br>
80
+ > *"Build a custom widget that sparklines my token usage and stick it as a 25% sidebar."*
81
+
82
+ Each of those is one message. The orchestrator owns the spec; you own
83
+ the ideas.
84
+
85
+ ### Who it's for
86
+
87
+ - **Devs running 2+ Claude sessions in parallel.** Refactor + tests +
88
+ review, frontend + backend, debug + bisect — all in one window with one
89
+ shared StatusBar of tokens, cost, and active children.
90
+ - **Code reviewers** who want a tab per PR with the right diff viewer
91
+ and file tree wired up automatically, and a saved layout that applies
92
+ in any repo.
93
+ - **Pipeline-builders and researchers** running one *notebook* agent and
94
+ several worker agents off it, with a single chronological feed of who's
95
+ doing what and an append-only JSONL audit trail per child.
96
+ - **People who hate switching terminal tabs.** The whole interface is
97
+ conversational; layout, theme, keybinding, tab, and cwd changes are a
98
+ sentence away — and every change persists.
99
+
100
+ ## Why use it
101
+
102
+ - **Run several Claude sessions side by side.** The orchestrator spawns
103
+ children with their own prompts, allowed tools, and cwd. Each gets a
104
+ transcript you can scroll, a state machine you can introspect, and a
105
+ direct-message input box when you want to bypass the orchestrator.
106
+ - **Talk to the UI like you talk to the agent.** "Open a diff viewer for
107
+ the last edit", "give me a 3-pane layout with file tree on the left",
108
+ "save that as `review`" — all of it routes through orchestrator tools
109
+ (`set_layout`, `save_layout`, `bind_key`, `set_theme`, …) and persists.
110
+ - **Structured introspection, not screen scraping.** The orchestrator
111
+ reads a child's transcript, sends messages, interrupts, kills — all via
112
+ in-process MCP tools layered on top of the Claude Agent SDK. No PTY
113
+ parsing, no fragile regex.
114
+ - **Persistent everything.** Workspaces (per-cwd), layouts, themes,
115
+ keybindings, transcripts, and a full agent history are stored on disk
116
+ and restored on next launch.
117
+ - **Real escape hatches.** A `Terminal` widget is a real PTY — drop into
118
+ the actual `claude` CLI, or your shell, in any panel. Mode-C custom
119
+ widgets let the orchestrator ship Python at runtime when the curated
120
+ widget library isn't enough.
121
+
122
+ ## Concept
123
+
124
+ ```
125
+ ┌─────────────────────┐ spawn / send / interrupt
126
+ you ───────▶ │ Orchestrator │ ──────────────────────────────┐
127
+ (cmd bar │ ClaudeSDKClient │ ▼
128
+ or chat) │ + injected tools │ ┌──────────────────┐
129
+ └──────────┬──────────┘ │ AgentManager │
130
+ │ │ ClaudeSDKClient │
131
+ │ │ × N children │
132
+ ▼ └────────┬─────────┘
133
+ ┌─────────────────────┐ │
134
+ │ LayoutEngine │ ◀── transcripts, state ─────┘
135
+ │ diff(old, new) │ events via EventBus
136
+ │ WidgetRegistry │
137
+ └──────────┬──────────┘
138
+
139
+ ┌─────────────────────┐
140
+ │ Textual App │
141
+ │ tabs · panels │
142
+ │ chrome (always-on)│
143
+ └─────────────────────┘
144
+ ```
145
+
146
+ A `LayoutSpec` is a tree of containers (`horizontal` / `vertical` splits)
147
+ and panels (`{ id, widget, props, size }`). The engine diffs the new spec
148
+ against the live tree by `id` — same id + same widget reuses the mounted
149
+ widget (no scroll-jump); a different widget at the same id swaps it; a
150
+ missing id unmounts. The chrome (`CommandBar`, `StatusBar`) is always
151
+ mounted and cannot be removed. `OrchestratorChat` must be present in
152
+ exactly one panel — the agent can shrink it but cannot hide its own input.
153
+
154
+ ## Built-in widgets
155
+
156
+ | Widget | Purpose |
157
+ |---|---|
158
+ | `OrchestratorChat` | The orchestrator session: rich transcript + input. |
159
+ | `AgentTable` | Sortable list of children: name, status, elapsed, cost. |
160
+ | `AgentTranscript` | One agent's full conversation, with a direct-message input box. |
161
+ | `ActivityFeed` | Cross-agent chronological event stream. |
162
+ | `FileTree` | Directory tree; emits `FileSelected` events on the bus. |
163
+ | `FileViewer` | Read-only syntax-highlighted file display; can follow `FileTree` selection. |
164
+ | `FileEditor` | Editable, syntax-highlighted; ctrl-s saves; warns on external changes. |
165
+ | `DiffViewer` | Unified-diff viewer (precomputed `diff` or `before` + `after`). |
166
+ | `LogTail` | Tails an arbitrary file (250 ms poll). |
167
+ | `Markdown` | Renders markdown from a string or file. |
168
+ | `Notebook` | Editable scratch buffer; persists to `<cwd>/.patchbai/scratch/<name>.md`. |
169
+ | `Terminal` | Real PTY — drop into `claude`, `$SHELL`, or any command. Opaque to the orchestrator. |
170
+
171
+ The orchestrator can also register **custom widgets** by emitting Python
172
+ source in the `custom_widgets` block of a `set_layout` call. The source
173
+ runs in an isolated module namespace; instantiation failures roll the
174
+ apply back so a broken widget can't brick the app.
175
+
176
+ ### Custom widgets
177
+
178
+ Drop a `.py` file in `~/.config/patchbai/widgets/` and patchbai will pick
179
+ it up at startup. One file = one widget. The stem of the filename is the
180
+ default registered name (`token_chart.py` → `TokenChart`); override it
181
+ with an optional module-level `__patchbai_widget__` dict. A minimal one
182
+ looks like:
183
+
184
+ ```python
185
+ from textual.widgets import Static
186
+
187
+ __patchbai_widget__ = {
188
+ "name": "Hello",
189
+ "description": "Says hi.",
190
+ "props_schema": {"who": str},
191
+ }
192
+
193
+ class Hello(Static):
194
+ def __init__(self, who: str = "world", **kw) -> None:
195
+ super().__init__(f"hello, {who}", **kw)
196
+ ```
197
+
198
+ Now ask the orchestrator: *"set a layout with a Hello panel where who is 'jimmy'."*
199
+
200
+ > **Trust model.** Files in `~/.config/patchbai/widgets/` are imported
201
+ > in-process with full Python privileges on every launch. Only put
202
+ > source there that you wrote (or audited). The orchestrator's
203
+ > `save_widget` tool persists files into this same directory — review
204
+ > what it generates before re-launching.
205
+
206
+ Reload semantics are restart-only by design — patchbai does not watch
207
+ the directory. The exception is the `save_widget` MCP tool: when the
208
+ orchestrator authors a widget through that tool, it's registered live
209
+ into the running app so you can use it in the same conversation. To
210
+ disable local-directory loading entirely (for security audits, or to
211
+ hand the laptop to a colleague), set `widgets.local_dir_enabled = false`
212
+ in `~/.config/patchbai/config.toml`. Built-in widgets always win on a
213
+ name collision; the loader skips your file and surfaces the conflict
214
+ in `list_widgets`'s `errors` array.
215
+
216
+ The deep-dive — class-detection precedence, common pitfalls, full
217
+ metadata reference — lives in
218
+ [docs/superpowers/notes/widget-authoring.md](docs/superpowers/notes/widget-authoring.md).
219
+
220
+ ## Tabs, layouts, and themes
221
+
222
+ - **Tabs.** `ctrl-t` to add, `ctrl-w` to close, `ctrl-1`..`ctrl-9` to jump,
223
+ `ctrl-pgup` / `ctrl-pgdn` to cycle. Each tab has its own `LayoutSpec` and
224
+ remembers which panel was last focused.
225
+ - **Named layouts.** `ctrl-l` opens the switcher. Layouts save to
226
+ `~/.config/patchbai/layouts/<name>.json`; the orchestrator can list /
227
+ load / save them via tools.
228
+ - **Named themes.** `ctrl-shift-l` opens the theme switcher. Themes are a
229
+ palette + extra Textual CSS; the orchestrator can author and apply them
230
+ with `set_theme`.
231
+ - **Drag to resize.** Dragging a splitter persists new sizes back to the
232
+ workspace; `ctrl-shift-r` resets the active tab to its named source.
233
+ - **Runtime cwd swap.** `ctrl-shift-d` (or `/cd <path>`) re-roots the app:
234
+ stops orchestrator + manager, swaps cwd, loads (or seeds) the new
235
+ workspace, re-applies the active theme. Refuses while children run.
236
+
237
+ ## Slash commands (orchestrator chat)
238
+
239
+ | Command | Action |
240
+ |---|---|
241
+ | `/reset` | Start a fresh orchestrator session. |
242
+ | `/resume` | Open the resume picker for a past orchestrator session. |
243
+ | `/rename` | Rename the current session's title. |
244
+ | `/cd <path>` | Change the workspace cwd. |
245
+ | `/help` | Show the slash-command list. |
246
+
247
+ `ctrl-c` while the chat is focused interrupts the orchestrator without
248
+ quitting the app.
249
+
250
+ ## Default keybindings
251
+
252
+ | Key | Action |
253
+ |---|---|
254
+ | `/` | Focus command bar |
255
+ | `?` | Show keybindings overlay |
256
+ | `ctrl-q` | Quit |
257
+ | `ctrl-h` | Open agent history |
258
+ | `ctrl-l` | Open layout switcher |
259
+ | `ctrl-shift-l` | Open theme switcher |
260
+ | `ctrl-shift-r` | Reset panel sizes for active tab |
261
+ | `ctrl-shift-d` | Change cwd |
262
+ | `ctrl-t` / `ctrl-w` | New tab / close active tab |
263
+ | `ctrl-1`..`ctrl-9` | Jump to tab N |
264
+
265
+ All of these are rebindable from inside the app — ask the orchestrator to
266
+ "bind ctrl-r to focus_orchestrator" and it will, via the `bind_key` tool.
267
+
268
+ ## Persistence
269
+
270
+ ```
271
+ <cwd>/.patchbai/
272
+ workspace.json # tabs + layouts for this directory
273
+ agents.json # every child agent ever spawned here
274
+ transcripts/
275
+ <agent_id>.jsonl # append-only message log per child
276
+ orchestrator.jsonl # the orchestrator's own transcript
277
+ scratch/ # for the Notebook widget
278
+
279
+ ~/.config/patchbai/
280
+ config.toml # bindings, theme, default model, tool allowlist
281
+ layouts/<name>.json # named layout presets
282
+ themes/<name>.json # named themes
283
+ ```
284
+
285
+ All writes are atomic (temp + fsync + rename). `.patchbai/` is in this
286
+ repo's `.gitignore` and you should add it to yours.
287
+
288
+ ## Installation
289
+
290
+ ### Requirements
291
+
292
+ - **Python 3.11+**
293
+ - The Claude CLI installed and authenticated (`claude --version`). patchbai
294
+ uses your `~/.claude/settings.json` for permissions and tool allowlists.
295
+ - A terminal with TrueColor support (any modern macOS / Linux terminal).
296
+
297
+ ### With `uv` (recommended, used by this repo)
298
+
299
+ ```bash
300
+ git clone <repo> patchbai
301
+ cd patchbai
302
+ uv sync # install runtime deps into .venv
303
+ uv run patchbai # or: uv run mt
304
+ ```
305
+
306
+ For development, sync the dev extras (pyright, pytest):
307
+
308
+ ```bash
309
+ uv sync --extra dev
310
+ uv run pytest
311
+ ./scripts/typecheck.sh # canonical pyright invocation
312
+ ```
313
+
314
+ ### With `pipx`
315
+
316
+ ```bash
317
+ pipx install .
318
+ patchbai # or: mt
319
+ ```
320
+
321
+ ### Editable install with `pip`
322
+
323
+ ```bash
324
+ python -m venv .venv && source .venv/bin/activate
325
+ pip install -e ".[dev]"
326
+ patchbai
327
+ ```
328
+
329
+ ## Running
330
+
331
+ ```bash
332
+ patchbai # use the current directory as the workspace cwd
333
+ ```
334
+
335
+ First launch in a directory seeds the built-in dashboard (orchestrator
336
+ chat + agent table + activity feed) and creates `<cwd>/.patchbai/`. Type
337
+ in the orchestrator chat or hit `/` to focus the command bar and start
338
+ talking to it.
339
+
340
+ Try:
341
+
342
+ - `spawn an agent that audits this repo for unused code`
343
+ - `give me a layout with the orchestrator on the left and a file tree + viewer on the right`
344
+ - `save that as "review"`
345
+ - `bind ctrl-r to focus_orchestrator`
346
+ - `make a theme called dim with a dark slate palette`
347
+
348
+ ## Examples: agent management
349
+
350
+ Spawning, supervising, redirecting, interrupting, and replaying children
351
+ — all conversational. Behind every example is a structured tool call
352
+ (`spawn_agent`, `send_to_agent`, `interrupt_agent`, `kill_agent`,
353
+ `read_agent_transcript`, …) layered on top of the Claude Agent SDK.
354
+
355
+ ### Spawn with narrow scope
356
+
357
+ > *"Spawn a `researcher` agent with only Read and WebSearch — have it survey alternatives to Pydantic v1 and write findings to `docs/migration-research.md`."*
358
+
359
+ Translates to roughly:
360
+
361
+ ```python
362
+ spawn_agent(
363
+ name="researcher",
364
+ prompt="Survey alternatives to Pydantic v1 and write findings "
365
+ "to docs/migration-research.md",
366
+ allowed_tools=["Read", "WebSearch", "Edit"],
367
+ )
368
+ ```
369
+
370
+ `allowed_tools` / `disallowed_tools` default to inheriting your
371
+ `~/.claude/settings.json`; the orchestrator can narrow per-spawn so a
372
+ read-only researcher can't accidentally `Bash` or a migrator can't reach
373
+ the network.
374
+
375
+ > *"Spawn a `migrator` agent in `~/Developer/auth-svc` running on Sonnet 4.5 — its job is to apply the Pydantic v2 migration to that repo."*
376
+ >
377
+ > *"Spawn `docs-writer` with only Read and Edit, system prompt: 'You are a docs writer. Use the project's existing voice. Never edit code.'"*
378
+
379
+ ### Run several in parallel
380
+
381
+ > *"Spawn three agents in parallel: `tests` running `pytest -x --ff`, `lint` running ruff + pyright, `format` running ruff format. Notify me when any of them fail."*
382
+
383
+ Each child gets its own row in the `AgentTable`, its own JSONL transcript
384
+ under `<cwd>/.patchbai/transcripts/<id>.jsonl`, and its own state
385
+ machine. Token / cost totals roll up to the StatusBar so you can watch
386
+ spend in aggregate.
387
+
388
+ > *"For every PR in this repo's queue, spawn a reviewer agent in its own tab named after the PR number, give each one the diff and a checklist."*
389
+
390
+ ### Watch and steer them
391
+
392
+ > *"Show me what `auth-refactor` is doing right now."* &nbsp;(reads the transcript, can also `set_layout` an `AgentTranscript` panel)
393
+ >
394
+ > *"Tell `auth-refactor` to also update the docstrings while it's in there."*
395
+ >
396
+ > *"Interrupt `migrator` — I want to change its instructions."*
397
+ >
398
+ > *"Kill `lint` and respawn it with allowlist Read + Bash only."*
399
+ >
400
+ > *"Summarize what every running child has done in the last 5 minutes."*
401
+
402
+ You can also focus an `AgentTranscript` panel and type into its bottom
403
+ input — that goes straight to the child, bypassing the orchestrator. The
404
+ orchestrator still sees your message in its event stream so it stays
405
+ informed without mediating.
406
+
407
+ ### Children that ask back
408
+
409
+ Children get two MCP tools injected automatically:
410
+
411
+ - **`notify_orchestrator(msg)`** — fire-and-forget. Surfaces in the
412
+ orchestrator's chat as `[child → orchestrator] msg`.
413
+ - **`ask_orchestrator(question, timeout_s=300)`** — blocks the child's
414
+ tool call until the orchestrator replies via `send_to_agent`, then
415
+ returns the reply as the tool result.
416
+
417
+ So a migration agent can stop and ask:
418
+
419
+ ```
420
+ [migrator → orchestrator] (asking) Should I bump min Python to 3.11
421
+ or stay on 3.10? The Pydantic v2 path is cleaner on 3.11.
422
+ ```
423
+
424
+ You answer through the orchestrator — *"Tell migrator to go with 3.11"*
425
+ — and the answer becomes the tool result on the child's side. No modal,
426
+ no context-switch.
427
+
428
+ ### Replay from history
429
+
430
+ `ctrl-h` opens the History view: every agent that has ever run in this
431
+ cwd, with its prompt, status, and link to its transcript. Pick one to
432
+ view its messages in a modal; ask the orchestrator to re-run it with
433
+ modifications and it spawns a fresh child built from the original prompt
434
+ plus your tweak.
435
+
436
+ > *"Re-run the last failed agent with debug logging on."*
437
+ >
438
+ > *"Look up that bisect agent from yesterday and continue the same task with the new commits."*
439
+ >
440
+ > *"Show me every agent that touched `src/auth.py` this week."*
441
+
442
+ ### Resume orchestrator sessions
443
+
444
+ The orchestrator's own conversation is journaled to
445
+ `<cwd>/.patchbai/transcripts/orchestrator.jsonl`. `/resume` (or
446
+ *"resume the session about the auth refactor"*) opens a picker; pick a
447
+ past orchestrator session and patchbai loads the full message history.
448
+ Children from that session are not auto-revived — they're listed in
449
+ History so you can re-run any that still matter, deliberately.
450
+
451
+ ## Examples: layout self-management
452
+
453
+ Everything below is something you literally type in the orchestrator chat
454
+ (or `/` command bar). The orchestrator translates intent into the right
455
+ combination of `add_tab` / `set_layout` / `save_layout` / `bind_key` /
456
+ `set_theme` tool calls and applies the change atomically — if anything
457
+ fails validation, the previous layout stays mounted.
458
+
459
+ ### Build new tabs
460
+
461
+ > *"Create a new tab called **Editor** with 20% FileTree on the left and 80% FileEditor on the right that follows the tree's selection."*
462
+
463
+ ```
464
+ ┌─ Files (20%) ─┐┌─ Editor (80%) ───────────────────┐
465
+ │ src/ ││ def handler(req): │
466
+ │ app.py ││ ... │
467
+ │ auth.py ││ │
468
+ │ tests/ ││ │
469
+ └───────────────┘└──────────────────────────────────┘
470
+ ```
471
+
472
+ Behind the scenes the orchestrator emits a `LayoutSpec` like:
473
+
474
+ ```json
475
+ {
476
+ "version": 1,
477
+ "layout": {
478
+ "type": "horizontal",
479
+ "children": [
480
+ { "id": "tree", "size": "20%", "widget": "FileTree",
481
+ "props": { "path": "." } },
482
+ { "id": "edit", "size": "80%", "widget": "FileEditor",
483
+ "props": { "follow_selection": true } }
484
+ ]
485
+ },
486
+ "focus": "edit"
487
+ }
488
+ ```
489
+
490
+ `FileTree` publishes `FileSelected` events on the bus; `FileEditor` with
491
+ `follow_selection: true` subscribes and reloads on click.
492
+
493
+ > *"Open a **Review** tab: orchestrator on top at 40%, below it a FileTree (30%) next to a DiffViewer (70%) showing the staged diff."*
494
+ >
495
+ > *"Add a **Logs** tab with a LogTail of `pytest.log` taking the full pane."*
496
+ >
497
+ > *"Make a **Triage** tab with the AgentTable on top and the ActivityFeed below it."*
498
+
499
+ ### Reshape the current layout
500
+
501
+ > *"Make the orchestrator panel 70% wide instead of 60."*
502
+ >
503
+ > *"Add a Notebook called `plan` to the right side of this layout at 25% width."*
504
+ >
505
+ > *"Drop a Terminal running `claude` at the bottom of this tab, 30% tall."*
506
+ >
507
+ > *"Replace the activity feed with an AgentTranscript bound to the `auth-refactor` child."*
508
+ >
509
+ > *"Stack the file tree and a Markdown viewer of `README.md` vertically in the left column."*
510
+
511
+ Same-id + same-widget panels are reused (no scroll-jump). Different
512
+ widget at the same id swaps in place. Missing ids unmount.
513
+
514
+ ### Save, load, and bind layouts
515
+
516
+ > *"Save this as `review` and bind `ctrl-shift-r` to load it."*
517
+ >
518
+ > *"Switch to the `dashboard` layout."*
519
+ >
520
+ > *"List my saved layouts."*
521
+ >
522
+ > *"Reset the panel sizes on this tab to whatever I had saved."* &nbsp;(or hit `ctrl-shift-r`)
523
+
524
+ Saved layouts live in `~/.config/patchbai/layouts/<name>.json` and survive
525
+ across cwds.
526
+
527
+ ### Multi-agent dashboards
528
+
529
+ > *"Spawn an agent named `tests` running `pytest -x --ff`, then put its transcript on the left and a LogTail of `pytest.log` on the right."*
530
+ >
531
+ > *"Open a 4-pane grid: orchestrator top-left, AgentTable top-right, AgentTranscript for `auth-refactor` bottom-left, DiffViewer of the latest edit bottom-right."*
532
+ >
533
+ > *"Give every running child its own tab, named after the child, each with just an AgentTranscript panel."*
534
+
535
+ ### Tabs, themes, and keys
536
+
537
+ > *"Move the Editor tab to first and switch to it."*
538
+ >
539
+ > *"Close the Logs tab."*
540
+ >
541
+ > *"Make a theme called `dim` with a dark slate palette and apply it to this project only."*
542
+ >
543
+ > *"Bind `ctrl-r` to `focus_orchestrator`, and `ctrl-shift-t` to `open_theme_switcher`."*
544
+
545
+ ### Custom widgets at runtime
546
+
547
+ When the curated library doesn't fit, the orchestrator can ship Python
548
+ source in the same `set_layout` call:
549
+
550
+ > *"Build a custom `TokenChart` widget that draws my token usage over the last hour as a sparkline, and put it as a 25% sidebar on the right."*
551
+
552
+ The source runs in an isolated module namespace; if instantiation fails
553
+ the whole apply rolls back and you get a `layout-failed` notification —
554
+ the last good layout stays mounted.
555
+
556
+ ## Limitations (v1)
557
+
558
+ - **No auto-resume of in-flight children** across restarts. Past agents
559
+ are visible in History (`ctrl-h`) and can be re-run from their original
560
+ prompt; they are not silently revived.
561
+ - **Custom widgets run in-process.** A `try/except` boundary at mount
562
+ time catches crashes, but there is no subprocess sandbox.
563
+ - **No peer-to-peer messaging between children.** All cross-agent traffic
564
+ is orchestrator-mediated.
565
+ - **Claude Agent SDK only.** The agent abstraction is designed to
566
+ accommodate other harnesses (Codex, Aider, Gemini CLI), but only the
567
+ Claude adapter ships.
568
+ - **No modal "approve this tool call?" UX.** Children inherit your
569
+ `~/.claude/settings.json` permissions, optionally narrowed at spawn.
570
+
571
+ ## License
572
+
573
+ [MIT](LICENSE) © Jimmy Mills.