Skip to main content
blackthorn serve runs an API on your own machine that speaks both OpenAI’s Chat Completions API and Anthropic’s Messages API. It seals each prompt there, so only the engine inside the GPU can read it, and the host and the network see ciphertext. A coding agent uses that local API as its model. bt-api-h3 serves Qwen3.5-9B (qwen3.5-9b-bllm).

Set up blackthorn serve

1

Install the CLI

blackthorn claude and the shared prompt prefix need blackthorn 0.3.0 or newer. Download the prebuilt binary (x86_64 or aarch64, Linux or macOS):
2

Log in and check the engine

3

Start the server

Leave it running while the agent works. Add --verbose to log each request’s size, how much of it the engine already held, and how long it took.

Claude Code

serve speaks Anthropic’s Messages API (/v1/messages and /v1/messages/count_tokens), so Claude Code talks to it directly, with no translating proxy. blackthorn claude starts Claude Code pointed at it.
1

Install Claude Code

blackthorn claude runs the claude on your PATH.
2

Run it

With blackthorn serve running, in another terminal:
Arguments after -- go to claude. For one prompt:
--bare skips Claude Code’s own system prompt, and --tools limits the tools. --tools takes every argument after it as a tool name, so put the prompt right after -p:
If serve listens on another port, pass the same --port to blackthorn claude.
blackthorn claude sets up Claude Code for the engine:
  • API: ANTHROPIC_BASE_URL points at serve, with a placeholder token. serve accepts requests only from this machine and seals them with your Blackthorn API key.
  • Model: the engine’s model for every task, including subagents and small background tasks.
  • Limits: a 32k context (CLAUDE_CODE_MAX_CONTEXT_TOKENS=32768), answers of at most 4,096 tokens, short Bash output (BASH_MAX_OUTPUT_LENGTH=1500), a 10-minute request timeout, and no nonessential traffic. Your environment overrides any of these.
  • Background requests: off (awaySummaryEnabled and promptSuggestionEnabled).
A session recap, which is on by default, starts a few minutes after you leave the terminal. It sends the whole conversation plus an instruction to summarize it. The engine would extend the conversation’s session with the recap and cannot take it back out, so your next message would match no open session, and the engine would read the whole conversation again. Your own Claude Code setup still applies: settings, CLAUDE.md, memory, skills, plugins, agents, MCP servers and output style.

What to expect

The engine keeps each conversation open. Each step sends only the tokens that are new since the last step, so only the first step of a conversation is slow: the engine reads the whole prompt then. Your setup adds to that prompt: CLAUDE.md, the memory index, the skill and agent lists, and an output style all go into it. --bare keeps it short, and the shared prompt prefix saves reading Claude Code’s tools. serve --verbose prints a line per request, for example:
held counts the tokens the engine already had from the earlier steps. When a request starts a new conversation although one was open, --verbose says where the prompt parted from the closest open conversation.
The context is 32,768 tokens, prompt and answer together, so a long Claude Code session runs out of room sooner than with Anthropic’s models. Keeping Bash output short leaves more room for the conversation. Qwen3.5-9B handles simple agent steps, such as reading a file to answer a question, but it is far smaller than the models Claude Code is built for.

Shared prompt prefix

Claude Code’s tool definitions come first in its prompt: about 8,600 tokens interactively, 7,600 with -p. They are the same in every conversation of a Claude Code release, whatever its output style, agents, skills or MCP servers. The engine keeps one shared copy of them. A new conversation starts from that copy instead of reading the tools again. The first conversation to find no copy reads them and publishes them for the next.
  • What is shared: only the prompts built into blackthorn, one per Claude Code release, matched on your machine against your own tokens. Another Claude Code release, or a setup that changes the tool list (such as --disallowedTools, or tool search turned off), shares nothing, and the conversation reads its whole prompt as before. Everything after the tools, including your CLAUDE.md and memory, is always read per conversation.
  • What the host learns: never what the copy holds, but which conversations started from it, so it can tell that you run Claude Code.
  • One copy: interactive and -p prompts have different tools, so they replace each other’s copy.
  • Turning it off: blackthorn serve --no-shared-prefix.
serve --verbose names the shared prompt when a conversation forks the copy (forked Claude Code 2.1.318 (interactive): tools) or publishes it (published …).

Codex

Codex does not work with serve yet.
Codex speaks only OpenAI’s Responses API (/v1/responses) and no longer accepts wire_api = "chat". serve offers Chat Completions and Anthropic’s Messages API, not the Responses API. A Codex provider pointed at serve fails with:

Other agents

An agent that speaks either API can use serve directly, with any API key:
  • OpenAI’s Chat Completions API: base URL http://127.0.0.1:8000/v1. system, tools, assistant tool_calls and tool messages work as in OpenAI’s API. tool_choice may only be auto or none, there are no images, and frequency_penalty, presence_penalty, logprobs and n > 1 are not supported.
  • Anthropic’s Messages API: base URL http://127.0.0.1:8000. Tools and system messages work, including system messages between turns. What a text-only model cannot take is left out rather than refused: an image becomes a note that it was left out, earlier thinking blocks are dropped, and so are tools Anthropic runs itself, such as web search. tool_choice any or tool is taken as auto.
An omitted temperature is 0 (greedy) in both. The Quickstart has examples for both APIs.