v0.25.0 c3476a8

subagents.md RawHistoryFolder

Resident subagents

V0.x breaking change: zut no longer supports subprocess subagent state. Previous state is ignored rather than read or migrated; remove it when you no longer need it. Existing child jobs are never resumed.

Subagents are independent core.Agent conversations resident in the same zut process as their parent. A child has a stable, private session identity, its own provider client and tool registry, a cancellation boundary, and an authoritative journal. Starting a child never launches another zut executable.

Profiles

Profiles are Markdown files discovered from ~/.agents/agents/*.md, paths in ZUT_AGENT_PROFILES, and the ~/.pi/agent/agents/*.md compatibility discovery location. They are inputs only; zut does not execute them.

---
name: reviewer
description: Read-only code reviewer
tools: [read, grep]
model: openai-codex/gpt-5.6-luna
thinking: high
systemPromptMode: replace
inheritProjectContext: false
inheritSkills: false
fastMode: false
---

Inspect the requested scope and report evidence-backed findings.

tools is a capability boundary. An omitted value inherits the child-safe catalogue, tools: [] grants no tools, and an explicit list replaces the default. Names unavailable to the child (including host-only extensions) and tools denied by subagents.allowed_tools are omitted from an explicit list; they never grant the child additional access. model, provider, thinking, the prompt mode, project/skill inheritance, and fastMode are resolved before the child is accepted. A spawn-level model, provider, reasoning, or fast-mode override takes precedence where supplied.

Children are always fresh conversations: they receive the delegated task and resolved host/profile context, never the parent transcript or hidden reasoning. They cannot recursively create more children.

Lifecycle and persistence

The manager records each accepted child under its managed state root:

subagents/<child-id>/
  transcript.jsonl  # authoritative accepted turns and finalized messages
  owner.lock        # host-ownership coordination; do not modify or remove
  .transcript-backup-* # retained private pre-repair transcript, when repaired
  metadata.json     # rebuildable bounded state
  result.json       # latest state plus a bounded final assistant summary
  patch.diff        # optional worktree capture

Acceptance is durable before subagent_spawn reports success. Finalized user, assistant, tool-call, and tool-result messages are journaled; streamed deltas and hidden reasoning are not exposed as ordinary history. A tool call is stored before execution and reconciliation repairs incomplete call/result pairs.

All children stop when the host exits. On the next start, queued or running turns are marked interrupted; zut never replays their task. Resume only with an explicit new prompt through subagent_resume, the child-session composer, or /subagents resume <id> <prompt>.

Multiple zut processes may share a state root. Each resident journal has one host owner at a time. A process that finds a child owned elsewhere reports it as such and does not inspect, recover, or modify its transcript. Resume that child from its owning host or after the owner exits. On a subsequent safe reconciliation, zut repairs only the known legacy false-recovery sequence; it leaves any ambiguous journal corruption untouched. A repair retains the pre-repair transcript as .transcript-backup-*; it can contain private session data and is intentionally not removed automatically.

subagent_status reports owned_elsewhere: true when another process owns a child. The field is omitted when false. A foreign-owned child cannot be resumed, or have its history or result read, from this process.

The global scheduler admits the oldest eligible accepted prompt, runs at most one turn for each child, and defaults to six concurrent turns. Set subagents.max_concurrent to a positive limit to override it. Queueing is unlimited by default; a positive subagents.queue_timeout cancels an accepted prompt that has not received a slot and records its terminal failure durably. subagents.allowed_tools is an allowlist for child-visible tools and subagents.allowed_roots limits eligible child workspaces. Removed legacy settings, including tui_subagent_position, are ignored.

required: true makes a delegated result an obligation of the parent turn. Failed, cancelled, and interrupted required work remains unresolved until an explicit successful follow-up. A host restart never retries it automatically.

Delegation ownership

Interactive proactive delegation keeps the primary agent on the critical path. Before spawning, it selects useful local work and delegates only a concrete, bounded sidecar with a non-overlapping question, responsibility, package, or file set. Immediate blockers and tightly coupled work stay local. While a child is active, it owns that scope; the primary continues only its preselected independent work instead of repeating the investigation, review, testing, or implementation. If an explicit user request or active workflow hands blocking work to a child, the primary yields for the completion update. Once a worktree child succeeds, the primary may apply and verify its captured patch without redoing the delegated task.

Explicit headless --orchestrate remains manager-only. Its primary divides the request into disjoint worker scopes, coordinates active children, and yields rather than implementing or reproducing delegated work. Children do not inherit the parent's strict orchestrator role. Headless orchestration waits for every accepted child before continuing its completion wave; required: true additionally creates a durable obligation. When proactive interactive delegation cannot spawn because of launch-time policy, the primary continues locally; a strict headless orchestrator instead reports the missing required capability.

Tools and slash commands

The model-facing tools retain their logical names:

  • subagent_spawn accepts task, optional agent, model and provider, reasoning, fast_mode, required, wait, and isolation (shared or worktree). wait is an explicit whole-second value from 1 through 300; when omitted, spawning returns immediately. A timed-out wait leaves the accepted child active, whether it is queued or running. Do not retry that task until it reaches a terminal failure, cancellation, or interruption. It returns a logical subagent://<id> reference.
  • subagent_status returns bounded current state for one child or the current set immediately.
  • subagent_stop stops one live child.
  • subagent_resume accepts an explicit follow-up prompt for an existing child.

Child execution started by subagent_spawn is asynchronous unless it receives an explicit wait value. For an unwaited spawn, completion arrives through the host’s typed completion update; subagent_status only returns the current state immediately. Do not use sleep loops, repeated status calls, journal files, or terminal UI inspection as a completion signal. Successful completions include the final visible assistant summary, capped at 256 KiB; open the child session for the complete durable transcript.

/subagents opens the resident-child list, ordered by the latest state change. Each row leads with the profile (or model), shows a human terminal state such as completed, a relative update time, and a short ID. Press Down from the main composer to open this list without clearing a draft when a child exists. Use arrows and Enter to open a child session; /subagents new <task> creates a child; /subagents logs <id> opens its history; /subagents result <id> shows the bounded final summary; kill <id> stops it; and resume <id> <prompt> continues it.

The child session uses the same transcript renderer as the main session. Recent history is bounded and loaded asynchronously; PgUp asks for an older page. Up/Down preserves the current reading position, and PgDn returns to the live tail after unread updates accumulate. The screen combines durable finalized history with an immutable in-memory projection of the active turn. Enter submits the local composer only after the manager durably accepts it; Esc closes the session. History may contain task text, tool arguments, tool results, and source-derived output, so treat it as private local session data.

Worktrees and references

Shared children use the host working directory. With isolation: "worktree", zut prepares a detached Git worktree, captures a patch and changed-file list on successful completion, and never applies that patch automatically. Failed or interrupted worktrees are retained for inspection; an idle successful worktree is cleaned when its child is explicitly stopped.

Logical references avoid exposing runtime paths:

subagent://<id>
subagent://<id>/history
subagent://<id>/result
subagent://<id>/patch

Provider caching

Each main and child conversation sends a stable logical session ID and a new turn ID per accepted prompt to the provider layer. Provider adapters decide whether and how to use them: OpenAI/Codex translates a supported stable session into its cache key and routing header, while other adapters preserve deterministic request input and use only cache controls their provider/model/endpoint supports. An OpenAI-compatible wire shape is not itself evidence that a cache extension or transport feature is available. Models continue through their declared provider transport; a transport change must not change the logical session or turn identity used by the provider request.

source
1# Resident subagents
2
3> **V0.x breaking change:** zut no longer supports subprocess subagent state.
4> Previous state is ignored rather than read or migrated; remove it when you
5> no longer need it. Existing child jobs are never resumed.
6
7Subagents are independent `core.Agent` conversations resident in the same zut
8process as their parent. A child has a stable, private session identity, its own
9provider client and tool registry, a cancellation boundary, and an authoritative
10journal. Starting a child never launches another zut executable.
11
12## Profiles
13
14Profiles are Markdown files discovered from `~/.agents/agents/*.md`, paths in
15`ZUT_AGENT_PROFILES`, and the `~/.pi/agent/agents/*.md` compatibility discovery
16location. They are inputs only; zut does not execute them.
17
18```markdown
19---
20name: reviewer
21description: Read-only code reviewer
22tools: [read, grep]
23model: openai-codex/gpt-5.6-luna
24thinking: high
25systemPromptMode: replace
26inheritProjectContext: false
27inheritSkills: false
28fastMode: false
29---
30
31Inspect the requested scope and report evidence-backed findings.
32```
33
34`tools` is a capability boundary. An omitted value inherits the child-safe
35catalogue, `tools: []` grants no tools, and an explicit list replaces the
36default. Names unavailable to the child (including host-only extensions) and
37tools denied by `subagents.allowed_tools` are omitted from an explicit list;
38they never grant the child additional access. `model`, `provider`, `thinking`,
39the prompt mode, project/skill inheritance, and `fastMode` are resolved before
40the child is accepted. A spawn-level model, provider, reasoning, or fast-mode
41override takes precedence where supplied.
42
43Children are always fresh conversations: they receive the delegated task and
44resolved host/profile context, never the parent transcript or hidden reasoning.
45They cannot recursively create more children.
46
47## Lifecycle and persistence
48
49The manager records each accepted child under its managed state root:
50
51```text
52subagents/<child-id>/
53  transcript.jsonl  # authoritative accepted turns and finalized messages
54  owner.lock        # host-ownership coordination; do not modify or remove
55  .transcript-backup-* # retained private pre-repair transcript, when repaired
56  metadata.json     # rebuildable bounded state
57  result.json       # latest state plus a bounded final assistant summary
58  patch.diff        # optional worktree capture
59```
60
61Acceptance is durable before `subagent_spawn` reports success. Finalized user,
62assistant, tool-call, and tool-result messages are journaled; streamed deltas
63and hidden reasoning are not exposed as ordinary history. A tool call is stored
64before execution and reconciliation repairs incomplete call/result pairs.
65
66All children stop when the host exits. On the next start, queued or running
67turns are marked `interrupted`; zut never replays their task. Resume only with
68an explicit new prompt through `subagent_resume`, the child-session composer,
69or `/subagents resume <id> <prompt>`.
70
71Multiple zut processes may share a state root. Each resident journal has one
72host owner at a time. A process that finds a child owned elsewhere reports it
73as such and does not inspect, recover, or modify its transcript. Resume that
74child from its owning host or after the owner exits. On a subsequent safe
75reconciliation, zut repairs only the known legacy false-recovery sequence; it
76leaves any ambiguous journal corruption untouched. A repair retains the
77pre-repair transcript as `.transcript-backup-*`; it can contain private session
78data and is intentionally not removed automatically.
79
80`subagent_status` reports `owned_elsewhere: true` when another process owns a
81child. The field is omitted when false. A foreign-owned child cannot be resumed,
82or have its history or result read, from this process.
83
84The global scheduler admits the oldest eligible accepted prompt, runs at most
85one turn for each child, and defaults to six concurrent turns. Set
86`subagents.max_concurrent` to a positive limit to override it. Queueing is
87unlimited by default; a positive `subagents.queue_timeout` cancels an accepted
88prompt that has not received a slot and records its terminal failure durably.
89`subagents.allowed_tools` is an allowlist for child-visible tools and
90`subagents.allowed_roots` limits eligible child workspaces. Removed legacy
91settings, including `tui_subagent_position`, are ignored.
92
93`required: true` makes a delegated result an obligation of the parent turn.
94Failed, cancelled, and interrupted required work remains unresolved until an
95explicit successful follow-up. A host restart never retries it automatically.
96
97## Delegation ownership
98
99Interactive proactive delegation keeps the primary agent on the critical path.
100Before spawning, it selects useful local work and delegates only a concrete,
101bounded sidecar with a non-overlapping question, responsibility, package, or
102file set. Immediate blockers and tightly coupled work stay local. While a child
103is active, it owns that scope; the primary continues only its preselected
104independent work instead of repeating the investigation, review, testing, or
105implementation. If an explicit user request or active workflow hands blocking
106work to a child, the primary yields for the completion update. Once a worktree
107child succeeds, the primary may apply and verify its captured patch without
108redoing the delegated task.
109
110Explicit headless `--orchestrate` remains manager-only. Its primary divides the
111request into disjoint worker scopes, coordinates active children, and yields
112rather than implementing or reproducing delegated work. Children do not inherit
113the parent's strict orchestrator role. Headless orchestration waits for every
114accepted child before continuing its completion wave; `required: true`
115additionally creates a durable obligation. When proactive
116interactive delegation cannot spawn because of launch-time policy, the primary
117continues locally; a strict headless orchestrator instead reports the missing
118required capability.
119
120## Tools and slash commands
121
122The model-facing tools retain their logical names:
123
124- `subagent_spawn` accepts `task`, optional `agent`, `model` and `provider`,
125  `reasoning`, `fast_mode`, `required`, `wait`, and `isolation` (`shared` or
126  `worktree`). `wait` is an explicit whole-second value from 1 through 300;
127  when omitted, spawning returns immediately. A timed-out wait leaves the
128  accepted child active, whether it is queued or running. Do not retry that
129  task until it reaches a terminal failure, cancellation, or interruption. It
130  returns a logical `subagent://<id>` reference.
131- `subagent_status` returns bounded current state for one child or the current
132  set immediately.
133- `subagent_stop` stops one live child.
134- `subagent_resume` accepts an explicit follow-up prompt for an existing child.
135
136Child execution started by `subagent_spawn` is asynchronous unless it receives
137an explicit `wait` value. For an unwaited spawn, completion arrives through the
138host’s typed completion update; `subagent_status` only returns the current
139state immediately. Do not use sleep loops, repeated status calls, journal
140files, or terminal UI inspection as a completion signal.
141Successful completions include the final visible assistant summary, capped at
142256 KiB; open the child session for the complete durable transcript.
143
144`/subagents` opens the resident-child list, ordered by the latest state change.
145Each row leads with the profile (or model), shows a human terminal state such
146as `completed`, a relative update time, and a short ID. Press Down from the
147main composer to open this list without clearing a draft when a child exists.
148Use arrows and Enter to open a child session; `/subagents new <task>` creates a child; `/subagents logs <id>`
149opens its history; `/subagents result <id>` shows the bounded final summary;
150`kill <id>` stops it; and `resume <id> <prompt>` continues it.
151
152The child session uses the same transcript renderer as the main session.
153Recent history is bounded and loaded asynchronously; PgUp asks for an older
154page. Up/Down preserves the current reading position, and PgDn returns to the
155live tail after unread updates accumulate. The screen combines durable finalized
156history with an immutable in-memory projection of the active turn. Enter submits
157the local composer only after the manager durably accepts it; Esc closes the session. History may contain task
158text, tool arguments, tool results, and source-derived output, so treat it as
159private local session data.
160
161## Worktrees and references
162
163Shared children use the host working directory. With `isolation: "worktree"`,
164zut prepares a detached Git worktree, captures a patch and changed-file list on
165successful completion, and never applies that patch automatically. Failed or
166interrupted worktrees are retained for inspection; an idle successful worktree
167is cleaned when its child is explicitly stopped.
168
169Logical references avoid exposing runtime paths:
170
171```text
172subagent://<id>
173subagent://<id>/history
174subagent://<id>/result
175subagent://<id>/patch
176```
177
178## Provider caching
179
180Each main and child conversation sends a stable logical session ID and a new
181turn ID per accepted prompt to the provider layer. Provider adapters decide
182whether and how to use them: OpenAI/Codex translates a supported stable session
183into its cache key and routing header, while other adapters preserve deterministic
184request input and use only cache controls their provider/model/endpoint supports.
185An OpenAI-compatible wire shape is not itself evidence that a cache extension
186or transport feature is available. Models continue through their declared
187provider transport; a transport change must not change the logical session or
188turn identity used by the provider request.

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 476

↑↓ moveenter openesc close