AI pair programming
in your terminal.
A native Claude client. One binary, no runtime. Reads your codebase, edits files, runs commands — sandboxed by default.
curl -fsSL https://github.com/1ay1/moha/releases/latest/download/moha-linux-x86_64 -o mohaor build from source — Linux x86_64/ARM64, macOS
Everything runs locally. Nothing phones home except the API call.
Streaming with input queueing
Type while the model answers. Your message queues and lands when the stream finishes. No waiting, no interrupted thoughts.
Sandboxed by default
bash runs inside bwrap (Linux) / sandbox-exec (macOS). Workspace and system libs reachable; ~/.ssh, /etc, other projects read-only. Even an approved command can't exfiltrate keys.
Air-gapped SSH
One command: moha airgap user@host. SOCKS5 over SSH, TLS end-to-end with the real upstream. The tunnel can't MITM you.
16 tools, purpose-built widgets
read, write, edit, bash, grep, glob, list_dir, find_definition, web_fetch, web_search, todo, diagnostics, git_*. Diffs render as diffs. Search results group by file.
Persistent threads
Conversations persist under ~/.moha/. Browse, fork, and delete from ^J. Resume any thread exactly where you left off.
Permission profiles
Write — autonomous. Ask — prompt before Exec/WriteFs/Net. Minimal — prompt for everything except Pure. Cycle with S-Tab.
The niche pick for single-binary, air-gapped Claude.
| moha | Claude Code | aider | |
|---|---|---|---|
| Language / runtime | C++26 — static binary | TypeScript / Node | Python |
| Footprint | ~9 MB | npm + Node runtime | pip + Python runtime |
| Air-gapped mode | Yes (SOCKS5 over SSH) | No | No |
| Auth | OAuth (Pro/Max) + API key | OAuth + API key | per-provider env vars |
| Models | Claude (Anthropic) | Claude (Anthropic) | many (OpenAI / local / …) |
| Sandbox | bwrap / sandbox-exec | No | No |
Multi-model? aider. Anthropic's first-party experience? Claude Code. Single binary with no runtime and air-gapped SSH? moha. Read more →
Pure-functional update loop. Strong types. Zero runtime.
Elm architecture
Pure-functional (Model, Msg) → (Model, Cmd). The reducer is one std::visit over a closed event sum. View is a single function Model → Element.
Strong ID newtypes
ThreadId, ToolCallId, ModelId, CheckpointId — swapping arguments is a compile error, not a debugging session.
maya TUI engine
Rendering delegated to maya, a sister header-mostly TUI engine. SIMD frame diff, Yoga flexbox layout, 69 widgets. moha builds widget Configs from Model state; maya owns every glyph.
Effect-based permissions
Tools declare EffectSet capabilities: ReadFs, WriteFs, Net, Exec, Pure. The permission policy reads these tags and only these — no per-tool overrides, no stringly-typed trust.