| 📦 Turbo Go 3d7798b k33g 13h ago | 1 | # How to talk to a coding agent from the editor |
| 2 | |
| 3 | This guide shows how to point Turbo Go at an agent that speaks the [Agent Client Protocol](https://agentclientprotocol.com), open a window onto it, and hold a conversation about the code you are editing. It assumes you already have Turbo Go running in a project. |
| 4 | |
| 5 | Turbo Go is an ACP **client**. It starts the agent as a child process and talks JSON-RPC to it over its standard input and output — the same arrangement Zed uses, so an agent that works there works here. |
| 6 | |
| 7 | ## Tell the editor about an agent |
| 8 | |
| 9 | Agents are listed in `acp.toml`. Choose **Agent ▸ Create agents file** and the editor writes a starter one into `.turbo-go/acp.toml` and opens it. |
| 10 | |
| 11 | An agent is one `[[agent]]` block: |
| 12 | |
| 13 | ```toml |
| 14 | [[agent]] |
| 15 | name = "Bob (llama.cpp)" |
| 16 | command = "docker" |
| 17 | args = ["agent", "serve", "acp", ".turbo-go/agent.yaml"] |
| 18 | env = { TELEMETRY_ENABLED = "false" } |
| 19 | ``` |
| 20 | |
| 21 | `name` is what the Agent menu shows and what the window is called. `command` and `args` are how the agent is started. That is the whole of it — the file is read again every time you open a window, so you never restart the editor to try a change. |
| 22 | |
| 23 | List as many as you like. Each becomes its own line in the menu, and each window you open from it is a separate process with a conversation of its own. |
| 24 | |
| 25 | ## Put the agent's own configuration beside it |
| 26 | |
| 27 | Most agents have a configuration file of their own, and `.turbo-go/` is a reasonable place to keep it so that it travels with the project. For `docker agent`, saving this as `.turbo-go/agent.yaml` is what the `args` above point at: |
| 28 | |
| 29 | ```yaml |
| 30 | providers: |
| 31 | llamacpp: |
| 32 | api_type: openai_chatcompletions |
| 33 | base_url: http://localhost:8080/v1 |
| 34 | |
| 35 | models: |
| 36 | mellum2: |
| 37 | provider: llamacpp |
| 38 | model: JetBrains/Mellum2-12B-A2.5B-Instruct-GGUF-Q4_K_M:Q4_K_M |
| 39 | temperature: 0.7 |
| 40 | provider_opts: |
| 41 | context_size: 262144 |
| 42 | |
| 43 | agents: |
| 44 | root: |
| 45 | model: mellum2 |
| 46 | description: A helpful AI assistant running on a local llama.cpp server |
| 47 | instruction: | |
| 48 | You name is Bob 🤓, you are a knowledgeable code assistant. |
| 49 | Be helpful, accurate, and concise in your responses. |
| 50 | You have access to the local filesystem and shell: use these tools |
| 51 | toolsets: |
| 52 | - type: filesystem |
| 53 | - type: shell |
| 54 | ``` |
| 55 | |
| 56 | ## Open a window on it |
| 57 | |
| 58 | Press `Alt-A`, or choose **Agent** from the menu bar, and pick the agent by name. |
| 59 | |
| 60 | A window opens, split in two: the conversation above, and a box to type in below. The agent is started when the window opens and stopped when it closes. |
| 61 | |
| 62 | ``` |
| 63 | ┌ Bob (llama.cpp) ───────────────────────────────[■]┐ |
| 64 | │ ‣ You │ |
| 65 | │ What does buildMenus do? │ |
| 66 | │ │ |
| 67 | │ ‣ Shell ls -1 internal/ ✓ done │ |
| 68 | │ golang │ |
| 69 | │ │ |
| 70 | │ ‣ Bob │ |
| 71 | │ It assembles the menu bar. Here is the shape: │ |
| 72 | │ │ |
| 73 | │ ```go │ |
| 74 | │ func (a *App) buildMenus() *ui.MenuBar { │ |
| 75 | │ return ui.NewMenuBar(a.allMenus()...) │ |
| 76 | │ } │ |
| 77 | │ ``` │ |
| 78 | ├───────────────────────────────────────────────────┤ |
| 79 | │ > _ │ |
| 80 | └───────────────────────────────────────────────────┘ |
| 81 | ``` |
| 82 | |
| 83 | Code the agent sends inside a fenced block is coloured by the same scanners the editor uses for files, so a Go answer is coloured as Go and a shell answer as shell. A fence naming a language the editor does not colour is left plain rather than guessed at. |
| 84 | |
| 85 | ## Hold the conversation |
| 86 | |
| 87 | | Key | Effect | |
| 88 | | --- | --- | |
| 89 | | `Enter` | Send what you have typed | |
| 90 | | `Alt-Enter` | Start a new line instead of sending | |
| 91 | | `Tab` | Move between the conversation and the input box | |
| 92 | | `PgUp` `PgDn` | Scroll the conversation a screenful at a time | |
| 93 | | `Esc` | Stop the turn in progress | |
| 94 | | `Ctrl-W` | Close the window, and stop the agent with it | |
| 95 | |
| 96 | While the agent is answering, its reply appears as it is written rather than all at once, and the rule between the two panes turns a spinner beside the word *thinking*. `Esc` interrupts it — the agent is told to stop, and what it had already said stays in the window. |
| 97 | |
| 98 | ## Use the agent's own commands |
| 99 | |
| 100 | Some agents answer to commands — `/compact`, `/web`, `/plan` — and tell the editor which ones. Type `/` as the first character of the box and the list opens over the conversation: each command, what it does, and in angle brackets what it wants after its name. |
| 101 | |
| 102 | Type on to narrow it, `↑` `↓` to move, then `Tab` to complete. A command that takes something is completed with a space after it, ready for you to type the rest; press `Enter` when the line is what you mean. If nothing appears when you type `/`, the agent announced no commands — **Agent ▸ Agent status** says so — and `/` is only a character. |
| 103 | |
| 104 | ## Point the agent at a file |
| 105 | |
| 106 | Type `@` anywhere in the box and the project's files appear. Type a few letters of the file's name to narrow the list, `Tab` to take the highlighted one: |
| 107 | |
| 108 | ``` |
| 109 | > explain what @internal/scanner.go does |
| 110 | ``` |
| 111 | |
| 112 | When you press `Enter`, the agent is given the **file**, not merely its name: its text when the agent accepts embedded context, a link to it otherwise. If the file is open in the editor with unsaved changes, it is your unsaved version that goes. The line stays in the conversation as you typed it. |
| 113 | |
| 114 | Several files in one prompt is several `@`. A word that begins with `@` but is not a file — an e-mail address — is left as text. |
| 115 | |
| 116 | ## Take something out of the conversation |
| 117 | |
| 118 | Press `Tab` to put the cursor in the conversation. The rule changes to say what the keys now do. |
| 119 | |
| 120 | | Key | Effect | |
| 121 | | --- | --- | |
| 122 | | `↑` `↓` `PgUp` `PgDn` | Move the cursor through what was said | |
| 123 | | `Shift-↑` `Shift-↓` | Select whole lines | |
| 124 | | Drag with the mouse | The same, by hand | |
| 125 | | `Ctrl-C` | Copy | |
| 126 | | `Esc` | Drop the selection | |
| 127 | | `Tab` | Back to the box | |
| 128 | |
| 129 | **With nothing selected, `Ctrl-C` copies the block the cursor is on** — one fenced code block, one paragraph, one tool's output — without the speaker's label above it and without the sentence after it. That is almost always what you wanted, and it saves selecting it by hand. |
| 130 | |
| 131 | What is copied goes to **two** clipboards: this editor's, so `Shift-Ins` pastes it into a file you have open, and your system's, so `Ctrl-V` pastes it anywhere else. The indentation the conversation is drawn with is taken off, so pasted code lands flush against the margin. |
| 132 | |
| 133 | The system half travels through your terminal (an escape sequence called OSC 52). Most terminals do it; a few refuse it for security, and some need it turned on. If `Ctrl-V` elsewhere gives you nothing, that is where to look — the editor's own clipboard has the text either way. |
| 134 | |
| 135 | ## Answer the agent when it asks permission |
| 136 | |
| 137 | An agent with a shell or a filesystem toolset asks before it uses one. A dialog names the tool and the exact command, and offers the choices the agent itself proposed — normally *Allow this action*, *Allow and remember my choice*, and *Skip this action*. |
| 138 | |
| 139 | ``` |
| 140 | ┌───────────── Bob (llama.cpp) wants to run ─────────────┐ |
| 141 | │ │ |
| 142 | │ Shell │ |
| 143 | │ ls -1 │ |
| 144 | │ │ |
| 145 | │ [ Allow ] [ Allow always ] [ Skip ] │ |
| 146 | └────────────────────────────────────────────────────────┘ |
| 147 | ``` |
| 148 | |
| 149 | *Allow always* is remembered by the agent, not by the editor, so what it covers and how long it lasts are the agent's business. Escape is the same answer as *Skip*. |
| 150 | |
| 151 | Nothing runs before you answer. An agent waiting on a permission dialog is simply blocked, which is the point. |
| 152 | |
| 153 | ## Let the agent see what you have not saved yet |
| 154 | |
| 155 | The editor offers the agent its own filesystem: when the agent reads a file you have open with unsaved changes, it is given **the text in the buffer**, not the older text on disk. That is usually what you want — you are asking about the edit you just made. |
| 156 | |
| 157 | When the agent writes a file, the change lands in the buffer and the window is marked modified, so you can read it, undo it with `Ctrl-Z`, or save it with `F2`. A file you do not have open is read from and written to disk directly. |
| 158 | |
| 159 | ## Run several agents at once |
| 160 | |
| 161 | Each window is its own process and its own conversation. Opening the same agent twice gives two independent sessions, and opening two different agents lets you put a fast local model and a slower careful one side by side — **Window ▸ Tile** arranges them. |
| 162 | |
| 163 | Leaving the editor stops every agent. |
| 164 | |
| 165 | ## Variants |
| 166 | |
| 167 | - **You want the agent to run somewhere other than the project root.** Add `cwd = "backend"` to its block. The path is relative to the project, and is both where the process starts and what the agent is told the working directory is. |
| 168 | - **The agent needs a credential.** Put it in `env`, or rely on it being in the environment you started the editor from — the agent inherits it. |
| 169 | - **The agent's commands do not appear when you type `/`.** Open **Agent ▸ Agent status** with the window in front. If it lists no commands, the agent announced none — or announced them in a shape this editor could not read, in which case the dialog names the update and the decoding error. To see exactly what went over the wire, start the editor with `TURBO_ACP_TRACE=/tmp/acp.log` and read the file: `->` is what the editor sent, `<-` what the agent answered. |
| 170 | - **The agent will not start.** **Agent ▸ Agent status** lists what was read from `acp.toml`, what each agent's command line came out as, and the error from anything that failed to start. Whatever the agent writes to its standard error is shown there too, which is where a misconfigured model endpoint reports itself. |
| 171 | - **You keep the same agent in every project.** Put the `[[agent]]` block in `~/.config/turbo-go/acp.toml` instead. A project's own file is read afterwards and an agent with the same `name` in it replaces yours. |
| 172 | |
| 173 | ## See also |
| 174 | |
| 175 | - Every key of the file, and exactly how much of the protocol is implemented: [Agents and ACP reference](../reference/acp.md) |
| 176 | - Why an agent is a window rather than a panel, and why permissions are modal: [Agent windows](../explanation/agent-windows.md) |
| 177 | - The protocol itself: [agentclientprotocol.com](https://agentclientprotocol.com) |