Docs
Jan Agent
Editors (ACP)

Editors (ACP)

jan acp serves Jan Agent over the Agent Client Protocol (opens in a new tab) (ACP), a JSON-RPC protocol that editors use to run coding agents. Once an editor is pointed at jan acp, you can pick Jan in its agent panel, send prompts, and watch the answer, reasoning, tool calls and plan stream in. The agent still uses Jan's own providers, tools and permissions.

⚠️

jan acp is experimental. It's off by default, hidden from jan --help, and may change between releases.

Turn it on

Pick one of these. The environment variable takes precedence over the config file, so JAN_EXPERIMENTAL_ACP=0 turns it off again:


export JAN_EXPERIMENTAL_ACP=1 # per process


# ~/.jan/config.toml # every process
[experimental]
acp = true

If you run jan acp without turning it on, it prints how to enable it and exits with status 2. It writes nothing to stdout.

Jan needs a working provider before any editor can use it. Run jan login, or jan config set --provider <name> --api-key <key> --base-url <url> --model <id>. The model is resolved the same way as in the TUI: agent.toml, then default_model in ~/.jan/config.toml.

Zed

Add Jan under agent_servers in Zed's settings.json:


{
"agent_servers": {
"Jan": {
"type": "custom",
"command": "jan",
"args": ["acp"],
"env": { "JAN_EXPERIMENTAL_ACP": "1" }
}
}
}

Open the agent panel, start a new thread and choose Jan. To see the raw traffic, run dev: open acp logs.

JetBrains

In AI Chat, open the menu and choose Add Custom Agent. This opens ~/.jetbrains/acp.json. Add Jan there. Use the absolute path to the binary:


{
"agent_servers": {
"Jan": {
"command": "/absolute/path/to/jan",
"args": ["acp"],
"env": { "JAN_EXPERIMENTAL_ACP": "1" }
}
}
}

What is supported

Jan speaks stable ACP protocol version 1. It doesn't enable any draft or unstable features.

ACPJan
initializeAdvertises loadSession, image and embedded-context prompts. Nothing else is advertised.
authenticateChecks that a provider is configured. Clients that can run a terminal get a sign-in method that runs jan acp --login.
session/newOpens a session in cwd, which must be absolute. The session id is a Jan thread id. MCP servers the editor passes over stdio are connected as well as the project's own.
session/loadReplays a saved thread, including ones started in the TUI or with jan cli agent run, then replies. Refused while that session has a prompt running.
session/promptRuns one turn. The reply's stopReason is end_turn, max_tokens, max_turn_requests (the session's cost ceiling was reached), refusal or cancelled. If the run fails, the error is shown in the reply text and the turn ends with end_turn.
session/cancelStops the turn. A tool call waiting for your permission never runs. The work done before the cancel is kept, so the next prompt continues from it.
session/request_permissionSent for every gated tool call. You get Allow, Always allow where Jan offers it, and Reject.

The session id is the thread id, so jan --resume <id> in the terminal opens a conversation that you started in the editor.

How Jan's events appear in the editor:

JanACP session/update
Answer text / reasoningagent_message_chunk / agent_thought_chunk
Tool call starts, runs, streams output, endstool_call then tool_call_update (pending, in_progress, completed, failed)
The todo listplan
Token usage for a turnusage_update

These have no standard ACP update, so they are left out rather than sent through a made-up extension: subagent progress (a subagent's permission prompts still reach you), notices, compaction and retry status, and background monitors. The ask tool isn't offered in an ACP session.

Permissions

An ACP session always asks before writes, shell commands and MCP tool calls. It's never auto-approved. It uses the same tool gate and project rules ([tools] in agent.toml) as the TUI. If you reject a call, or cancel the prompt, the call is refused just as it would be in the terminal. Always allow covers that tool for the rest of the session.

Not yet supported

  • Jan uses its own filesystem and shell tools. It doesn't read the editor's unsaved buffers or run commands in the editor's terminal, so fs/* and terminal/* are never requested.
  • Editor MCP servers over HTTP or SSE are skipped. Only stdio servers are connected, alongside the servers set up for the project (see MCP).
  • There's no session/set_mode yet, so plan mode and model switching aren't available from the editor.