Skip to content

ccbud/qodercli-plugin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

qodercli-plugin

A ccbud sidecar plugin that runs Claude Code and Codex on Qoder by bridging to the official qodercli --acp agent (Agent Client Protocol) — using either your Qoder CLI login or a Qoder personal access token (PAT), with no patching of the CLI. It also exposes an adjustable thinking depth knob.

ccbud forwards standard OpenAI-Chat requests to this plugin; the plugin launches the official Qoder CLI in ACP mode, drives a session over stdio, and relays the agent's streaming output back as a chat.completion stream. Auth, crypto, and inference all stay inside Qoder's own binary — the plugin only speaks its published protocol.

This is the sanctioned successor to the earlier qoder-local-bridge approach: it replaces reused WASM crypto + direct gateway calls with Qoder's own ACP interface (the same one Zed and other editors use).

How it works

@qoder-ai/qodercli ships an official --acp mode ("Starts the agent in ACP mode") — newline-delimited JSON-RPC 2.0 over stdio, the Agent Client Protocol. We run it as-shipped and act as the ACP client:

ccbud host ─POST /v1/chat/completions─▶ qodercli-plugin (Node)
                                     │  1. OpenAI-Chat messages → one ACP prompt turn
                                     │  2. session/new + session/prompt
                                     │  3. stream session/update → chat.completion SSE
                                     │  4. serve fs/terminal/permission for the agent
                                     ▼
                          qodercli --acp   (official CLI; auth + crypto + inference)
                          • initialize / authenticate (reuses your login)
                          • session/prompt → agent_message_chunk / tool_call / plan …
  • src/acp/ — the ACP client: launches qodercli --acp, does the initialize/authenticate handshake, and correlates JSON-RPC requests, responses, and session/update notifications.
  • src/proxy/chatAcp.ts — the OpenAI-Chat ⇄ ACP bridge (prompt building + streaming translation).

Qoder runs as a full agent

Because ACP exposes Qoder as an agent (not a raw completion model), Qoder runs its own tool loop. This plugin runs it in full-agent mode:

  • It advertises client fs/terminal capabilities and auto-approves session/request_permission, so Qoder can read/write files and run commands in the workspace (--cwd, default: the process's current directory).
  • File writes are scoped to the workspace by default; reads and commands are not.
  • ccbud's OpenAI-style tools/function-calls do not round-trip through ACP — Qoder uses its own tools. This bridge is best for chat/ask and agentic edits, not for driving Qoder as a tool-emitting model.

⚠️ Full-agent mode lets the model modify files and execute commands without prompting. Point --cwd at a project you're comfortable letting it change.

Auth

Credential priority is:

  1. The Qoder PAT in CC Buddy's existing API Key field. CC Buddy forwards it as Authorization: Bearer …; older x-api-key forwarding is also accepted.
  2. QODER_PERSONAL_ACCESS_TOKEN in the sidecar environment.
  3. The persisted Qoder CLI login created by qodercli login.

Each PAT is passed only to the matching qodercli --acp child process. Different credentials are never reused across Agent processes, and a rejected PAT fails closed instead of opening or falling back to the interactive login flow. PAT Agents use a private temporary Qoder config directory (removed on shutdown), and Agent-run terminal commands cannot inherit or inject the PAT. With no PAT, the ACP agent restores the persisted CLI login while creating a session and the plugin invokes qodercli-login only when the agent explicitly requires it. The plugin never signs in/out and redacts PATs from forwarded Agent output.

Thinking depth

Send a reasoning knob on the chat request — OpenAI's reasoning_effort or a Responses-style reasoning.effort (both accepted). It is normalized to Qoder's {low, medium, high} and passed to the agent as --reasoning-effort:

{ "model": "Ultimate", "reasoning_effort": "high", "messages": [ ... ] }

minimal|none → low, max|ultra|xhigh → high.

Requirements

  • Node.js ≥ 20
  • @qoder-ai/qodercli (pulled as a dependency; or on PATH / via QODER_CLI_PATH), signed in with qodercli login

Build & run

make dist                       # npm install + bundle the server
node dist/main.mjs serve --port 8899 --cwd /path/to/workspace
curl -N http://127.0.0.1:8899/v1/chat/completions -H 'content-type: application/json' \
  -H 'authorization: Bearer <qoder-personal-access-token>' \
  -d '{"model":"Auto","stream":true,"messages":[{"role":"user","content":"hi"}]}'

Install via ccbud's plugins page → 从 Git 添加 (needs git + Node): ccbud clones, runs make dist, and registers a Qoder service.

Runtime (how ccbud launches it)

ccbud's runtime.exec is a per-platform binary map. A Node plugin has no native binary, so each platform points at a small launcher shim (bin/launch.sh, bin/launch.cmd) that finds node and runs the plugin — so node (≥20) must be on the PATH ccbud spawns with. The shim prefers dist/main.mjs and falls back to the TypeScript source, so the plugin still starts (and reports logged_out) before make dist has run.

Env Default Meaning
QODER_CONFIG_DIR ~/.qoder Qoder config / credentials (also passed to the agent)
QODER_ACP_CWD process cwd Workspace the agent reads/writes/runs in
QODER_CLI_PATH auto Override the qodercli launch (bundle path or executable)
QODER_PERSONAL_ACCESS_TOKEN Default PAT when the request has no CC Buddy API Key

Endpoints

  • POST /v1/chat/completions — OpenAI-Chat (stream + non-stream), thinking depth
  • GET /v1/models — the model aliases (Auto / Ultimate / Performance / Efficient / Lite)
  • GET /healthz, GET /v1/plugin/status, GET /v1/plugin/auth — control plane

All endpoints are loopback-only (Host/Origin are validated) to blunt DNS-rebinding and drive-by browser requests.

Maintenance (qodercli upgrades)

ACP is a stable, versioned protocol, so upgrades are far less fragile than the old bundle-patching approach. If a new @qoder-ai/qodercli changes behavior:

  1. Handshake fails: check initialize — the plugin logs the agent's protocolVersion / capabilities. Bump ACP_PROTOCOL_VERSION in src/acp/protocol.ts if Qoder advances it.
  2. Empty/odd output: the session/update variants moved — adjust updateToDelta() in src/proxy/chatAcp.ts.
  3. Auth loops: confirm the authMethods[].id the agent returns still matches what ensureAuth() sends.

Disclaimer & legal notice

This is an unofficial, independent integration — not affiliated with, endorsed by, or supported by Qoder or ccbud.

  • Official interface. It drives Qoder only through the documented qodercli --acp protocol and your own qodercli login; it does not patch the CLI, reuse its crypto, or call Qoder's gateway directly. Use is still subject to Qoder's Terms of Service — use an account you control, at your own risk.
  • Full-agent autonomy. In full-agent mode the plugin auto-approves the agent's actions, so Qoder can modify files and run commands in --cwd. Scope it to a project you're comfortable with.
  • No redistribution of Qoder's code. The GPL-3.0 license (LICENSE) covers only src/ and this repo's build scripts. @qoder-ai/qodercli is proprietary to Qoder, is a normal npm dependency (not included or relicensed here). Nothing here grants rights to Qoder's code or service.
  • No warranty. Provided "as is" (see LICENSE).

Status

Working: launches the official qodercli --acp, initialize/auth handshake, control plane, streaming text + reasoning with adjustable depth, full-agent fs/terminal + auto-permission, loopback guard, clean shutdown. Verify the streaming inference path against your own qodercli login. Partial / TODO: session reuse across turns (sessions are currently created per request), live model listing, and image inputs beyond data: URLs.

Pure Node standard library at runtime (only dep is the Qoder CLI it drives). Licensed GPL-3.0-only — see LICENSE. Note the disclaimer above.

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors