A local-first, Claude-Code-class AI coding assistant for your terminal — and your browser.
LocalCode is a terminal + web AI pair-programming assistant. It speaks to any LLM (local or cloud), gives the model a curated toolbox (read/write files, run commands, browse the web, view images, manage Jupyter notebooks, etc.), keeps everything you do in a local SQLite session store, and ships extensive controls so the assistant is fast, safe, and inspectable.
Built on Bun + ink (TUI) + Vite/React (Web). Single statically-compiled binary, no Electron, no cloud calls unless you opt in.
localcode # terminal UI (default)
localcode --web # browser UI (opens automatically)- Highlights
- Supported providers
- Requirements
- Install
- Docker
- Quick start
- CLI flags
- Web mode
- Slash commands
- Tools for the model
- Permission profiles
- Memory & skills
- Hooks & sensitive files
- Sub-agents
- MCP servers
- Configuration
- Architecture
- Testing
- License
- Bring your own LLM — Ollama, LM Studio, OpenAI, Anthropic, OpenRouter, Google Gemini, and any OpenAI-compatible URL (Groq, Together, Fireworks, Mistral, vLLM, llama.cpp…). One UI, seven backends.
- Two surfaces, same brain — gorgeous ink TUI and a polished web UI (tabs, dock, voice in/out, drag-drop, PDF, whiteboard).
- Real tool calling with approval gates — diff previews, command previews, per-tool auto-approve, five permission profiles (
default,acceptEdits,plan,dontAsk,bypassPermissions). - Sub-agents on-demand — spawn specialist workers (
architect,debugger,security-reviewer, language reviewers, etc.) from a curated catalog. Switch between them, send extra context, see live progress. - Memory — persistent file-based per-project memory (
user/feedback/project/reference) injected into every system prompt. - Hooks — shell scripts at
PreToolUse/PostToolUse/UserPromptSubmit/SessionStart/Stop/PreCompact/SessionEnd. - MCP support — Model Context Protocol over
stdioorhttp; tools auto-namespaced asmcp__<server>__<tool>. - Cost tracking — per-message cost chip using real OpenRouter / static pricing.
/usagedashboard,/costper-session, token visualizer with sparklines. - Smart inputs — paste an image path → auto-attached as multimodal. Drag-drop files in the web. Voice in/out via Web Speech API. PDF parsing.
- Diagnostics + recovery — process introspection (
/watch <cmd>+/diagnose), conversation branching,/undo, full diff viewer, health watchdog, error banner with retry. - Codebase ontology — TypeScript LSP-powered knowledge graph; new tools
find_call_sites,impacts_of,type_hierarchy. - Architecture rules — declare layering rules in
.localcode/arch.toml; PreToolUse validator blocks forbidden imports. - Built-in security — secret scanner pre-commit hook (AWS / GitHub / OpenAI / Anthropic / Stripe / private-key patterns + entropy heuristic), sensitive-files gating, redaction.
- LAN sharing — mDNS discovery + HMAC pairing + AES-GCM session sync; share a session with a colleague on the same network without any cloud round-trip.
- Multi-user web — two browser tabs on the same session see each other's messages live, with typing presence and colored peer dots.
- Sandboxed
run_command— every shell command runs throughsandbox-exec(macOS),firejail(Linux), or Docker — fully configurable per-platform. - Plan mode — visible 🔒 banner + Ctrl+P hotkey; write & run tools blocked so the model can plan before touching anything.
- Batch approval — when the model emits 3+ mutating tool calls, a single 2-pane dialog reviews them all at once.
- Crash journal + resume — synchronous JSONL per chunk; on next start, offer to resume any session interrupted by SIGKILL / power loss.
- Cost forecast —
~$0.02 next turnchip before sending; cumulative session + today totals in the footer. - Smarter context compression — semantic dedup of repeated
read_fileresults, write/run preserved verbatim, middle summarised via a cheap model. - Image paste TUI — Ctrl+V pastes the clipboard image straight into the conversation (mac / linux / win).
- Skill auto-suggest — when your message matches a skill's
triggersregex, a toast offers Tab-to-activate. - Marketplace browse —
/skills browse(anthropics/skills) and/mcp browse(modelcontextprotocol/servers) install with one keypress. - Migration from Claude Code —
/import claude-codeimports your~/.claude/projects/*/history into the local SQLite. - /metrics dashboard — opt-in tool success rate, cache hit %, cost per model, top expensive sessions — all local.
- i18n — full UI in English and Russian, switchable live; all 6 main overlays fully translated.
| Provider | Type | Setup |
|---|---|---|
| Ollama | Local | Install Ollama, run ollama serve |
| LM Studio | Local | Install LM Studio, enable the local server |
| OpenAI | Cloud | API key via OPENAI_API_KEY or /provider |
| Anthropic | Cloud | API key via ANTHROPIC_API_KEY or /provider |
| OpenRouter | Cloud | API key via OPENROUTER_API_KEY or /provider |
| Google Gemini | Cloud | API key via GEMINI_API_KEY or /provider |
| Custom | Cloud | Any OpenAI-compatible base URL (Groq, Together, Fireworks, Mistral, …) |
Explicit apiKey in ~/.localcode/config.toml wins; environment variables are the fallback. See docs/PROVIDERS.md for per-provider examples.
- Bun ≥ 1.1 — runtime, package manager, and bundler.
- macOS or Linux. Windows is supported via WSL.
- At least one reachable LLM backend (local server or cloud API key).
Pick whichever channel fits your platform — all paths land at the same binary.
VER=0.20.0
curl -fsSL -o localcode.deb \
https://github.com/grosa787/localcode/releases/download/v${VER}/localcode_${VER}_amd64.deb
sudo dpkg -i localcode.deb
# arm64: replace amd64 with arm64 in the URL above.VER=0.20.0
sudo dnf install \
https://github.com/grosa787/localcode/releases/download/v${VER}/localcode-${VER}-1.x86_64.rpm
# arm64: replace x86_64 with aarch64.brew install grosa787/tap/localcodeAuto-resolves the right prebuilt binary for darwin-arm64, darwin-x64,
linux-arm64, or linux-x64. Upgrade later with brew upgrade localcode.
See docs/HOMEBREW.md for tap-bootstrap and maintainer
setup details.
scoop bucket add localcode https://github.com/grosa787/scoop-bucket
scoop install localcodeSee docs/SCOOP.md for bucket-bootstrap and maintainer setup.
# Claude-Code-style installer (clones + builds with Bun)
curl -fsSL https://raw.githubusercontent.com/grosa787/localcode/main/install.sh | bash
# Or pin a version / branch / tag
curl -fsSL https://raw.githubusercontent.com/grosa787/localcode/main/install.sh | LOCALCODE_REF=v0.19.0 bashThe installer detects your OS/arch, installs Bun if missing (via the official bun.sh/install), clones LocalCode into ~/.local/share/localcode, runs bun install && bun run build, and symlinks dist/cli.js. It prefers ~/.local/bin (no sudo); only if that directory isn't writable does it fall back to /usr/local/bin with sudo. Re-running the same command updates an existing install.
Flags & env overrides:
curl -fsSL .../install.sh | bash -s -- --update # git pull + rebuild
curl -fsSL .../install.sh | bash -s -- --uninstall # remove symlink + install dir
curl -fsSL .../install.sh | bash -s -- --verbose # debug output
LOCALCODE_HOME=/opt/localcode bash install.sh # custom install dir
LOCALCODE_BIN_DIR=$HOME/bin bash install.sh # custom PATH dirManual install (existing clone):
git clone https://github.com/grosa787/localcode.git
cd localcode
./install.shTo run without installing:
bun install
bun run dev # alias for: bun run src/cli.tsxLocalCode ships as a multi-arch image (linux/amd64 + linux/arm64) to GitHub
Container Registry: ghcr.io/grosa787/localcode. Tags: latest, vX.Y.Z,
and X.Y.Z per release.
# TUI (needs an interactive TTY)
docker run -it --rm \
-v "$(pwd):/workspace" \
-v "$HOME/.localcode:/root/.localcode" \
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
ghcr.io/grosa787/localcode:latest
# Web UI (port-mapped, no TTY)
docker run --rm -p 7777:7777 \
-v "$(pwd):/workspace" \
-v "$HOME/.localcode:/root/.localcode" \
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
ghcr.io/grosa787/localcode:latest \
--web --web-host 0.0.0.0 --no-openFor local backends (Ollama / LM Studio) running on the host, use
host.docker.internal (Docker Desktop) or add
--add-host=host.docker.internal:host-gateway on Linux. Full usage,
auth, persistence, and compose recipes: docs/DOCKER.md.
localcode # open the current directory
localcode ~/path/to/project # open a specific project
localcode --resume ab12cd34 # resume a session by id prefix
localcode --model claude-3-5-sonnet # override the model
localcode --profile plan # start in Plan Mode (no mutations)
localcode --web # browser UI
localcode --help # full flag list
localcode --versionFirst launch triggers onboarding: pick a backend, confirm the URL, choose a model, and you're in the chat.
localcode [projectRoot] [flags]
| Flag | What it does |
|---|---|
[projectRoot] |
Positional. Path to the project. Defaults to process.cwd(). |
--profile <name> |
Permission profile: default · acceptEdits · plan · dontAsk · bypassPermissions. Overrides persisted config. |
--dangerously-allow-all |
DEPRECATED. Equivalent to --profile dontAsk. Skips approvals. |
--resume <sessionId> |
Resume a session. Accepts full UUID or sufficiently-unique prefix. |
--model <name> |
Override the active model for this run only (does NOT modify persisted config). |
--reconfigure |
Re-run onboarding, overwriting config. |
--no-refresh-models |
Skip startup model-list refresh. |
--web |
Launch the browser-based UI instead of the terminal. |
--web-host <host> |
Bind host for --web. Default 127.0.0.1. Pass 0.0.0.0 to expose on the LAN. |
--web-port <port> |
First port to try for --web. Default 7777. Probes subsequent ports if busy. |
--no-open |
Do not auto-open the browser when --web starts. URL still printed to stdout. |
--lan |
Enable LAN P2P session sharing via mDNS (off by default). |
--help, -h |
Show usage and exit. |
--version, -v |
Print version and exit. |
| Subcommand | Description |
|---|---|
localcode plugin <action> |
Manage plugins: install <path> · uninstall <id> · list · enable <id> · disable <id> |
localcode daemon |
Run the persistent cron daemon (background scheduled wakeups). |
localcode doctor [--json] |
Diagnose installation health: config, backend, models, disk, hooks, MCP, git. |
localcode completion <sh> |
Print a shell-completion script (bash, zsh, fish) to stdout. |
localcode demo |
Replay a short bundled tour that demonstrates what LocalCode can do. |
localcode update <action> |
Auto-update from GitHub Releases (supports delta patches — typical update is ~200 KB). |
localcode --web boots a local server on 127.0.0.1:7777 (configurable), prints the URL with a one-shot CSRF token in the fragment, and auto-opens your default browser.
The web UI features:
- Tabbed sessions (Cmd/Ctrl + 1…9 to switch, Cmd/Ctrl + T new, Cmd/Ctrl + W close).
- Resizable / dockable panels.
- Top-bar icon panels: Tasks · Agents · Browser · Memory · Files · Usage · Notifications · Settings.
- Voice input (push-to-talk) + voice output (TTS) via the Web Speech API.
- Drag-drop files from OS (images become multimodal attachments, text becomes
@path). - PDF parsing with page-by-page preview.
- High-quality whiteboard via
tldraw— sketch a diagram → send to chat as multimodal image. - Mermaid diagrams rendered as SVG, full-screen zoom/pan.
- Light & dark themes.
- Live cost meter, queued-message indicator, error banner with Retry last.
Every slash command runs locally — none are sent to the LLM.
Show all commands
| Command | What it does |
|---|---|
/help |
List every registered command. |
/init |
Scan project & write .localcode/LOCALCODE.md. |
/model [name] |
Open picker or switch directly. |
/provider [...] |
Switch backend (Ollama / LM Studio / OpenAI / Anthropic / OpenRouter / Google / custom). |
/profile [name] |
Switch permission profile: default · acceptEdits · plan · dontAsk · bypassPermissions. |
/style [name] |
Output style: concise · explanatory · verbose. |
/statusline |
Configure the status line template. |
/resume [id] |
Pick or load a session. |
/clear |
Persist a summary, start a fresh chat. |
/context |
Show token usage, active skills, LOCALCODE.md status. |
/ctxsize [n] |
Tune num_ctx and keep-alive. |
/compress |
Compact context into one summary message. |
/settings |
Edit generation params (temperature, top_p, repeat_penalty, max_tokens). |
/permissions |
Toggle per-tool auto-approval. |
/diff [ref] |
Open the full-screen diff viewer. |
/undo [N|list] |
Roll back the last N file mutations from the in-memory snapshot stack. |
/review |
One-shot LLM code review. |
/plan |
Two-phase plan generation. |
/skills |
Manage skills. |
/new-skill |
Paste or supply a path for a new skill. |
/memory |
Open memory entries list. |
/memory-save <id> |
Save a staged feedback proposal. |
/todos |
Open the Tasks panel. |
/usage |
Cumulative usage dashboard with cost per model. |
/cost |
Current-session cost breakdown per turn. |
/perf /tokens |
Token visualizer with sparkline charts. |
/agent |
Run the agentic loop on a task. |
/spawn [id task] |
Spawn a specialist worker from the catalog. |
/agents diff <id> |
Show worktree diff for a sub-agent. |
/branch [...] |
Branching sessions: list · <name> · switch <name> · delete <name>. |
/conv diff A B |
Compare two branches. |
/record |
Record / replay session: start · stop · save · list. |
/replay <file> |
Replay a recording at chosen speed. |
/cron |
Persistent cron schedules. |
/wakeups |
In-session deferred-continuation list. |
/watch <cmd> |
Watch a long-running process (dev server, test runner) for diagnostic signals. |
/diagnose [id] |
Surface compile / test errors from watched processes. |
/arch |
Architecture rules: check · rules · init · ignore <pattern>. |
/ontology |
Codebase knowledge graph: status · refresh · graph <symbol>. |
/secrets |
Secret scanner: scan · scan-all · allow <pattern>. |
/sensitive |
Sensitive-files gating: list · add <pattern> · check <path>. |
/worktrees |
Worktree management for sub-agents. |
/plugin |
Plugin management. |
/share |
LAN P2P session sharing: start · stop · peers · accept. |
/whiteboard |
Open the web whiteboard. |
/filter |
Hide/show thinking / tool calls / system notes in chat. |
/suggest |
Toggle proactive suggestions panel. |
/exit |
Quit and persist the session summary. |
The model gets a typed toolbox. Read-only tools auto-run; mutating tools go through approval (unless pre-approved or under dontAsk).
Read-only / inspect
| Tool | Purpose |
|---|---|
read_file |
Read file under projectRoot; auto-paginate >1 MB. |
list_dir |
Tree listing with .gitignore honoured. |
glob_search |
fast-glob lookup, gitignore-aware, symlink-safe. |
find_symbol |
Symbol search via tsserver. |
find_call_sites |
Ontology query: all callers of a function/method. |
impacts_of |
Ontology query: transitive impact graph. |
type_hierarchy |
Ontology query: ancestors/descendants/siblings. |
lint_file |
Native syntax check (tsc / ruff / go vet / rustc). |
fetch_image |
Download HTTPS or data:image/* URL; attach as multimodal. |
web_fetch |
URL → markdown. |
web_search |
DuckDuckGo top results. |
notebook_read |
Read a .ipynb. |
pdf_read |
Parse PDF pages to text. |
monitor |
Status of a background bash task. |
process_status |
Status of watched processes. |
git_status/diff/log/branch |
Read-only Git ops. |
Mutating (approval required by default)
| Tool | Purpose |
|---|---|
write_file |
Replace file (two-phase preview + commit). |
edit_file |
Unique-string search/replace. |
multi_edit |
Atomic batch edits on one file. |
notebook_edit |
Replace / insert / delete a notebook cell. |
run_command |
sh -c … (optionally runInBackground: true). |
git_commit |
Make a commit (also runs secret-scanner hook). |
todo_write |
Update in-session task list. |
schedule_wakeup |
Defer continuation 60–3600 s. |
spawn_agent |
Spawn a sub-agent worker. |
team_send / team_read |
Inter-agent communication via TeamBus. |
| Profile | read-only | write_file / edit_file |
run_command / git_commit / browser_evaluate |
|---|---|---|---|
default |
run | approval | approval |
acceptEdits |
run | auto | approval |
plan |
run | blocked | blocked |
dontAsk |
run | auto | auto |
bypassPermissions |
run | auto + ⚠ banner | auto + ⚠ banner |
Switch at any time with /profile <name> or Ctrl+P (TUI). Sensitive-files gating overrides every profile.
Memory lives at <projectRoot>/.localcode/memory/*.md. Four types: user / feedback / project / reference. Each entry is a markdown file with YAML frontmatter. The full memory section is injected into the system prompt byte-stably so prompt-prefix caching stays hot. Indexed in MEMORY.md at the root.
Skills are markdown files in .localcode/skills/ (project-local) + ~/.localcode/skills/ (global). Project wins on id collision. Hot-reloaded via chokidar. Manage via /skills and /new-skill.
Hooks are shell scripts wired through [[hooks]] blocks in ~/.localcode/config.toml. Triggers:
PreToolUse— can BLOCK a tool call (non-zero exit → tool fails).PostToolUse— synthetic system note only.UserPromptSubmit— fires before context commit; blocking aborts the turn.SessionStart/SessionEnd/Stop/PreCompact— lifecycle.
Built-in secret-scanner hook auto-registers on PreToolUse:git_commit — refuses to commit AWS keys, GitHub PATs, OpenAI/Anthropic/Stripe/Google keys, private keys, or high-entropy assignments.
Sensitive files at ~/.localcode/sensitive-files.toml (or .localcode/sensitive-files.toml) declare path globs (e.g. .env*, **/secrets/**, *.pem, **/.ssh/**) that always require approval, even under dontAsk.
Spawn specialist workers from the curated catalog (10 templates):
architect · debugger · security-reviewer · typescript-reviewer ·
python-reviewer · rust-reviewer · go-reviewer · test-engineer ·
performance-optimizer · doc-writer
/spawn debugger "find why the migration timed out"Workers run in isolated git worktrees, communicate via TeamBus. In TUI press Tab to enter agent-focus mode, ↑/↓ to select, Enter to attach and chat with a worker; Esc to return to the lead. In the web UI click a worker in the Agents panel to enter reply mode.
Completed workers automatically move to history; toggle visibility per panel.
LocalCode is a Model Context Protocol client. Configure via TOML:
[[mcpServers.my-server]]
type = "stdio"
command = "uvx"
args = ["mcp-server-time"]
[[mcpServers.docs]]
type = "http"
url = "https://example.com/mcp"
headers = { Authorization = "Bearer …" }Tools are auto-namespaced as mcp__<server>__<tool>. Status panel at GET /api/mcp.
All config lives at ~/.localcode/config.toml (global) + per-project overrides at <projectRoot>/.localcode/settings.json. The first run scaffolds defaults; subsequent edits are atomic (temp + rename) and Zod-validated.
Sample:
[backend]
type = "openrouter"
baseUrl = "https://openrouter.ai/api/v1"
[model]
current = "anthropic/claude-3.5-sonnet"
[permissions]
profile = "acceptEdits"
autoApprove = ["read_file", "list_dir"]
[context]
maxTokens = 32768
keepAliveSeconds = 1800
autoCompressPercent = 0.80
maxRecentMessages = 20
[sound]
enabled = false
outputStyle = "concise"
[statusline]
enabled = true
template = "{provider} · {model} · {tokens}/{maxTokens} ({pct}%) · {profile}"Full schema: docs/CONFIG.md.
src/
├── cli.tsx argv + ink mount
├── app.tsx composition root
├── llm/ adapter (OpenAI-compat + Anthropic), context, executor, pricing
├── tools/ 30+ tool implementations
├── sessions/ bun:sqlite, FTS5 search, branching
├── commands/ slash-command factories
├── config/ Zod-validated TOML
├── skills/ chokidar-watched markdown skills
├── memory/ persistent memory entries
├── hooks/ shell-hook engine (7 triggers)
├── mcp/ Model Context Protocol client
├── agents/ orchestrator, TeamBus, worker pool, worktree GC, catalog
├── ontology/ TS LSP knowledge graph
├── architecture/ arch.toml validator
├── security/ secret scanner, sensitive files
├── process-monitor/ watched-process diagnoser
├── networking/ LAN P2P (mDNS + HMAC + AES-GCM)
├── recordings/ session record/replay
├── scheduling/ wakeups + persistent crons
├── web/ REST + WS server, runtime pool, approval bridge
└── ui/ ink TUI (screens, components, overlays)
web-frontend/ Vite + React SPA (Zustand, CSS Modules, tldraw)
Single-process Bun, no daemons (except optional localcode daemon for crons). Web SPA is embedded as base64 in the CLI binary by scripts/embed-web.ts.
bun test # full suite (3196 passing)
bun test tests/llm/adapter.test.ts # single file
bunx tsc --noEmit # type-check
bun run build # bundle to dist/cli.js
cd web-frontend && bunx vitest run # web tests (435 passing)CI: bunx tsc --noEmit, bun test, bun build, and a lint job that fails the build on any : any / <any> / as any / @ts-ignore in src/.
MIT — the LocalCode binary you install is free to use, modify, and redistribute.
LocalCode's distribution lives here: installer, docs, packaging, landing page, and the issue tracker. Active development happens in a separate, private repository.
- Binaries are MIT. Anything you download from Releases is yours to use, fork, and redistribute under those terms.
- Bug reports + feature requests — open an issue. This is where we triage everything.
- Want to contribute code? Open an issue describing the change. We accept code contributions via a short CLA + invite to the private source repo. See
CONTRIBUTING.mdandBUILD_FROM_SOURCE.md.
We picked this layout to keep the public surface focused on real users (downloads, issues, docs) while shipping fast. If you've used LocalCode under MIT, you keep MIT — closing future development doesn't retroactively close past releases.
Made with ☕, late nights, and a lot of /undos.