Lumen — a privacy-first coding harness. Run local LLMs offline, or bring your own OpenRouter key for the full catalogue. Your code never leaves your machine.
Project description
Lumen
A privacy-first coding harness. Run local LLMs offline, or bring your own OpenRouter key for the full catalogue. Your code never leaves your machine when you don't want it to.
Tired of daily limits on hosted coding tools? Lumen is your own agentic terminal coding assistant. Point it at a local model (Ollama, LM Studio, llama.cpp — fully offline) or at OpenRouter's entire model catalogue with a key you control. One interface, both worlds.
┌────────────────────────────────────────┐
│ LUMEN privacy-first coding harness │
│ │
│ provider local │
│ model qwen3-coder:30b │
│ mode offline · code never leaves │
│ this machine │
│ approval prompt before writes / shell │
└────────────────────────────────────────┘
Why
- Privacy first. In
localmode every byte stays on your machine — no network calls at all. Great for proprietary code. - No daily limits. Bring your own OpenRouter key and pay per token, or run entirely free on local hardware.
- The whole catalogue. OpenRouter exposes hundreds of models (Claude, GPT, Gemini, Llama, Qwen, DeepSeek…). Switch between any of them — and your local models — without leaving the REPL.
- A real agent. Not a chat box. Lumen reads and edits files, runs shell commands, and searches your code with an approval gate on anything destructive.
What's inside
- 🔒 Airgap mode —
--airgap(or/airgap) patches the socket layer to hard-block all outbound network. Local model servers keep working; anything that would leave the machine is refused before a byte moves. Privacy you can prove, not just promise. - 🛡 Secret Guard — before any cloud request, Lumen scans outgoing messages for API keys, private keys and
.envvalues, and lets you block or redact them. Inlocal/offline mode it's skipped entirely — nothing leaves the machine. - 📝 Diff before write — every
write_file/edit_fileshows a colored unified diff before it's applied; approve withy/n/a. - ↩ Undo —
/undoreverts the last file change (restores edits, deletes newly-created files). - 💾 Local sessions — conversations are saved under
~/.lumen/sessions/; resume with--continueor--resume <id>, browse withlumen sessions. - 🧠 Project memory — a
LUMEN.md(orAGENTS.md) in your repo is auto-loaded into the system prompt;/initgenerates one by exploring the codebase. - 🔁 Auto-fallback — if a provider errors (local server down, cloud rate-limited), Lumen fails over to the configured
fallbackprovider, warning you if code will now leave the machine. - Runs any local model — parses tool calls even from models that emit them as plain text (
<tool_call>…,<function=…>, fenced JSON), not just those returning structuredtool_calls. - @file mentions — reference a file with
@path/to/filein your prompt and Lumen inlines its contents.
Install
Requires Python 3.10+.
# from this directory
uv pip install -e . # or: pip install -e .
This installs the lumen command.
Quick start
Local (offline, private)
Install Ollama and pull a tool-capable coding model:
ollama pull qwen3-coder:30b # or any tool-capable model
lumen # local is the default provider
Also works with any OpenAI-compatible local server — LM Studio, llama.cpp's
server, vLLM — just point the local provider's base_url at it.
OpenRouter (your key, full catalogue)
export OPENROUTER_API_KEY=sk-or-... # or: lumen config set-key openrouter sk-or-...
lumen -p openrouter -m anthropic/claude-sonnet-4.5
One-shot (scripting)
lumen "refactor utils.py to remove the duplicated date parsing"
lumen -p openrouter -m openai/gpt-4o "explain what main.go does"
In-REPL commands
| command | what it does |
|---|---|
/models [filter] |
list the provider's catalogue (with context & price) |
/model <id> |
switch model |
/provider <name> |
switch between local, openrouter, … |
/providers |
list configured providers (and their fallback) |
/init |
explore the repo and generate a LUMEN.md |
/undo |
revert the last file change Lumen made |
/sessions |
list saved sessions (resume with lumen --resume <id>) |
/guard |
toggle the Secret Guard on/off |
/airgap |
toggle airgap mode (hard-block all network egress) |
/auto |
toggle auto-approve (skip permission prompts) |
/tools |
list available tools |
/cost |
token usage (and $ cost on OpenRouter) |
/clear |
reset the conversation |
/save |
persist current provider/model to config |
/help |
full command list |
Ctrl-D to exit, Ctrl-C to cancel the current line.
Flags: --continue/-c (resume latest session here) · --resume <id> · --yolo (auto-approve) · --no-guard (disable Secret Guard) · --airgap (block all network) · -p/--provider · -m/--model.
Tools the agent can use
read_file · write_file · edit_file · list_dir · run_bash · search (regex/ripgrep) · find_files (glob).
Writes and shell commands prompt for approval by default: answer y (once), n (deny), or a (allow all for this session). Start with --yolo or toggle /auto to run unattended.
Configuration
Config lives at ~/.lumen/config.json (override with LUMEN_HOME). Add or edit providers there — anything OpenAI-compatible works:
{
"provider": "local",
"providers": {
"local": { "base_url": "http://localhost:11434/v1", "model": "qwen3-coder:30b", "offline": true },
"lmstudio": { "base_url": "http://localhost:1234/v1", "model": "your-local-model", "offline": true },
"openrouter": { "base_url": "https://openrouter.ai/api/v1", "model": "anthropic/claude-sonnet-4.5",
"api_key_env": "OPENROUTER_API_KEY" }
}
}
Architecture
lumen/
cli.py argument parsing + interactive REPL + slash commands
agent.py the agent loop: stream → run tools → repeat
session.py conversation state + usage/cost totals
config.py providers, models, keys, preferences
prompts.py system prompt
providers/
openai_compat.py one OpenAI-compatible client for local + cloud
base.py Delta / Completion / ToolCall types
tools/
fs.py read / write / edit / list
shell.py run_bash
search.py regex search + glob find
registry.py schema export + dispatch
ui/console.py rich-based streaming, tool display, permissions
Local and cloud share one client because Ollama, LM Studio, llama.cpp and
OpenRouter all speak the OpenAI /chat/completions dialect — only the base URL
and key differ. Adding a new backend is a config entry, not code.
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lumen_code-0.1.0.tar.gz.
File metadata
- Download URL: lumen_code-0.1.0.tar.gz
- Upload date:
- Size: 92.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c674d8d081f5114d71d96c6cf1d5b044dd21e18480486c22926be25840b08cd5
|
|
| MD5 |
41ba84bfe4a2ee376d63e48e808814e6
|
|
| BLAKE2b-256 |
e425f12786b557b42897bdc0d77bbe5aa6fa6ca886845a41d77294125f4421d8
|
File details
Details for the file lumen_code-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lumen_code-0.1.0-py3-none-any.whl
- Upload date:
- Size: 36.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae069b26fca6d933f5932d616874d274a8b2f4c15361b8d81cd6115e02bece50
|
|
| MD5 |
6b3a65e3fd9d8cd6741c4734368f48ce
|
|
| BLAKE2b-256 |
e60741d743fb7b03e7d66604bcf539619cf4d641269d51e962b9f5f0e85d9b27
|