Skip to content

ZettCode in VS Code ​

The extension puts the same agent the terminal app runs into the editor's secondary side bar: ask for a change, watch it work, review the files it touched, and keep control of every shell command. It speaks to zettcode-server over HTTP on your own machine, and the server does the work.

  • Ask and watch. Answers stream in with coloured code, tables, formulas and diagrams. Every file read, edit and command is a row you can open to see what happened; a failed one opens with the reason.
  • Jump to the code. A path in an answer is a link: it opens the file at the line.
  • Review what changed. Each request ends with a card of the files it changed, with lines added and removed, and a normal VS Code diff behind each one.
  • Stay in control. Shell commands ask before they run, questions wait for an answer, and you can steer a request while it is going.
  • Reopen, and the pictures are there. A stored conversation comes back whole, images included.

Install ​

The extension is on the Visual Studio Marketplace, under the publisher zettcode.

  1. Open the extensions view (Ctrl/Cmd+Shift+X), search for ZettCode, and install it. Or install the .vsix:

    bash
    code --install-extension zettcode-0.1.7.vsix

    The marketplace page says which version is the newest; a .vsix from the releases page can be newer still.

  2. Open a folder. The extension serves one folder per window; in a multi-root workspace the first folder is used.

  3. Click the ZettCode icon in the secondary side bar on the right, or run ZettCode: Focus Chat. Prefer the left side? Drag the icon there.

  4. Nothing else to install. The first time the chat starts, the extension looks for a zettcode-server on your PATH or in the folder's .venv; if there is none, it installs one into an environment of its own (globalStorage/server/venv), with uv or your python3. It is the same package as the terminal's agent, in an environment of its own, apart from your project. To do it by hand instead:

    bash
    uv tool install zettcode

    Turn that off with zettcode.server.autoInstall if you would rather it never did.

  5. Add a model from the welcome card: the model id, and optionally an API key. Models you set up in the terminal app are used as they are, because the configuration file is the same one.

  6. Ask something, for example Explain this codebase.

VS Code asks you to trust the folder first: the agent runs commands and edits files in it.

Asking for work ​

You want toDo this
SendEnter; Shift+Enter for another line
Say something while it worksEnter queues a follow-up; Ctrl/Cmd+Enter steers the request that is going
StopEsc, or the stop button
Find in the conversationCtrl/Cmd+F while the chat has the cursor; Enter / Shift+Enter for the next and previous match, Esc to close
Mention a fileType @ and pick one
Attach a picturePaste it, drop it on the view, or press the paperclip
Attach any other filePress the paperclip and pick it: a PDF or an archive goes into the message as its path, which the agent opens with its own tools
Paste a copied fileCopy a file in the explorer or the file manager and paste it: its full path goes into the box, not its bare name. A page is given a file's name and contents but no path, so the extension asks the system's clipboard for the real one (macOS, Windows and Linux; a file of any size, from anywhere, such as a PDF on the Desktop). Failing that it uses the workspace file with the very same contents, else keeps a copy of the contents in its own storage; a file over 10 MB can only be found by name. In a remote window (SSH, WSL, a container) the clipboard is not the one you copied on, so the contents are used
Run a commandType /: new, resume, continue, compact, fork, rename, export, model, effort, permission, harness, usage, context, doctor, btw
Ask without adding to the conversation/btw your question

The pictures you attach are sent to a model that can see images, and are kept with the conversation, so reopening the session shows them again instead of only counting them.

Moving around the conversation ​

  • The rail on the left edge marks each message you sent. Point at it and the bars near the pointer swell and show their message; press one to go there. When there are so many that the bars would touch, one bar stands for ten messages: press it and the ten are listed beside the rail, and you pick one.
  • Show earlier requests loads older messages a page at a time, keeping your place.
  • Compaction appears as a row where it happened; press it to read the summary it left.

Several sessions at once ​

A request keeps running when you look at another session. Open the session list and start a new session, or open an older one, while the agent works: the work goes on where it is, and a small spinner (with the word running) marks that session in the list. Open it again and its conversation is there as it got to, still streaming if it is not done. Each session has its own approvals, questions and steering, so a command waiting for you in one session does not appear in another; the extension says when a session in the background is waiting for an answer or has finished.

Messages between sessions ​

Write @name in a message to point the model at another ZettCode session (a terminal, or another editor window). The model reads which session that is and can send it a message with its tool: the send shows as a send_message row, with the text and the delivery line, and your own message shows as you typed it. What another session sends to this one arrives as its own request, marked from @name, and the agent answers it here; if it should answer the sender too, it sends a message back.

Approvals, questions, steering ​

The shell permission decides what the agent may run on its own:

LevelWhat happens
denyNo shell commands at all.
askEvery command waits for your approval.
safeEvery command runs in a sandbox that writes only the workspace and /tmp, with no network.
fullEvery command runs with your own access, without asking. (auto is the old name.)

The level chosen in the chat is remembered for the next new session in the workspace. An approval waits zettcode.answerTimeout seconds, then the safe answer is used. A question waits until you answer it; it has no timeout.

Pictures, diagrams and code ​

Anything too small for the column opens in one lightbox over the conversation: a picture, a Mermaid diagram, a table or a code block. What it is decides how much it can be enlarged.

WhatWhat happens
A picture you sentPress it (in the message, or in the strip under the box) to open it over the conversation, fitted to the window
A Mermaid diagramA ```mermaid fence is drawn, not shown as code. Press it, or the expand button in its header, to open it larger
A tableThe expand button in its corner opens it at full width
A code blockThe expand button in its header opens it at full width, without the column's narrow limit

In the lightbox, the mouse wheel zooms at the pointer, + and − zoom, 0 fits the content again, dragging moves it, and a double click switches between fitted and real size. Esc closes it, and does not reach the message box, so it never stops a request running behind it. A diagram that cannot be drawn stays as its code with the first line of the reason, and the source of any diagram is one press away.

Models, effort and permission ​

The chips under the message box pick the model, the reasoning effort and the shell permission; the same three are in the Command Palette as Select Model, Select Reasoning Effort and Select Shell Permission. Add Model writes a new entry to the same config.toml the terminal app uses.

The add-model form takes the same keys as the terminal's /config. Only the model id is required; the API key can be left empty for a local server (Ollama, LM Studio, vLLM), or to use OPENAI_API_KEY / ANTHROPIC_API_KEY. API is a choice of Chat completions (written as chat = true), the Responses API or the Anthropic Messages API, one of the three. Temperature is a number from 0 to 2 (0 to 1 for Anthropic), and left empty none is sent. Web search lets the provider search the web for the model, and a tool name overrides what its API sends by default (web_search, web_search_20260318 for Anthropic, web_search_20250305 for DeepSeek); DeepSeek is accepted only over the Anthropic API, and the form says so before anything is sent. Edit Model changes the same things on a model that is already there: choosing another API takes the old flag out of the file instead of leaving anthropic = false behind, and clearing the temperature or turning search off removes the key.

Spending ​

ZettCode: Usage opens a page with the terminal's three tabs — models, sessions and calendar — for this workspace only: each folder keeps its own ledger, so another project's spending is not in it. The page says which folder it is for, under its title.

Plugins ​

A plugin installed beside the server adds commands here too: they appear in the / menu with the rest, and as ZettCode: Run a Plugin Command in the Command Palette. A command that answers with words gets a line in the conversation; one that is a preset for a request starts that request, with the command as its line and the preset as what the model reads.

ZettCode: Show Plugins lists every plugin you can switch: the ones compiled into the program first, then the ones installed beside it, each with a switch and the reason on any that failed. A switch is written down now and honoured the next time the server starts — this one does the work it loaded, so ZettCode: Restart Server applies it. Where it is written is the plugin's own business: an installed plugin goes in the file the terminal's /plugins writes, a compiled-in one in your configuration file ([skills] enabled, [mcp] enabled, …). That file is read and replaced as a whole, so two programs writing it at the same moment keep the last write; the terminal and one server are the ordinary case.

Settings ​

Search for ZettCode in Settings:

SettingDefaultMeaning
zettcode.permissionaskThe shell permission a session starts with when you have not chosen one: deny, ask, safe (a sandbox) or full
zettcode.harnessfalseStart with the tool harness on: the model may write small Python tools of its own and run them, outside the shell permission. /harness on or /harness off switches it for a session
zettcode.restoreSessiontrueReopen the conversation this folder had last
zettcode.autoTitletrueLet the model name an untitled conversation after its first answer
zettcode.answerTimeout90Seconds an approval waits
zettcode.historyLimit50How many stored conversations Recent Sessions lists
zettcode.server.commandzettcode-serverWhere the server is, if not on your PATH or in the folder's .venv
zettcode.server.args[]Extra arguments for it
zettcode.server.port0A fixed port; 0 picks a free one
zettcode.server.autoStarttrueStart the server with the chat
zettcode.server.autoInstalltrueInstall the server into the extension's own environment when it cannot be found
zettcode.server.externalUrlemptyUse a server you started yourself instead of launching one
zettcode.server.externalTokenemptyIts token, when it needs one
zettcode.server.useTokentrueProtect the server the extension starts with a token per window

Skills, MCP servers and AGENTS.md work in the editor exactly as they do in the terminal: see Skills & MCP and Project instructions. <workspace>/.agents/skills, ~/.agents/skills and the matching mcp.json files are read too, so a skill written for another coding agent is found without copying it.

When something goes wrong ​

What you seeWhat to do
The chat says the server is not runningZettCode: Show Server Log has the reason; ZettCode: Restart Server after fixing it
No modelZettCode: Add Model, or copy the [[models]] entry from ~/.zettcode/config.toml
A command was refusedThe shell permission is deny; pick ask, safe or full under the message box
A diagram says it could not be drawnThe fence is not valid Mermaid; the source is in the block, and the reason is on its first line

Only in the terminal ​

/theme, /pet and the rest of the full-screen interface belong to the terminal app. The editor has its own theme, and its own shortcuts.

Released under the MIT license.