patchfeld 0.2.0__py3-none-any.whl
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.
- patchfeld/__init__.py +1 -0
- patchfeld/__main__.py +32 -0
- patchfeld/actions.py +34 -0
- patchfeld/activity/__init__.py +0 -0
- patchfeld/activity/log.py +237 -0
- patchfeld/agents/__init__.py +0 -0
- patchfeld/agents/child_tools.py +66 -0
- patchfeld/agents/fake_sdk_adapter.py +45 -0
- patchfeld/agents/manager.py +365 -0
- patchfeld/agents/permission_grants.py +98 -0
- patchfeld/agents/permission_inbox.py +91 -0
- patchfeld/agents/request_inbox.py +65 -0
- patchfeld/agents/sdk_adapter.py +49 -0
- patchfeld/agents/session.py +250 -0
- patchfeld/agents/sort.py +66 -0
- patchfeld/agents/state.py +81 -0
- patchfeld/app.py +1433 -0
- patchfeld/config.py +128 -0
- patchfeld/events.py +260 -0
- patchfeld/layout/__init__.py +0 -0
- patchfeld/layout/custom_widgets.py +82 -0
- patchfeld/layout/defaults.py +33 -0
- patchfeld/layout/engine.py +241 -0
- patchfeld/layout/local_widgets.py +188 -0
- patchfeld/layout/registry.py +69 -0
- patchfeld/layout/spec.py +104 -0
- patchfeld/layout/splitter.py +170 -0
- patchfeld/layout/titles.py +70 -0
- patchfeld/orchestrator/__init__.py +0 -0
- patchfeld/orchestrator/formatting.py +15 -0
- patchfeld/orchestrator/session.py +785 -0
- patchfeld/orchestrator/tabs_tools.py +149 -0
- patchfeld/orchestrator/tools.py +976 -0
- patchfeld/persistence/__init__.py +0 -0
- patchfeld/persistence/agents_index.py +68 -0
- patchfeld/persistence/atomic.py +47 -0
- patchfeld/persistence/layout_store.py +25 -0
- patchfeld/persistence/layouts_store.py +61 -0
- patchfeld/persistence/orchestrator_sessions.py +127 -0
- patchfeld/persistence/paths.py +48 -0
- patchfeld/persistence/themes_store.py +44 -0
- patchfeld/persistence/transcript_store.py +64 -0
- patchfeld/persistence/workspace_store.py +25 -0
- patchfeld/theme/__init__.py +0 -0
- patchfeld/theme/engine.py +75 -0
- patchfeld/theme/spec.py +31 -0
- patchfeld/widgets/__init__.py +0 -0
- patchfeld/widgets/_file_lang.py +36 -0
- patchfeld/widgets/_terminal_keys.py +89 -0
- patchfeld/widgets/_terminal_render.py +147 -0
- patchfeld/widgets/activity_feed.py +365 -0
- patchfeld/widgets/agent_table.py +236 -0
- patchfeld/widgets/agent_transcript.py +85 -0
- patchfeld/widgets/change_cwd_screen.py +39 -0
- patchfeld/widgets/chrome.py +210 -0
- patchfeld/widgets/diff_viewer.py +52 -0
- patchfeld/widgets/file_editor.py +258 -0
- patchfeld/widgets/file_tree.py +33 -0
- patchfeld/widgets/file_viewer.py +77 -0
- patchfeld/widgets/history_screen.py +58 -0
- patchfeld/widgets/layout_switcher.py +126 -0
- patchfeld/widgets/log_tail.py +113 -0
- patchfeld/widgets/markdown.py +65 -0
- patchfeld/widgets/new_tab_screen.py +31 -0
- patchfeld/widgets/notebook.py +45 -0
- patchfeld/widgets/orchestrator_chat.py +73 -0
- patchfeld/widgets/permission_modal.py +185 -0
- patchfeld/widgets/permission_request_bar.py +90 -0
- patchfeld/widgets/resume_screen.py +179 -0
- patchfeld/widgets/rich_transcript.py +606 -0
- patchfeld/widgets/system_usage.py +244 -0
- patchfeld/widgets/terminal.py +251 -0
- patchfeld/widgets/theme_switcher.py +63 -0
- patchfeld/widgets/transcript_screen.py +39 -0
- patchfeld/workspace/__init__.py +3 -0
- patchfeld/workspace/spec.py +72 -0
- patchfeld-0.2.0.dist-info/METADATA +584 -0
- patchfeld-0.2.0.dist-info/RECORD +81 -0
- patchfeld-0.2.0.dist-info/WHEEL +4 -0
- patchfeld-0.2.0.dist-info/entry_points.txt +3 -0
- patchfeld-0.2.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: patchfeld
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: A Textual TUI for managing multiple Claude Code agent sessions
|
|
5
|
+
Project-URL: Homepage, https://github.com/jimmymills/patchfeld
|
|
6
|
+
Project-URL: Repository, https://github.com/jimmymills/patchfeld
|
|
7
|
+
Project-URL: Issues, https://github.com/jimmymills/patchfeld/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
|
+
# Patchfeld
|
|
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
|
+

|
|
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
|
+
**Patchfeld 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
|
+
- **Approve tool calls without leaving the room.** When a child wants
|
|
122
|
+
to use a tool that isn't auto-approved, a modal pops in patchfeld with
|
|
123
|
+
the tool name and full arguments. Approve once, deny once, always
|
|
124
|
+
allow this tool for any agent named X (persisted to disk), or always
|
|
125
|
+
deny. The agent's status flips to `awaiting permission` and the
|
|
126
|
+
request also surfaces inline in its `AgentTranscript` panel so you
|
|
127
|
+
can clear it without opening the modal. Launch with
|
|
128
|
+
`--bypass-permissions` for "trust everything"; flip mid-session with
|
|
129
|
+
`/bypass-permissions` and `/require-permissions`.
|
|
130
|
+
|
|
131
|
+
## Concept
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
┌─────────────────────┐ spawn / send / interrupt
|
|
135
|
+
you ───────▶ │ Orchestrator │ ──────────────────────────────┐
|
|
136
|
+
(cmd bar │ ClaudeSDKClient │ ▼
|
|
137
|
+
or chat) │ + injected tools │ ┌──────────────────┐
|
|
138
|
+
└──────────┬──────────┘ │ AgentManager │
|
|
139
|
+
│ │ ClaudeSDKClient │
|
|
140
|
+
│ │ × N children │
|
|
141
|
+
▼ └────────┬─────────┘
|
|
142
|
+
┌─────────────────────┐ │
|
|
143
|
+
│ LayoutEngine │ ◀── transcripts, state ─────┘
|
|
144
|
+
│ diff(old, new) │ events via EventBus
|
|
145
|
+
│ WidgetRegistry │
|
|
146
|
+
└──────────┬──────────┘
|
|
147
|
+
▼
|
|
148
|
+
┌─────────────────────┐
|
|
149
|
+
│ Textual App │
|
|
150
|
+
│ tabs · panels │
|
|
151
|
+
│ chrome (always-on)│
|
|
152
|
+
└─────────────────────┘
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
A `LayoutSpec` is a tree of containers (`horizontal` / `vertical` splits)
|
|
156
|
+
and panels (`{ id, widget, props, size }`). The engine diffs the new spec
|
|
157
|
+
against the live tree by `id` — same id + same widget reuses the mounted
|
|
158
|
+
widget (no scroll-jump); a different widget at the same id swaps it; a
|
|
159
|
+
missing id unmounts. The chrome (`CommandBar`, `StatusBar`) is always
|
|
160
|
+
mounted and cannot be removed. `OrchestratorChat` must be present in
|
|
161
|
+
exactly one panel — the agent can shrink it but cannot hide its own input.
|
|
162
|
+
|
|
163
|
+
## Built-in widgets
|
|
164
|
+
|
|
165
|
+
| Widget | Purpose |
|
|
166
|
+
|---|---|
|
|
167
|
+
| `OrchestratorChat` | The orchestrator session: rich transcript + input. |
|
|
168
|
+
| `AgentTable` | Sortable list of children: name, status, elapsed, cost. |
|
|
169
|
+
| `AgentTranscript` | One agent's full conversation, with a direct-message input box. |
|
|
170
|
+
| `ActivityFeed` | Cross-agent chronological event stream. |
|
|
171
|
+
| `FileTree` | Directory tree; emits `FileSelected` events on the bus. |
|
|
172
|
+
| `FileViewer` | Read-only syntax-highlighted file display; can follow `FileTree` selection. |
|
|
173
|
+
| `FileEditor` | Editable, syntax-highlighted; ctrl-s saves; warns on external changes. |
|
|
174
|
+
| `DiffViewer` | Unified-diff viewer (precomputed `diff` or `before` + `after`). |
|
|
175
|
+
| `LogTail` | Tails an arbitrary file (250 ms poll). |
|
|
176
|
+
| `Markdown` | Renders markdown from a string or file. |
|
|
177
|
+
| `Notebook` | Editable scratch buffer; persists to `<cwd>/.patchfeld/scratch/<name>.md`. |
|
|
178
|
+
| `Terminal` | Real PTY — drop into `claude`, `$SHELL`, or any command. Opaque to the orchestrator. |
|
|
179
|
+
| `SystemUsage` | Compact CPU + RAM gauges with auto-refresh and threshold-colored bars. Uses `psutil` if installed; otherwise async `top` / `vm_stat` shell-out on macOS. |
|
|
180
|
+
|
|
181
|
+
The orchestrator can also register **custom widgets** by emitting Python
|
|
182
|
+
source in the `custom_widgets` block of a `set_layout` call. The source
|
|
183
|
+
runs in an isolated module namespace; instantiation failures roll the
|
|
184
|
+
apply back so a broken widget can't brick the app.
|
|
185
|
+
|
|
186
|
+
### Custom widgets
|
|
187
|
+
|
|
188
|
+
Drop a `.py` file in `~/.config/patchfeld/widgets/` and patchfeld will pick
|
|
189
|
+
it up at startup. One file = one widget. The stem of the filename is the
|
|
190
|
+
default registered name (`token_chart.py` → `TokenChart`); override it
|
|
191
|
+
with an optional module-level `__patchfeld_widget__` dict. A minimal one
|
|
192
|
+
looks like:
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
from textual.widgets import Static
|
|
196
|
+
|
|
197
|
+
__patchfeld_widget__ = {
|
|
198
|
+
"name": "Hello",
|
|
199
|
+
"description": "Says hi.",
|
|
200
|
+
"props_schema": {"who": str},
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
class Hello(Static):
|
|
204
|
+
def __init__(self, who: str = "world", **kw) -> None:
|
|
205
|
+
super().__init__(f"hello, {who}", **kw)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Now ask the orchestrator: *"set a layout with a Hello panel where who is 'jimmy'."*
|
|
209
|
+
|
|
210
|
+
> **Trust model.** Files in `~/.config/patchfeld/widgets/` are imported
|
|
211
|
+
> in-process with full Python privileges on every launch. Only put
|
|
212
|
+
> source there that you wrote (or audited). The orchestrator's
|
|
213
|
+
> `save_widget` tool persists files into this same directory — review
|
|
214
|
+
> what it generates before re-launching.
|
|
215
|
+
|
|
216
|
+
Reload semantics are restart-only by design — patchfeld does not watch
|
|
217
|
+
the directory. The exception is the `save_widget` MCP tool: when the
|
|
218
|
+
orchestrator authors a widget through that tool, it's registered live
|
|
219
|
+
into the running app so you can use it in the same conversation. To
|
|
220
|
+
disable local-directory loading entirely (for security audits, or to
|
|
221
|
+
hand the laptop to a colleague), set `widgets.local_dir_enabled = false`
|
|
222
|
+
in `~/.config/patchfeld/config.toml`. Built-in widgets always win on a
|
|
223
|
+
name collision; the loader skips your file and surfaces the conflict
|
|
224
|
+
in `list_widgets`'s `errors` array.
|
|
225
|
+
|
|
226
|
+
The deep-dive — class-detection precedence, common pitfalls, full
|
|
227
|
+
metadata reference — lives in
|
|
228
|
+
[docs/superpowers/notes/widget-authoring.md](docs/superpowers/notes/widget-authoring.md).
|
|
229
|
+
|
|
230
|
+
## Tabs, layouts, and themes
|
|
231
|
+
|
|
232
|
+
- **Tabs.** `ctrl-t` to add, `ctrl-w` to close, `ctrl-1`..`ctrl-9` to jump,
|
|
233
|
+
`ctrl-pgup` / `ctrl-pgdn` to cycle. Each tab has its own `LayoutSpec` and
|
|
234
|
+
remembers which panel was last focused.
|
|
235
|
+
- **Named layouts.** `ctrl-l` opens the switcher. Layouts save to
|
|
236
|
+
`~/.config/patchfeld/layouts/<name>.json`; the orchestrator can list /
|
|
237
|
+
load / save them via tools.
|
|
238
|
+
- **Named themes.** `ctrl-shift-l` opens the theme switcher. Themes are a
|
|
239
|
+
palette + extra Textual CSS; the orchestrator can author and apply them
|
|
240
|
+
with `set_theme`.
|
|
241
|
+
- **Drag to resize.** Dragging a splitter persists new sizes back to the
|
|
242
|
+
workspace; `ctrl-shift-r` resets the active tab to its named source.
|
|
243
|
+
- **Runtime cwd swap.** `ctrl-shift-d` (or `/cd <path>`) re-roots the app:
|
|
244
|
+
stops orchestrator + manager, swaps cwd, loads (or seeds) the new
|
|
245
|
+
workspace, re-applies the active theme. Refuses while children run.
|
|
246
|
+
|
|
247
|
+
## Slash commands (orchestrator chat)
|
|
248
|
+
|
|
249
|
+
| Command | Action |
|
|
250
|
+
|---|---|
|
|
251
|
+
| `/reset` | Start a fresh orchestrator session. |
|
|
252
|
+
| `/resume` | Open the resume picker for a past orchestrator session. |
|
|
253
|
+
| `/rename` | Rename the current session's title. |
|
|
254
|
+
| `/cd <path>` | Change the workspace cwd. |
|
|
255
|
+
| `/bypass-permissions` | Switch the running session to bypass-all-permissions mode (no modals). |
|
|
256
|
+
| `/require-permissions` | Switch back to permission-modal mode. |
|
|
257
|
+
| `/help` | Show the slash-command list. |
|
|
258
|
+
|
|
259
|
+
`ctrl-c` while the chat is focused interrupts the orchestrator without
|
|
260
|
+
quitting the app.
|
|
261
|
+
|
|
262
|
+
## Default keybindings
|
|
263
|
+
|
|
264
|
+
| Key | Action |
|
|
265
|
+
|---|---|
|
|
266
|
+
| `/` | Focus command bar |
|
|
267
|
+
| `?` | Show keybindings overlay |
|
|
268
|
+
| `ctrl-q` | Quit |
|
|
269
|
+
| `ctrl-h` | Open agent history |
|
|
270
|
+
| `ctrl-l` | Open layout switcher |
|
|
271
|
+
| `ctrl-shift-l` | Open theme switcher |
|
|
272
|
+
| `ctrl-shift-r` | Reset panel sizes for active tab |
|
|
273
|
+
| `ctrl-shift-d` | Change cwd |
|
|
274
|
+
| `ctrl-t` / `ctrl-w` | New tab / close active tab |
|
|
275
|
+
| `ctrl-1`..`ctrl-9` | Jump to tab N |
|
|
276
|
+
|
|
277
|
+
All of these are rebindable from inside the app — ask the orchestrator to
|
|
278
|
+
"bind ctrl-r to focus_orchestrator" and it will, via the `bind_key` tool.
|
|
279
|
+
|
|
280
|
+
## Persistence
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
<cwd>/.patchfeld/
|
|
284
|
+
workspace.json # tabs + layouts for this directory
|
|
285
|
+
agents.json # every child agent ever spawned here
|
|
286
|
+
transcripts/
|
|
287
|
+
<agent_id>.jsonl # append-only message log per child
|
|
288
|
+
orchestrator.jsonl # the orchestrator's own transcript
|
|
289
|
+
scratch/ # for the Notebook widget
|
|
290
|
+
|
|
291
|
+
~/.config/patchfeld/
|
|
292
|
+
config.toml # bindings, theme, default model, tool allowlist
|
|
293
|
+
layouts/<name>.json # named layout presets
|
|
294
|
+
themes/<name>.json # named themes
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
All writes are atomic (temp + fsync + rename). `.patchfeld/` is in this
|
|
298
|
+
repo's `.gitignore` and you should add it to yours.
|
|
299
|
+
|
|
300
|
+
## Installation
|
|
301
|
+
|
|
302
|
+
### Requirements
|
|
303
|
+
|
|
304
|
+
- **Python 3.11+**
|
|
305
|
+
- The Claude CLI installed and authenticated (`claude --version`). patchfeld
|
|
306
|
+
uses your `~/.claude/settings.json` for permissions and tool allowlists.
|
|
307
|
+
- A terminal with TrueColor support (any modern macOS / Linux terminal).
|
|
308
|
+
|
|
309
|
+
### From PyPI (recommended)
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
pipx install patchfeld # isolated, on PATH
|
|
313
|
+
patchfeld # or: mt
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Or with `uv`:
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
uv tool install patchfeld
|
|
320
|
+
patchfeld
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Or with plain `pip` into a venv:
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
python -m venv .venv && source .venv/bin/activate
|
|
327
|
+
pip install patchfeld
|
|
328
|
+
patchfeld
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### From source (for hacking on patchfeld itself)
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
git clone https://github.com/jimmymills/patchfeld.git
|
|
335
|
+
cd patchfeld
|
|
336
|
+
uv sync --extra dev # runtime + dev deps (pyright, pytest)
|
|
337
|
+
uv run patchfeld # or: uv run mt
|
|
338
|
+
uv run pytest
|
|
339
|
+
./scripts/typecheck.sh # canonical pyright invocation
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## Running
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
patchfeld # use the current directory as the workspace cwd
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
First launch in a directory seeds the built-in dashboard (orchestrator
|
|
349
|
+
chat + agent table + activity feed) and creates `<cwd>/.patchfeld/`. Type
|
|
350
|
+
in the orchestrator chat or hit `/` to focus the command bar and start
|
|
351
|
+
talking to it.
|
|
352
|
+
|
|
353
|
+
Try:
|
|
354
|
+
|
|
355
|
+
- `spawn an agent that audits this repo for unused code`
|
|
356
|
+
- `give me a layout with the orchestrator on the left and a file tree + viewer on the right`
|
|
357
|
+
- `save that as "review"`
|
|
358
|
+
- `bind ctrl-r to focus_orchestrator`
|
|
359
|
+
- `make a theme called dim with a dark slate palette`
|
|
360
|
+
|
|
361
|
+
## Examples: agent management
|
|
362
|
+
|
|
363
|
+
Spawning, supervising, redirecting, interrupting, and replaying children
|
|
364
|
+
— all conversational. Behind every example is a structured tool call
|
|
365
|
+
(`spawn_agent`, `send_to_agent`, `interrupt_agent`, `kill_agent`,
|
|
366
|
+
`read_agent_transcript`, …) layered on top of the Claude Agent SDK.
|
|
367
|
+
|
|
368
|
+
### Spawn with narrow scope
|
|
369
|
+
|
|
370
|
+
> *"Spawn a `researcher` agent with only Read and WebSearch — have it survey alternatives to Pydantic v1 and write findings to `docs/migration-research.md`."*
|
|
371
|
+
|
|
372
|
+
Translates to roughly:
|
|
373
|
+
|
|
374
|
+
```python
|
|
375
|
+
spawn_agent(
|
|
376
|
+
name="researcher",
|
|
377
|
+
prompt="Survey alternatives to Pydantic v1 and write findings "
|
|
378
|
+
"to docs/migration-research.md",
|
|
379
|
+
allowed_tools=["Read", "WebSearch", "Edit"],
|
|
380
|
+
)
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
`allowed_tools` / `disallowed_tools` default to inheriting your
|
|
384
|
+
`~/.claude/settings.json`; the orchestrator can narrow per-spawn so a
|
|
385
|
+
read-only researcher can't accidentally `Bash` or a migrator can't reach
|
|
386
|
+
the network.
|
|
387
|
+
|
|
388
|
+
> *"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."*
|
|
389
|
+
>
|
|
390
|
+
> *"Spawn `docs-writer` with only Read and Edit, system prompt: 'You are a docs writer. Use the project's existing voice. Never edit code.'"*
|
|
391
|
+
|
|
392
|
+
### Run several in parallel
|
|
393
|
+
|
|
394
|
+
> *"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."*
|
|
395
|
+
|
|
396
|
+
Each child gets its own row in the `AgentTable`, its own JSONL transcript
|
|
397
|
+
under `<cwd>/.patchfeld/transcripts/<id>.jsonl`, and its own state
|
|
398
|
+
machine. Token / cost totals roll up to the StatusBar so you can watch
|
|
399
|
+
spend in aggregate.
|
|
400
|
+
|
|
401
|
+
> *"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."*
|
|
402
|
+
|
|
403
|
+
### Watch and steer them
|
|
404
|
+
|
|
405
|
+
> *"Show me what `auth-refactor` is doing right now."* (reads the transcript, can also `set_layout` an `AgentTranscript` panel)
|
|
406
|
+
>
|
|
407
|
+
> *"Tell `auth-refactor` to also update the docstrings while it's in there."*
|
|
408
|
+
>
|
|
409
|
+
> *"Interrupt `migrator` — I want to change its instructions."*
|
|
410
|
+
>
|
|
411
|
+
> *"Kill `lint` and respawn it with allowlist Read + Bash only."*
|
|
412
|
+
>
|
|
413
|
+
> *"Summarize what every running child has done in the last 5 minutes."*
|
|
414
|
+
|
|
415
|
+
You can also focus an `AgentTranscript` panel and type into its bottom
|
|
416
|
+
input — that goes straight to the child, bypassing the orchestrator. The
|
|
417
|
+
orchestrator still sees your message in its event stream so it stays
|
|
418
|
+
informed without mediating.
|
|
419
|
+
|
|
420
|
+
### Children that ask back
|
|
421
|
+
|
|
422
|
+
Children get two MCP tools injected automatically:
|
|
423
|
+
|
|
424
|
+
- **`notify_orchestrator(msg)`** — fire-and-forget. Surfaces in the
|
|
425
|
+
orchestrator's chat as `[child → orchestrator] msg`.
|
|
426
|
+
- **`ask_orchestrator(question, timeout_s=300)`** — blocks the child's
|
|
427
|
+
tool call until the orchestrator replies via `send_to_agent`, then
|
|
428
|
+
returns the reply as the tool result.
|
|
429
|
+
|
|
430
|
+
So a migration agent can stop and ask:
|
|
431
|
+
|
|
432
|
+
```
|
|
433
|
+
[migrator → orchestrator] (asking) Should I bump min Python to 3.11
|
|
434
|
+
or stay on 3.10? The Pydantic v2 path is cleaner on 3.11.
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
You answer through the orchestrator — *"Tell migrator to go with 3.11"*
|
|
438
|
+
— and the answer becomes the tool result on the child's side. No modal,
|
|
439
|
+
no context-switch.
|
|
440
|
+
|
|
441
|
+
### Replay from history
|
|
442
|
+
|
|
443
|
+
`ctrl-h` opens the History view: every agent that has ever run in this
|
|
444
|
+
cwd, with its prompt, status, and link to its transcript. Pick one to
|
|
445
|
+
view its messages in a modal; ask the orchestrator to re-run it with
|
|
446
|
+
modifications and it spawns a fresh child built from the original prompt
|
|
447
|
+
plus your tweak.
|
|
448
|
+
|
|
449
|
+
> *"Re-run the last failed agent with debug logging on."*
|
|
450
|
+
>
|
|
451
|
+
> *"Look up that bisect agent from yesterday and continue the same task with the new commits."*
|
|
452
|
+
>
|
|
453
|
+
> *"Show me every agent that touched `src/auth.py` this week."*
|
|
454
|
+
|
|
455
|
+
### Resume orchestrator sessions
|
|
456
|
+
|
|
457
|
+
The orchestrator's own conversation is journaled to
|
|
458
|
+
`<cwd>/.patchfeld/transcripts/orchestrator.jsonl`. `/resume` (or
|
|
459
|
+
*"resume the session about the auth refactor"*) opens a picker; pick a
|
|
460
|
+
past orchestrator session and patchfeld loads the full message history.
|
|
461
|
+
Children from that session are not auto-revived — they're listed in
|
|
462
|
+
History so you can re-run any that still matter, deliberately.
|
|
463
|
+
|
|
464
|
+
## Examples: layout self-management
|
|
465
|
+
|
|
466
|
+
Everything below is something you literally type in the orchestrator chat
|
|
467
|
+
(or `/` command bar). The orchestrator translates intent into the right
|
|
468
|
+
combination of `add_tab` / `set_layout` / `save_layout` / `bind_key` /
|
|
469
|
+
`set_theme` tool calls and applies the change atomically — if anything
|
|
470
|
+
fails validation, the previous layout stays mounted.
|
|
471
|
+
|
|
472
|
+
### Build new tabs
|
|
473
|
+
|
|
474
|
+
> *"Create a new tab called **Editor** with 20% FileTree on the left and 80% FileEditor on the right that follows the tree's selection."*
|
|
475
|
+
|
|
476
|
+
```
|
|
477
|
+
┌─ Files (20%) ─┐┌─ Editor (80%) ───────────────────┐
|
|
478
|
+
│ src/ ││ def handler(req): │
|
|
479
|
+
│ app.py ││ ... │
|
|
480
|
+
│ auth.py ││ │
|
|
481
|
+
│ tests/ ││ │
|
|
482
|
+
└───────────────┘└──────────────────────────────────┘
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
Behind the scenes the orchestrator emits a `LayoutSpec` like:
|
|
486
|
+
|
|
487
|
+
```json
|
|
488
|
+
{
|
|
489
|
+
"version": 1,
|
|
490
|
+
"layout": {
|
|
491
|
+
"type": "horizontal",
|
|
492
|
+
"children": [
|
|
493
|
+
{ "id": "tree", "size": "20%", "widget": "FileTree",
|
|
494
|
+
"props": { "path": "." } },
|
|
495
|
+
{ "id": "edit", "size": "80%", "widget": "FileEditor",
|
|
496
|
+
"props": { "follow_selection": true } }
|
|
497
|
+
]
|
|
498
|
+
},
|
|
499
|
+
"focus": "edit"
|
|
500
|
+
}
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
`FileTree` publishes `FileSelected` events on the bus; `FileEditor` with
|
|
504
|
+
`follow_selection: true` subscribes and reloads on click.
|
|
505
|
+
|
|
506
|
+
> *"Open a **Review** tab: orchestrator on top at 40%, below it a FileTree (30%) next to a DiffViewer (70%) showing the staged diff."*
|
|
507
|
+
>
|
|
508
|
+
> *"Add a **Logs** tab with a LogTail of `pytest.log` taking the full pane."*
|
|
509
|
+
>
|
|
510
|
+
> *"Make a **Triage** tab with the AgentTable on top and the ActivityFeed below it."*
|
|
511
|
+
|
|
512
|
+
### Reshape the current layout
|
|
513
|
+
|
|
514
|
+
> *"Make the orchestrator panel 70% wide instead of 60."*
|
|
515
|
+
>
|
|
516
|
+
> *"Add a Notebook called `plan` to the right side of this layout at 25% width."*
|
|
517
|
+
>
|
|
518
|
+
> *"Drop a Terminal running `claude` at the bottom of this tab, 30% tall."*
|
|
519
|
+
>
|
|
520
|
+
> *"Replace the activity feed with an AgentTranscript bound to the `auth-refactor` child."*
|
|
521
|
+
>
|
|
522
|
+
> *"Stack the file tree and a Markdown viewer of `README.md` vertically in the left column."*
|
|
523
|
+
|
|
524
|
+
Same-id + same-widget panels are reused (no scroll-jump). Different
|
|
525
|
+
widget at the same id swaps in place. Missing ids unmount.
|
|
526
|
+
|
|
527
|
+
### Save, load, and bind layouts
|
|
528
|
+
|
|
529
|
+
> *"Save this as `review` and bind `ctrl-shift-r` to load it."*
|
|
530
|
+
>
|
|
531
|
+
> *"Switch to the `dashboard` layout."*
|
|
532
|
+
>
|
|
533
|
+
> *"List my saved layouts."*
|
|
534
|
+
>
|
|
535
|
+
> *"Reset the panel sizes on this tab to whatever I had saved."* (or hit `ctrl-shift-r`)
|
|
536
|
+
|
|
537
|
+
Saved layouts live in `~/.config/patchfeld/layouts/<name>.json` and survive
|
|
538
|
+
across cwds.
|
|
539
|
+
|
|
540
|
+
### Multi-agent dashboards
|
|
541
|
+
|
|
542
|
+
> *"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."*
|
|
543
|
+
>
|
|
544
|
+
> *"Open a 4-pane grid: orchestrator top-left, AgentTable top-right, AgentTranscript for `auth-refactor` bottom-left, DiffViewer of the latest edit bottom-right."*
|
|
545
|
+
>
|
|
546
|
+
> *"Give every running child its own tab, named after the child, each with just an AgentTranscript panel."*
|
|
547
|
+
|
|
548
|
+
### Tabs, themes, and keys
|
|
549
|
+
|
|
550
|
+
> *"Move the Editor tab to first and switch to it."*
|
|
551
|
+
>
|
|
552
|
+
> *"Close the Logs tab."*
|
|
553
|
+
>
|
|
554
|
+
> *"Make a theme called `dim` with a dark slate palette and apply it to this project only."*
|
|
555
|
+
>
|
|
556
|
+
> *"Bind `ctrl-r` to `focus_orchestrator`, and `ctrl-shift-t` to `open_theme_switcher`."*
|
|
557
|
+
|
|
558
|
+
### Custom widgets at runtime
|
|
559
|
+
|
|
560
|
+
When the curated library doesn't fit, the orchestrator can ship Python
|
|
561
|
+
source in the same `set_layout` call:
|
|
562
|
+
|
|
563
|
+
> *"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."*
|
|
564
|
+
|
|
565
|
+
The source runs in an isolated module namespace; if instantiation fails
|
|
566
|
+
the whole apply rolls back and you get a `layout-failed` notification —
|
|
567
|
+
the last good layout stays mounted.
|
|
568
|
+
|
|
569
|
+
## Limitations (v1)
|
|
570
|
+
|
|
571
|
+
- **No auto-resume of in-flight children** across restarts. Past agents
|
|
572
|
+
are visible in History (`ctrl-h`) and can be re-run from their original
|
|
573
|
+
prompt; they are not silently revived.
|
|
574
|
+
- **Custom widgets run in-process.** A `try/except` boundary at mount
|
|
575
|
+
time catches crashes, but there is no subprocess sandbox.
|
|
576
|
+
- **No peer-to-peer messaging between children.** All cross-agent traffic
|
|
577
|
+
is orchestrator-mediated.
|
|
578
|
+
- **Claude Agent SDK only.** The agent abstraction is designed to
|
|
579
|
+
accommodate other harnesses (Codex, Aider, Gemini CLI), but only the
|
|
580
|
+
Claude adapter ships.
|
|
581
|
+
|
|
582
|
+
## License
|
|
583
|
+
|
|
584
|
+
[MIT](LICENSE) © Jimmy Mills.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
patchfeld/__init__.py,sha256=rnObPjuBcEStqSO0S6gsdS_ot8ITOQjVj_-P1LUUYpg,22
|
|
2
|
+
patchfeld/__main__.py,sha256=vpItaFeUQ8Ry6P3Eown2UVofwpnSl3VSl5ESjA6ymUc,920
|
|
3
|
+
patchfeld/actions.py,sha256=r_XAr9GmtKdTLWK81SsaAhZ0ZOUoCdoBXnM7J3yAduw,1005
|
|
4
|
+
patchfeld/app.py,sha256=B1IzCX_-HIaWiMjUzdtOfMw4slKw-to-OqbUvaZOQ98,62520
|
|
5
|
+
patchfeld/config.py,sha256=Qjysjn6O1Y9ADNY3-IhN5G2dZWUE7ZvAEoAy2HYJDOw,4162
|
|
6
|
+
patchfeld/events.py,sha256=UJW77afeGxYX4tKpFZfO9h2PMBpJcRpHhUk-59Qsh-Q,7713
|
|
7
|
+
patchfeld/activity/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
patchfeld/activity/log.py,sha256=q6_b363i3CwxIBeBpDNTzmGjj4CkYrO1KErbeoTu8DM,8906
|
|
9
|
+
patchfeld/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
patchfeld/agents/child_tools.py,sha256=8VkHmZ007fPk8UVp9RIsOFmMtkqn7_Onds7185ob9BA,2307
|
|
11
|
+
patchfeld/agents/fake_sdk_adapter.py,sha256=zQpPomgWK4M-uFp7tPfPmTU8RxC9YEQzC0dBoUQryyE,1460
|
|
12
|
+
patchfeld/agents/manager.py,sha256=Z9Ecnr41_Xb8SuOjmdiBM-zv0cxsRP6kL8vZbsjbbd4,14839
|
|
13
|
+
patchfeld/agents/permission_grants.py,sha256=SZhH29rhG7yF3E-35msLXdmI4UqaLVwSI1l9SnxO1cA,3383
|
|
14
|
+
patchfeld/agents/permission_inbox.py,sha256=WWhJsd6lZl1VSDwSdPqfjKaeK4bFomvK-hGehOAKTTA,2920
|
|
15
|
+
patchfeld/agents/request_inbox.py,sha256=RJSSEr7ErGeAYUdMzH_qaCJHxgF7p1FiAOrZ57eYIT8,2414
|
|
16
|
+
patchfeld/agents/sdk_adapter.py,sha256=l9nKjcgnGypNV864YWsgNmaDZMTzDGcFSxAe-N5caPE,1771
|
|
17
|
+
patchfeld/agents/session.py,sha256=FntnnUa6xnfy1O-mQErHlkpTlyRK585t37FrtsxLavY,9230
|
|
18
|
+
patchfeld/agents/sort.py,sha256=paMxenRAdJ1jtbNiDAmL3bB20OjiDp8jiH42yA7U6Zc,2353
|
|
19
|
+
patchfeld/agents/state.py,sha256=zyV3AXzjCcNvtkzhXf3cCAdH0icaUzjdDWSEbg0X38I,2616
|
|
20
|
+
patchfeld/layout/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
+
patchfeld/layout/custom_widgets.py,sha256=2nCCOWyuHI31W58cxSBALAQKlCwFQI2x9y0By82HxZY,2638
|
|
22
|
+
patchfeld/layout/defaults.py,sha256=pqx1MvmHX60cOZKzxsccGOPJu93jdKcM9MFc1bmKxVo,1218
|
|
23
|
+
patchfeld/layout/engine.py,sha256=OThUDlhXr7GWxJFrIFuFgknBCjO090Zg0gswEZm5mro,9771
|
|
24
|
+
patchfeld/layout/local_widgets.py,sha256=qtuz_Y0sLC9L5AM2H7wARJsdcPvJHxNVzpzT_g-Y4k4,6586
|
|
25
|
+
patchfeld/layout/registry.py,sha256=Wf4OBC3jKQI9RnACpLYUPT67-kOQ4yaq8mco81lMWio,2017
|
|
26
|
+
patchfeld/layout/spec.py,sha256=BnqMHcshso6a1m8UUBqhxRBtD_C9d884ibFXnPYfIus,3504
|
|
27
|
+
patchfeld/layout/splitter.py,sha256=Dh7ewUIEqQXKmRCGjOJDwvRvXuIhHLiyMC8_Ms-ykPY,6012
|
|
28
|
+
patchfeld/layout/titles.py,sha256=3tk9mF3S_2ZBOfSoEU1kpvq0VXEhlXhMn0q6MQpMj4M,2436
|
|
29
|
+
patchfeld/orchestrator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
|
+
patchfeld/orchestrator/formatting.py,sha256=HS_AJMNn9xWjR34xUy7N8vLuvUnpabgB6Bdzjx-F364,644
|
|
31
|
+
patchfeld/orchestrator/session.py,sha256=33L61rVqQUPzR4l9NfxpQrwvihLIZtsh8K4gaVbj7ks,32805
|
|
32
|
+
patchfeld/orchestrator/tabs_tools.py,sha256=4MmQC2t8ICumwdH5UQppp5rQT34vTkgcktgNUsC-EZA,5350
|
|
33
|
+
patchfeld/orchestrator/tools.py,sha256=dJptnvLGTgjBxchUX4CPIjZWvoeSB7Cz1EccI43zZdg,42342
|
|
34
|
+
patchfeld/persistence/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
+
patchfeld/persistence/agents_index.py,sha256=-03jMKMWqMouAXz4InSb99RA0B4sG0RNWB6A_NLvkb4,2343
|
|
36
|
+
patchfeld/persistence/atomic.py,sha256=Hv7S4tn-G3hn75Qj2bS2HMDdPND6q9wJpaSYEBB3-Hg,1607
|
|
37
|
+
patchfeld/persistence/layout_store.py,sha256=jikLv6JLjwvqItantOSNpi_iAuVbhZbzkLM5AdtUguI,720
|
|
38
|
+
patchfeld/persistence/layouts_store.py,sha256=IprfaXLkVNVI9ryOmq3FHea-7tbnLOgpVhmSBdI0fDI,2099
|
|
39
|
+
patchfeld/persistence/orchestrator_sessions.py,sha256=0Ywkvk_HuXnGuoLZv4HFOMlQP_QZ6YBnSDR7jrUrHE4,4346
|
|
40
|
+
patchfeld/persistence/paths.py,sha256=LPdqmJxQG1kBx-NOF3bI4_Ach1HHHrfGm3tYbNX7nqA,1446
|
|
41
|
+
patchfeld/persistence/themes_store.py,sha256=3Lal-uVuOxKhbGhc_BfV8GglPHEB41KOeGo9A1U4v-U,1395
|
|
42
|
+
patchfeld/persistence/transcript_store.py,sha256=YKvMkTI5soNVuTPJDt6vk8bfOKG12pt2_pGLe9xxpOw,2090
|
|
43
|
+
patchfeld/persistence/workspace_store.py,sha256=QsJjdqO9pHcnPIFksiXzO1rnwE-AHHdQMIBdF6HkWCc,749
|
|
44
|
+
patchfeld/theme/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
45
|
+
patchfeld/theme/engine.py,sha256=6lDpdCAIdm-1IwsQH8dXD5qrvWypMl85AXqf4TJoXX0,2955
|
|
46
|
+
patchfeld/theme/spec.py,sha256=7BuWEAmjV9nf4HmdNwZH8-DJ6e8WV9tPbZ11KS8sAAM,888
|
|
47
|
+
patchfeld/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
48
|
+
patchfeld/widgets/_file_lang.py,sha256=2UvPx4XEmGEJ-RqdixS0p-0Oiqotj6IlV3BXHv2LXe0,865
|
|
49
|
+
patchfeld/widgets/_terminal_keys.py,sha256=Nz8T96D3lcVqWVM9LV8yia9DlxsY4OInp8RDxf7EEbE,2737
|
|
50
|
+
patchfeld/widgets/_terminal_render.py,sha256=1E6eiK1_95xlhA-2PGSPQ1MgTenUs19HUyO2Kyz_4b4,5427
|
|
51
|
+
patchfeld/widgets/activity_feed.py,sha256=KJtWSCD1WLY__1BAFzXwK3R9agd4iBFmUXydzIB1t4Q,13265
|
|
52
|
+
patchfeld/widgets/agent_table.py,sha256=j9ndc7CWoNR5udq79hpH-LoPUgstXpJfGG6OkcdqHhk,9036
|
|
53
|
+
patchfeld/widgets/agent_transcript.py,sha256=dHetUnfkeidIH-5Yi2fPgzbzIzhQyiYIJUaRsBMgqt0,2968
|
|
54
|
+
patchfeld/widgets/change_cwd_screen.py,sha256=GZRLEY-eGcyCHjDXvXbcaXGplKJtPIynhTDZ4pRk_Ok,1217
|
|
55
|
+
patchfeld/widgets/chrome.py,sha256=wAJqP51sAewRz_IjVdXgZNfwwpFLHlPaHW9xi83M1yk,7955
|
|
56
|
+
patchfeld/widgets/diff_viewer.py,sha256=OlkcUuqr3zft5oURk-knhylthT_N-swsC35YDwQTHZ8,1371
|
|
57
|
+
patchfeld/widgets/file_editor.py,sha256=sJKIlwVIflaCueO1vAcjsrt-C8t6Xi0I1vIvtIe9UPo,8873
|
|
58
|
+
patchfeld/widgets/file_tree.py,sha256=gBO3Ld0mMNI_sVaeWDHGRViOdGroPj6MwSAthZ1PVgc,954
|
|
59
|
+
patchfeld/widgets/file_viewer.py,sha256=TcVnU9xIRF4-2TEUZsD8Nq-owWxlHC9FwyX2-7MCXy0,2434
|
|
60
|
+
patchfeld/widgets/history_screen.py,sha256=DhJ-ZiHAjFIorRrhNp3ehP8g5EnxMA_a2dzDw1L5qng,1744
|
|
61
|
+
patchfeld/widgets/layout_switcher.py,sha256=LrhCc38dh_La9pr60NnBSIG7dPNUHca7wqgXTC_lKOU,4342
|
|
62
|
+
patchfeld/widgets/log_tail.py,sha256=jtLh7GouK_7gfH1I5-JVFgGMErSA1re8wpeGyCJzHfM,3702
|
|
63
|
+
patchfeld/widgets/markdown.py,sha256=y0oTzeb7H21Z0YPlY4FywAwBjuU3kd8agVut1Sa8Y_Q,2484
|
|
64
|
+
patchfeld/widgets/new_tab_screen.py,sha256=NgigJ_U3zRChYztiUULAE5wk7kmcvDL_XaNezKVGR8E,967
|
|
65
|
+
patchfeld/widgets/notebook.py,sha256=aYEuIKEzhBuW-ci4cQAQ1EOhWa5AYqq65Y20WTF_jIg,1244
|
|
66
|
+
patchfeld/widgets/orchestrator_chat.py,sha256=l21xAgxLwqHV01Dli_79q8ulXNOrNg86XAGtLbmGdHA,2243
|
|
67
|
+
patchfeld/widgets/permission_modal.py,sha256=u7mhdCT88bOPUuo3Tf2X8Kx-JyqtYZJ58lZRJej1GOs,7003
|
|
68
|
+
patchfeld/widgets/permission_request_bar.py,sha256=W_wzBxsMROvcXYqKbNdZL0zOqYo9QNdkUO_2We1Kj0s,3239
|
|
69
|
+
patchfeld/widgets/resume_screen.py,sha256=Zptt3q1cofa6hpcZqCYdR0IWnQB3ckNwDNwbJaNlcvs,5339
|
|
70
|
+
patchfeld/widgets/rich_transcript.py,sha256=lZw-pJoLltO32HTodTRT2obw1v9ouyAJ8oD1XKsAt4o,22423
|
|
71
|
+
patchfeld/widgets/system_usage.py,sha256=6zMMY5LopJ3dt9RDM8mxVxl7uzljjPFf8TPIaaLqRE4,7868
|
|
72
|
+
patchfeld/widgets/terminal.py,sha256=di4N-6plucXvh6Iq-UfVV9riUXYYah_2qmU0LkK-ILo,8603
|
|
73
|
+
patchfeld/widgets/theme_switcher.py,sha256=6616l2R0tPSFZUJ5YFnrd7JUIo0XosPIIrBjt0nULKI,1947
|
|
74
|
+
patchfeld/widgets/transcript_screen.py,sha256=oQs2czxYwi5N6lSCuGRRfmILADc5ZKxXj3f4qLZX52w,1079
|
|
75
|
+
patchfeld/workspace/__init__.py,sha256=GwSCbJs1eBRF_adGE3E7TR_8PpwmysKgYhQQxxuzNaA,132
|
|
76
|
+
patchfeld/workspace/spec.py,sha256=wM7YUHkaNmYkcSDG4T-jXFCZijmkD7468pqshyigmA8,2577
|
|
77
|
+
patchfeld-0.2.0.dist-info/METADATA,sha256=6TU9vwqcaEeQy9CrfWw53YVuf4-zlRB7oyTUeYRk3W4,24818
|
|
78
|
+
patchfeld-0.2.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
79
|
+
patchfeld-0.2.0.dist-info/entry_points.txt,sha256=2akJPrE9Nn9M-xU6rMlxYXjc8M-MutR20dndeAbUakM,83
|
|
80
|
+
patchfeld-0.2.0.dist-info/licenses/LICENSE,sha256=yFtLaiPTIawj7BA5P7eKt5ZRzc0qAIiQZZWagxAPjtg,1068
|
|
81
|
+
patchfeld-0.2.0.dist-info/RECORD,,
|