The TUI has four visual regions. The chat list sidebar on the right is optional
and can be toggled with Ctrl+B:
┌─────────────────────────────────────────┬───────────────────┐
│ gpt-4o agent ctx:18% ⠿ run_terminal │ ● New chat │ status bar
├─────────────────────────────────────────┤ ○ Rate limiter │
│ │ ○ Codebase review │
│ chat pane │ ✓ Auth redesign │
│ (scrollable conversation history) │ │
│ │ n:new d:del a:arch│
├─────────────────────────────────────────┤ │
│ > type here and press Enter │ │
└─────────────────────────────────────────┴───────────────────┘
Status bar — always visible at the top. Shows:
- Model name (e.g.
gpt-4o) - Current agent mode (
research,plan, oragent) - Context usage as a percentage (
ctx:18%) - A spinner and the name of any tool currently running
Chat pane — the conversation history. User messages, agent responses, and collapsed tool calls are all shown here. Scrolls independently of the input box.
Input box — a multi-line text field. Press Enter to send, Shift+Enter
to insert a newline.
Chat list sidebar — shows all open sessions. The active session is
highlighted. Sessions running a background agent task show a spinner. Toggle
with Ctrl+B.
The TUI has two focusable panes: the chat pane and the input box. Focus starts on the input box.
Switch focus with the Ctrl+W chord:
| Sequence | Effect |
|---|---|
Ctrl+W then K or ↑ |
Focus the chat pane |
Ctrl+W then J or ↓ |
Focus the input box |
When the chat pane has focus, navigation keys work as described below. When the input box has focus, all printable characters go to the text field.
The chat list sidebar lets you manage multiple concurrent conversations without leaving the TUI. Each session runs its own independent agent task — you can have one session researching a problem while another is implementing a fix.
Opening and navigating the sidebar
Press Ctrl+B to show the sidebar and give it keyboard focus. Press Ctrl+B
again (or Esc, q, h, or ←) to return focus to the input box.
| Key | Action |
|---|---|
Ctrl+B |
Toggle sidebar visibility / focus |
j / ↓ |
Move selection down |
k / ↑ |
Move selection up |
Enter / l / → |
Switch to the selected session |
n |
Create a new empty session |
d / Delete |
Delete the selected session (cannot delete the active one) |
a |
Archive the selected session |
+ / = |
Widen the sidebar |
- |
Narrow the sidebar |
Session status icons
| Icon | Meaning |
|---|---|
⣾ (spinner) |
Agent is currently running in this session |
● |
Active session, idle |
○ |
Inactive session, idle |
✓ |
Session completed |
Per-session model and mode
Each session keeps its own model and mode. Running /model or /mode in one
session does not affect any other session. New sessions always start with the
default model and mode from your configuration.
Background sessions
When you switch away from a session that has an agent running, it keeps running in the background. The spinner in the sidebar shows which sessions are still active. You can switch back at any time to see the results.
First switch focus to the chat pane with Ctrl+W K.
| Key | Action |
|---|---|
j / ↓ |
Scroll down one line |
k / ↑ |
Scroll up one line |
J |
Scroll down one line (shift variant) |
K |
Scroll up one line (shift variant) |
Ctrl+D |
Scroll down half a page |
Ctrl+U |
Scroll up half a page |
g |
Jump to the very top |
G |
Jump to the very bottom |
Press / while the chat pane has focus to open the search bar at the bottom
of the screen. Type to filter the conversation in real time.
| Key | Action |
|---|---|
/ |
Open search |
n |
Jump to next match |
N |
Jump to previous match |
Esc or Enter |
Close search and stay on the current match |
If you want to correct or rephrase a message you already sent, navigate to it
in the chat pane and press e. The message text appears in the input box for
editing. When you are happy with the change, press Enter to re-submit it as
if it were a new message. Press Esc to cancel and restore the original.
Press Ctrl+T to open the full-screen pager. This expands the chat history to
fill the whole terminal, which is useful for reading long responses or code
blocks without the input box taking up space. Press Esc or q to close the
pager.
Press F1 to toggle the in-app help overlay, which lists all key bindings.
By default, sven embeds a headless Neovim instance and uses it as the chat buffer. This gives the chat pane full Neovim editing capabilities:
- Navigate and scroll the chat with all standard Neovim motions
- Use
:qor:qato quit sven - Press
Ctrl+Enterfrom the chat pane to submit the buffer content as a message
Sven defaults to the plain ratatui view. To enable the embedded Neovim chat
pane instead, pass --nvim:
sven --nvimIn the default ratatui mode, tool calls and thinking blocks in the history are collapsed by default to keep the view compact.
Modes control what tools the agent is allowed to use. Choosing the right mode prevents unintended changes and makes the agent's output more predictable.
The agent can only read. It can run commands like ls, cat, grep, and
find, but cannot write to any file. Use this when you want to explore a
codebase without any risk of modification.
sven --mode research "What does the authentication module do?"The agent reads freely and produces a written plan but does not write any
files. The output is typically a list of steps or a design document. Use this
before an agent run to review what will happen.
sven --mode plan "Design a rate-limiting layer for the API."The agent can read, write, delete files and run any command. This is the default mode. Use it when you want sven to implement something end-to-end.
sven "Implement the rate-limiting layer described in the plan."Press F4 inside the TUI to cycle through research → plan → agent → research.
The status bar updates immediately to show the new mode. Changes take effect on
the next message you send.
sven has a set of built-in tools it can call to complete tasks:
| Tool | What it does |
|---|---|
run_terminal_command |
Run a shell command |
read_file |
Read a file |
write |
Write or create a file |
edit_file |
Edit part of a file |
delete_file |
Delete a file |
list_dir |
List directory contents |
glob_file_search |
Find files by pattern |
grep |
Search file contents |
search_codebase |
Semantic search of a codebase |
apply_patch |
Apply a unified diff patch |
web_fetch |
Fetch a URL |
web_search |
Search the web |
read_lints |
Read linter diagnostics |
todo |
Read or update the task list for the current session (call with no args to read) |
ask_question |
Ask you a clarifying question |
switch_mode |
Change the agent mode mid-session |
gdb_start_server |
Start a GDB server in the background |
gdb_connect |
Connect gdb-multiarch to the running server |
gdb_command |
Run a GDB command and return its output |
gdb_interrupt |
Interrupt execution (Ctrl+C equivalent) |
gdb_stop |
Stop the debugging session and kill the server |
Sven is the first AI agent with native GDB integration for autonomous embedded hardware debugging. Give it a plain-English task and it handles the entire debug lifecycle — from starting the server and loading firmware through setting breakpoints, inspecting state, and cleaning up — without any manual intervention.
The five GDB tools form a lifecycle:
gdb_start_server → gdb_connect → gdb_command / gdb_interrupt → gdb_stop
The screenshots below show a real session: the user asks sven to find the parameters passed to an nRF UART TX function, and the agent works through the full debug cycle autonomously.
Task start and target discovery (ratatui TUI):
Inspecting parameters and final summary (ratatui TUI):
Same session in the embedded Neovim view:
Starting a server
If you do not supply a command, sven searches your project for configuration hints in this order:
.gdbinit— looks for# JLinkGDBServer ...comments ortarget remotelines.vscode/launch.json— readsdebugServerPath,debugServerArgs, andservertypeopenocd.cfg— builds an OpenOCD command from the config fileplatformio.ini— readsdebug_serverordebug_toolCMakeLists.txt/Cargo.toml— matches MCU family names (STM32, AT32, NRF, …)
If discovery fails, sven asks the user for the target device name.
Example session
User: Flash and debug my firmware. The device is an AT32F435RMT7.
Agent calls:
gdb_start_server {"target": "AT32F435RMT7"}
gdb_connect {"executable": "build/firmware.elf"}
gdb_command {"command": "load"}
gdb_command {"command": "break main"}
gdb_command {"command": "continue"}
gdb_command {"command": "info registers"}
gdb_stop
Before running a shell command, sven checks it against approval rules:
- Auto-approved patterns run without prompting (e.g.
cat *,ls *,grep *). - Denied patterns are blocked outright (e.g.
rm -rf /*). - Everything else is presented for confirmation if the agent requests it.
You can customise these patterns in the configuration file — see Configuration.
You can run several conversations simultaneously without restarting sven. Open
the chat list sidebar with Ctrl+B and press n to create a new session, or
use the /new command from the input box. Switch between sessions by selecting
one and pressing Enter.
Each session has its own:
- Conversation history
- Agent task (background sessions keep running while you work elsewhere)
- Model and mode settings (changed with
/modeland/mode)
All sessions are automatically saved to ~/.config/sven/history/ as YAML files
and restored the next time you launch sven.
To list saved conversations:
sven chatsOutput:
ID (use with --resume) DATE TURNS TITLE
-----------------------------------------------------------------------------------------------
3f4a... 2025-01-15 10:42 12 Codebase analysis
a1b2... 2025-01-14 09:11 5 Rate limiter design
To resume a session, pass its ID (or a unique prefix) to --resume:
sven --resume 3f4aIf you omit the ID entirely, sven opens an interactive fuzzy-finder (requires
fzf) so you can pick the session visually:
sven --resumeFor longer-running work, a conversation file gives you a plain-text record that you can edit directly. See Quick Start for an introduction, and CI and Pipelines for the full file format.
Every message you send, every tool call, and every response is stored in the conversation context. Language models have a finite context window, and when the conversation grows long enough, older messages must be summarised to make room for new ones.
sven tracks context usage and shows it in the status bar (ctx:X%). When usage
reaches the configured threshold (85% by default), sven automatically compacts
the oldest part of the conversation into a short summary before sending the
next message. This happens transparently in the background.
You will not lose any information that sven has already used; compaction only affects how much raw history the model can see at once.
If the agent is in the middle of a long task and you want to stop it, press
Ctrl+C from the input box. The current tool call is cancelled and sven
returns to idle, ready for your next message.
Type / in the input box to see all available commands. Tab-completion works
for both command names and their arguments.
| Command | Description |
|---|---|
/new |
Start a new chat session. A fresh tab appears in the sidebar with its own isolated agent, model, and mode. |
/clear |
Clear the current session's message history. The session itself stays open; only the visible conversation is erased. |
/model <provider/name> |
Switch the model for this session (e.g. /model anthropic/claude-opus-4-6). Tab-completes over your configured models. The switch takes effect on the next message you send. |
/mode <research|plan|agent> |
Switch the agent mode for this session. Tab-completes all three modes. |
/provider <name> |
Switch provider while keeping the current model name. |
/abort |
Abort the current agent turn. Queued messages stay queued; partial output is preserved. |
/refresh |
Re-scan skill directories and register any newly added skills as commands. |
/skills |
Open the skills inspector — a browsable tree of all loaded skills. |
/subagents |
Show all configured subagents with their descriptions, models, and paths. |
/peers |
Show active subagent subprocess buffers and configured peer agents. |
/context |
Show the current agent context: project root, skill and agent counts, output buffer handles. |
/tools |
Show all available tools with descriptions and parameter counts. |
/approve [task_id] |
Approve a teammate's pending plan (team mode). |
/reject [task_id] [reason] |
Reject a plan with feedback (team mode). |
/agents |
Show the team members overlay (also Ctrl+A). |
/tasks |
Show the current team task list (also Alt+T). |
/quit |
Exit sven. In the Neovim buffer, use :q or :qa. |
Every skill you have installed is also available as a slash command named after
its directory path — for example /sven, /sven/plan, or /git-workflow.
See the Skills section for details.
Skills are instruction packages that teach sven how to handle a specific type of task. Each skill lives in its own directory alongside any helper scripts or reference files it needs. When you invoke a skill, sven loads its instructions and follows them for your task.
Skills are discovered automatically from your project and home directory on startup. You do not need to configure anything; drop a skill directory in the right place and it appears immediately.
Every discovered skill is registered as a slash command named after its
directory path. Type / followed by the skill name in the input box:
/sven
/sven/plan
/git-workflow
/docker/compose
You can optionally follow the command with a task description on the same line:
/sven implement the rate-limiting feature described in the issue
/sven/plan analyse the authentication module
/git-workflow rebase my branch onto main
When you submit, sven receives the skill's full instruction set as your message, with your task appended at the end. The skill guides the agent's behaviour for the rest of that turn.
Skills can be nested. A top-level skill like sven describes a high-level
workflow and lists the sub-skills that handle each phase. Each sub-skill is
also a fully independent slash command:
/sven run the full three-phase workflow
/sven/plan run only the planning phase
/sven/implement run only the implementation phase
/sven/review run only the review checklist
When the model loads a parent skill, it receives a compact list of the
available sub-skills. It then calls load_skill("sven/plan") etc. exactly
when it enters each phase — not before. This means sub-skill instructions are
loaded only when actually needed, keeping each turn's token usage minimal.
Sven looks for skills in the following locations, with later sources taking precedence when the same command exists in multiple places:
| Location | When to use |
|---|---|
~/.sven/skills/ |
Your personal skills, available in every project |
~/.agents/skills/ |
Cross-agent skills shared with other agents |
<project>/.sven/skills/ |
Skills specific to this project |
<project>/.agents/skills/ |
Project skills shared with other agents |
Project-level skills always win over global ones.
A skill is a directory containing a SKILL.md file:
.sven/skills/
└── deploy/
├── SKILL.md
└── scripts/
└── pre-flight.sh
SKILL.md starts with a YAML frontmatter block followed by the instruction
body:
---
description: |
Use this skill when the user asks to deploy, release, or ship the application.
Trigger phrases: "deploy", "release", "ship to production".
name: Deploy # optional — defaults to directory name
version: 1.0.0 # optional
---
# Deploy
Before deploying, run the pre-flight checklist in scripts/pre-flight.sh.
1. Confirm the target environment with the user.
2. Run `scripts/pre-flight.sh` and fix any failures.
3. Build the release artefact.
4. Push and tag.The description field is the only required frontmatter key. The model reads
it to decide whether to use the skill, so write it as a list of trigger phrases
and use-cases rather than a technical summary.
Nest sub-skill directories inside the parent:
.sven/skills/
└── deploy/
├── SKILL.md /deploy
├── pre-flight/
│ └── SKILL.md /deploy/pre-flight
└── rollback/
└── SKILL.md /deploy/rollback
In the parent SKILL.md, tell the model to load sub-skills at the right time:
---
description: |
Full deployment workflow. Use when deploying to any environment.
---
# Deploy Workflow
Follow these phases in order:
1. Pre-flight checks — call `load_skill("deploy/pre-flight")` before touching
any infrastructure.
2. Deploy the artefact.
3. If anything fails — call `load_skill("deploy/rollback")` immediately.Sub-skills are automatically listed to the model when the parent is loaded, so you do not need to declare them in the frontmatter. Just create the directory.
| Key | Type | Required | Description |
|---|---|---|---|
description |
string | yes | Trigger phrases and use-cases. The model matches this against the user's request. |
name |
string | no | Human-readable label shown in the UI. Defaults to the directory name. |
version |
string | no | Semver version string for your own tracking. |
sven.always |
bool | no | Always include this skill's metadata in the system prompt, regardless of the token budget. Useful for a project-wide coding-style skill. Default: false. |
sven.requires_bins |
list | no | Skip this skill if any of the listed binaries are absent from PATH (e.g. [docker, kubectl]). |
sven.requires_env |
list | no | Skip this skill if any of the listed environment variables are unset (e.g. [AWS_PROFILE]). |
sven.user_invocable_only |
bool | no | Hide the skill from the model's automatic matching. It still appears as a /command. Use for skills you always want to invoke deliberately. Default: false. |
Any file in a skill directory that is not a SKILL.md is a bundled file —
a script, reference document, template, or data file the skill's instructions
may use. Subdirectories without their own SKILL.md are support directories,
not sub-skills.
When a skill is loaded via load_skill, the agent receives a listing of up to
20 bundled file paths relative to the skill directory. The skill body can
reference them:
Run the helper at `scripts/validate.py` before proceeding.The agent resolves that path against the base directory shown in the tool
response and reads the file with read_file.
Write descriptions as trigger phrases. The model matches the description
against what the user asked. "Use when deploying to production" is more
useful than "Deployment skill".
Keep parent bodies short. The parent skill should describe the workflow and tell the model when to call each sub-skill. Put the detailed instructions in the sub-skills.
Use always: true sparingly. Skills marked always are included in every
system prompt. Reserve this for genuinely project-wide rules (e.g. a coding
style guide) rather than task-specific workflows.
Use user_invocable_only: true for personal workflows. If a skill
contains steps you always want to review before running (e.g. a production
deployment), mark it user_invocable_only so the model never triggers it
automatically.
Override globals with project skills. A project-level skill at
.sven/skills/deploy/ silently replaces any global skill with the same command.
This lets you tailor shared skills for a specific repository.
For projects with multiple specialist agents or skills, a routing table in the
project context file (AGENTS.md or .sven/context.md) encodes which domain
expert to consult before editing a given area of the codebase.
The agent reads this table as part of "Project Instructions" and follows it automatically — no additional tooling required.
Add an ## Agent Routing section to your AGENTS.md:
## Agent Routing
Before modifying files that match the patterns below, load the indicated skill
or agent first.
| File pattern | Before changes: load |
|---------------------------|-----------------------------------|
| crates/sven-p2p/** | `/p2p-specialist` |
| crates/sven-model/** | `/model-integrator` |
| .sven/knowledge/** | update `updated:` date when done |
| src/auth/** | `/security-auditor` (readonly) |The routing table is written for the AI, not for humans. When Sven sees
"Project Instructions" in its system prompt, it treats the table as binding
rules. The model will call load_skill or suggest the indicated agent before
touching matching files.
- Use glob patterns.
crates/sven-p2p/**matches any file under that directory;src/**/*.rsmatches all Rust source files. - Cross-reference with knowledge docs. If a subsystem has a knowledge doc,
note it in the routing table:
| crates/sven-p2p/** | search_knowledge "P2P Networking" before changes |
- Combine with skills. Skills can themselves contain routing sub-tables for their own sub-components.
- Start small. A two-row routing table covering your two most error-prone subsystems is more effective than a twenty-row table the model ignores due to length.
Sven implements the Agent Client Protocol (ACP), so ACP-aware editors can launch it as a subprocess and interact with it as a first-class AI coding agent — with streaming output, tool-call visibility, plan updates, and mode switching — all without a separate daemon or relay.
Sven manages its own language model configuration (
~/.config/sven/config.yaml). You do not need to configure a language model inside the IDE; the "no language model configured" prompt that some IDEs show before connecting an ACP agent can be ignored or dismissed.
Add to ~/.config/zed/settings.json:
{
"agent_servers": {
"sven": {
"type": "custom",
"command": "sven",
"args": ["acp", "serve"]
}
}
}Open the assistant panel and select sven from the agent picker.
Add to .vscode/settings.json or your user settings:
{
"acp.agents": [
{
"id": "sven",
"name": "Sven",
"command": "sven",
"args": ["acp", "serve"]
}
]
}Open Settings → Tools → ACP Agents and create a new entry:
| Field | Value |
|---|---|
| Name | Sven |
| Command | sven |
| Arguments | acp serve |
If a sven node is already running (e.g. a team server or CI orchestrator),
point the IDE at it instead of spawning a local agent:
{
"agent_servers": {
"sven-node": {
"type": "custom",
"command": "sven",
"args": ["acp", "serve", "--node-url", "wss://localhost:8443"],
"env": {
"SVEN_NODE_TOKEN": "<token printed by sven node start>"
}
}
}
}The token can also be exported in your shell profile instead of hardcoding it:
export SVEN_NODE_TOKEN=<token>Once connected, the IDE assistant panel provides:
| Feature | Description |
|---|---|
| Streaming text | Responses appear word-by-word as the model generates them |
| Tool calls | Every file read/write/shell command is shown with its status |
| Plan | Sven's todo list surfaces as a structured plan panel |
| Mode switching | Switch between agent, plan, and research without restarting |
See docs/technical/acp.md for the full protocol reference.


