Run the NOOA coding agent inside your editor. nooa-acp is an
Agent Client Protocol server, so any
ACP-speaking client — Zed today — can drive the same agent the terminal host
uses: CodeAct, repository tools, a persistent shell, installed skills, workspace
slash commands and durable sessions, with file edits and terminal commands
surfaced as structured activity.
It hosts nooa_cli.coding.CodingAgent directly. Repository instructions
(AGENTS.md), coding tools, summarization, installed nooa.skills entry points
and semantic file and terminal activity therefore have no separate ACP
implementations — fix something here and the terminal host gets it too.
This is new and we would like it exercised. If something breaks, please say so.
uv add nooa-acp # or: uv add "nooa[acp]"There is no default model. Set NOOA_MODEL or pass --model, or the command
exits with a usage error.
Zed launches ACP agents as "external agents". Add NOOA to settings.json
(cmd-,):
{
"agent_servers": {
"NOOA": {
"type": "custom",
"command": "uvx",
"args": ["nooa-acp"],
"env": {
"NOOA_MODEL": "nvidia_nim/nvidia/nemotron-3-super-120b-a12b",
"NVIDIA_API_KEY": "nvapi-..."
}
}
}
}Open a repository, then pick NOOA from the + menu in the agent panel. Zed
runs the command with your worktree as its working directory, so repository
instructions, project skills and sessions resolve against the open project.
Credentials go in env here rather than in Zed's own settings: the agent is a
separate process and inherits only what Zed passes it. Use a secret-manager
wrapper as the command if you would rather not put a key in settings.json.
From a checkout of this repository, point the client at the workspace package instead:
uv run --project "$PWD" --package nooa-acp -- nooa-acpRemote MCP servers you authenticated inside Zed are not usable from an ACP
agent. Zed holds those OAuth tokens itself and does not pass them down, so a
server showing a green indicator in Zed's own UI arrives at the agent either
with no tools at all or with nothing but its authenticate /
__complete_authentication stubs. Local stdio MCP servers are unaffected.
This is a known Zed limitation, tracked in
zed-industries/zed#54410
(open, labelled area:ai/mcp + area:ai/acp). A maintainer has said the
plumbing largely exists and the work is queued, but as of this writing it is
unresolved.
Configure the MCP server directly for NOOA instead — through NOOA's own
.mcp.json — and it works normally, because the agent then owns the
connection and its credentials rather than borrowing Zed's.
nooa-acp --model nvidia_nim/nvidia/nemotron-3-super-120b-a12bThis is a JSON-RPC server, not an interactive program: it speaks ACP on
stdin/stdout and exits when its input closes, so running it in a terminal
without a client does nothing. Launch it this way to wire up an ACP client
other than Zed, or to watch the diagnostics it writes to stderr while a client
drives it. --model accepts any LiteLLM model name or configured NOOA alias.
Creating a session imports Python from the workspace, before you send a prompt. This is deliberate — it is how workspace skills work — but it means opening a folder is enough to execute code it contains. Treat opening a repository with NOOA as equivalent to running its build.
Three paths load workspace code at session/new and session/load:
- Skill roots. Every
.pyfile under.agents/skills,.cursor/skills,.claude/skills, or.claude/commandsis imported. Module-level code runs during import, before anything checks whether the file defines a skill, so the contents are irrelevant. - Workspace settings.
<workspace>/.nooa/settings.yamland the legacy.nooa/config.tomlmay name additional skill roots. Those paths are not confined to the workspace: a relative path escaping it, an absolute path, or a symlink is accepted as written. - Libraries.
<workspace>/.nooa/libs/<package>/is imported and its directory is prepended tosys.pathfor the life of the process. One ACP server serves several workspaces, so a package name there can shadow the same import for later sessions on other workspaces.
The agent runs as you, in a process holding your model credentials. There is no consent prompt on these paths.
Open repositories you would run. For anything else, use an OS-level sandbox, or start a separate server per workspace with credentials scoped to that task.
ACP uses standard input and output for JSON-RPC. Diagnostics are written to standard error. The agent can execute generated Python and shell commands, so use an OS-level sandbox for untrusted tasks. Generated code shares the agent's process environment, including model credentials; launch it with only the credentials and network access that the session may use. Cancellation stops cooperative local work immediately. An in-flight provider request may finish in the background when its client does not support transport-level aborts. Slash commands run on the agent's event loop so they have the same semantics as the native TUI and can safely start agent jobs. An async command is cooperatively cancellable; a synchronous command that blocks that loop cannot be preempted by the current in-process adapter. The planned one-process-per-agent boundary is the safe kill mechanism for that case.
Each ACP session has an independent live agent and allows one foreground prompt
at a time. Sessions are stored in <workspace>/.nooa/sessions, where the TUI
and ACP adapter can share list and replay metadata. These files are inside the
workspace trust boundary: a repository can supply session records that appear
in session/list and are replayed as conversation history by session/load.
Open only repositories whose code and conversation history you trust. The
adapter also advertises session close; closing a live session preserves its
durable history.
The current stdio adapter hosts those live agents in its own process. That is
an adapter-private implementation detail rather than part of the durable
session API: the live-session registry is isolated inside nooa-acp so it can
later be replaced by handles to an agent daemon without changing stored
sessions, the shared coding agent, or the ACP protocol surface.
Python skill packages use the interpreter's normal import machinery. Multiple sessions may use distinct skill package names, but two workspaces must not load different checkouts under the same top-level Python package name in one ACP server process. Launch a separate stdio server for those workspaces. A future one-process-per-agent daemon will make that isolation an OS process boundary.
Installed nooa.skills entry points are loaded into the shared skill registry
but remain opt-in. The agent can activate a relevant skill with
self.skills.activate(["name"]). Stdio MCP servers supplied by an ACP client
are registered and activated as mcp.<name> skills for that session.
Workspace and user skill roots are shared with the terminal host through
layered settings.yaml. New configuration should use:
coding:
additional_skills_dirs:
- ../nemo-oo-skillsThe existing tui.additional_skills_dirs key remains supported during the
migration, as does the older project-local .nooa/config.toml key
[tui].libs_dirs. Packaged libraries declared through nooa.skills, SKILL.md
skills, and standalone Python skills are discovered from each configured root.
Loaded @slash_command methods are advertised through ACP and matching
/command arguments prompts are dispatched through the shared typed command
router. Command discovery is refreshed when loaded skills change.
The current adapter accepts text and resource-link prompts plus stdio, HTTP, and SSE MCP servers forwarded by an ACP client. ACP-transport MCP proxies, additional workspace directories, images, and embedded resources are not advertised yet. An unavailable, duplicate, or unsupported MCP server is skipped with a session warning so it cannot prevent a new or restored NOOA session from opening.