Skip to content

Feature: register custom/third-party ACP runtimes (e.g. Hermes, self-hosted, SSH-bridged agents) #16

Description

@rexamus

Summary

Today the ACP runtime registry is hard-coded to four entries — codex-acp, claude-acp, gemini-acp, kilo-acp — in apps/desktop/src/features/ai/utils/runtimeMetadata.ts (RUNTIME_METADATA). The customBinaryPath setting in AIProvidersSettings.tsx only overrides the binary path for those four IDs; it doesn't allow registering a new runtime.

This means users with their own ACP-speaking agents (Hermes, internal tooling, fine-tuned wrappers, SSH-bridged remote agents, etc.) can't connect them to NeverWrite — even though Zed and other ACP clients let you do this with a few lines of config.

Use cases

  • Custom memory/indexing wrappers — agents that wrap an LLM with their own persistent memory store. Routing prompts through them via ACP captures the conversation + file context into that memory; routing through the built-in Claude/Codex runtimes does not.
  • Remote agents over SSH — running an ACP server on a workstation/cluster and tunneling stdio over SSH from the laptop running NeverWrite.
  • Fine-tuned or self-hosted models — anything that speaks ACP/JSON-RPC over stdio.
  • OSS ACP runtimes that ship later — avoids needing a NeverWrite release every time a new ACP agent appears.

Proposed shape

A user-defined runtime entry, configured in Settings → AI Providers, with at minimum:

Field Notes
id user-chosen, must be unique
name display name
command program to launch (absolute path or PATH-resolved)
args array of arguments
env optional environment variables
cwd optional working directory
capabilities optional override; default to a conservative set

Persisted in the same settings store the existing runtime overrides use. Spawned the same way the built-in ACP sidecars are spawned (stdio JSON-RPC).

Why this is low-risk

  • ACP is already the transport for the four built-ins, so the spawn/lifecycle/IPC code paths exist.
  • The change is essentially: turn RUNTIME_METADATA from a const array into [...builtIns, ...userRuntimes], and add a small CRUD UI in AIProvidersSettings.tsx.
  • Capability discovery already happens at runtime via the ACP handshake, so the hard-coded capabilities arrays in runtimeMetadata.ts are nice-to-have hints rather than load-bearing.

Workaround until then

Users can sacrifice one of the built-in slots (e.g. Kilo) by pointing its customBinaryPath at a wrapper script that exec's their own ACP server. This works but mislabels the runtime in the UI and inherits Kilo's hard-coded capability list.

Happy to contribute

If a maintainer signals this is in scope, I'm willing to take a stab at a PR. Wanted to file the issue first so the design isn't wasted effort.

Activity

  1. jsgrrchg commented on May 2, 2026

    @jsgrrchg
    Owner

    Thanks for opening this.

    I agree this is in scope for NeverWrite, it hasn't been done because the app is VERY young, less than 3 months old source code, and it has a very delicate ai change control layer that I needed to nailed for the main providers before exploring others. This is the most difficult part. Because of NeverWrite's ethics, we need to make sure that the review layer always work, is the only way I found myself confortable to build something like this, where users are in control of what AI reads and writes. Every single tool needs to be registered and informed to the users in the streaming of the chat, no ofuscation of any kind. In vendor you can see that I have custom ACP to provide all of goodies from codex, that is not possible on the current zed implementation of the same acp.

    The codebase still needs a lot of love. During the previous heavy development phase, I explored several different paths to make the idea work the way I wanted, so you’ll definitely find some noodle code here and there. This issue is part of the technical debt that we need to address. There are also a lot of inline comments documenting edge cases, decisions, tradeoffs, and things like that. It was messy, but that phase has ended. NeverWrite now feels like a product with a real identity, so we can move full speed ahead, give users all the bells and whistles of ACP, and expand the provider library from 4 providers to all of them. I've studied extensively the source code of zed, I even have a fork of it, there are a lot of inspiration from there in NeverWrite, so I have a clear picture on how to move foward for more official agents.

    That will also take time, and a lot of API credits, because every provider needs to be extensively tested and tuned to work properly with the diff engine. Each provider has its own quirks, so they all need to be tested carefully and adapted where needed. I'd also LOVE some help in this regard, so we can talk more if you want to collaborate, I really want to make this the best open source agentic markdown workspace for everyone, and that's a BIG project for someone that picked up programming after 10 years of no code and with no prior formal dev experience or formation, so I will take every helping hand in the way.

    Also, unlike a code editor, this app is atracting and will continue to do so, non technical people (there is currently an issue of someone who didn't even had claude code installed in their computer). So me need to protect the review changes and the bundled acp (codex and claude) for normal folks. UI wise, in the settings window, it needs to be very clear what is intended for normal users with a different section for power users so they can setup there their own ACP config, and a way to reset all custom acp to factory with a clear button.

    Going back to the specifics of your issue, it makes me think, the priority is to offer power users as soon as possible with a way to setup custom acp, so here are my thoughts about it:

    The current customBinaryPath override is useful as an escape hatch, but it is not a real custom runtime registration mechanism. It still forces users to “borrow” one of the built-in provider slots, which means the UI label, auth assumptions, setup status, and backend validation all continue to behave as if the runtime were Codex/Claude/Gemini/Kilo.

    A clean implementation should introduce an explicit runtime registry with two sources:

    • Built-in runtime definitions
    • User-defined ACP runtime definitions persisted in settings

    The backend should own the authoritative registry, since it currently validates runtime IDs, resolves launch commands, reports setup status, and starts ACP stdio processes. The frontend should then render the runtime descriptors returned by the backend instead of treating the static provider catalog as the source of truth.

    For a first version, I think custom runtimes can be conservative:

    • id
    • name
    • command
    • args
    • optional env
    • optional cwd
    • optional/default capabilities
    • no provider-specific managed auth by default

    That would support wrappers, SSH bridges, self-hosted agents, and future ACP-compatible runtimes without requiring a NeverWrite release for each one.

    So yes, I’d be very happy to review a PR in this direction. The main thing I’d ask is that it avoids only patching RUNTIME_METADATA; custom runtimes need to pass backend validation and spawn through the same ACP lifecycle without inheriting assumptions from the built-in providers. Please also test extensively to make sure your changes don’t interfere with the bundled providers, the auth flow, or the app’s review/change layer, we need to think about the normal folks and getting this tech reliably on their hands.

    I won’t be committing changes over the next three days — I need to touch some grass — so if you’re able to move ahead, please do it against the current main branch. Looking forward to the PR and to learning from you :)

    Best,

    José.

  2. Repository owner locked and limited conversation to collaborators on May 2, 2026
  3. converted this issue into a discussion #17 on May 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions