detached 610b8db

Merge pull request #85 from bnema/fix/profile-manifest-without-auto-subagents

fix(subagents): expose profiles outside orchestrator mode
commit
610b8db92fef6086626b128a6d7e665435fc4a52
author
bnema · · 2026-08-08 14:56 UTC
committer
GitHub · · 2026-08-08 14:56 UTC
merge of
66e9275 + 46740b9 · diff against the first parent
signature
GPG UnverifiedB5690EEEBB952194 The key is unknown
6 files · +55 -37
M README.md +3 -3
@@ -391,11 +391,11 @@ Background subagents that run alongside your main session. Each one is a separat
391391
392392 **`/session export` does NOT bundle subagents.** A `.zutsession` is just the main chat transcript; per-agent state (session file, unix-socket inbox) is machine-local and doesn't round-trip through a JSONL file. To share what an agent said, copy it out of the transcript view manually.
393393
394-**Auto-subagents.** With `/settings` -> auto-subagents on, the interactive primary agent enters strict orchestrator mode and gets whichever of the canonical `subagent_spawn` and `subagent_status` tools are permitted by launch-time policy. It must delegate all implementation, debugging/testing, and code-review work to an appropriately named profile, or to a clearly described general worker when no profile fits. It must not write or edit code, make direct implementation tool calls, inspect or review code, or apply worker patches itself. It may decompose requests, select and spawn workers, check status, coordinate follow-ups, and synthesize results. Give workers self-contained tasks: shared-worktree workers edit the same working directory and need coordination, while `isolation:"worktree"` is for parallel coding in separate trees; a worktree patch must be integrated by a worker rather than applied by the primary agent. Child workers cannot recursively spawn more sub-agents in v1. The `subagent_status` tool accepts an optional `agent_id`: omit it to list visible workers, or pass a full id / unique prefix to query one without waiting for completion. It returns privacy-safe JSON metadata with the worker id, lifecycle state (`starting`, `running`, `completed`, `failed`, `cancelled`, or `detached`), underlying process/turn state, timestamps, a bounded first-line task summary, and terminal-result metadata when available; it does not return prompts, transcripts, result output, credentials, provider settings, or filesystem paths. The spawn tool returns the child id and initial state immediately; completion is a durable `turn.result` with a `subagent://<id>/result` reference. It accepts named profiles, timeout, `max_turns`, and shared/worktree isolation. Omit `max_turns` to use the supervisor policy; the default ceiling is 3 and `subagents.max_turns` changes it. Global concurrency limits apply equally to slash commands, tool calls, and batches. Completion is host-event-driven: wait for the host-injected `[auto-subagents update]`, the only completion signal. Never use `bash sleep`, `watch`, `tail -f`, polling loops, repeated `subagent_status`, or dashboard/metadata/event-log/file checks solely to wait; work on unrelated independent tasks or end/yield your turn. Legitimate waits inside user-requested commands, provider flows, extensions, or tests remain allowed. Off by default; toggle from `/settings`. When off, the permitted canonical subagent tools remain available for user-requested delegation or when an active skill workflow requires it; the primary otherwise performs work itself without the strict orchestrator contract or profile manifest.
394+**Auto-subagents.** With `/settings` -> auto-subagents on, the interactive primary agent enters strict orchestrator mode and gets whichever of the canonical `subagent_spawn` and `subagent_status` tools are permitted by launch-time policy. It must delegate all implementation, debugging/testing, and code-review work to an appropriately named profile, or to a clearly described general worker when no profile fits. It must not write or edit code, make direct implementation tool calls, inspect or review code, or apply worker patches itself. It may decompose requests, select and spawn workers, check status, coordinate follow-ups, and synthesize results. Give workers self-contained tasks: shared-worktree workers edit the same working directory and need coordination, while `isolation:"worktree"` is for parallel coding in separate trees; a worktree patch must be integrated by a worker rather than applied by the primary agent. Child workers cannot recursively spawn more sub-agents in v1. The `subagent_status` tool accepts an optional `agent_id`: omit it to list visible workers, or pass a full id / unique prefix to query one without waiting for completion. It returns privacy-safe JSON metadata with the worker id, lifecycle state (`starting`, `running`, `completed`, `failed`, `cancelled`, or `detached`), underlying process/turn state, timestamps, a bounded first-line task summary, and terminal-result metadata when available; it does not return prompts, transcripts, result output, credentials, provider settings, or filesystem paths. The spawn tool returns the child id and initial state immediately; completion is a durable `turn.result` with a `subagent://<id>/result` reference. It accepts named profiles, timeout, `max_turns`, and shared/worktree isolation. Omit `max_turns` to use the supervisor policy; the default ceiling is 3 and `subagents.max_turns` changes it. Global concurrency limits apply equally to slash commands, tool calls, and batches. Completion is host-event-driven: wait for the host-injected `[auto-subagents update]`, the only completion signal. Never use `bash sleep`, `watch`, `tail -f`, polling loops, repeated `subagent_status`, or dashboard/metadata/event-log/file checks solely to wait; work on unrelated independent tasks or end/yield your turn. Legitimate waits inside user-requested commands, provider flows, extensions, or tests remain allowed. Off by default; toggle from `/settings`. When off, the permitted canonical subagent tools and profile manifest remain available for user-requested delegation or when an active skill workflow requires it; the primary otherwise performs work itself without the strict orchestrator contract.
395395
396396 ### Named subagent profiles
397397
398-zut discovers the common markdown/frontmatter profile layout from `~/.agents/agents/*.md` by default. With auto-subagents enabled and `subagent_spawn` available, the orchestrator receives `[subagents_list]` metadata and should select the appropriately named profile for each worker when one matches; otherwise it can spawn a clearly described general worker without an `agent` field. If launch-time policy withholds `subagent_spawn`, strict orchestrator guidance remains active but profile metadata is omitted; the primary reports that delegation is unavailable instead of implementing directly. Profile bodies are applied only to the selected child. See [docs/subagents.md](docs/subagents.md) for discovery, supported fields, reasoning levels, and examples.
398+zut discovers the common markdown/frontmatter profile layout from `~/.agents/agents/*.md` by default. Whenever `subagent_spawn` is available, the primary agent receives `[subagents_list]` metadata and should select the appropriately named profile for each worker when one matches; otherwise it can spawn a clearly described general worker without an `agent` field. If launch-time policy withholds `subagent_spawn`, strict orchestrator guidance remains active but profile metadata is omitted; the primary reports that delegation is unavailable instead of implementing directly. Profile bodies are applied only to the selected child. See [docs/subagents.md](docs/subagents.md) for discovery, supported fields, reasoning levels, and examples.
399399
400400 ### `/settings`
401401
@@ -405,7 +405,7 @@ Opens a dialog with every persistent setting. `up`/`down` to navigate, `enter` o
405405 - **render images when supported** — draw screenshots / `read`-returned images inline using the terminal's image protocol, or fall back to a text placeholder. Auto-detected from `TERM_PROGRAM`; the toggle overrides the detection. The row is greyed out and forced off on terminals that don't speak any image protocol.
406406 - **terminal alerts** — emit a terminal bell when the main session stops with work that may need attention, or when an extension raises a structured alert. Enabled by default; changes apply immediately and persist as `terminal_alerts_enabled`. Terminal emulators may render the bell audibly, visually, or not at all.
407407 - **AI terminal titles** — after the first real prompt of a fresh interactive session, make one small hidden request to the active model and set the terminal title to `zut: <title>`. The title is limited to 40 Unicode characters, persisted with the session, restored on resume, and never added to the conversation. Enabled by default; disable it to avoid the extra model request. The toggle applies immediately, but title generation still waits for the first real prompt and never starts from startup context, resumed history, or slash commands. Persists as `terminal_title_enabled`.
408-- **auto-subagents** — enable strict primary-agent orchestrator mode: delegate implementation, debugging/testing, and code-review work to named or general workers; the primary agent coordinates but does not make direct implementation changes. It can spawn background sub-agents via `subagent_spawn` and query live state via `subagent_status` when those tools are permitted. If delegation is unavailable because of launch-time restrictions, the contract remains active, profile metadata is withheld, and the primary reports the limitation rather than implementing directly. Off by default. When off, the permitted canonical subagent tools remain available for user-requested delegation or when an active skill workflow requires it; the primary otherwise works directly without the strict orchestrator contract or profile manifest. The tools accept named profiles, reasoning, timeout, turn limits, and shared/worktree isolation where applicable; lifecycle and result references are persisted. Completion is host-event-driven: `[auto-subagents update]` completion updates are the only signal; do not poll or inspect dashboards, metadata, event logs, or files solely to wait. See `/subagents` and [docs/subagents.md](docs/subagents.md) for details.
408+- **auto-subagents** — enable strict primary-agent orchestrator mode: delegate implementation, debugging/testing, and code-review work to named or general workers; the primary agent coordinates but does not make direct implementation changes. It can spawn background sub-agents via `subagent_spawn` and query live state via `subagent_status` when those tools are permitted. If delegation is unavailable because of launch-time restrictions, the contract remains active, profile metadata is withheld, and the primary reports the limitation rather than implementing directly. Off by default. When off, the permitted canonical subagent tools and profile manifest remain available for user-requested delegation or when an active skill workflow requires it; the primary otherwise works directly without the strict orchestrator contract. The tools accept named profiles, reasoning, timeout, turn limits, and shared/worktree isolation where applicable; lifecycle and result references are persisted. Completion is host-event-driven: `[auto-subagents update]` completion updates are the only signal; do not poll or inspect dashboards, metadata, event logs, or files solely to wait. See `/subagents` and [docs/subagents.md](docs/subagents.md) for details.
409409 - **Ponytail coding mode** — include compact engineering guidance in each resolved system prompt; the guidance tells the model to apply it to coding, debugging, and review work rather than ordinary conversation. It favors understanding the real flow, small validated changes, reuse, and preserving safety checks. Enabled by default; changes apply to the next model call and persist as `ponytail_enabled` in `$ZUT_HOME/config.json`. It is included by interactive, print, stream, JSON, RPC, subagent, bot, SDK, and Zutfile agents.
410410 - **fast mode** — request the provider's fast tier where supported. It currently uses OpenAI's Fast service tier for OpenAI, OpenAI Responses, and OpenAI Codex models. Off by default; toggle it with `/fast` or `/settings`; changes apply on the next model call and persist as `fast_mode`. Other providers currently return an unsupported-provider error. Fast mode may cost more and depends on the selected model/account.
411411 - **lsp in main session** — enable the built-in `lsp` tool and code diagnostics for the main agent. Enabled by default; changes persist as `lsp_enabled`.
@@ -391,11 +391,11 @@ Background subagents that run alongside your main session. Each one is a separat
391 391
392 **`/session export` does NOT bundle subagents.** A `.zutsession` is just the main chat transcript; per-agent state (session file, unix-socket inbox) is machine-local and doesn't round-trip through a JSONL file. To share what an agent said, copy it out of the transcript view manually.392 **`/session export` does NOT bundle subagents.** A `.zutsession` is just the main chat transcript; per-agent state (session file, unix-socket inbox) is machine-local and doesn't round-trip through a JSONL file. To share what an agent said, copy it out of the transcript view manually.
393 393
394-**Auto-subagents.** With `/settings` -> auto-subagents on, the interactive primary agent enters strict orchestrator mode and gets whichever of the canonical `subagent_spawn` and `subagent_status` tools are permitted by launch-time policy. It must delegate all implementation, debugging/testing, and code-review work to an appropriately named profile, or to a clearly described general worker when no profile fits. It must not write or edit code, make direct implementation tool calls, inspect or review code, or apply worker patches itself. It may decompose requests, select and spawn workers, check status, coordinate follow-ups, and synthesize results. Give workers self-contained tasks: shared-worktree workers edit the same working directory and need coordination, while `isolation:"worktree"` is for parallel coding in separate trees; a worktree patch must be integrated by a worker rather than applied by the primary agent. Child workers cannot recursively spawn more sub-agents in v1. The `subagent_status` tool accepts an optional `agent_id`: omit it to list visible workers, or pass a full id / unique prefix to query one without waiting for completion. It returns privacy-safe JSON metadata with the worker id, lifecycle state (`starting`, `running`, `completed`, `failed`, `cancelled`, or `detached`), underlying process/turn state, timestamps, a bounded first-line task summary, and terminal-result metadata when available; it does not return prompts, transcripts, result output, credentials, provider settings, or filesystem paths. The spawn tool returns the child id and initial state immediately; completion is a durable `turn.result` with a `subagent://<id>/result` reference. It accepts named profiles, timeout, `max_turns`, and shared/worktree isolation. Omit `max_turns` to use the supervisor policy; the default ceiling is 3 and `subagents.max_turns` changes it. Global concurrency limits apply equally to slash commands, tool calls, and batches. Completion is host-event-driven: wait for the host-injected `[auto-subagents update]`, the only completion signal. Never use `bash sleep`, `watch`, `tail -f`, polling loops, repeated `subagent_status`, or dashboard/metadata/event-log/file checks solely to wait; work on unrelated independent tasks or end/yield your turn. Legitimate waits inside user-requested commands, provider flows, extensions, or tests remain allowed. Off by default; toggle from `/settings`. When off, the permitted canonical subagent tools remain available for user-requested delegation or when an active skill workflow requires it; the primary otherwise performs work itself without the strict orchestrator contract or profile manifest.394+**Auto-subagents.** With `/settings` -> auto-subagents on, the interactive primary agent enters strict orchestrator mode and gets whichever of the canonical `subagent_spawn` and `subagent_status` tools are permitted by launch-time policy. It must delegate all implementation, debugging/testing, and code-review work to an appropriately named profile, or to a clearly described general worker when no profile fits. It must not write or edit code, make direct implementation tool calls, inspect or review code, or apply worker patches itself. It may decompose requests, select and spawn workers, check status, coordinate follow-ups, and synthesize results. Give workers self-contained tasks: shared-worktree workers edit the same working directory and need coordination, while `isolation:"worktree"` is for parallel coding in separate trees; a worktree patch must be integrated by a worker rather than applied by the primary agent. Child workers cannot recursively spawn more sub-agents in v1. The `subagent_status` tool accepts an optional `agent_id`: omit it to list visible workers, or pass a full id / unique prefix to query one without waiting for completion. It returns privacy-safe JSON metadata with the worker id, lifecycle state (`starting`, `running`, `completed`, `failed`, `cancelled`, or `detached`), underlying process/turn state, timestamps, a bounded first-line task summary, and terminal-result metadata when available; it does not return prompts, transcripts, result output, credentials, provider settings, or filesystem paths. The spawn tool returns the child id and initial state immediately; completion is a durable `turn.result` with a `subagent://<id>/result` reference. It accepts named profiles, timeout, `max_turns`, and shared/worktree isolation. Omit `max_turns` to use the supervisor policy; the default ceiling is 3 and `subagents.max_turns` changes it. Global concurrency limits apply equally to slash commands, tool calls, and batches. Completion is host-event-driven: wait for the host-injected `[auto-subagents update]`, the only completion signal. Never use `bash sleep`, `watch`, `tail -f`, polling loops, repeated `subagent_status`, or dashboard/metadata/event-log/file checks solely to wait; work on unrelated independent tasks or end/yield your turn. Legitimate waits inside user-requested commands, provider flows, extensions, or tests remain allowed. Off by default; toggle from `/settings`. When off, the permitted canonical subagent tools and profile manifest remain available for user-requested delegation or when an active skill workflow requires it; the primary otherwise performs work itself without the strict orchestrator contract.
395 395
396 ### Named subagent profiles396 ### Named subagent profiles
397 397
398-zut discovers the common markdown/frontmatter profile layout from `~/.agents/agents/*.md` by default. With auto-subagents enabled and `subagent_spawn` available, the orchestrator receives `[subagents_list]` metadata and should select the appropriately named profile for each worker when one matches; otherwise it can spawn a clearly described general worker without an `agent` field. If launch-time policy withholds `subagent_spawn`, strict orchestrator guidance remains active but profile metadata is omitted; the primary reports that delegation is unavailable instead of implementing directly. Profile bodies are applied only to the selected child. See [docs/subagents.md](docs/subagents.md) for discovery, supported fields, reasoning levels, and examples.398+zut discovers the common markdown/frontmatter profile layout from `~/.agents/agents/*.md` by default. Whenever `subagent_spawn` is available, the primary agent receives `[subagents_list]` metadata and should select the appropriately named profile for each worker when one matches; otherwise it can spawn a clearly described general worker without an `agent` field. If launch-time policy withholds `subagent_spawn`, strict orchestrator guidance remains active but profile metadata is omitted; the primary reports that delegation is unavailable instead of implementing directly. Profile bodies are applied only to the selected child. See [docs/subagents.md](docs/subagents.md) for discovery, supported fields, reasoning levels, and examples.
399 399
400 ### `/settings`400 ### `/settings`
401 401
@@ -405,7 +405,7 @@ Opens a dialog with every persistent setting. `up`/`down` to navigate, `enter` o
405 - **render images when supported** — draw screenshots / `read`-returned images inline using the terminal's image protocol, or fall back to a text placeholder. Auto-detected from `TERM_PROGRAM`; the toggle overrides the detection. The row is greyed out and forced off on terminals that don't speak any image protocol.405 - **render images when supported** — draw screenshots / `read`-returned images inline using the terminal's image protocol, or fall back to a text placeholder. Auto-detected from `TERM_PROGRAM`; the toggle overrides the detection. The row is greyed out and forced off on terminals that don't speak any image protocol.
406 - **terminal alerts** — emit a terminal bell when the main session stops with work that may need attention, or when an extension raises a structured alert. Enabled by default; changes apply immediately and persist as `terminal_alerts_enabled`. Terminal emulators may render the bell audibly, visually, or not at all.406 - **terminal alerts** — emit a terminal bell when the main session stops with work that may need attention, or when an extension raises a structured alert. Enabled by default; changes apply immediately and persist as `terminal_alerts_enabled`. Terminal emulators may render the bell audibly, visually, or not at all.
407 - **AI terminal titles** — after the first real prompt of a fresh interactive session, make one small hidden request to the active model and set the terminal title to `zut: <title>`. The title is limited to 40 Unicode characters, persisted with the session, restored on resume, and never added to the conversation. Enabled by default; disable it to avoid the extra model request. The toggle applies immediately, but title generation still waits for the first real prompt and never starts from startup context, resumed history, or slash commands. Persists as `terminal_title_enabled`.407 - **AI terminal titles** — after the first real prompt of a fresh interactive session, make one small hidden request to the active model and set the terminal title to `zut: <title>`. The title is limited to 40 Unicode characters, persisted with the session, restored on resume, and never added to the conversation. Enabled by default; disable it to avoid the extra model request. The toggle applies immediately, but title generation still waits for the first real prompt and never starts from startup context, resumed history, or slash commands. Persists as `terminal_title_enabled`.
408-- **auto-subagents** — enable strict primary-agent orchestrator mode: delegate implementation, debugging/testing, and code-review work to named or general workers; the primary agent coordinates but does not make direct implementation changes. It can spawn background sub-agents via `subagent_spawn` and query live state via `subagent_status` when those tools are permitted. If delegation is unavailable because of launch-time restrictions, the contract remains active, profile metadata is withheld, and the primary reports the limitation rather than implementing directly. Off by default. When off, the permitted canonical subagent tools remain available for user-requested delegation or when an active skill workflow requires it; the primary otherwise works directly without the strict orchestrator contract or profile manifest. The tools accept named profiles, reasoning, timeout, turn limits, and shared/worktree isolation where applicable; lifecycle and result references are persisted. Completion is host-event-driven: `[auto-subagents update]` completion updates are the only signal; do not poll or inspect dashboards, metadata, event logs, or files solely to wait. See `/subagents` and [docs/subagents.md](docs/subagents.md) for details.408+- **auto-subagents** — enable strict primary-agent orchestrator mode: delegate implementation, debugging/testing, and code-review work to named or general workers; the primary agent coordinates but does not make direct implementation changes. It can spawn background sub-agents via `subagent_spawn` and query live state via `subagent_status` when those tools are permitted. If delegation is unavailable because of launch-time restrictions, the contract remains active, profile metadata is withheld, and the primary reports the limitation rather than implementing directly. Off by default. When off, the permitted canonical subagent tools and profile manifest remain available for user-requested delegation or when an active skill workflow requires it; the primary otherwise works directly without the strict orchestrator contract. The tools accept named profiles, reasoning, timeout, turn limits, and shared/worktree isolation where applicable; lifecycle and result references are persisted. Completion is host-event-driven: `[auto-subagents update]` completion updates are the only signal; do not poll or inspect dashboards, metadata, event logs, or files solely to wait. See `/subagents` and [docs/subagents.md](docs/subagents.md) for details.
409 - **Ponytail coding mode** — include compact engineering guidance in each resolved system prompt; the guidance tells the model to apply it to coding, debugging, and review work rather than ordinary conversation. It favors understanding the real flow, small validated changes, reuse, and preserving safety checks. Enabled by default; changes apply to the next model call and persist as `ponytail_enabled` in `$ZUT_HOME/config.json`. It is included by interactive, print, stream, JSON, RPC, subagent, bot, SDK, and Zutfile agents.409 - **Ponytail coding mode** — include compact engineering guidance in each resolved system prompt; the guidance tells the model to apply it to coding, debugging, and review work rather than ordinary conversation. It favors understanding the real flow, small validated changes, reuse, and preserving safety checks. Enabled by default; changes apply to the next model call and persist as `ponytail_enabled` in `$ZUT_HOME/config.json`. It is included by interactive, print, stream, JSON, RPC, subagent, bot, SDK, and Zutfile agents.
410 - **fast mode** — request the provider's fast tier where supported. It currently uses OpenAI's Fast service tier for OpenAI, OpenAI Responses, and OpenAI Codex models. Off by default; toggle it with `/fast` or `/settings`; changes apply on the next model call and persist as `fast_mode`. Other providers currently return an unsupported-provider error. Fast mode may cost more and depends on the selected model/account.410 - **fast mode** — request the provider's fast tier where supported. It currently uses OpenAI's Fast service tier for OpenAI, OpenAI Responses, and OpenAI Codex models. Off by default; toggle it with `/fast` or `/settings`; changes apply on the next model call and persist as `fast_mode`. Other providers currently return an unsupported-provider error. Fast mode may cost more and depends on the selected model/account.
411 - **lsp in main session** — enable the built-in `lsp` tool and code diagnostics for the main agent. Enabled by default; changes persist as `lsp_enabled`.411 - **lsp in main session** — enable the built-in `lsp` tool and code diagnostics for the main agent. Enabled by default; changes persist as `lsp_enabled`.
M docs/subagents.md +2 -2
@@ -56,9 +56,9 @@ Other frontmatter from another agent host is ignored when zut does not have an e
5656
5757 When **auto-subagents** is enabled in `/settings`, the interactive primary agent runs in strict orchestrator mode. It must delegate all implementation, debugging/testing, and code-review work to an appropriately named profile, or to a clearly described general worker when no profile fits. The primary agent must not write or edit code, make direct implementation tool calls, inspect or review code, or apply worker patches. It may decompose requests, select and spawn workers, check status, coordinate follow-ups, and synthesize their results.
5858
59-When auto-subagents is disabled, the canonical subagent tools remain available subject to launch-time policy. The primary may use them when the user requests delegation or an active skill workflow requires delegation. It continues to perform work itself otherwise and does not receive the profile manifest or strict orchestrator contract. The setting changes prompting, not tool availability.
59+When auto-subagents is disabled, the canonical subagent tools remain available subject to launch-time policy. The primary may use them when the user requests delegation or an active skill workflow requires delegation. It continues to perform work itself otherwise and does not receive the strict orchestrator contract. The setting changes orchestration prompting, not tool or profile availability.
6060
61-When `subagent_spawn` is available, the orchestrator receives a compact `[subagents_list]` section in its system prompt and should select the profile whose description best matches each worker task. If launch-time policy withholds `subagent_spawn`, strict orchestrator guidance remains active, profile metadata is omitted, and the primary must report that delegation is unavailable rather than implementing directly. If no profile fits when spawning is available, omit `agent` to use a general worker:
61+When `subagent_spawn` is available, the primary agent receives a compact `[subagents_list]` section in its system prompt and should select the profile whose description best matches each worker task. If launch-time policy withholds `subagent_spawn`, strict orchestrator guidance remains active, profile metadata is omitted, and the primary must report that delegation is unavailable rather than implementing directly. If no profile fits when spawning is available, omit `agent` to use a general worker:
6262
6363 ```json
6464 {
@@ -56,9 +56,9 @@ Other frontmatter from another agent host is ignored when zut does not have an e
56 56
57 When **auto-subagents** is enabled in `/settings`, the interactive primary agent runs in strict orchestrator mode. It must delegate all implementation, debugging/testing, and code-review work to an appropriately named profile, or to a clearly described general worker when no profile fits. The primary agent must not write or edit code, make direct implementation tool calls, inspect or review code, or apply worker patches. It may decompose requests, select and spawn workers, check status, coordinate follow-ups, and synthesize their results.57 When **auto-subagents** is enabled in `/settings`, the interactive primary agent runs in strict orchestrator mode. It must delegate all implementation, debugging/testing, and code-review work to an appropriately named profile, or to a clearly described general worker when no profile fits. The primary agent must not write or edit code, make direct implementation tool calls, inspect or review code, or apply worker patches. It may decompose requests, select and spawn workers, check status, coordinate follow-ups, and synthesize their results.
58 58
59-When auto-subagents is disabled, the canonical subagent tools remain available subject to launch-time policy. The primary may use them when the user requests delegation or an active skill workflow requires delegation. It continues to perform work itself otherwise and does not receive the profile manifest or strict orchestrator contract. The setting changes prompting, not tool availability.59+When auto-subagents is disabled, the canonical subagent tools remain available subject to launch-time policy. The primary may use them when the user requests delegation or an active skill workflow requires delegation. It continues to perform work itself otherwise and does not receive the strict orchestrator contract. The setting changes orchestration prompting, not tool or profile availability.
60 60
61-When `subagent_spawn` is available, the orchestrator receives a compact `[subagents_list]` section in its system prompt and should select the profile whose description best matches each worker task. If launch-time policy withholds `subagent_spawn`, strict orchestrator guidance remains active, profile metadata is omitted, and the primary must report that delegation is unavailable rather than implementing directly. If no profile fits when spawning is available, omit `agent` to use a general worker:61+When `subagent_spawn` is available, the primary agent receives a compact `[subagents_list]` section in its system prompt and should select the profile whose description best matches each worker task. If launch-time policy withholds `subagent_spawn`, strict orchestrator guidance remains active, profile metadata is omitted, and the primary must report that delegation is unavailable rather than implementing directly. If no profile fits when spawning is available, omit `agent` to use a general worker:
62 62
63 ```json63 ```json
64 {64 {
M packages/agent/build.go +9 -8
@@ -857,20 +857,21 @@ func Resolve(args Args, requireCred bool) (Resolved, error) {
857857 append_ = append(append_, skillAddendum)
858858 }
859859 interactiveMode := args.Mode == "" || args.Mode == ModeInteractive
860- if selectedProfile == nil && interactiveMode && cfg.AutoSubagentsEnabled != nil && *cfg.AutoSubagentsEnabled {
861- if autoSubagentsToolAllowed(args) {
862- homeDir, _ := os.UserHomeDir()
863- profiles, _ := subagents.Discover(args.CWD, homeDir)
864- if subagentsAddendum := subagents.SystemPromptAddendum(profiles); subagentsAddendum != "" {
865- append_ = append(append_, subagentsAddendum)
866- }
860+ primaryInteractive := selectedProfile == nil && interactiveMode
861+ if primaryInteractive && autoSubagentsToolAllowed(args) {
862+ homeDir, _ := os.UserHomeDir()
863+ profiles, _ := subagents.Discover(args.CWD, homeDir)
864+ if subagentsAddendum := subagents.SystemPromptAddendum(profiles); subagentsAddendum != "" {
865+ append_ = append(append_, subagentsAddendum)
867866 }
867+ }
868+ if primaryInteractive && cfg.AutoSubagentsEnabled != nil && *cfg.AutoSubagentsEnabled {
868869 append_ = append(append_, AutoSubagentsSystemAddendumFor(
869870 autoSubagentsToolAllowed(args),
870871 autoSubagentsStopToolAllowed(args),
871872 autoSubagentsResumeToolAllowed(args),
872873 ))
873- } else if selectedProfile == nil && interactiveMode && autoSubagentsAnyToolAllowed(args) {
874+ } else if primaryInteractive && autoSubagentsAnyToolAllowed(args) {
874875 append_ = append(append_, OnDemandSubagentsSystemAddendum)
875876 }
876877 if selectedProfile != nil && selectedProfile.SystemPromptMode != "replace" && selectedProfile.SystemPrompt != "" {
@@ -857,20 +857,21 @@ func Resolve(args Args, requireCred bool) (Resolved, error) {
857 append_ = append(append_, skillAddendum)857 append_ = append(append_, skillAddendum)
858 }858 }
859 interactiveMode := args.Mode == "" || args.Mode == ModeInteractive859 interactiveMode := args.Mode == "" || args.Mode == ModeInteractive
860- if selectedProfile == nil && interactiveMode && cfg.AutoSubagentsEnabled != nil && *cfg.AutoSubagentsEnabled {860+ primaryInteractive := selectedProfile == nil && interactiveMode
861- if autoSubagentsToolAllowed(args) {861+ if primaryInteractive && autoSubagentsToolAllowed(args) {
862- homeDir, _ := os.UserHomeDir()862+ homeDir, _ := os.UserHomeDir()
863- profiles, _ := subagents.Discover(args.CWD, homeDir)863+ profiles, _ := subagents.Discover(args.CWD, homeDir)
864- if subagentsAddendum := subagents.SystemPromptAddendum(profiles); subagentsAddendum != "" {864+ if subagentsAddendum := subagents.SystemPromptAddendum(profiles); subagentsAddendum != "" {
865- append_ = append(append_, subagentsAddendum)865+ append_ = append(append_, subagentsAddendum)
866- }
867 }866 }
867+ }
868+ if primaryInteractive && cfg.AutoSubagentsEnabled != nil && *cfg.AutoSubagentsEnabled {
868 append_ = append(append_, AutoSubagentsSystemAddendumFor(869 append_ = append(append_, AutoSubagentsSystemAddendumFor(
869 autoSubagentsToolAllowed(args),870 autoSubagentsToolAllowed(args),
870 autoSubagentsStopToolAllowed(args),871 autoSubagentsStopToolAllowed(args),
871 autoSubagentsResumeToolAllowed(args),872 autoSubagentsResumeToolAllowed(args),
872 ))873 ))
873- } else if selectedProfile == nil && interactiveMode && autoSubagentsAnyToolAllowed(args) {874+ } else if primaryInteractive && autoSubagentsAnyToolAllowed(args) {
874 append_ = append(append_, OnDemandSubagentsSystemAddendum)875 append_ = append(append_, OnDemandSubagentsSystemAddendum)
875 }876 }
876 if selectedProfile != nil && selectedProfile.SystemPromptMode != "replace" && selectedProfile.SystemPrompt != "" {877 if selectedProfile != nil && selectedProfile.SystemPromptMode != "replace" && selectedProfile.SystemPrompt != "" {
M packages/agent/build_test.go +15 -3
@@ -473,20 +473,29 @@ func TestAutoSubagentsSystemAddendumRequiresHostCompletionUpdate(t *testing.T) {
473473 }
474474 }
475475
476-func TestResolveOmitsAutoSubagentsOrchestratorContractWhenDisabled(t *testing.T) {
476+func TestResolveKeepsNamedSubagentsListWithoutOrchestratorContractWhenDisabled(t *testing.T) {
477477 root := t.TempDir()
478478 home := filepath.Join(root, "home")
479479 zutHome := filepath.Join(root, "zut-home")
480480 project := filepath.Join(root, "repo")
481+ profilesDir := filepath.Join(home, ".agents", "agents")
482+ if err := os.MkdirAll(profilesDir, 0o755); err != nil {
483+ t.Fatal(err)
484+ }
481485 if err := os.MkdirAll(project, 0o755); err != nil {
482486 t.Fatal(err)
483487 }
484488 t.Setenv("HOME", home)
485489 t.Setenv("ZUT_HOME", zutHome)
490+ t.Setenv("ZUT_AGENT_PROFILES", profilesDir)
486491 disabled := false
487492 if err := SaveConfig(Config{Provider: "openai", Model: "gpt-5", AutoSubagentsEnabled: &disabled}); err != nil {
488493 t.Fatal(err)
489494 }
495+ profile := "---\nname: reviewer\ndescription: Read-only code reviewer\n---\nReview without editing.\n"
496+ if err := os.WriteFile(filepath.Join(profilesDir, "reviewer.md"), []byte(profile), 0o600); err != nil {
497+ t.Fatal(err)
498+ }
490499
491500 r, err := Resolve(Args{CWD: project}, false)
492501 if err != nil {
@@ -495,18 +504,21 @@ func TestResolveOmitsAutoSubagentsOrchestratorContractWhenDisabled(t *testing.T)
495504 for _, unwanted := range []string{
496505 AutoSubagentsSystemAddendum,
497506 "primary-agent orchestrator",
498- "[subagents_list]",
499507 } {
500508 if strings.Contains(r.SystemPrompt, unwanted) {
501509 t.Fatalf("disabled system prompt contains auto-subagents contract %q:\n%s", unwanted, r.SystemPrompt)
502510 }
503511 }
504512 for _, required := range []string{
513+ "[subagents_list]",
514+ "reviewer",
515+ "Read-only code reviewer",
516+ "[/subagents_list]",
505517 "user asks you to delegate",
506518 "active skill workflow requires delegation",
507519 } {
508520 if !strings.Contains(r.SystemPrompt, required) {
509- t.Fatalf("disabled system prompt omits permitted delegation path %q:\n%s", required, r.SystemPrompt)
521+ t.Fatalf("disabled system prompt omits available delegation context %q:\n%s", required, r.SystemPrompt)
510522 }
511523 }
512524 }
@@ -473,20 +473,29 @@ func TestAutoSubagentsSystemAddendumRequiresHostCompletionUpdate(t *testing.T) {
473 }473 }
474 }474 }
475 475
476-func TestResolveOmitsAutoSubagentsOrchestratorContractWhenDisabled(t *testing.T) {476+func TestResolveKeepsNamedSubagentsListWithoutOrchestratorContractWhenDisabled(t *testing.T) {
477 root := t.TempDir()477 root := t.TempDir()
478 home := filepath.Join(root, "home")478 home := filepath.Join(root, "home")
479 zutHome := filepath.Join(root, "zut-home")479 zutHome := filepath.Join(root, "zut-home")
480 project := filepath.Join(root, "repo")480 project := filepath.Join(root, "repo")
481+ profilesDir := filepath.Join(home, ".agents", "agents")
482+ if err := os.MkdirAll(profilesDir, 0o755); err != nil {
483+ t.Fatal(err)
484+ }
481 if err := os.MkdirAll(project, 0o755); err != nil {485 if err := os.MkdirAll(project, 0o755); err != nil {
482 t.Fatal(err)486 t.Fatal(err)
483 }487 }
484 t.Setenv("HOME", home)488 t.Setenv("HOME", home)
485 t.Setenv("ZUT_HOME", zutHome)489 t.Setenv("ZUT_HOME", zutHome)
490+ t.Setenv("ZUT_AGENT_PROFILES", profilesDir)
486 disabled := false491 disabled := false
487 if err := SaveConfig(Config{Provider: "openai", Model: "gpt-5", AutoSubagentsEnabled: &disabled}); err != nil {492 if err := SaveConfig(Config{Provider: "openai", Model: "gpt-5", AutoSubagentsEnabled: &disabled}); err != nil {
488 t.Fatal(err)493 t.Fatal(err)
489 }494 }
495+ profile := "---\nname: reviewer\ndescription: Read-only code reviewer\n---\nReview without editing.\n"
496+ if err := os.WriteFile(filepath.Join(profilesDir, "reviewer.md"), []byte(profile), 0o600); err != nil {
497+ t.Fatal(err)
498+ }
490 499
491 r, err := Resolve(Args{CWD: project}, false)500 r, err := Resolve(Args{CWD: project}, false)
492 if err != nil {501 if err != nil {
@@ -495,18 +504,21 @@ func TestResolveOmitsAutoSubagentsOrchestratorContractWhenDisabled(t *testing.T)
495 for _, unwanted := range []string{504 for _, unwanted := range []string{
496 AutoSubagentsSystemAddendum,505 AutoSubagentsSystemAddendum,
497 "primary-agent orchestrator",506 "primary-agent orchestrator",
498- "[subagents_list]",
499 } {507 } {
500 if strings.Contains(r.SystemPrompt, unwanted) {508 if strings.Contains(r.SystemPrompt, unwanted) {
501 t.Fatalf("disabled system prompt contains auto-subagents contract %q:\n%s", unwanted, r.SystemPrompt)509 t.Fatalf("disabled system prompt contains auto-subagents contract %q:\n%s", unwanted, r.SystemPrompt)
502 }510 }
503 }511 }
504 for _, required := range []string{512 for _, required := range []string{
513+ "[subagents_list]",
514+ "reviewer",
515+ "Read-only code reviewer",
516+ "[/subagents_list]",
505 "user asks you to delegate",517 "user asks you to delegate",
506 "active skill workflow requires delegation",518 "active skill workflow requires delegation",
507 } {519 } {
508 if !strings.Contains(r.SystemPrompt, required) {520 if !strings.Contains(r.SystemPrompt, required) {
509- t.Fatalf("disabled system prompt omits permitted delegation path %q:\n%s", required, r.SystemPrompt)521+ t.Fatalf("disabled system prompt omits available delegation context %q:\n%s", required, r.SystemPrompt)
510 }522 }
511 }523 }
512 }524 }
M packages/agent/modes/auto_subagents_test.go +9 -5
@@ -15,7 +15,7 @@ import (
1515
1616 const autoSubagentsTestTimeout = 10 * time.Second
1717
18-func TestAutoSubagentsSystemPromptTogglesProfileManifestWithDelegationGuidance(t *testing.T) {
18+func TestAutoSubagentsSystemPromptKeepsProfileManifestWhileTogglingDelegationGuidance(t *testing.T) {
1919 const onDemand = "delegate only on an explicit user request"
2020 iv := &Interactive{
2121 agent: &core.Agent{System: "base system"},
@@ -38,8 +38,11 @@ func TestAutoSubagentsSystemPromptTogglesProfileManifestWithDelegationGuidance(t
3838 }
3939
4040 iv.applyAutoSubagentsSystemPrompt(false)
41- if strings.Contains(iv.agent.System, "[subagents_list]") || strings.Contains(iv.agent.System, "auto-subagents guidance") {
42- t.Fatalf("disabled system prompt retained subagent blocks: %q", iv.agent.System)
41+ if !strings.Contains(iv.agent.System, "[subagents_list]") {
42+ t.Fatalf("disabled system prompt omitted profile manifest: %q", iv.agent.System)
43+ }
44+ if strings.Contains(iv.agent.System, "auto-subagents guidance") {
45+ t.Fatalf("disabled system prompt retained orchestrator guidance: %q", iv.agent.System)
4346 }
4447 if !strings.Contains(iv.agent.System, onDemand) {
4548 t.Fatalf("disabled system prompt omitted on-demand delegation guidance: %q", iv.agent.System)
@@ -64,8 +67,9 @@ func TestAutoSubagentsTogglePreservesMatchingBasePromptBlocks(t *testing.T) {
6467 t.Fatalf("enabling should append owned duplicate blocks: %q", iv.agent.System)
6568 }
6669 iv.applyAutoSubagentsSystemPrompt(false)
67- if got := strings.TrimSpace(iv.agent.System); got != base {
68- t.Fatalf("disabling changed matching base prompt: %q; want %q", got, base)
70+ want := base + "\n\n" + manifest
71+ if got := strings.TrimSpace(iv.agent.System); got != want {
72+ t.Fatalf("disabling changed matching base prompt blocks: %q; want %q", got, want)
6973 }
7074 }
7175
@@ -15,7 +15,7 @@ import (
15 15
16 const autoSubagentsTestTimeout = 10 * time.Second16 const autoSubagentsTestTimeout = 10 * time.Second
17 17
18-func TestAutoSubagentsSystemPromptTogglesProfileManifestWithDelegationGuidance(t *testing.T) {18+func TestAutoSubagentsSystemPromptKeepsProfileManifestWhileTogglingDelegationGuidance(t *testing.T) {
19 const onDemand = "delegate only on an explicit user request"19 const onDemand = "delegate only on an explicit user request"
20 iv := &Interactive{20 iv := &Interactive{
21 agent: &core.Agent{System: "base system"},21 agent: &core.Agent{System: "base system"},
@@ -38,8 +38,11 @@ func TestAutoSubagentsSystemPromptTogglesProfileManifestWithDelegationGuidance(t
38 }38 }
39 39
40 iv.applyAutoSubagentsSystemPrompt(false)40 iv.applyAutoSubagentsSystemPrompt(false)
41- if strings.Contains(iv.agent.System, "[subagents_list]") || strings.Contains(iv.agent.System, "auto-subagents guidance") {41+ if !strings.Contains(iv.agent.System, "[subagents_list]") {
42- t.Fatalf("disabled system prompt retained subagent blocks: %q", iv.agent.System)42+ t.Fatalf("disabled system prompt omitted profile manifest: %q", iv.agent.System)
43+ }
44+ if strings.Contains(iv.agent.System, "auto-subagents guidance") {
45+ t.Fatalf("disabled system prompt retained orchestrator guidance: %q", iv.agent.System)
43 }46 }
44 if !strings.Contains(iv.agent.System, onDemand) {47 if !strings.Contains(iv.agent.System, onDemand) {
45 t.Fatalf("disabled system prompt omitted on-demand delegation guidance: %q", iv.agent.System)48 t.Fatalf("disabled system prompt omitted on-demand delegation guidance: %q", iv.agent.System)
@@ -64,8 +67,9 @@ func TestAutoSubagentsTogglePreservesMatchingBasePromptBlocks(t *testing.T) {
64 t.Fatalf("enabling should append owned duplicate blocks: %q", iv.agent.System)67 t.Fatalf("enabling should append owned duplicate blocks: %q", iv.agent.System)
65 }68 }
66 iv.applyAutoSubagentsSystemPrompt(false)69 iv.applyAutoSubagentsSystemPrompt(false)
67- if got := strings.TrimSpace(iv.agent.System); got != base {70+ want := base + "\n\n" + manifest
68- t.Fatalf("disabling changed matching base prompt: %q; want %q", got, base)71+ if got := strings.TrimSpace(iv.agent.System); got != want {
72+ t.Fatalf("disabling changed matching base prompt blocks: %q; want %q", got, want)
69 }73 }
70 }74 }
71 75
M packages/agent/modes/interactive.go +17 -16
@@ -189,7 +189,7 @@ type InteractiveConfig struct {
189189 OnDemandSubagentsSystemAddendum string
190190
191191 // SubagentsSystemAddendum is the metadata-only [subagents_list]
192- // block that is added or removed together with auto-subagents.
192+ // block available whenever the primary agent can spawn subagents.
193193 SubagentsSystemAddendum string
194194 SettingsStore SettingsStore
195195
@@ -8856,25 +8856,26 @@ func truncateForSummary(s string, n int) string {
88568856 return s[:n-3] + "..."
88578857 }
88588858
8859-// autoSubagentsAddenda returns the prompt blocks owned by the auto-subagents
8860-// setting, in the same order Resolve appends them to a new agent.
8859+// autoSubagentsAddenda returns the prompt blocks owned by subagent prompting,
8860+// in the same order Resolve appends them to a new agent. The profile manifest
8861+// is independent of strict orchestration and remains available in on-demand
8862+// mode whenever the primary agent can spawn a worker.
88618863 func autoSubagentsAddenda(cfg InteractiveConfig, orchestrating bool) []string {
8862- if !orchestrating {
8863- if cfg.Supervisor == nil || !autoSubagentsAnyToolAllowedConfig(cfg) {
8864- return nil
8865- }
8866- if addendum := strings.TrimSpace(cfg.OnDemandSubagentsSystemAddendum); addendum != "" {
8867- return []string{addendum}
8868- }
8869- return nil
8870- }
8871-
88728864 addenda := make([]string, 0, 2)
88738865 if cfg.Supervisor != nil && autoSubagentsToolAllowedConfig(cfg) {
88748866 if addendum := strings.TrimSpace(cfg.SubagentsSystemAddendum); addendum != "" {
88758867 addenda = append(addenda, addendum)
88768868 }
88778869 }
8870+ if !orchestrating {
8871+ if cfg.Supervisor != nil && autoSubagentsAnyToolAllowedConfig(cfg) {
8872+ if addendum := strings.TrimSpace(cfg.OnDemandSubagentsSystemAddendum); addendum != "" {
8873+ addenda = append(addenda, addendum)
8874+ }
8875+ }
8876+ return addenda
8877+ }
8878+
88788879 if addendum := strings.TrimSpace(cfg.AutoSubagentsSystemAddendum); addendum != "" {
88798880 addenda = append(addenda, addendum)
88808881 }
@@ -8892,9 +8893,9 @@ func removeLastAutoSubagentsAddendum(system, addendum string) (string, bool) {
88928893 return system[:idx] + system[idx+len(addendum):], true
88938894 }
88948895
8895-// applyAutoSubagentsSystemPrompt swaps the prompt blocks owned by the
8896-// auto-subagents setting on the running agent. The profile manifest belongs
8897-// only to strict orchestration; disabled mode keeps on-demand guidance.
8896+// applyAutoSubagentsSystemPrompt swaps the prompt blocks owned by subagent
8897+// prompting on the running agent. Toggling strict orchestration changes the
8898+// delegation guidance while retaining the profile manifest when usable.
88988899 func (i *Interactive) applyAutoSubagentsSystemPrompt(orchestrating bool) {
88998900 // i.mu is sufficient here: this path updates the existing agent's system
89008901 // prompt and managed addenda in place; it does not replace the agent or
@@ -189,7 +189,7 @@ type InteractiveConfig struct {
189 OnDemandSubagentsSystemAddendum string189 OnDemandSubagentsSystemAddendum string
190 190
191 // SubagentsSystemAddendum is the metadata-only [subagents_list]191 // SubagentsSystemAddendum is the metadata-only [subagents_list]
192- // block that is added or removed together with auto-subagents.192+ // block available whenever the primary agent can spawn subagents.
193 SubagentsSystemAddendum string193 SubagentsSystemAddendum string
194 SettingsStore SettingsStore194 SettingsStore SettingsStore
195 195
@@ -8856,25 +8856,26 @@ func truncateForSummary(s string, n int) string {
8856 return s[:n-3] + "..."8856 return s[:n-3] + "..."
8857 }8857 }
8858 8858
8859-// autoSubagentsAddenda returns the prompt blocks owned by the auto-subagents8859+// autoSubagentsAddenda returns the prompt blocks owned by subagent prompting,
8860-// setting, in the same order Resolve appends them to a new agent.8860+// in the same order Resolve appends them to a new agent. The profile manifest
8861+// is independent of strict orchestration and remains available in on-demand
8862+// mode whenever the primary agent can spawn a worker.
8861 func autoSubagentsAddenda(cfg InteractiveConfig, orchestrating bool) []string {8863 func autoSubagentsAddenda(cfg InteractiveConfig, orchestrating bool) []string {
8862- if !orchestrating {
8863- if cfg.Supervisor == nil || !autoSubagentsAnyToolAllowedConfig(cfg) {
8864- return nil
8865- }
8866- if addendum := strings.TrimSpace(cfg.OnDemandSubagentsSystemAddendum); addendum != "" {
8867- return []string{addendum}
8868- }
8869- return nil
8870- }
8871-
8872 addenda := make([]string, 0, 2)8864 addenda := make([]string, 0, 2)
8873 if cfg.Supervisor != nil && autoSubagentsToolAllowedConfig(cfg) {8865 if cfg.Supervisor != nil && autoSubagentsToolAllowedConfig(cfg) {
8874 if addendum := strings.TrimSpace(cfg.SubagentsSystemAddendum); addendum != "" {8866 if addendum := strings.TrimSpace(cfg.SubagentsSystemAddendum); addendum != "" {
8875 addenda = append(addenda, addendum)8867 addenda = append(addenda, addendum)
8876 }8868 }
8877 }8869 }
8870+ if !orchestrating {
8871+ if cfg.Supervisor != nil && autoSubagentsAnyToolAllowedConfig(cfg) {
8872+ if addendum := strings.TrimSpace(cfg.OnDemandSubagentsSystemAddendum); addendum != "" {
8873+ addenda = append(addenda, addendum)
8874+ }
8875+ }
8876+ return addenda
8877+ }
8878+
8878 if addendum := strings.TrimSpace(cfg.AutoSubagentsSystemAddendum); addendum != "" {8879 if addendum := strings.TrimSpace(cfg.AutoSubagentsSystemAddendum); addendum != "" {
8879 addenda = append(addenda, addendum)8880 addenda = append(addenda, addendum)
8880 }8881 }
@@ -8892,9 +8893,9 @@ func removeLastAutoSubagentsAddendum(system, addendum string) (string, bool) {
8892 return system[:idx] + system[idx+len(addendum):], true8893 return system[:idx] + system[idx+len(addendum):], true
8893 }8894 }
8894 8895
8895-// applyAutoSubagentsSystemPrompt swaps the prompt blocks owned by the8896+// applyAutoSubagentsSystemPrompt swaps the prompt blocks owned by subagent
8896-// auto-subagents setting on the running agent. The profile manifest belongs8897+// prompting on the running agent. Toggling strict orchestration changes the
8897-// only to strict orchestration; disabled mode keeps on-demand guidance.8898+// delegation guidance while retaining the profile manifest when usable.
8898 func (i *Interactive) applyAutoSubagentsSystemPrompt(orchestrating bool) {8899 func (i *Interactive) applyAutoSubagentsSystemPrompt(orchestrating bool) {
8899 // i.mu is sufficient here: this path updates the existing agent's system8900 // i.mu is sufficient here: this path updates the existing agent's system
8900 // prompt and managed addenda in place; it does not replace the agent or8901 // prompt and managed addenda in place; it does not replace the agent or

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