Cogitator
Integrations

ACP (Agent Client Protocol)

Use Cogitator agents in Zed, JetBrains, Neovim and VS Code over the Agent Client Protocol, and run Claude Code, Codex or Gemini CLI as agents of your own app-server.

Overview

The Agent Client Protocol is how editors talk to coding agents. @cogitator-ai/acp speaks it both ways:

  • Cogitator in your editor - cogitator acp (or createAcpAgent()) serves a Cogitator agent to any ACP editor. A Cogitator thread is an ACP session, a prompt is a turn.
  • Other agents in Cogitator - AcpAgentProvider launches an external ACP agent (Claude Code, Codex, Gemini CLI, any agent of the ACP registry) and serves it next to your own agents in an app-server. Its permission requests are decided by Cogitator's permission engine.
pnpm add @cogitator-ai/acp @cogitator-ai/app-server @cogitator-ai/core

It is built on the official TypeScript SDK, @agentclientprotocol/sdk (ACP v1).

Cogitator in your editor

With the CLI there is nothing to write. In Zed's settings.json:

{
  "agent_servers": {
    "Cogitator": {
      "command": "npx",
      "args": ["-y", "@cogitator-ai/cli", "acp", "-m", "ollama/qwen3:8b"]
    }
  }
}

cogitator acp runs the coding harness agent: workspace tools and a shell, a todo list, skills, subagents, commands and the project's instructions, on the model of -m, of cogitator.yml or of a local Ollama. Sessions live in ~/.cogitator/sessions.db, so the editor can list, load and resume them across restarts. It works in the project it is launched in, where its settings, commands, subagents and hooks are read: a session in a directory outside it is refused.

FlagWhat
-m, --modelThe model, as provider/model
-c, --configThe config file (default ./cogitator.yml)
--models <models...>More models a session may switch to, next to the local Ollama models
--trustTrust the project: its subagents, commands, hooks and allow rules apply, "always" answers go to a file
--no-session-persistenceKeep sessions in this process only

What you see in the editor

  • Messages and thoughts stream as they are written.
  • Tool calls show what they do (Edit file: src/app.ts, a command line), their kind, the files they touch and, for an edit, the diff. A command shows the editor's terminal it ran in.
  • The plan is the agent's todo list from write_todos, kept current.
  • Commands: the / menu lists the project's commands (Markdown files in commands/ folders) and the agent's skills. /review src runs a command, /<skill> what to do asks the agent to use a skill.
  • Modes: the session's mode is a permission mode (default, acceptEdits, plan, dontAsk, bypassPermissions). The model and the reasoning effort are configuration options too.
  • Compaction of a long conversation is shown as it happens.

Permissions

Edits and commands ask with session/request_permission in the default mode. The editor offers four answers:

AnswerWhat happens
AllowThe call runs
Always allowThe call runs, and the rule the request suggests is saved as an allow rule
RejectThe call is refused, the model reads why
Always rejectThe call is refused, and the same rule is saved as a deny rule

A suggested rule names what the call does, such as run_command(npm test *) or edit_file(./src/app.ts). Without --trust it lasts for the session, with it the rule goes to .cogitator/settings.local.json, where the permission rules of later sessions read it.

In plan mode only reads run. When the agent presents its plan, the editor asks "Ready to code?": yes goes on in acceptEdits or default, no keeps planning.

Files and terminals

When the editor offers them, the agent reads and writes files through it (fs/read_text_file, fs/write_text_file), so it sees unsaved changes and the editor follows its edits, and runs commands in the editor's terminals (terminal/*). Listings, searches, deletes and every path check stay on the session's directory, which the agent cannot leave.

MCP servers

The MCP servers the editor names for a session connect through Cogitator's MCPClient (stdio, HTTP and SSE). Their tools are named mcp__<server>__<tool>, so permission rules name them as in Claude Code.

Serve your own agent

import { Agent, Cogitator, workspaceTools } from '@cogitator-ai/core';
import { SessionHost } from '@cogitator-ai/app-server';
import { createAcpAgent, serveAcpStdio } from '@cogitator-ai/acp';

const cogitator = new Cogitator({
  memory: { adapter: 'sqlite', sqlite: { path: './sessions.db' } },
  permissions: {},
});
const coder = new Agent({
  name: 'coder',
  model: 'ollama/qwen3:8b',
  instructions: 'You are a careful coding agent.',
  tools: workspaceTools(),
  todos: true,
});

const host = new SessionHost({ cogitator, agents: { coder } });
const acp = createAcpAgent({
  host,
  cogitator,
  agentInfo: { name: 'my-agent', version: '1.0.0' },
  models: ['ollama/qwen3:8b', 'anthropic/claude-sonnet-5-5'],
});
await serveAcpStdio(acp);
await host.close();
OptionWhat
host, cogitatorThe app-server host whose threads are the sessions, and its runtime
agentThe agent of the host sessions run (default: the host's default agent)
agentInfoWhat initialize says of the agent
modelsModels a session may switch to
modes, defaultModePermission modes offered and the one a session starts in (default: all but auto)
effortsReasoning efforts offered
workspace(cwd)The workspace on this machine for a session's directory (default LocalWorkspace)
mcpHow MCP servers connect (default the connector of @cogitator-ai/mcp)
rootsDirectories sessions may work in, a session outside them refused (default any)
authMethods, authenticateThe auth methods initialize offers and the check of authenticate

Nothing but the protocol may write to stdout: log to stderr.

Run external ACP agents

AcpAgentProvider makes an ACP agent a session provider of an app-server host: each thread is a session of the agent, each turn a prompt, and its stream reaches app-server clients as the events of any turn.

import { Agent, Cogitator, LocalWorkspace } from '@cogitator-ai/core';
import { SessionHost, createAppServer, serveStdio } from '@cogitator-ai/app-server';
import { AcpAgentProvider, resolveAcpAgent } from '@cogitator-ai/acp';

const workspace = new LocalWorkspace({ root: process.cwd() });
const launch = await resolveAcpAgent('claude');
const claude = new AcpAgentProvider({
  agent: { command: launch.command, args: launch.args },
  workspace,
  name: 'claude',
  permissions: { rules: { allow: ['Bash(npm test *)'], deny: ['Bash(rm *)'] } },
});

const host = new SessionHost({
  cogitator: new Cogitator({ memory: { adapter: 'sqlite', sqlite: { path: './sessions.db' } } }),
  agents: {
    assistant: new Agent({ name: 'assistant', model: 'ollama/qwen3:8b', instructions: 'Help.' }),
  },
  providers: { claude },
});
await serveStdio(createAppServer(host));
await host.close();
await claude.close();

Or from the CLI:

cogitator app-server -m ollama/qwen3:8b --acp-agent claude --acp-agent mine="./my-agent --acp"

resolveAcpAgent() knows the presets claude, codex and gemini (launched with npx), registry:<id> for an agent of the ACP registry, and any command line.

How Cogitator decides for the agent

Every session/request_permission of the agent goes through resolvePermission, in the thread's permission mode, with the rules in code, the settings files when asked to read them, and the rules people saved:

The agent's callIs read asRules that name it
execute (a command)run_commandBash(npm test *)
read, search of pathsread_fileRead(src/**)
edit, delete, moveedit_fileEdit(src/**)
fetch of a URLweb_fetchWebFetch(domain:...)
any other toolacp__<agent>__<tool>its name

What the rules allow is allowed, what they deny is refused, and what would ask goes to the client of the turn (approval/request of the app-server). An "always" answer saves the rule for the thread, or to the settings file of permissions.rememberIn, but not for a call known only by its kind (no tool name, command or paths). Without a client to ask, it is refused. A mode the settings files disable, and auto, decide as default. The files and terminals the agent asks for are served from the provider's workspace, inside its root, checked the same way: each request is decided with the mode and the rules of the moment (a call approved earlier in the turn is not asked about again), a terminal's directory and environment are checked with its command, it runs the program the agent names with its exact arguments, and its output is kept up to outputByteLimit (1 MiB by default). Leaving plan mode (switch_mode) always asks, and once approved the thread goes on in the mode the agent picked.

The agent's session follows the thread's permission mode when the agent has a mode of that name (Claude Code does), and the turn's model when the agent offers it. Its threads cannot be forked, rewound or reviewed, and a turn of one takes no steering.

The registry

packages/acp/registry/cogitator/ holds the card of cogitator acp for the ACP registry: agent.json, with the npx distribution of @cogitator-ai/cli and acp as its argument, and a 16x16 icon. The registry lists agents that offer an auth method: cogitator acp offers one that uses the model providers of the configuration, and authenticate says how to set one up when there is none.

On this page