Frames are the envelope.
Sessions run inside a frame. Personal plus N user-defined (work, research, side projects, anything). Each frame carries its own provider, vault subtree, MCP gating, glyph, accent, and orchestrator mode.
What's in a frame
A frame is a named bundle of context that scopes every session opened against it. The full set of per-frame properties:
- glyph: single emoji shown in the header pill.
- accent: color from an eight-name palette (
rust,slate,olive,teal,plum,cream,sand,navy). - provider + model +
provider_override: per-frame billing keys and base URLs that shadow the shared pantry. - vault subtree:
notes_writeis scoped here. system_prompt_append: extra system-prompt lines appended after the base prompt.cwd_hints: auto-pick at fresh launch.- capabilities: calendar, drive, mail, whatever the frame should reach.
- MCP-server gating: the top-level
mcp_servers:list is global, but each entry's optionalframes:field restricts that server to a subset of frames. - orchestrator
mode:solo/tight/orchestrator.
On-disk layout
Every frame gets its own subtree under ~/.carlos/frames/<name>/. Research notes, shell logs, worktrees, and digests all live frame-local. The F-17 migration moves legacy paths idempotently on first boot of a newer build.
frames/ personal/ research/ deep-dive-1717948800.md routing-sketch-1717952400.md usershell/ 8f3a-2026-06-10T09:14:22Z.log worktrees/ a1b2c3/ digest/ work/ research/ incident-2026-05-1717862400.md usershell/ worktrees/ digest/ # slug format: <slug>-<unix-ts>.md # usershell logs are keyed by job id # F-17 migrated legacy ~/.carlos/research, etc., into frame-local subtrees
Cross-frame rules
Reading across frames is friction-free. Writing across frames is not. Every cross-frame write is intercepted ahead of the layered permission chain and surfaces a distinct audit reason so the trail stays legible after the fact.
| action | behavior | audit reason |
|---|---|---|
| read | notes_get / notes_search against another frame's subtree auto-approve. |
ReasonBuiltinAllow |
| write (approved) | The F-12 detector intercepts write / edit ahead of the chain and prompts the user. |
ReasonCrossFrameAllow |
| write (declined) | Same detector path, user said no. The chain never runs. | ReasonCrossFrameDeny |
The notes_write tool is hard-scoped to the active frame's vault_subtree. Cross-vault or cross-subtree writes never go through notes_write; they route through the generic write tool with full prompting.
Modes
Three orchestrator modes per frame. The mode shapes the system prompt and gates the supervisor's spawn cap.
| mode | spawn cap | shape |
|---|---|---|
solo |
0 | Single-agent only. No delegation. |
tight |
1 | At most one delegated sub-agent at a time. |
orchestrator |
5 | Up to five parallel children. |
NewPersonal defaults to orchestrator (was solo through v0.7.5). The solo default refused every Spawn, which left the chat-side /agents surface empty and the agent delegation tool unreachable from a fresh install; flipping to orchestrator matches the pre-modes behavior and lets sub-agents work out of the box. /mode solo brings the strict default back any time.
Mode shows up in two places: the supervisor's SpawnCapFor enforces 0 / 1 / 5 in-flight children, and the system prompt's Frame block tells the model how to behave under that cap (do the work yourself / one focused task at a time / delegate by default for anything beyond a single-line edit). The two layers are coupled but distinct: solo refuses every spawn even if the model asked; orchestrator never pauses for per-turn confirmation.
Spawn enforcement returns mode-specific error variants: ErrSpawnRefusedSolo when a child is requested under solo, and ErrSpawnBusyTight when a tight frame already has one in flight.
DeepMind arXiv:2512.08296 finds that multi-agent coordination nets negative once single-agent baselines exceed roughly 45% on a task class. Sequential and decision-dense work (coding, writing) degrades 39 to 70% under MAS. carlos surfaces the trade-off through mode selection rather than a per-turn overlay: pick solo for strict single-agent semantics, tight for sequential delegation, orchestrator when the parallel-fan-out shape pays.
Switching frames
Switching is first-class. The takeover switcher, slash commands, and the mode flip all rebuild the active session in place.
- Ctrl + F opens the full-screen 3×2 takeover switcher. Three columns at
innerW ≥ 100, two at≥ 70, one below. Number keys1through6jump; Ctrl + ← / → paginate. /frame listand/frame switch <name>work from the composer./mode solo|tight|orchestratorflips the active frame's mode./frame new [name]opens the new-frame wizard./whoamiechoes frame + mode + provider + model in one line.
Live mid-session swap rebuilds dispatch, sysprompt, and chatglue.Loop atomically. The transcript stays. In-process FrameUI refresh updates glyph, accent, mode, and capabilities immediately, without dropping a frame.
Sub-agent split
When sub-agents are live and chat width is at least 120 columns, the transcript splits horizontally with a right-side children panel: state, last event, elapsed, tokens, spend. Below 120, a dim fallback line appears above the footer instead. A 250 ms tick keeps the panel current while it is up.
Why a frame, not a project
A frame is not a project. It is the answer to "what should carlos consider in scope right now?" Two frames can share a working directory but write to different vault subtrees, prompt the user differently on cross-frame writes, and even use different providers. The provider_override field lets the work frame put OpenAI on a corporate billing key while personal stays on Anthropic, without touching the shared pantry.
Quick-glance properties
Provider + billing
Per-frame provider_override shadows the shared pantry with its own API key and base URL. Work pays from one budget; personal pays from another.
Vault subtree
One vault_subtree per frame. notes_write is hard-scoped to it. notes_get across subtrees is free.
MCP gating
The top-level mcp_servers: list is global; each entry's frames: field restricts that server to a subset.
cwd_hints
Path hints picked up at fresh launch, so opening carlos from ~/code/work-repo auto-selects the work frame.
Orchestrator mode
solo / tight / orchestrator. Sets the supervisor's spawn cap and reshapes the system prompt.
system_prompt_append
Extra system-prompt lines per frame. Pin house style, role rules, or escalation hints without forking the base prompt.
Related
Permissions model covers the three-layer approval chain that the cross-frame detector sits in front of. Sub-agent supervision details the spawn caps each mode enforces. The config reference documents every per-frame field; slash commands covers /frame, /mode, and /whoami.