Help us shape the future of Go! Take the 2026 Go Developer Survey

janus

module
v0.9.0-rc.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2026 License: MIT

README

Janus

test

A local proxy, written in Go, that bridges Claude Code to both the Anthropic API and a local model in LM Studio. Claude is the brain, the local model is the workhorse, and Janus decides which one each piece of work needs, local-first, to keep upstream token spend down.

Status: M6 (privacy) complete; M5 and M7 to come. Janus is a transparent proxy that keeps the books and can send chosen requests to the local model by rule. Claude Code's subagents can run on LM Studio while the main conversation stays with Claude, with no change to Claude Code: see the recipe.

There are three levels of trust in the local model, each a rule: shadow runs it alongside Claude and only compares; local-then-escalate checks each local answer and asks Claude instead if it is broken; local uses it outright. If LM Studio is down, requests go to Claude; and a rule can have the local model stand in when Claude is down. The checks catch broken answers, not wrong ones.

With features.guard on, Janus looks for credentials in requests going upstream and records what it finds. With guard.redact as well, it replaces each one with a placeholder before the request leaves and puts it back in the answer, so Claude can use a secret without seeing it. A local-only policy goes further: name files, directories, or a marker, and what is in them is withheld from Anthropic whatever it looks like, or the request is answered by the local model instead. janus audit shows what went to Anthropic and, with -verify, re-reads what was sent to check it. See the guard.

janus mcp is a separate piece: an MCP server giving Claude a tool that has the local model read files and report back. It trades time for upstream usage at a steep rate (41% less cost and 12 times slower, on the task that suited it best), and Claude only uses it when asked; read the recipe before using it.

Using it

About the project

Installing

Download the archive for your machine from the releases page, check it, and unpack it. There is one binary and nothing else to install.

# macOS on Apple silicon. Put the current version in place of 1.0.0; the
# other builds are darwin_amd64, linux_amd64, and linux_arm64.
curl -LO https://github.com/risadams/Janus/releases/download/v1.0.0/janus_1.0.0_darwin_arm64.tar.gz
curl -LO https://github.com/risadams/Janus/releases/download/v1.0.0/checksums.txt
shasum -a 256 -c checksums.txt --ignore-missing
tar -xzf janus_1.0.0_darwin_arm64.tar.gz
./janus_1.0.0_darwin_arm64/janus version

On Windows, download janus_1.0.0_windows_amd64.zip, unpack it, and run janus.exe from a terminal. Compare its SHA-256 with checksums.txt using Get-FileHash.

The binaries are not signed. A copy downloaded with a browser on macOS is quarantined and will be refused; curl does not set the quarantine, or clear it with xattr -d com.apple.quarantine janus.

With Go 1.25 or later you can build it instead:

go install github.com/risadams/janus/cmd/janus@latest

Running

janus doctor   # check the setup first
janus

janus doctor checks the config, the port, the upstream, LM Studio, and the log directory, and says what to fix. It writes nothing.

Janus prints the address it is listening on and the exact command that points Claude Code at it:

ANTHROPIC_BASE_URL=http://127.0.0.1:8787 ENABLE_TOOL_SEARCH=true claude

Your credentials pass through untouched, and so does everything else, with one exception: on Messages requests Janus asks the upstream to compress with gzip rather than brotli or zstd, so that it can read the response. Settings live in janus.config.json, written on first run; see Configuration.

Janus writes a ledger and captures under logs/. The ledger is one line per request with token usage and no content. Captures are the full requests and responses, including your prompts and code; they are kept for a week by default and can be switched off.

./janus stats -since 24h

shows tokens, cache hit rate, and estimated cost by request class, model, and backend.

Testing

go test ./...

License

MIT

Directories

Path Synopsis
cmd
janus command
audit.go — the `janus audit` command: what left this machine.
audit.go — the `janus audit` command: what left this machine.
internal
anthropic
Package anthropic holds the Messages API wire types: requests, content blocks, and stream events.
Package anthropic holds the Messages API wire types: requests, content blocks, and stream events.
backend
Package backend defines the interface every model backend satisfies, and its two implementations: the upstream Anthropic API and local LM Studio.
Package backend defines the interface every model backend satisfies, and its two implementations: the upstream Anthropic API and local LM Studio.
capture
Package capture writes the readable per-request logs: a Markdown render plus the raw request and response.
Package capture writes the readable per-request logs: a Markdown render plus the raw request and response.
config
Package config loads and validates the config file, layered with flags and environment overrides.
Package config loads and validates the config file, layered with flags and environment overrides.
guard
Package guard finds secrets in what is about to leave the machine.
Package guard finds secrets in what is about to leave the machine.
guard/guardtest
Package guardtest holds the corpus of invented secrets that the guard's tests, and the leak tests, are run against.
Package guardtest holds the corpus of invented secrets that the guard's tests, and the leak tests, are run against.
ledger
Package ledger writes one decision record per request to an append-only log, and computes the cache-weighted cost figures reported by janus stats.
Package ledger writes one decision record per request to an append-only log, and computes the cache-weighted cost figures reported by janus stats.
mcp
Package mcp is a small Model Context Protocol server: enough of the protocol to offer tools to a client over standard input and output.
Package mcp is a small Model Context Protocol server: enough of the protocol to offer tools to a client over standard input and output.
proxy
Package proxy is the HTTP front door: it accepts Messages API requests from the client, runs them through the pipeline, and relays the chosen backend's response, streaming included.
Package proxy is the HTTP front door: it accepts Messages API requests from the client, runs them through the pipeline, and relays the chosen backend's response, streaming included.
route
Package route classifies requests and applies the routing policy that picks a backend for each one.
Package route classifies requests and applies the routing policy that picks a backend for each one.
shadow
Package shadow runs a request a second time on the local model, after the real answer has gone out, and records how the two compare.
Package shadow runs a request a second time on the local model, after the real answer has gone out, and records how the two compare.
validate
Package validate decides whether a local model's answer is fit to give to the client, or should be thrown away in favour of asking Claude.
Package validate decides whether a local model's answer is fit to give to the client, or should be thrown away in favour of asking Claude.
worker
Package worker holds the tools janus offers Claude for handing work to the local model: reading that would otherwise fill Claude's context, done locally, with only a short answer going back.
Package worker holds the tools janus offers Claude for handing work to the local model: reading that would otherwise fill Claude's context, done locally, with only a short answer going back.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL