Skip to main content

Transparent LLM API monitoring proxy

Project description

Malcolm

Malcolm, your AI monitoring

[!WARNING] Malcolm is in early development. APIs and configuration may change between releases.

A transparent monitoring proxy for LLM API calls. Malcolm sits between your LLM client tools (like Claude Code or OpenCode) and the actual model backend, logging every request and response for inspection.

Why?

Tools like claude and opencode construct complex prompts with system instructions, tool definitions, and conversation history. Malcolm lets you see exactly what gets sent to the model. It's useful for debugging, understanding tool behavior, and optimizing prompts.

Quick start

# Either install from `pip`
pip install malcolm-proxy

# Or from `git`
git clone https://github.com/malcolm-proxy/malcolm
cd malcolm
uv pip install -e .

# Start the proxy
malcolm --malcolm-target-url=http://localhost:11434/v1

Then point your LLM tool to Malcolm:

ANTHROPIC_AUTH_TOKEN=ollama \
ANTHROPIC_BASE_URL=http://127.0.0.1:8900 \
ANTHROPIC_API_KEY="" \
claude --model qwen3-coder:30b

Or do both in a single command — Malcolm starts the proxy silently and opens Claude Code already wired to it. With no other arguments, the target defaults to Anthropic:

malcolm --launch-claude

For other backends, combine --launch-claude with the usual flags:

malcolm --launch-claude \
  --malcolm-target-url=http://localhost:11434/v1 \
  --anthropic-api-key="" --anthropic-auth-token=ollama \
  --model=qwen3-coder:30b

When Claude Code exits, Malcolm shuts down. See docs/scenarios.md for one-liners covering Anthropic, OpenAI, and Ollama.

Browse logged requests with the terminal UI:

malcolm tui                          # uses default malcolm.db
malcolm tui --db-path ./other.db     # use a specific database

Terminal UI

Malcolm includes an agnostic TUI for browsing logs directly from the terminal, without a browser.

Two-level drill-down: Request listDetail view (annotations + full JSON with syntax highlighting).

The request list shows ID, timestamp, status code, and duration. When the llm_annotator annotator is enabled, additional columns (model, stream) appear dynamically from annotations.

Key Action
Navigate
Enter Open
Esc Back
n / p Next / previous page
f Toggle follow mode (auto-refresh every second)
c Copy to clipboard (content view)
w Toggle word wrap (content view)
r Reload
t Toggle dark/light theme
q Quit

The TUI reads directly from the SQLite database, so it works while the proxy is running. Use follow mode (f) to see new requests appear automatically, or press r to refresh manually.

Configuration

Environment variables

Core proxy settings via environment variables (or .env file):

Variable Default Description
MALCOLM_TARGET_URL (required) Backend API base URL
MALCOLM_TARGET_API_KEY (empty) API key for the backend. If empty, forwards the client's Authorization header
MALCOLM_HOST 127.0.0.1 Listen address
MALCOLM_PORT 8900 Listen port
MALCOLM_STORAGE_ENABLED true Enable/disable SQLite persistence
MALCOLM_DB_PATH malcolm.db SQLite database file path
MALCOLM_LOG_LEVEL info Log level
MALCOLM_CONFIG_FILE malcolm.yaml Path to the transform pipeline config file

The --launch-claude, --model, --anthropic-api-key, and --anthropic-auth-token flags are CLI-only — they configure the launched client, not the proxy itself, and have no MALCOLM_* env counterparts.

Transform pipeline

Transforms are configured in malcolm.yaml. Each transform is a pluggable module that can modify requests and responses as they pass through the proxy. The list order defines the pipeline order.

transforms:
  - ghostkey
  - translation:
      direction: anthropic_to_openai

Available plugins (the transforms: list accepts both):

Plugin Kind Config Description
llm_annotator annotator (none) Extracts LLM metadata (model, messages, tools, usage) as annotations for the TUI
ghostkey transform (none) Obfuscates secrets (API keys, tokens) before they reach the backend
translation transform direction Protocol translation: anthropic_to_openai or openai_to_anthropic

Transforms mutate the traffic; annotators only observe it and emit structured metadata (no mutation, errors never break forwarding). A single plugin may implement both roles.

Additional plugins can be installed as pip packages — Malcolm discovers them at startup via Python entry points. See malcolm-proxy/malcolm-transform-example for a working reference implementation you can install directly (uv pip install git+https://github.com/malcolm-proxy/malcolm-transform-example) or fork as a template for your own.

See docs/configuration.md for details and docs/scenarios.md for complete setup examples with Claude Code, OpenCode, and various backends (Anthropic, OpenAI, Ollama).

How it works

flowchart LR
    Client["Your LLM tool<br><span style="color: lightgray;">claude / opencode / curl</span>"]
    Malcolm["Malcolm<br><span style="color: lightgray;">localhost:8900</span>"]
    Backend["Real LLM API"]
    DB[("SQLite<br><span style="color: lightgray;">malcolm.db</span>")]

    Client -- request --> Malcolm
    Malcolm -- forward --> Backend
    Backend -- response --> Malcolm
    Malcolm -- response --> Client
    Malcolm -. logs .-> DB

Malcolm acts as a catch-all proxy: it accepts requests in any format (OpenAI, Anthropic, or any other HTTP API), captures the full request, forwards it to the configured backend, captures the full response (including streaming), and stores everything in a local SQLite database for later inspection.

When client and backend speak different protocols, Malcolm can translate between them on the fly. Add translation to the transform pipeline in malcolm.yaml with the desired direction, and Malcolm will automatically convert requests, responses, and streaming events; including path rewriting (from /v1/messages to /v1/chat/completions and viceversa).

See docs/architecture.md for the full architecture overview.

Development

# Install with dev dependencies
uv sync

# Run tests
uv run pytest

# Run the proxy
uv run malcolm

License

Malcolm is distributed under a MIT license. See LICENSE for more details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

malcolm_proxy-0.1.0.tar.gz (2.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

malcolm_proxy-0.1.0-py3-none-any.whl (43.5 kB view details)

Uploaded Python 3

File details

Details for the file malcolm_proxy-0.1.0.tar.gz.

File metadata

  • Download URL: malcolm_proxy-0.1.0.tar.gz
  • Upload date:
  • Size: 2.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for malcolm_proxy-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c961846078aea5e170bb4c3051c02b8c5c7bdbfa98edc8b62d7c3442aede5a2f
MD5 90d337cd4078df1962f530a3a0983528
BLAKE2b-256 2b1a27f6d4694fd730f1c6c6464ffa5e7a5dc7f68037252fda033df3404b3612

See more details on using hashes here.

Provenance

The following attestation bundles were made for malcolm_proxy-0.1.0.tar.gz:

Publisher: publish.yml on malcolm-proxy/malcolm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file malcolm_proxy-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: malcolm_proxy-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 43.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for malcolm_proxy-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a813464a0bd4d909dd087be8c5a17477f9c91610e07cd7776c5e89d51b32840f
MD5 f7a8d90955d9e85dabbbe384bb29f688
BLAKE2b-256 9ad6c53a93092deb3f06032c0f9549bfc5ee12f969e1a021257ade31b6bf7891

See more details on using hashes here.

Provenance

The following attestation bundles were made for malcolm_proxy-0.1.0-py3-none-any.whl:

Publisher: publish.yml on malcolm-proxy/malcolm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page