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:

CategoryExamples
Root filesystem wiperm -rf /
Disk destructionmkfs*, dd of=/dev/sda
Fork bomb:(){ :|: & };:
Remote code execcurl … | bash, wget … | python
Privilege escalationsudo mkfs, sudo dd, sudo shutdown, chmod 777 /
Credential exfilcat ~/.ssh/… | curl, history | curl
Encoded payloadsHex/base64 pipe chains into sh

Approval-required:

  • rm, rmdir, unlink
  • sudo rm, sudo rmdir, sudo unlink
  • find … -delete, find … -exec rm

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 readslastReadIndex tracks what the agent has already seen.