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

millivolt

package module
v0.4.9 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2026 License: MIT Imports: 6 Imported by: 0

README

millivolt

Diagram showing OpenAI Chat Completions, OpenAI Responses, and Anthropic Messages clients routing through one proxy to any configured upstream, with SQLite metadata below

See every AI request. Keep your own routing. millivolt is a patch bay for model traffic. OpenAI Chat Completions, OpenAI Responses, and Anthropic Messages clients plug in on one side. The upstream you choose answers on the other. It can translate when the two ends disagree, pass the request through untouched, and measure the crossing: timing, tokens, cost, retries, outcome. Body capture only when you ask.

millivolt stays a relay, not a platform. No separate provider registry, no API-key vault, no user accounts. One Go binary. One dashboard. One operator or a small team.

Checks and images

Quickstart · Documentation · Docs site · Dashboard guide · Support · Security

Pre-1.0 · Linux · MIT · single operator or small team. The 0.x series can change configuration and API details between releases.


01 / FIRST RUN

Quickstart

Linux with Docker Engine and the Compose plugin. No Go, Node, or source checkout is needed for the container path.

Docker Compose
curl -fsSL https://raw.githubusercontent.com/LLM-4-People/millivolt/main/compose.yaml -o compose.yaml
export MILLIVOLT_OPERATOR_TOKEN='replace-with-a-long-random-value'
docker compose up -d

Open http://127.0.0.1:8080/ and sign in with that token. If the container exits, run docker compose logs --tail 50.

[!IMPORTANT] One shared operator credential protects the dashboard and operator plane only. Inference is transparent: it forwards your upstream key and does not use the operator token. There are no user accounts. Keep the listener on loopback, or put the network or ingress boundary in front. With the token unset, the dashboard denies every request. Read Security before network exposure.

The Compose file publishes on loopback only. It keeps history and settings in named volumes, runs non-root with a read-only root filesystem, and accepts MILLIVOLT_PORT for an unused host port. For bind mounts, pre-create directories writable by UID/GID 65532:65532; see persistent state. For image selection, backups, updates, shutdown, or protected ingress, see container operation and the reverse-proxy guide.

The published image is ghcr.io/llm-4-people/millivolt:main for amd64 and arm64. Version tags identify releases; pin a digest when exact bytes matter. See versions and images.

From source

Install the Go toolchain required by go.mod, then:

git clone https://github.com/LLM-4-People/millivolt.git
cd millivolt
test -e proxy.yaml || cp proxy.example.yaml proxy.yaml
export MILLIVOLT_OPERATOR_TOKEN='replace-with-a-long-random-value'
go run ./cmd/proxy -config proxy.yaml -listen 127.0.0.1:8080

For isolated development and checks, see Contributing.


02 / CONNECT

Connect a client

Point an OpenAI Chat Completions, OpenAI Responses, or Anthropic Messages client at the proxy. The upstream URL and key stay yours; the proxy does not register providers or keys. The request path selects the client protocol, and X-Proxy-Format selects the upstream protocol.

Client setting Value
API base URL http://127.0.0.1:8080/v1
API key your upstream key. It is forwarded upstream, Authorization by default; it does not authenticate dashboard access.
X-Proxy-Base-URL your upstream API base URL, including its path, such as /v1.
X-Proxy-Client optional label for this client in the dashboard.
curl -sS http://127.0.0.1:8080/v1/chat/completions \
  -H "X-Proxy-Base-URL: $UPSTREAM_BASE_URL" \
  -H "Authorization: Bearer $UPSTREAM_API_KEY" \
  -H 'Content-Type: application/json' \
  -d "{\"model\":\"$UPSTREAM_MODEL\",\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}]}"

A response means the proxy answered; check the status code for the upstream outcome. The request should appear in the dashboard. That is the whole integration.

On a shared Compose network, use http://millivolt:8080/v1 instead of loopback. /v1/chat/completions, /v1/responses, and /v1/messages are all available. Each can reach Chat, Responses, or Anthropic upstreams; only a Chat client can target the Cursor bridge. Read upstream compatibility and cross-protocol translation.

Relay is transparent by default, not byte-identical by contract: buffering, retries, SSE keepalives, translation, and overrides can change bytes. See protocol.


03 / OBSERVE

Dashboard overview

Global totals stay global. Explorer cards, timelines, and the request log share one selected scope. See the visual guide for focused captures of tokens, speed and latency, cost, providers, models, conversations, and Settings.

Screenshot of the millivolt dashboard with global request, token, and cost totals above a scoped request log and timeline

Static capture from an authorized, redacted history snapshot; identifiers are replaced. The offline indicator reflects the capture session, not service health; see capture limitations.


04 / CONTROL

What you get

Three moves: route, watch, intervene.

A Route: your URL, your key

Choose the upstream base URL, credentials, authentication header or prefix, path, and query on each request. Constrain accepted URL prefixes in configuration. Optional adapters translate between OpenAI Chat Completions, OpenAI Responses, and Anthropic Messages through one canonical model; the Cursor Connect bridge is a separate, Chat-only direct path.

B Watch: the request, not just the total

Watch in-flight requests next to global request, token, and cost totals. Open a row for TTFT, throughput, retries, queue wait, token mix, and provider-reported cost. History stays in SQLite; an in-memory ring is available when you do not need retention. Scope by client, provider, model, conversation, tool, status, error, time, or key without losing the selected filter.

C Intervene: before the retry storm

Pause new sends and retries by client, provider, or all traffic; running sends finish. Set provider-wide concurrency, request-rate, and token-rate limits, plus an opt-in anti-burst ramp that eases a new provider+key group up to the concurrency target. Capture scoped debug bodies, export exactly the records you filtered, and turn on error-storm protection with recovery probes. These are operator actions, not per-user permissions.

One Go service also carries the dashboard, SQLite, and a 22-tool MCP server at /mcp. An LLM client needs only the endpoint and its Bearer credential. See the MCP server guide.


05 / BOUNDARIES

What it is not

millivolt is deliberately narrow. It is not a multi-tenant gateway, a billing system, or a compliance audit log.

Boundary What it means
Tenancy Not multi-tenant. One shared operator credential protects the dashboard and operator plane only. Inference is transparent and depends on the network or ingress boundary. There are no per-user accounts.
Accounting Best-effort, not a guarantee. Sustained overload can drop records even when inference succeeds. Backups, capacity, and storage drops are covered in storage and accounting.
Relay contract Transparent by default, not byte-for-byte or exactly-once. Normal paths preserve content, with documented exceptions. See protocol.
Billing and compliance Not an invoice or audit log. Cost is provider-reported; this is not an independent billing system or a complete compliance record.
Portability Linux is the only supported target. See containers.

06 / REFERENCE

Performance and footprint

Small image, not magic RAM. Performance has the measurements and caveats.

Configuration

proxy.example.yaml is the generated, documented example. It includes enabled compatibility profiles without registering provider keys or upstream URLs. Your local proxy.yaml is ignored; do not commit it.

Defaults, example profiles, and validation are defined in internal/config; Settings uses that same schema. See operations for overrides, reloads, backups, and restart requirements.

VERSION owns the application version; versions and images covers publication and verification.

Contributing

Work lands on testing first. main is promotion-only and protected: open a pull request from testing, wait for the required check, and merge with a merge commit. See the branch workflow for the full checklist, version rules, and promotion proofs. Use support for usage questions and the private channel in security for vulnerabilities.


07 / FIELD GUIDE

Documentation

Guide Path Covers
01 Quickstart · container operation First run, images, volumes, shutdown
02 Protocol · adapters Client setup, translation, compatibility
03 Operations · performance · reverse proxy Day-to-day operation and measurements
04 MCP server The 22-tool operator API
05 Architecture Ownership and invariants
06 Contributing · support · security Development, help, reporting

The application is MIT licensed. Dependency notices are listed in THIRD_PARTY_NOTICES.md.

Documentation

Overview

Package millivolt exposes the release identity shared by every build path.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CompareVersions added in v0.3.30

func CompareVersions(a, b string) (int, error)

CompareVersions compares two validated release versions using SemVer 2.0.0 precedence. It returns -1 when a sorts before b, 0 when they are equal, and 1 when a sorts after b. Build metadata is not accepted.

func ValidateRevision

func ValidateRevision(revision string) error

ValidateRevision accepts a full lowercase Git SHA-1 or SHA-256 object ID.

func ValidateVersion

func ValidateVersion(version string) error

ValidateVersion enforces the release naming policy, including numeric prerelease identifiers without leading zeroes. It accepts no whitespace, leading v, or build metadata suffix.

func Version

func Version() string

Version returns the embedded application version, without the file newline.

Types

type BuildInfo

type BuildInfo struct {
	Version   string `json:"version"`
	Revision  string `json:"revision"`
	Modified  *bool  `json:"modified"`
	GoVersion string `json:"go_version"`
}

BuildInfo identifies the running binary. A nil Modified means the source tree's cleanliness is unknown, not clean. Revision is "unknown" when absent.

func CurrentBuild

func CurrentBuild() (BuildInfo, error)

CurrentBuild reads the standard Go build metadata. No subprocess, filesystem scan, clock stamp, configuration load, or network access is needed.

type ReleaseInfo

type ReleaseInfo struct {
	Version    string
	Revision   string
	Prerelease bool
}

ReleaseInfo is validated metadata for the container/release workflow. Tag is optional for default-branch builds; when present it must match VERSION exactly.

func ReleaseMetadata

func ReleaseMetadata(tag, revision string) (ReleaseInfo, error)

Directories

Path Synopsis
cmd
proxy command
release command
Command release validates release metadata and writes GitHub output lines.
Command release validates release metadata and writes GitHub output lines.
stress command
stress measures the real, isolated dev proxy against an in-process local upstream.
stress measures the real, isolated dev proxy against an in-process local upstream.
internal
adminjson
Package adminjson owns the JSON trust boundary for operator mutations.
Package adminjson owns the JSON trust boundary for operator mutations.
backup
Package backup is the single owner of millivolt operator backup archives.
Package backup is the single owner of millivolt operator backup archives.
format
Package format implements the wire codecs for the supported client and upstream protocols and translates between them through the canonical IR.
Package format implements the wire codecs for the supported client and upstream protocols and translates between them through the canonical IR.
format/ir
Package ir defines the protocol-neutral request, response and streaming event model that every wire codec translates through.
Package ir defines the protocol-neutral request, response and streaming event model that every wire codec translates through.
jsonnum
Package jsonnum owns exact decoding of JSON number literals that must be integers.
Package jsonnum owns exact decoding of JSON number literals that must be integers.
mcp
Package mcp wraps millivolt's operator and observability HTTP surface as an MCP server, so an LLM can run analytical queries against a running proxy and drive its safe operator controls.
Package mcp wraps millivolt's operator and observability HTTP surface as an MCP server, so an LLM can run analytical queries against a running proxy and drive its safe operator controls.
scheduler
Package scheduler provides a provider-agnostic, FIFO-ordered request queue with per-group concurrency caps and adaptive rate-limit pacing.
Package scheduler provides a provider-agnostic, FIFO-ordered request queue with per-group concurrency caps and adaptive rate-limit pacing.
sse
Package sse provides minimal, allocation-conscious parsers for extracting metrics from OpenAI-compatible SSE chat completion streams, plus the client-facing frame primitives and completion envelopes (frames.go, envelope.go) the proxy and its format bridges render through.
Package sse provides minimal, allocation-conscious parsers for extracting metrics from OpenAI-compatible SSE chat completion streams, plus the client-facing frame primitives and completion envelopes (frames.go, envelope.go) the proxy and its format bridges render through.
storage
Package storage provides durable per-request storage using an embedded SQLite database.
Package storage provides durable per-request storage using an embedded SQLite database.
web
Package web serves the embedded metrics dashboard.
Package web serves the embedded metrics dashboard.
scripts
licenses command
Command licenses bundles the notices from the exact target binary dependency graph.
Command licenses bundles the notices from the exact target binary dependency graph.
tests
_go
_go/cmd/proxy command
_go/cmd/release command
_go/cmd/stress command
containercheck command
Command containercheck owns only disposable, network-isolated Docker fixtures.
Command containercheck owns only disposable, network-isolated Docker fixtures.

Jump to

Keyboard shortcuts

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