A standalone, agentic LLM shell for your terminal.
Nitro is a local-first agentic coding/chat shell built on llama.cpp, rendered with notcurses. No server, no browser tab, no cloud dependency — just a fast terminal UI driving a local model with tool use, RAG, MCP, Web development server and careful context management.
Most agentic shells assume a hosted API and treat context as free. Nitro assumes neither: it's built for consumer GPUs (developed against an 8GB RTX 5060) where the KV cache is a scarce resource and every tool call has to earn its place in the context window.
-
notcurses TUI — plane-based rendering, modal popups, persistent input history (Up/Down navigation), live
/setcommands for generation parameters, and Kitty keyboard protocol support for reliable input in modern terminals. -
Fragmentation-aware KV cache management —
full_flush_except_system()as a graceful recovery path when sequence removal fragments the cache instead of compacting it; aKVCachePresetenum (F16/Balanced/Compact) coupled to flash-attention settings. -
Dynamic tool-result budgeting —
max_tool_result_size()targets ~75% of remaining context so a single large tool result can't blow the budget. -
Unambiguous tool-call protocol — an explicit
NITRO_END_TOOLterminator so tool boundaries never get confused with model chatter. -
A full sandboxed tool suite — every file operation is scoped to a sandbox root (the directory Nitro is launched in, or an explicit path argument):
Tool Purpose TOOL:LIST,TOOL:READ,TOOL:EXISTSInspect files inside the sandbox TOOL:WRITE,TOOL:APPEND,TOOL:PATCH,TOOL:MKDIRModify files inside the sandbox TOOL:RUNRun a program inside the sandbox, gated by an optional run_allowedallowlistTOOL:CURLHTTP GET via libcurl, with HTML-to-text stripping and a response size cap TOOL:RAGQuery the local RAG index for extra context TOOL:ASKAsk the user directly, for interactive/agentic flows TOOL:GRAPHRender bar charts and tree diagrams as ASCII art from a small JSON schema TOOL:MCPInvoke a tool on a connected MCP server TOOL:PERMISSIONExplicit user confirmation before destructive or irreversible actions TOOL:RESTARTHand off to a fresh session, writing current task context to SESSION.mdfirstTOOL:DATE,TOOL:TIME,TOOL:RND,TOOL:INTROSPECTSmall utility/introspection tools -
MCP client — connect to external Model Context Protocol servers (e.g. JetBrains IDE built-in MCP servers) with
--mcp, filter which tools get exposed with--mcp-filter, and dry-run the resulting system context with--mcp-test. Server connection details live inmcp.json. -
Skills system — load one or more markdown skill files into the static system-prompt prefix at session start with
--skill <name>(no per-turn routing, so it doesn't disrupt the KV cache).nitro.md,persona.md,AGENTS.md, andREADME.mdare auto-discovered from the current directory if present. Theskills/folder ships a starter set covering debugging, TDD, code review, CMake/build troubleshooting, memory-safety review, dependency-free frontend work, SmallBASIC's raylib plugin, free JSON API sourcing, a local-info feed pattern, and a few just-for-fun ones (chess, an ELIZA-style roleplay, generative interactive fiction, a self-scoring introspection game). -
Pure C++ RAG pipeline — semantic chunker, binary
.dbindex, deduplicatingRagSession, with a folder picker for building indexes on the fly. -
Persistent settings — configuration lives in
~/.config/nitro.settings.json, or point at a specific file with-c/--config(defaults tonitro.config.json). -
Test suite — unit tests under
tests/(file operations, string/Unicode utilities, MCP message formatting, the graph renderer), runnable via CTest.
Nitro vendors llama.cpp as a submodule and links everything statically.
git clone --recurse-submodules https://github.com/chrisws/nitro.git
cd nitro
cmake -B build -DLLAMA_BACKEND=AUTO
cmake --build build -j
./build/bin/nitro
cmake -B build-tests -S tests
cmake --build build-tests -j
ctest --test-dir build-tests
-DLLAMA_BACKEND= |
Behavior |
|---|---|
AUTO (default) |
Probes for nvcc; falls back to CPU + OpenMP if CUDA isn't found |
CPU |
Forces CPU with native SIMD optimizations |
GPU |
Non-CUDA GPU path, CPU/OpenMP fallback |
CUDA |
Forces CUDA; fails the configure step if nvcc isn't found |
| Library | Required | Notes |
|---|---|---|
| notcurses | Yes | apt install libnotcurses-dev, or -DNOTCURSES_DIR=<prefix> |
| libcurl | No | Enables TOOL:CURL; apt install libcurl4-openssl-dev, or -DCURL_DIR=<prefix> |
| CUDA toolkit | No | Only for -DLLAMA_BACKEND=CUDA/AUTO with an NVIDIA GPU: apt install nvidia-open cuda-toolkit |
| yyjson | Vendored | JSON parsing for MCP and tool payloads; bundled under yyjson/, no system package needed |
| utfcpp | Vendored | Unicode-aware string handling for chat display; bundled under lib/utfcpp/, no system package needed |
nitro [sandbox-dir] [options]
-m, --model <path> path to a GGUF model
-e, --embed <path> path to an embedding model (for RAG)
-g, --gpu-layers <n> number of layers to offload to GPU
--skill <name> load a skill file into the system prompt (repeatable)
--mcp enable the MCP client
--mcp-filter <name> only expose this MCP tool (repeatable)
--mcp-test print the resolved MCP system context and exit
-c, --config <path> load settings from a specific JSON file
-l, --log <path> write logs to a file
-t, --think disable model "thinking" output
-p, --prompt-permission require explicit confirmation before destructive tool calls
-w, --web-dev-port enables web development mode, web server with reload when the model changes a html file
-b, --backup-path create file backups prior to invoking TOOL::WRITE
-h, --help show this help
A positional argument sets the sandbox root — the directory all file tools (TOOL:LIST/TOOL:READ/TOOL:WRITE/etc.) are confined to. It defaults to the current directory.
nitro/
├── CMakeLists.txt
├── mcp.json # MCP server connection config
├── nitro.config.json # example runtime settings
├── skills/ # markdown skill files, loaded via --skill
├── src/
│ ├── main.cpp # entry point, CLI parsing
│ ├── agent.cpp/.h # tool dispatch, system prompt assembly
│ ├── tui.cpp/.h # notcurses UI, input, rendering
│ ├── config.cpp/.h # settings, persistence, help text
│ ├── llama_sb.cpp/.h # llama.cpp wrapper
│ ├── llama_sb_rag.cpp/.h # RAG session, chunker, indexer
│ ├── mcp_client.cpp/.h # MCP protocol client
│ ├── mcp_format.cpp/.h # MCP message formatting
│ ├── graph.cpp/.h # TOOL:GRAPH ASCII chart/tree renderer
│ ├── curl.cpp/.h # TOOL:CURL via libcurl
│ ├── file.cpp/.h # sandboxed file tool implementations
│ ├── json.cpp/.h # yyjson wrapper
│ ├── string_utils.cpp/.h # Unicode-aware string helpers
│ ├── input.cpp, input_event.h, input_history.h # keyboard input handling
│ └── logging.cpp/.h # log file handling
├── tests/ # unit tests, CTest-driven
├── lib/utfcpp/ # vendored Unicode library
├── yyjson/ # vendored JSON library
└── llama.cpp/ # submodule
GPL2 — see LICENSE.