Skip to content

Deep Terminal

Persistent shell sessions that survive across multiple tool calls. Unlike one-shot commands, deep terminal sessions retain state — env vars, working directory, and shell history persist for the session’s lifetime.

graph TB A[Agent calls deep_terminal] --> B{Action?} B -->|start| C[Spawn child process<br/>bash / PowerShell] B -->|execute| D[Validate command<br/>permission scope → blocked patterns<br/>→ security.json → approval gate] B -->|read| E[Read from<br/>CircularBuffer 2000 chunks] B -->|terminate| F[Kill + cleanup] D -->|pass| G[Write to stdin] D -->|blocked| H[Reject with error] D -->|needs approval| I[Modal prompt] G --> J[Output → CircularBuffer]

Start:

deep_terminal: start session_id="build" shell="/bin/bash"

Spawns a child process in workspace root with TERM=xterm-256color. Defaults to /bin/bash on Unix, powershell.exe on Windows. Override via shell.

Execute:

deep_terminal: execute session_id="build" command="npm run build"

Runs through 4 validation layers:

  1. Permission scope — restricted blocks all commands.
  2. Hard-blocked patterns (below).
  3. .codebuddy/security.json external policy.
  4. Approval gate — deletion commands prompt the user.

Read:

deep_terminal: read session_id="build"

Returns new output since the last read. Circular buffer of 2000 chunks; oldest overwrites when full.

Terminate:

deep_terminal: terminate session_id="build"

Kills child process, removes session.

Hard-blocked in all profiles: catastrophic operations — whole-disk wipes and raw-device writes, fork bombs, piping remote content into a shell, and credential-exfiltration patterns — are refused regardless of profile. The full pattern set is intentionally not published.

Approval-required: destructive filesystem commands (deletions and recursive removals) prompt for explicit approval before running.

Extending patterns at runtime:

deepTerminal.addBlockedPatterns([/docker\s+system\s+prune/]);
deepTerminal.addApprovalPatterns([/kubectl\s+delete/]);

Or declaratively in .codebuddy/security.json:

{ "commandDenyPatterns": ["docker\\s+system\\s+prune"] }

For commands where the agent needs output before proceeding, sendCommandAndWait:

  • Writes to stdin, waits for output.
  • Default 10 s timeout, configurable per call.
  • Output capped at 10 MB.
  • Returns { output, exitCode, success }.

Each session uses CircularBuffer<string>, capacity 2000 chunks:

  • Bounded memory — never grows unbounded.
  • Fast append — O(1) write, oldest overwrites when full.
  • Incremental reads — lastReadIndex tracks what the agent has already seen.