Babitdor/NovaCode

A powerful open-source terminal-based AI coding assistant that runs in your terminal, Built on top of the deepagents library which provides the core agent architecture.

Python

2

469 commits

updated Oct 17, 2026

See the code

README

Nova CLI Banner

NOVA : Agentic Coding Tool

Version License: MIT Python

An open-source, terminal-based AI coding assistant built on LangGraph and the deepagents framework. NOVA runs entirely in your terminal with a Textual TUI, a headless non-interactive mode for scripting and CI, and remote bridges for Discord/Telegram — similar to Claude Code, but extensible and transparent.

Nova CLI Preview

Features

Core Intelligence

  • LangGraph Agent Loop: Deep agent architecture with planning, subagents, filesystem access, and tool-calling — all orchestrated through a shared async event loop
  • Multi-Provider LLM Support: OpenAI, Anthropic, Google Gemini, NVIDIA, OpenRouter, OpenCode, and local Ollama — configure any provider via environment variables, the OS keychain, or the onboarding wizard, and switch with /model. Thinking models round-trip their reasoning_content, so multi-turn tool use works on providers that require it
  • Autonomous Learning System (Hermes): Periodically reviews tool usage patterns, extracts lessons, and autonomously creates reusable skills — the agent improves itself over time without user intervention
  • Memory System: Two-tier persistent memory — auto-maintained markdown files (USER.md/MEMORY.md) plus a LangGraph key/value store (remember/recall) for cross-session facts
  • Context Management: A three-stage pipeline sized to the model's actual context window — older tool results are cleared first (and offloaded to /cleared/ so the agent can read them back instead of losing them), then the conversation is compacted hierarchically, with a hard backstop that always keeps an 8k-token reserve. The pre-compaction transcript is archived to ~/.nova/sessions/<thread>/, and the context meter survives /resume
  • System One Compaction (experimental): Nova can ask Jev or a compatible local/custom decision model whether each old tool result is still needed, and clear only results scored stale. Configure Jev through /auth, or supply a custom System One endpoint and model. Cleared results are offloaded to /cleared/. Off by default; see System One Compaction
  • Native Vision: A multimodal main model sees pasted images directly; a text-only one gets them captioned by an auxiliary vision model. Capability is detected from the model profile and can be overridden with /vision
  • Council Planning: /council <task> has several agents propose plans independently, critique each other anonymously, and vote; a judge picks the top 3 and nothing is implemented until you approve one
  • Research Swarm: /research fans a question out to 7 research personas (web researcher, fact checker, literature reviewer, market analyst, financial analyst, technical researcher, synthesizer) and merges their findings
  • Plan Mode with Stored Plans: Read-only investigation, then a plan you approve. A plan you approve is saved to the project's .nova/plans/; a plan Nova approves on its own (auto-approve) goes to the global ~/.nova/plans/<project>/ archive
  • Steering Instructions: Persistent user-defined directives injected into every model call — set once, always respected
  • Inline Verification Loop: After each task, an out-of-band LLM call grades the output against a rubric — on a failing verdict, the agent is automatically re-driven with feedback (up to 3 retries). Fail-open by design
  • Prompt-Template Hill Climbing: When reviews repeatedly flag the same class of misunderstanding, the system proposes a targeted rewrite of the relevant .jinja template, A/B tests it against the current version using verifier pass/fail as the quality signal, and promotes or discards it. Packaged templates are never modified — all overrides live in ~/.nova/prompt_history/
  • Threshold Auto-Tuner: Reads the durable trace data Hermes already records and nudges review-trigger thresholds toward the observed working style — more real work ⇒ review sooner; more browsing ⇒ review less. Damped convergence with hard floor/ceiling bounds
  • Cron / Heartbeat Scheduler: Proactive scheduled tasks via standard 5-field cron expressions — fired jobs go on the same queue as remote bridges, so they run like any prompt. Manage with /cron
  • Webhook Ingress Server: Let external systems (GitHub, Linear, or any signed sender) trigger a Nova run without a human relaying through Discord/Telegram. Per-source HMAC-SHA256 secrets, timing-safe verification, binds to 127.0.0.1 by default. Manage with /webhook
  • Reasoning Effort Control: Dynamically adjust LLM reasoning effort (/effort low|medium|high|off) — hot-swaps the model without restarting. Supports OpenAI o-series, Gemini 2.5/3, and Claude 3.7 Sonnet
  • Self-Evolution Log: Track the agent's own growth over time (/evolution) — skills unlocked and levelled up at the completion of complex tasks, persisted in durable store
  • Autonomous Goal Mode: Set a persistent goal (/goal <text>) that is injected into every turn, with an optional acceptance rubric (/goal rubric <criteria>) graded by deepagents' RubricMiddleware. The agent runs autonomously toward the goal (capped at 5 turns by default) and stops when it declares GOAL ACHIEVED
  • Side Questions: Ask a question on an ephemeral thread without touching the main conversation (/btw <question>)
  • Refinement Loop: /refine runs a refinement audit trail over the session's work, with history and rollback <id> subcommands
  • Headless Mode: Run a single prompt non-interactively and exit (nova -p "...", or pipe the prompt on stdin) with text, json, or stream-json output — built for scripting and CI. --max-turns caps the run; --deny-tools auto-rejects tool approvals (fail-closed)

UI & Interaction

  • Textual TUI: Modern terminal UI with chat messages, modals, animations, keyboard shortcuts, condensed tool groups, and click-to-copy
  • Built to Stay Smooth: Status ticks repaint in place instead of reflowing the screen, rendered Markdown is cached per width, static data stays out of checkpoints, subagent graphs compile on first use, the skill listing is cached across restarts, and garbage collection is tuned to run while you are idle. A watchdog logs any UI freeze over 1s to ~/.nova/logs/freeze.log
  • Multi-line Prompt: The input grows with its content; shift+enter inserts a newline
  • Parallel Session Panes: Run several sessions side by side (/session new, ctrl+n, alt+<n>) and switch between them
  • Cross-project Agent Messages: Address another live tab with @tab:<session-id> <message> or @<unique-title> <message>. Tab addresses appear in @ autocomplete. Requests queue while the recipient is busy; linked final replies appear in collapsed Markdown panels in both transcripts. Expand a panel to read it, use Attach to prompt to append it to your draft, or Open tab to navigate to the peer. Attachment never submits the draft or stops your current task. Agents can use list_sessions, send_session_message, read_session_messages, and reply_session_message. Each recipient keeps its own project and tool approvals. Only the explicit message is shared. Communication currently covers tabs in one Nova window; pending messages are held in memory. Use the explicit @tab: form when a title also names a file or subagent. Peer messages are agent prompts; slash-command text inside them is context rather than a CLI command.
  • Docked Todo Checklist: The todo list stays on screen and can be clicked to collapse/expand
  • Condensed Tool UI: Consecutive tool calls grouped into collapsible sections — full diffs shown for code edits; reads, searches, and other calls stay compact
  • Syntax-Highlighted Diffs: Diff previews are syntax-highlighted per line (Pygments, keyed off the file extension) — token colours overlay the +/- marker colour, so added/removed lines stay visually distinct
  • Modal Animations: Entrance effects (fade/slide/zoom) for all modal dialogs, pulsing borders, and a shimmer status bar
  • Web Chat UI: Launch a local browser-based chat interface via /chat — dark-themed, Claude-inspired, with Markdown rendering and code highlighting
  • Nova Cowork Desktop App: Launch a desktop companion app via /cowork (alias /desktop) for a native window onto the same agent
  • Local Voice I/O (optional): Speak prompts and hear Nova's prose replies, fully offline — Faster-Whisper (STT), Silero VAD (utterance endpointing), and Piper (TTS). Push-to-talk (ctrl+g) or hands-free always-listening (ctrl+l); code blocks are stripped before speaking. One-command install: uv tool install -e .[voice], or uv pip install -e '.[voice]' for uv run; manage with /voice. Swappable TTS/STT providers: cloud (ElevenLabs / Deepgram), Orpheus — an optional, very natural LLM-based local TTS (/voice settings tts orpheus; uv pip install -e '.[voice-orpheus]' + the CPU llama-cpp-python wheel; ~2GB model, slower than Piper), Parakeet — NVIDIA's local STT via sherpa-onnx (/voice settings stt parakeet; uv pip install -e '.[voice-parakeet]'), or Pocket TTS — Kyutai's lightweight local TTS (/voice settings tts pocket; uv pip install -e '.[voice-pocket]')

Tools & Capabilities

  • 50+ Built-in Tools: File operations, shell commands, web search (Tavily + DuckDuckGo), docs search, HTTP fetch, subagent delegation, semantic code search, project graph queries, wiki management, plan mode, artifacts, background tasks, daemons, a persistent Python kernel, and more. Rarely used tools are deferred behind tool_search, so they cost no context until needed
  • Artifacts: Create, update, and list durable artifacts (create_artifact, update_artifact, list_artifacts) that persist across resume — browse them with /artifacts
  • Background Tasks: Long-running shell jobs are monitored and reported back when they finish; inspect them with list_background_tasks, get_task_status, get_task_logs, terminate_task, restart_task, or the /tasks panel
  • Daemons: Start, stop, and tail long-lived background processes (daemon) — dev servers, watchers, and the like
  • Persistent Python Kernel: Run Python in a long-lived kernel that keeps state between calls (python_kernel)
  • Multi-Model Oracle: Ask several models the same question and have a judge synthesize the best answer (oracle)
  • Web Scraping: GitHub trending repos, Hacker News headlines, LinkedIn jobs, Reddit posts — no external API keys required
  • Semantic Code Search: Find code by description or meaning, not just exact text matches (code_search, find_related_code)
  • LSP Integration: Language Server Protocol support for go-to-definition, find references, rename, diagnostics, and more
  • Project Graph: Visualize and query your codebase architecture — 5000+ nodes, community detection, dependency analysis, blast radius tracking

Extensibility

  • MCP Support: Extend capabilities with Model Context Protocol servers (14 curated presets, plus any custom server) — tools eagerly discovered with server-prefixed names to avoid collisions Presets: Playwright, Serena, Context7, Apify, CUA Driver, Sequential Thinking, Chrome DevTools, Firecrawl, Tavily, Exa, and Perplexity. Perplexity requires an API key; select it in /mcp to configure it.
  • Skills System: 50+ built-in skills with progressive disclosure — domain-specific workflows loaded on demand. Install skills from any public GitHub repo
  • Plugin System: Python entry-point based plugins that can register slash commands, add middleware at defined slots, and extend the agent
  • Custom Subagents: 4 built-in in-process specialists (code exploration, refactoring, bug fixing, browser automation), plus the 7 research-swarm personas and any agents you define yourself. Longer, self-contained jobs go to the async agents below
  • Async Subagents: 9 background agents on a LangGraph server that Nova launches itself, on demand, in your project directory (no Docker needed) — documentation updates, code reviews, test generation, dependency audits, refactoring, plan scouting, security audits, test runs, web research; results are automatically reported when the agent is idle. Without a usable server Nova falls back to the in-process subagents
  • Wiki System: Persistent project wiki at .nova/wiki/ — ingest web clippings (/ingest), ask questions with wiki context (/ask), file conversation knowledge as wiki pages (/file), and browse the vault (/wiki)

Sandbox & Safety

  • Sandbox Execution: Run code safely in sandboxes — OS (workspace-confined), Docker, Modal, Runloop, Daytona, LangSmith (hardware-virtualized microVMs)
  • Security-First: Automatic .gitignore enforcement, command injection detection, URL sanitization, and input validation
  • File Recovery: Automatic snapshots before destructive operations — restore deleted or overwritten files via /restore or agent tools (list_trash, restore_file)
  • Human-in-the-Loop (HITL): Configurable interrupt system requiring user approval before destructive or external operations
  • Path Approval: Path-based operation approval for filesystem access outside the project root

Infrastructure

  • Session Management: Save, restore, auto-save, and resume sessions. Compact conversation history via /compact. Run several sessions in parallel panes (/session new) and resume a saved session for the current path with /resume <id>
  • Remote Bridges: Discord and Telegram integration for remote agent interaction. Telegram accepts photos and image files: send one in a session's topic with a caption telling Nova what to do. Without a caption, Nova describes the image. Images join that session's conversation context; images received during a task are queued for a new turn. Images are limited to 20 MB and 7680 pixels per dimension. Telegram also accepts voice notes — they're transcribed with your configured /voice STT provider and sent to the agent as an ordinary prompt (the transcript is echoed back so you can see what was heard). In a Telegram forum each session gets its own topic, and a question Nova asks you is deleted from the chat once you answer it
  • Vixie Desktop Companion: Background server for desktop notifications and system tray integration
  • Hooks System: Lifecycle hooks at key points (pre/post tool call, on message, on error) — shell commands or Python scripts
  • Process Manager: Subprocess lifecycle, health checks, and cleanup for dev servers and background tasks
  • LangSmith Tracing: Built-in LangSmith integration for debugging, monitoring, and evaluating agent runs
  • Doctor Command: System diagnostics to verify your environment, API keys, and dependencies
  • Onboarding System: First-run setup that checks what you enter before saving it: an API key is tested against the provider and an Ollama host must answer with a model installed, so a typo shows up on the setup screen, not on your first prompt. Keys go to the OS keychain
  • Configuration Migration: Migrate from legacy directory structure to Claude Code-compatible layout

Quick Start (Two Commands)

git clone https://github.com/Babitdor/NovaCode.git
cd NovaCode
uv sync

Run it:

uv run nova

Headless (non-interactive) — for scripting and CI:

# Run a single prompt and exit
uv run nova -p "summarize the changes in this repo"

# Machine-readable output, capped at 10 turns, no tool approvals
uv run nova -p "summarize the changes in this repo" --output-format json --max-turns 10 --timeout 120 --deny-tools

# Explicitly allow unattended tool approvals for an execution task
uv run nova -p "run the test suite and report failures" --auto-approve --output-format json --timeout 300

# Stream JSON lines, including provisional text updates
uv run nova -p "explain src/main.py" --output-format stream-json --include-partial-messages --timeout 120

# Or pipe the prompt on stdin
echo "explain src/main.py" | uv run nova -p

The one-shot -p mode accepts UTF-8 text (up to 1 MiB): close stdin and read the result on stdout. Diagnostics, native writes, and inherited subprocess output go to stderr. JSON records include schema_version: 1; the terminal result includes exit_code. Partial text events are provisional: a text_discard event invalidates the current preview, and committed assistant events remain authoritative.

--print does not enable auto-approve or silently trust a directory. Existing policy and session allowances still apply; actions requiring a human are rejected and reported with exit code 3. Pass --auto-approve explicitly when unattended execution is intended. --deny-tools rejects approval requests, but does not disable all tools or guarantee a read-only run. For an unapproved workspace, approve it interactively first or explicitly pass --trust-workspace to grant folder-only trust.

Exit codes: 0 success, 1 execution/startup/incomplete-stream error, 2 observed turn limit, 3 human input required, 124 timeout, 130 cancellation, 141 closed output pipe. Invalid CLI options use argparse's exit code 2. --max-turns counts observed main-agent rounds; it is not an exact API-call or spend limit. --timeout covers asynchronous startup and execution; cleanup gets a bounded grace period. A caller needing a strict wall-clock limit should also enforce a process timeout. This mode does not accept interactive replies or multiple JSON requests on stdin.

Persistent pipe mode — for the Nova Remote App:

nova --mode pipe
# Alias: nova --headless

Wait for the JSON ready event, then send JSON lines such as {"type":"prompt","id":"mobile-1","content":"Investigate failing tests"}. The process stays alive for multiple prompts and streams structured text, tool, approval, and completion events. cancel stops work; shutdown exits cleanly. Use an approved project as the child process's working directory, an absolute binary, and shell: false. See the protocol and bridge guide and Node process adapter. For the Nova Remote App setup, pairing, project registry, relay, and multi-session integration sequence, see the Remote App integration guide.

Optional — voice I/O adds STT, TTS, and VAD (~2 GB extra):

uv run nova
/voice test     # verify it works
ctrl+g          # push-to-talk

No need to install anything globally. uv run nova always runs the latest code from the repo — no stale snapshots, no PATH issues, no "which Python".

If you want a global nova command that works from any directory, add the repo's .venv to your PATH:

# Windows PowerShell:
$env:Path += ";$pwd\.venv\Scripts"
# Or add `B:\Summer Project 2026\Nova-Code\nova-code-cli\.venv\Scripts` to your system PATH

Then just type nova anywhere.

Alternative: Install with pip

# 1. Clone the repository
git clone https://github.com/Babitdor/NovaCode.git
cd NovaCode

# 2. Create a virtual environment
python -m venv .venv

# 3. Activate the virtual environment
# On Windows (PowerShell):
.venv\Scripts\Activate.ps1
# On Windows (Command Prompt):
.venv\Scripts\activate.bat
# On macOS/Linux:
source .venv/bin/activate

# 4. Upgrade pip
pip install --upgrade pip

# 5. Install dependencies
pip install -e .

Verify Installation

# Check if nova is installed
nova --version

# Run system diagnostics
nova doctor

# Start the CLI
nova

Update Nova

nova update --check  # check now without installing
nova update          # update the Nova installation running this command

The TUI checks in the background at startup and hourly. When an update is available, a notification and a transcript notice tell you to exit and run nova update, then restart. /update checks immediately from the TUI. Set NOVA_DISABLE_UPDATE_CHECK=1 to disable background checks; manual checks still work. Checks use a one-hour cache and stay quiet when offline.

Repo and Git installs compare commits against the tracked branch (Git package installs use main), so pushing code can trigger a notification without changing the package version. Package-index installs check the published package version. For a stable release workflow, bump the version and publish the package for each release; repo users can receive changes directly from Git.

Source checkouts must have no local changes and track the matching origin branch. Updates fetch and merge with --ff-only, then refresh dependencies with uv or pip. uv tool installations use uv tool upgrade; other package installs use the running Python environment. Pinned Git refs, forks, and archive installs remain managed through their original installer. Nova settings, sessions, MCPs, and skills remain in their existing directories.

On Windows, uv-managed updates run in a separate process after nova update and its launcher exit. Installer progress and the final result appear live in the same terminal. When no update is needed, Nova displays NovaCode is up to date. Close other Nova sessions before updating. If an older updater reports Failed to install entrypoint or Windows could not move Nova's launcher, run this directly from PowerShell after closing Nova to install the corrected updater:

uv tool upgrade novacode-cli --reinstall

API Keys Setup

Configure your preferred LLM provider by setting environment variables:

# OpenAI (default)
export OPENAI_API_KEY="your-openai-api-key"

# Or Anthropic
export ANTHROPIC_API_KEY="your-anthropic-api-key"

# Or Google Gemini / NVIDIA / OpenRouter
export GOOGLE_API_KEY="your-google-api-key"
export NVIDIA_API_KEY="your-nvidia-api-key"
export OPENROUTER_API_KEY="your-openrouter-api-key"

# Optional: Web search (Tavily)
export TAVILY_API_KEY="your-tavily-api-key"

Option 2: .env File

Create a .env file in your project root or home directory:

# .env file
OPENAI_API_KEY=your-openai-api-key
ANTHROPIC_API_KEY=your-anthropic-api-key
TAVILY_API_KEY=your-tavily-api-key

Option 3: Configuration File (Secure Keychain)

# Store keys securely via OS keychain
nova secrets set openai_api_key
nova secrets set anthropic_api_key

Troubleshooting

IssueSolution
Python version mismatchpython --version → specify version: uv venv --python 3.11
Virtual env not activating (Windows)Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser then retry
Package installation failsuv cache clean && uv sync --reinstall
Missing dependenciesuv sync --all-extras
Import errorsuv pip install -e . --force-reinstall

Development Setup

# Install development dependencies
uv sync --all-extras

# Run tests
pytest tests/

# Format and lint code
make format
make lint

# Type checking
mypy novacode_cli/

CLI Reference

Top-Level Subcommands

CommandDescription
nova initInitialize project or global configuration
nova listList all available agents
nova helpShow help information
nova reset --agent <name>Reset an agent's memory/store
nova skillsManage agent skills (list, create, add, remove, find, update)
nova mcpManage MCP servers (add, remove, list, install)
nova configView or edit configuration (show, set, get)
nova secretsManage API keys securely (set, list, delete)
nova doctorValidate configuration and connections
nova pathsManage approved file system paths (list, revoke, clear)
nova migrateMigrate to new directory structure

Flags

FlagDefaultDescription
--agent"nova-agent"Agent identifier for separate memory stores
--auto-approveoffAuto-approve tool usage (disables HITL)
--sandboxos (Linux/macOS), none (Windows)Sandbox provider: none, os, modal, daytona, runloop, docker, langsmith
--no-sandboxoffRun shell commands unconfined on the host (disables OS/Docker sandbox)
--sandbox-idNoneReuse an existing sandbox (skips create/cleanup)
--sandbox-setupNonePath to setup script to run in sandbox after creation
--sandbox-vcpusNoneNumber of virtual CPUs (LangSmith sandbox only)
--sandbox-mem-bytesNoneMemory in bytes (LangSmith sandbox only, e.g. 8589934592 for 8GB)
--sandbox-fs-capacity-bytesNoneFilesystem capacity in bytes (LangSmith sandbox only)
--sandbox-snapshotNoneSnapshot name to boot from (LangSmith only)
--sandbox-snapshot-idNoneSnapshot ID to boot from (LangSmith only)
--portsNonePort forwarding for Docker sandbox (format: PORT or HOST:CONTAINER, comma-separated)
--no-splashoffDisable the startup splash screen
--continue / -coffContinue last session (optionally specify session ID)
--resume / -roffInteractively select and resume a session
--print / -poffRun a single prompt non-interactively and exit (pass the prompt as the value, or omit it to read from stdin)
--output-formattextHeadless output format: text, json, or stream-json
--max-turnsNoneHeadless only: cap the number of agent turns
--deny-toolsoffHeadless only: auto-reject tool approvals (fail-closed) instead of prompting
--timeoutunlimitedHeadless deadline in seconds, including asynchronous startup
--include-partial-messagesoffAdd provisional text events to stream-json output
--trust-workspaceoffHeadless only: explicitly grant current-folder trust
--version—Show version number and exit

Shell commands in the TUI

Enter !command to stream output in the chat. Nova records the output and reports the result to the agent. Enter !!command to open an interactive terminal view for prompts, menus, and other commands that need keyboard input. Press Ctrl+G or Shift+Tab to return to chat while the command keeps running; use /tasks to inspect or stop it.

Interactive Slash Commands

CommandDescription
/helpShow interactive help
/exit / /quit / /qExit the CLI
/clearClear conversation history and reset session
/tokensDisplay token usage for the session
/contextDisplay current context window status
/costShow session token spend
/verboseToggle verbose mode (show internal agent context)
/steerSet persistent steering instructions for the agent
/goalSet a persistent goal injected into every turn (/goal rubric <criteria> for an acceptance rubric; status / clear)
/btwAsk a side question on an ephemeral thread without touching the main conversation
/saveSave current session
/compactCompact conversation history with optional focus
/sessionsList, select, or delete saved sessions
/uiInspect the optional UI panels; use patch, preview, commit, rollback, or reset
/tabsSession tabs: launch opens the approved project picker; resume picks a saved session to reopen as a tab; resume <id> accepts an exact ID or unique prefix. list / close manage tabs (ctrl+n, alt+<n>)
/resumeResume a saved session for this path (/resume <id>)
/restoreRestore a previous file version from snapshots
/filesShow file operation summary for the session
/imagesManage tracked image references
/artifactsOpen the artifacts list
/tasksOpen the selected tab's background tasks panel (t: terminate, r: restart, l: logs)
/logShow workspace log files
/serversShow active server processes
/testsRun test suites
/killKill a process by PID
/notificationsReview and manage notifications
/remoteManage remote sandbox connections
/reindexRebuild semantic code search index
/copyCopy the last response (or the whole chat)
/themeSwitch color theme
CommandDescription
/initGenerate/update project documentation and graph
/mcpInteractive MCP server management menu
/modelSwitch the model for the main agent, the subagents, the async agents or the dynamic agents
/hooksManage lifecycle hooks (list, add, remove, enable, disable)
/skillsInteractive skills manager
/agentsCustom agent management (view, create, delete)
/plugins / /pluginNova plugin management (list, enable, disable)
/middlewareList active middleware (/reload-plugins to reload)
/reload-pluginsReload plugin registrations
/planInvoke plan-mode agent for investigation & approval (approved plans are saved to .nova/plans/)
/agent-serverControl the local LangGraph server for async agents — status, start, stop, restart, logs
/traceLangSmith tracing management (status, enable, projects)
/ralphAutonomous looping mode (background task execution)
/council <task>Plan a task with the council: agents propose independently, critique anonymously, vote, and a judge picks the top 3 for you to approve
/council view [n]Show the selected plans, or plan n in full
/council approve <n>Approve plan n and hand it to the coding agent (nothing is implemented before this)
/council revise <notes>Re-plan with your changes
/council historyPast council runs (kept in .nova/council/)
/chatLaunch local browser-based chat UI
/cowork / /desktopLaunch the Nova Cowork desktop app (/cowork [task])
/trelloBrowser-based task board server
/researchMulti-agent research swarm (academic/market/stocks/technical/general)
/dreamRun memory consolidation
/browser-useAI-powered browser automation
/createLaunch the Skills & Agents web UI for browsing, editing, and creating skills/agents
/skill:<name>Directly invoke a skill by name (e.g., /skill:api-testing)
/cronManage scheduled (heartbeat) tasks — list, add, remove, fire now
/webhookManage webhook ingress server — start, stop, register sources, status
/promptManage evolving system-prompt templates — status, rollback, accept, reject
/refineRefinement audit trail (/refine history, /refine rollback <id>)
/voiceLocal voice I/O — status, on/off, mode ptt|listen, test (ctrl+g talk, ctrl+l listen)
/effortSet reasoning effort level — low, medium, high, or off (hot-swaps model)
/visionConfigure image handling — status, set the auxiliary vision model, or force the main model multimodal/text-only
/evolutionView the self-evolution log — skills unlocked (🧬) and levelled up (⬆️)
/learningToggle Nova's autonomous learning loop (/learning on|off|status)
/ingestIngest captured sources (Obsidian Web Clipper) into synthesized wiki pages
/askAsk a question informed by wiki context — searches wiki and answers with relevant knowledge
/fileFile recent conversation knowledge as a wiki page under a topic path
/wikiList all synthesized pages in the project wiki vault

In Telegram, send /tab to pick an approved project, then confirm the launch in that topic. The new tab gets its own topic named NovaCode · <session name>; chat there to work in that project. Existing topics adopt the session name on reconnect, preserving their history. Names are synchronized when topics are attached, with long names shortened to Telegram's 128-character limit. Use /tab close to choose a tab to close. Telegram photos and image documents are delivered to the session belonging to their topic.

In the main session's Telegram topic, slash commands use the normal TUI handlers, including /skills, /model, /settings, and plugin commands. Interactive panels show numbered choices: /choose N selects an action, /set N value fills a field, /input N value submits it, /panel N changes pages, and /back closes the panel. Only the requester in that topic can operate its controls. Commands received during a task wait until it finishes. Invoke skills with /skill:name arguments or /name arguments; skill invocation also works in child-session topics, using that session's workspace. Child topics use the shared CLI handlers for other commands; TUI-only management panels are available in the main topic.

Type / in Telegram to open its native command autocomplete menu. Nova publishes commands and enabled skills for the configured chat on connection and refreshes after skill management or plugin reload. Telegram allows up to 100 menu entries; commands take priority, followed by skills. Names with hyphens appear with underscores (for example /api_testing). Skills outside the menu remain available with /skill:name. The menu is shared by all topics in that chat.

Each TUI tab shows its own Tasks footer. Open /tasks (or Ctrl+B with an empty prompt) to select and terminate a background command. You can also ask Nova to list or stop its background tasks; task IDs apply only within that session.

Nova saves an incoming prompt before model execution, checkpoints active sessions every five seconds, and saves again when a turn ends. Atomic recovery snapshots preserve the last complete conversation after a crash. Resume with nova --continue or choose a session with /sessions. Abrupt termination can lose progress since the last completed save and tokens the model has not yet committed to its history.

On restore, Nova rebuilds a continuation from saved history and session memory. The loaded history is limited to approximately 30,000 tokens, including tool-call arguments and retained reasoning; unpaired tool calls and results are excluded. /context estimates the newly loaded context, including the continuation briefing, current instructions, memory, and tool schemas. It does not reuse the previous request's token total: provider usage becomes available after the next model call.

The local TUI supports optional notes, workspace files, and activity panels. Ask Nova to customize them, or use /ui patch with a JSON object, then /ui preview and /ui commit. Panel order follows the panels list. Layouts are saved per workspace under ~/.nova/ui/. /ui rollback restores the saved layout. Use /ui reset, Ctrl+Shift+Backspace, or start with nova --safe-ui for recovery. Custom panel shortcuts use F6–F12; custom panel commands use /ui-<name>. Conversation, input, approvals, and session controls stay protected. This first version uses registered components; it does not load generated Python widgets.

Example: /ui patch {"panels":[{"id":"notes","type":"notes","title":"Notes","text":"Current task"}],"width":28}

External histories can be viewed or imported through /sessions, /import codex --last, or /import claude <id-or-file>. Switch the loaded reference with /context imported full|compact|relevant [query]; compare histories using /compare claude:<id> codex:<id>. Startup also supports nova --import claude --latest. See session import and adapter plugins.

The Active subagents panel shows running tasks with their model and elapsed time. It disappears when no tasks are active; Alt+S collapses or expands it.

Built-in Tools

ToolDescription
lsList files and directories
read_fileRead contents of a file
write_fileCreate or overwrite a file
edit_fileMake targeted edits to existing files
globFind files matching a pattern (e.g., **/*.py)
grepSearch for text patterns across files
shellExecute shell commands (local mode)
executeExecute commands in remote sandbox (sandbox mode)
taskDelegate work to subagents for parallel execution
write_todosCreate and manage task lists for complex work
thinkStructured reasoning and reflection before acting
web_searchSearch the web using Tavily API
duckduckgo_searchWeb search using DuckDuckGo (no API key required)
docs_searchSearch official documentation sites
fetch_urlFetch and convert web pages to markdown (covers all HTTP methods)
github_trendingScrape GitHub trending repositories by language/time range
hacker_newsScrape Hacker News front page headlines
linkedin_jobsSearch LinkedIn job listings (Playwright-based, no login)
reddit_postsScrape Reddit posts by subreddit, user, or search query
package_infoGet package version and dependency info (PyPI / npm)
read_memory / write_memoryRead and write persistent markdown agent memories
remember / recallStore and fetch durable cross-session facts by key
list_memories / forgetList and delete stored durable memory facts
list_trashList file snapshots available for recovery
restore_fileRestore a deleted or overwritten file from snapshots
create_artifactCreate a durable artifact (markdown, code, etc.) that persists across resume
update_artifactUpdate an existing artifact's title, type, or content
list_artifactsList all artifacts in the session
list_background_tasksList agent-launched background shell jobs
get_task_statusGet a background task's status, runtime, and exit code
get_task_logsRead the recent output of a background task
terminate_taskStop a running background task
restart_taskRestart a background task
daemonStart, stop, and tail long-lived background processes
python_kernelRun Python in a persistent kernel that keeps state between calls
oracleAsk several models the same question and have a judge synthesize the answer
query_project_graphQuery the project graph for architectural information
code_searchSemantic code search by description or symbol name
find_related_codeFind code semantically similar to a known location
start_async_taskStart a background task on a remote LangGraph server
check_async_taskCheck status and result of a background task
update_async_taskSend updated instructions to a running background task
cancel_async_taskCancel a running background task
list_async_tasksList all tracked background tasks
speakSpeak a short summary aloud via TTS
skill_manageCreate, refine, or remove reusable skills
wiki_readRead a wiki page by path
wiki_searchSearch the project wiki for pages matching a query
wiki_update_indexAdd or update an entry in the wiki index
wiki_writeWrite or overwrite a wiki page
enter_plan_modeSwitch to read-only investigation mode before coding
exit_plan_modePresent a plan for user approval and exit plan mode
ask_user_questionAsk the user a multiple-choice question and wait for response

Note: Potentially destructive operations require user approval. Use --auto-approve to skip prompts.

Trello Task Board

NOVA includes a browser-based task board for managing and processing tasks visually. Start it with /trello.

/trello              Start the task board server and open browser
/trello stop         Stop the task board server
/trello status       Show current task board state

Task Lifecycle

StatusDescription
LoadedTask added, waiting to be processed
ProcessingAgent is currently working on the task
DoneTask completed by the agent

Add tasks from Telegram

  1. Configure your Telegram bot and group with /remote once. The group must have Topics enabled, and the bot needs permission to manage topics.
  2. Open /trello and turn on Telegram in the board header.
  3. Click Open topic when the connection is ready. Nova creates a dedicated Trello topic, separate from the session topics.
  4. Send a text message or /add <task> in that topic. It becomes a card in Loaded. Use /status to see board counts.

Only authorized Telegram users can add cards. Turning the toggle off pauses intake and keeps the topic and existing cards. Telegram task intake does not change your tool approval mode.

Move a card to Processing, or enable Auto-advance, to run it. In the TUI, execution waits until the board's owning tab is selected and idle. Keep Nova and the board running: cards are held in memory and are not restored after a restart. This topic accepts text tasks; use a session topic for images.

Web Chat UI

Launch a local browser-based chat interface with /chat:

/chat              Start the chat server and open browser
/chat stop         Stop the chat server
/chat status       Show chat server status
  • Dark-themed UI: Claude-inspired design with red accents
  • Markdown Rendering: Full Markdown + syntax highlighting via marked + highlight.js
  • Typing Indicator: Animated bouncing dots while the agent responds
  • Same Agent: Connects to the same LangGraph agent — no separate config

Web Scraping Tools

Built-in tools that work with public data — no API keys required:

ToolData Source
github_trendingGitHub trending repositories
hacker_newsHacker News front page
linkedin_jobsLinkedIn job listings (Playwright)
reddit_postsReddit posts by subreddit/user/search

Standalone CLI scripts also available in scripts/scraper/.

Autonomous Learning System (Hermes)

NOVA includes Hermes, an autonomous learning system that runs in the background:

  • Self-Review: Every ~10 tool calls, Hermes reviews tool usage patterns and extracts lessons
  • Self-Improving Memory: Automatically maintains two memory tiers:
    • USER.md — User model: communication style, preferences, workflows, recurring frustrations
    • MEMORY.md — Cross-session memory: architecture decisions, reusable patterns, key facts
  • Skill Creation: Analyzes repeated successful tool sequences and autonomously creates reusable skills with deterministic naming and refinement
  • Skill Debate: skill_debate.py — Multi-perspective skill evaluation that compares new skills against existing ones, flags overlap, and suggests merges
  • Skill Manager: skill_manager.py — Orchestrates skill creation from review feedback, failure-grounded refinement, and background curation
  • Tool Usage Tracker: tracker.py — Counts tool calls, maintains per-tool stats, and tracks skill invocations to drive refinement decisions
  • Review Runner: review.py — Decides when to review (signal-based: failure bursts, substantive windows, hard cap) and runs out-of-band LLM reviews
  • Curator: curator.py — Archives unused skills and flags overlapping ones to keep the skill library lean
  • Evolution Logger: evolution.py — Tracks skill unlocks and level-ups, persisted in durable store, viewable via /evolution
  • No Interruption: Reviews run out-of-band in the background — no pause in agent operation
  • Live Indicator: Visible indicator in the TUI status line when Hermes is reviewing

Loop Engineering Enhancements

Hermes has been extended with five self-improving subsystems, each closing a different feedback loop:

EnhancementModuleWhat It Does
1. Inline Verification Loopcore/verification_loop.py, hermes/verifier.pyAfter each task, an out-of-band LLM call grades the output against a rubric. On a failing verdict, the agent is re-driven with feedback (up to 3 retries). Fail-open: any grading error yields a pass
2. Prompt-Template Hill Climbinghermes/prompt_evolution.pyWhen reviews repeatedly flag the same class of misunderstanding, proposes a targeted rewrite of the relevant .jinja template, A/B tests it using verifier pass/fail as the quality signal, and promotes or discards it. Packaged templates are never modified — overrides live in ~/.nova/prompt_history/
3. Cron / Heartbeat Schedulerremote/scheduler.py, commands/cron_handler.pyProactive scheduled tasks via standard 5-field cron expressions. Fired jobs go on the same queue as remote bridges, so they run like any prompt. Manage with /cron
4. Threshold Auto-Tunerhermes/tuner.pyReads durable trace data and nudges review-trigger thresholds toward the observed working style. Damped convergence (0.2 weight) with hard floor/ceiling bounds — can never starve reviews or burn tokens
5. Webhook Ingress Serverremote/webhook_server.py, remote/webhook_adapters.py, commands/webhook_handler.pyLet external systems (GitHub, Linear, or any signed sender) trigger a Nova run. Per-source HMAC-SHA256 secrets, timing-safe verification, binds to 127.0.0.1 by default. Manage with /webhook

All enhancements share the same design principles:

  • Fail-open: Any failure logs and degrades gracefully — the agent turn is never blocked
  • Durable: State persists in the LangGraph store under named namespaces (hermes/config.py)
  • Background: Run as fire-and-forget asyncio tasks — no pause in agent operation
  • Configurable: All thresholds and bounds are centralized in hermes/config.py

Middleware Stack

Every model call passes through this middleware chain (in order):

LayerModulePurpose
ModelRetryMiddlewaredeepagentsRetry transient model failures (rate limits, 429) with exponential backoff
VisionCaptionMiddlewarebootstrap/vision_router.pyConvert images to text for a text-only main model; pass-through when the main model is multimodal
NovaLearningMiddlewarehermes/middleware.pyHermes learning system — tool usage tracking, review cycles, memory tiers (opt-in)
SecurityMiddlewaresecurity/URL sanitization, unicode attack prevention
BootstrapMiddlewarebootstrap/Environment snapshot injection
SteeringMiddlewarebootstrap/steering.pyInjects persistent user instructions (mid-run steering)
FileTrackerMiddlewaretracking/File-op tracking, result truncation
LoopGuardMiddlewaretracking/loop_guard.pyBreak stuck identical tool-call loops
RubricMiddlewaredeepagentsRubric self-evaluation — dormant unless a rubric is set via /goal rubric
VerdictScorer middlewareagents/tool_verdicts.pyScores old tool results with the System One decision model so the next layer clears only the stale ones (inserted only when tool_verdicts_enabled is on)
ContextEditingMiddlewarelangchain.agents.middlewareClear older tool-call outputs when the window-relative token trigger is reached; cleared results are offloaded to /cleared/ (agents/tool_offload.py)
ShellMiddlewareshell.pyShell tool + sandbox execution
AgentMemoryMiddlewarememory/Agent memory loading (USER.md, MEMORY.md, project NOVA.md)
TaskDisciplineMiddlewareagents/task_discipline.pyTodo recitation appended to the final system message
MCPMiddlewaremcp/middleware.pyMCP tool provisioning (inserted dynamically when MCP servers configured)
GraphContextMiddlewarebootstrap/graph_context.pyInjects project graph legend summary

Project Graph

The project graph (.nova/project-graph.json, ~5000 nodes, ~13000 edges) is built by the /init pipeline. It provides:

  • Community Detection: Tightly coupled module clusters identified via graph analysis
  • Central Hubs: High-degree nodes — files with wide blast radius (e.g., Settings with 502 connections)
  • Dependency Analysis: Cross-module connections and architectural seams
  • Queryable: Ask the agent query_project_graph("Settings") to find connected modules and community structure

Refresh with /init (full rebuild) or /init --update (incremental).

Configuration

Directory Structure

Global Configuration (~/.nova/):

~/.nova/
├── agents/
│   └── default/
│       └── agent.md
├── skills/
│   └── web-research/
│       └── SKILL.md
├── hooks/
│   ├── pre_tool_call.py
│   └── post_tool_call.sh
└── trash/
    └── <session-id>/
        ├── manifest.json
        └── <snapshots>

Project Configuration (in your project root):

my-project/
├── AGENTS.md          # Optional concise instructions; Codex-compatible
├── .nova/
│   ├── NOVA.md        # Project-specific context and conventions
│   ├── config.json    # Project configuration
│   ├── hooks.json     # Project-specific hooks
│   └── skills/        # Project-specific skills
├── .claude/           # Also supported (Claude Code compatible)
└── .nova.config.json  # Project-level config (scoped)

Agent Memory

  • Global (~/.nova/agents/default/agent.md): Your personality, style, and universal preferences
  • Project (NOVA.md, .nova/NOVA.md, CLAUDE.md, .claude/CLAUDE.md, or AGENTS.md): Project-specific instructions are combined when present. /init creates .nova/NOVA.md; project files never grant tool or path approvals.

Keep the project guide short: what the project does, exact test/build commands, protected files, useful examples, and what counts as done. For a debugging request, give Nova the failing test or full error and the relevant file. For a style-sensitive change, point to an example file. For a decision, give the constraints and acceptance criteria. Nova should run the narrowest relevant check and report what it verified before calling the task complete.

Skills

Manage skills with:

# List all skills
nova skills list

# Create a new skill
nova skills create my-skill

# Create a project-specific skill
nova skills create my-skill --project

# View skill details
nova skills info web-research

Installing Skills

nova skills add runs the official Skills CLI (npx --yes skills@latest add) with your arguments unchanged. It requires Node.js (current Skills CLI: Node 22.20+), npm/npx, and Git for repository sources. The first run downloads the CLI; subsequent runs use npm's cache and check for updates. It runs without Nova onboarding or an LLM API key.

# Discover skills and select which ones to install interactively
nova skills add vercel-labs/agent-skills

# List available skills without installing
nova skills add vercel-labs/agent-skills --list

# Select several skills; --skill selects existing names, it does not rename them
nova skills add owner/repo --skill first-skill second-skill

# Install to the shared directory that Nova reads (project scope is the default)
nova skills add owner/repo --agent universal --skill my-skill -y

# Install globally for all projects
nova skills add owner/repo --agent universal --skill my-skill -g -y

# Local folders, GitHub/GitLab URLs, SSH URLs, and owner/repo@skill are supported
nova skills add ./local-skills --agent universal --copy -y
nova skills add owner/repo@my-skill --agent universal -y

# Install every skill to every supported upstream agent
nova skills add owner/repo --all

# Alias
nova add skill owner/repo --list

The official installer controls selection, confirmation, copy/symlink behavior, complete supporting files (including binary assets), errors, and lock files. Nova reads shared skills from .agents/skills/ and ~/.agents/skills/ alongside its existing .nova/skills/ and Claude skill directories. For Nova-only installs, use --agent universal; other --agent choices target the upstream agents. A source without valid skills produces the upstream result; add no longer fabricates a skill from a README. Use nova skills create to author a new skill.

New installs use the upstream lock files and can be maintained with npx skills check, npx skills update, and npx skills remove. Nova's existing update command continues to manage older .nova lock entries. The previous add-only --project flag is unnecessary (project is the default), and --force is replaced by the upstream confirmation/--yes workflow.

System One Compaction

The TUI's CTX meter uses the latest main-model input usage when available and an estimated summary/tail breakdown after compaction or resume. Its percentage uses the selected model's detected context window. SESSION accumulates main-model input and output across tool-loop calls against a configured token budget (1M by default); it is not a provider quota or billing estimate. Compaction preserves SESSION usage, while /clear resets it. Subagents and auxiliary model calls are not included, and historical usage is not restored from saved sessions.

By default the context pipeline clears every tool result older than the token trigger except the newest few. System One compaction replaces that age rule with a judgement: a small decision model is shown a skeleton of the conversation and asked, per result, whether it is still needed. Only results scored below the keep threshold are cleared, and an unjudged result is always kept (the feature fails open).

It is off by default. Open /model → Decisions to select Jev, Tev1, or Custom System One, edit the decision model and endpoint, and toggle Enable System One tool pruning. Save persists the settings and rebuilds the current agent while retaining your chat model and conversation. Cancel discards the changes.

To use hosted Jev, open /auth, select Jev (System One compaction), and save your TypeSafe API key. The Decisions tab's Manage API key button opens the same manager without discarding your draft. Keys use Nova's existing credential store as TYPESAFE_API_KEY. Saving a key does not change the decision model or enable pruning; those settings belong to the Decisions tab. Create keys in the TypeSafe console; the official API reference describes the request format.

For environment-based authentication, set TYPESAFE_API_KEY and configure:

{
  "tool_verdicts_enabled": true,
  "tool_verdict_endpoint": "https://api.typesafe.ai/v1/systemone",
  "tool_verdict_model": "jev-latest"
}

Local and custom models remain optional. Set their full System One endpoint and the model name accepted by that server in ~/.nova/Nova.config.json. There is no model allowlist: Kev1 and future compatible models work through the same interface. For example, the existing local Tev1 setup is:

{
  "tool_verdicts_enabled": true,
  "tool_verdict_endpoint": "http://localhost:11434/v1/systemone",
  "tool_verdict_model": "tev1:4b",
  "tool_verdict_keep_threshold": 0.5
}
KeyMeaningDefault
tool_verdicts_enabledMaster switchfalse
tool_verdict_endpointSystem One endpointhttp://localhost:11434/v1/systemone
tool_verdict_modelDecision model (tev1:4b separates answers cleanly; the 0.8B size does not)tev1:4b
tool_verdict_keep_thresholdMinimum probability a result is still needed for it to survive0.5

If a custom endpoint requires authentication, use Custom System One (optional API key) in /auth, or set SYSTEM_ONE_API_KEY. Local endpoints can run without a real key. TypeSafe credentials are sent only to the exact official Jev endpoint; custom endpoints use the separate custom credential. Configure the endpoint/model and toggle pruning in Decisions. Hand-edited configuration applies after restarting Nova; set tool_verdicts_enabled to false to disable it.

This feature decides which tool outputs to offload during context management. /compact summary generation continues to use your active session model. Thresholds should be evaluated separately for each decision model.

Why it is opt-in: the current scorer budgets about 2,000 tokens and considers only the newest 12 results, including when Jev is selected. Measured on six real sessions with Tev1, the default age rule cleared more (70 results / 72,682 chars against 49 / 18,364) with fewer regretted clears (0.19 against 0.44 per 1k). These measurements do not establish Jev's performance. The flag stays so each model can be tried live and re-measured.

Tool discovery

Nova keeps less-used tool schemas out of the model's prompt and loads them with search_tools. Search covers every currently available tool, including core and already loaded tools, plus specialist subagents. Use a capability description, an exact name, a partial name, or a wildcard such as playwright_*.

search_tools(query="*", limit=20, offset=0) browses the catalog; increase offset to retrieve later pages. Results load the tools for the next model call and indicate whether a subagent uses task or start_async_task. Search covers tools registered for the current session.

Built-in Subagents

NOVA has two kinds of subagent. In-process specialists run inside the session, behind its approvals and sandbox, and answer in the same turn. Async agents run in the background and report back when they finish.

In-process Specialists

SubagentDescriptionAuto-loaded Skills
general-purposeAny delegated task; the default—
code-explorerNavigate, understand, and query large codebasescodebase-explorer/, graphify/
refactoring-specialist-agentCode smells, technical debt, design patternsimprove-codebase-architecture/
bug-fix-agentSystematic bug diagnosis and fixsystematic-debugging/
browser-automation-agentWeb testing, forms, screenshots, data extraction; drives a real browser through the Playwright MCP tools, and the desktop through cua-driveragent-browser/, browser-use/, web-research/

Their graphs are compiled on first use, so unused ones cost nothing at start-up.

Longer, self-contained jobs (review, documentation, tests, security audits, research) are async agents, below. Domain know-how such as frontend, backend or Docker work is a skill the main agent loads on demand.

Research Swarm

Dispatched by /research; kept out of the everyday roster and loaded on demand.

SubagentDescription
web-researcherBroad web search and source gathering
fact-checkerVerifies claims against independent sources
literature-reviewerAcademic papers and prior work
market-analystMarkets, competitors, and trends
financial-analystStocks and financial data
technical-researcherLibraries, APIs, and technical trade-offs
research-synthesizerMerges the findings into one report

Async Background Agents (Remote LangGraph)

SubagentDescription
documentation-update-agentAuto-synchronize project docs and changelogs with git commits
code-review-agentReview uncommitted/recent changes asynchronously
test-generation-agentGenerate/maintain test suites in the background
dependency-audit-agentAudit dependencies for updates and security vulnerabilities
refactoring-agentAnalyze and improve code quality in the background
plan-scout-agentRead-only directory scans dispatched during plan mode
security-audit-agentFull security audit (OWASP Top 10, secrets, auth flaws); read-only
test-runner-agentRun the test suite and report failures with likely causes; test-runner commands only
research-agentWeb research with sourced findings

Async agents read, search and report; the ones that write (documentation, tests, refactoring) do so unattended, so give them a self-contained task. Work that needs your approval along the way belongs with an in-process specialist, because approvals do not reach the server.

Start any with start_async_task(), check status with check_async_task(). When Nova has a local server planned or a usable external server, the async tools stay visible to the model without a tool search. The local server starts on the first dispatch. Otherwise Nova uses its in-process subagents.

The dynamic subagents panel shows only active tasks. Completed, failed and stopped rows disappear, and the panel hides when no tasks remain active. Background tasks remain visible across foreground turns while they are running.

Hooks System

Lifecycle hooks for customizing agent behavior:

HookWhen It FiresUse Case
pre_tool_callBefore a tool is executedValidate inputs, log, modify params
post_tool_callAfter a tool completesProcess results, log, trigger notifications
on_messageWhen a message is receivedFilter content, add context
on_errorWhen an error occursCustom error handling, recovery
# List all hooks
/hooks list

# Add a hook
/hooks add pre_tool_call my_hook --command "echo 'Tool called'"

# Add a hook from a file
/hooks add post_tool_call logger --file hooks/logger.py

# Enable/disable hooks
/hooks enable my_hook
/hooks disable my_hook

Hooks can be Python scripts (full access to internals), shell commands, or any executable.

MCP Integration

Extend the agent with Model Context Protocol servers:

# Add from preset
nova mcp add google-drive --preset google-drive
nova mcp add gmail --preset gmail
nova mcp add google-docs --preset google-docs
nova mcp add playwright --preset playwright

# Custom HTTP transport
nova mcp add my-server --transport http --url https://example.com/mcp

# Custom stdio transport
nova mcp add my-server --transport stdio --command "python -m my_mcp_server"

Available Presets: google-drive, gmail, google-docs, playwright, serena, context7, apify, cua-driver, sequential-thinking, chrome-devtools, firecrawl, tavily, exa, perplexity

Google MCP setup: Open /mcp, select Google Drive, Gmail, or Google Docs, and install the preset. These use the community-maintained Google Workspace MCP server, launched through uvx workspace-mcp with only the selected service's core tools. uv must be installed.

Create a Google Cloud OAuth client using the upstream quick-start guide, enable the Drive, Gmail, and Docs APIs you intend to use, and download its client JSON. Register http://localhost:8001/oauth2callback for Drive, http://localhost:8002/oauth2callback for Gmail, and http://localhost:8003/oauth2callback for Docs. Supply the JSON file's full path when Nova prompts; the same file can serve all three presets. Google consent is completed through the server's authentication flow after restarting the session. Nova stores the file path in MCP configuration; the client secret remains in your JSON file. No Google account is connected merely by adding a catalog preset.

MCP Management:

nova mcp list              # List all configured servers
nova mcp remove my-server  # Remove a server

Sandbox Execution

NOVA supports multiple sandbox providers for safe code execution:

# OS sandbox (default on Linux/macOS — host files, shell confined to workspace)
nova --sandbox os

# Docker (opt-in on Windows, with workspace binding)
nova --sandbox docker

# Modal (cloud)
nova --sandbox modal

# Runloop (cloud)
nova --sandbox runloop

# Daytona (cloud)
nova --sandbox daytona

# LangSmith Sandboxes (hardware-virtualized microVMs)
nova --sandbox langsmith

# Force unconfined local execution
nova --no-sandbox

# Reuse an existing sandbox
nova --sandbox-id <id>

# Port forwarding (Docker)
nova --sandbox docker --ports 8080:8080

# LangSmith sandbox resource config
nova --sandbox langsmith --sandbox-vcpus 2 --sandbox-mem-bytes 8589934592

The default sandbox image is python:3.11-slim.

Plugin System

NOVA supports Python entry-point based plugins that can register slash commands and add middleware at defined slots. Plugins are discovered via the nova.plugins entry point group and can contribute:

  • Slash Commands: Custom interactive commands
  • Middleware: Add behavior at named slots in the middleware stack
  • Skills: Domain-specific workflows
# List plugins
/plugins

# Enable/disable a plugin
/plugins enable my-plugin
/plugins disable my-plugin

File Recovery

NOVA automatically snapshots files before destructive operations:

  • Files targeted by rm shell commands — captured before deletion
  • Files overwritten by write_file — previous content saved
  • Files modified by edit_file — pre-edit content saved
# Interactive restore
/restore

# Restore by index
/restore 1

# Restore by path
/restore src/utils.py

Agent tools: list_trash() to see snapshots, restore_file("path") to restore.

Snapshots stored in ~/.nova/trash/<session-id>/. Files over 10 MB skipped.

Vixie Desktop Companion

NOVA includes Vixie, a background desktop companion server:

  • Desktop Notifications: Task completion and status alerts
  • System Tray Integration: Quick access to Nova status
  • WebSocket Server: Real-time event streaming

Testing

# Run unit tests
make test

# Run all tests (including integration)
make test_all

# Run with coverage
make test_cov

# Run specific test file
make test TEST_FILE=tests/unit_tests/test_specific.py

# Watch mode
make test_watch

Test suite includes:

DirectoryWhat it tests
tests/test_hermes/Hermes learning system — middleware, memory, skill discovery, verifier, tuner, prompt evolution
tests/test_tui_app.pyTextual TUI — animations, chat, modals, tool groups
tests/test_workdir_grep.pySandbox-backed grep path-rebased execution
tests/test_notifications.pyNotification system integration
tests/test_context_breakdown_tokens.pyToken budget and context optimization
tests/test_backends/Filesystem backend virtual-path operations
tests/test_remote_cron.pyCron scheduler — expression parsing, job lifecycle, tick loop
tests/test_webhook_server.pyWebhook ingress — signature verification, adapter parsing, server lifecycle

Makefile Commands

CommandDescription
make testRun unit tests (ignores shell/process/e2e tests)
make test_integrationRun integration tests
make test_allRun all tests
make test_watchWatch mode with ptw
make test_covRun tests with coverage (term-missing report)
make runRun uv run nova
make syncSync dependencies (uv sync)
make lockLock dependencies (uv lock)
make treeShow dependency tree (uv tree)
make outdatedShow outdated packages (uv tree --outdated)
make add PACKAGE=<name>Add a dependency (uv add)
make add-dev PACKAGE=<name>Add a dev dependency
make remove PACKAGE=<name>Remove a dependency
make reinstallFull reinstall of novacode-cli + deepagents
make run_reinstallReinstall then run nova
make lintCheck formatting and linting
make formatAuto-format code
make cleanClean caches

Architecture

User Input → CLI Entry (main.py) → Agent Loop (core/agent_loop.py) → UI Renderer

Core Flow

  1. CLI Entry (main.py → cli_main()) — parses args, initializes SessionState, runs optional onboarding, then enters the Textual TUI (or the headless runner with -p)
  2. Agent Loop (core/agent_loop.py → iterate_agent_events()) — the single canonical async generator driving the LangGraph agent stream
  3. UI Events (ui_events.py) — dataclass instances decoupled from rendering; the TUI, the headless runner, and the remote bridges all consume the same event types
  4. Middleware Stack — wraps every model call (ModelRetry → VisionCaption → NovaLearning → Security → Bootstrap → Steering → FileTracker → LoopGuard → Rubric → ContextEditing → Shell → AgentMemory → TaskDiscipline)

Module Structure

Core:

  • main.py — Entry point, CLI loop, argument parsing
  • cli_session.py — Session management, auto-save, display helpers
  • input.py — prompt_toolkit input handling, completers, image paste, keybindings
  • core/agent_loop.py — Canonical async generator driving the LangGraph agent stream
  • core/verification_loop.py — Inline verification wrapper around iterate_agent_events (Enhancement 1)

Agent:

  • agents/core_agent.py — Agent creation, configuration, middleware wiring
  • agents/default_subagents/ — the in-process specialists, the research personas, and the client specs for the async agents
  • agents/async_agents/ — the nine async agent graphs and their langgraph.json
  • agents/server_launcher.py — launches the async agents' server on demand, in the session's project
  • agents/plan_agent/ — Plan mode agent with planning middleware

Commands:

  • commands/ — 20+ CLI command handlers (commands/__init__.py aggregates via CommandRegistry)
  • commands/chat_handler.py — /chat command — local web chat UI
  • commands/cron_handler.py — /cron command — scheduled task management (Enhancement 3)
  • commands/webhook_handler.py — /webhook command — webhook ingress server management (Enhancement 5)
  • commands/prompt_handler.py — /prompt command — evolving prompt template management (Enhancement 2)

Configuration:

  • config/config.py — Settings hub (502 connections), color scheme, model factory, console init
  • config/nova_config.py — Persistent JSON config (~/.nova/Nova.config.json)
  • config/model_create.py — Model instantiation for all providers
  • config/model_manager.py — Model provider management

Context & Memory:

  • context/ — Context budget tracking, eviction, optimization, growth monitoring
  • memory/store.py — Durable LangGraph key/value store with stdlib-fallback
  • prompts/ — Jinja2 template rendering

Learning (Hermes):

  • hermes/middleware.py — NovaLearningMiddleware (thin orchestrator)
  • hermes/tracker.py — ToolUsageTracker: counters, per-tool stats, skill invocation tracking
  • hermes/review.py — ReviewRunner: signal-based review scheduling, out-of-band LLM review
  • hermes/skill_manager.py — SkillManager: create-from-review, failure-grounded refinement
  • hermes/skill_discovery.py — Skill spec parsing/writing, effectiveness checks, refinement
  • hermes/curator.py — Archive unused skills, flag overlapping ones
  • hermes/skill_debate.py — Multi-perspective skill evaluation and merge suggestions
  • hermes/evolution.py — Skill unlock/level-up tracking, viewable via /evolution
  • hermes/memory_tiers.py — USER.md / MEMORY.md auto-maintenance
  • hermes/config.py — Centralized thresholds, bounds, and store namespace constants
  • hermes/verifier.py — Inline output verifier (Enhancement 1)
  • hermes/prompt_evolution.py — Prompt-template hill climbing with A/B testing (Enhancement 2)
  • hermes/tuner.py — Threshold auto-tuner via hill-climbing inward (Enhancement 4)

UI (Rich console):

  • ui/ui_elements.py — Token tracking, help, diff rendering, todos
  • ui/execution.py — Tool execution orchestration and approval flow
  • ui/streaming.py — Real-time output streaming
  • ui/tool_processing.py — Tool call formatting and display
  • ui/hitl_approval.py — Human-in-the-loop approval UI
  • ui/subagent_tracking.py — Subagent progress visualization

TUI (Textual):

  • tui/app.py — NovaApp: chat messages, modals, keyboard shortcuts, condensed tool groups, history, parallel session panes
  • tui/animations.py — Fade/slide/zoom, pulsing borders, shimmer, thinking dots

Headless:

  • headless/runner.py — Non-interactive single-prompt runner (nova -p)
  • headless/output.py — text / json / stream-json output formatting

Tools:

  • tools/ — HTTP fetch, search, web scraping, package info, git, LSP, browser, memory, reflection, project graph, code search, plan mode, artifacts, background jobs, daemons, Python kernel, oracle

Integrations:

  • integrations/ — Sandbox providers and workdir backend
  • mcp/ — MCP client, config, middleware, presets
  • remote/ — Discord and Telegram bridges, cron scheduler, webhook ingress server
  • remote/scheduler.py — Cron / heartbeat scheduler (Enhancement 3)
  • remote/webhook_server.py — Webhook ingress HTTP server (Enhancement 5)
  • remote/webhook_adapters.py — Per-source payload adapters with timing-safe signature verification

Infrastructure:

  • session/ — Session persistence, restore, summarization, prompt building
  • sessions/ — Parallel session supervisor, worker, lease, and worktree management
  • states/slices/ — 6 state slices (UISettings, AgentRuntime, RemoteBridge, BackgroundTask, Notifications, Wiki)
  • states/Session.py — SessionState composite dataclass
  • artifacts/ — Durable artifact registry and serving
  • daemons/ — Long-lived background process registry
  • cowork/ — Nova Cowork desktop app launcher, broker middleware, and policy
  • server/ — Local HTTP server, event adapter, and session manager
  • audio/ — Voice I/O: capture, VAD, STT/TTS providers, speakable-text extraction
  • server_runner/ — Dev server and test runner lifecycle
  • process_manager.py — Subprocess lifecycle, health checks, cleanup
  • tracking/ — File tracking, run logging, LangSmith, workspace anchoring, loop guard

Safety & Recovery:

  • errors/ — Error taxonomy (14 categories) and recovery handlers
  • security/ — Unicode security and input validation
  • git_safety.py — Dangerous command detection and injection prevention
  • file_ops.py — File operation tracking, diff, approval previews
  • recovery.py — File recovery snapshots
  • path_approval.py — Path-based operation approval

Specialized:

  • bootstrap/ — Environment snapshots, project graph context, steering instructions
  • init/ — Project initialization (detect → extract → generate → graph)
  • skills/ — Skill loading, creation, locking, system prompt generation
  • hitl/ — Human-in-the-loop interrupt configuration
  • bootstrap/vision_router.py — Vision captioning middleware (converts images to text for a text-only main model; passes images straight through when the main model is multimodal — see config/model_capabilities.py and the /vision command)
  • vixie/ — Desktop companion server (notifications, system tray)
  • plugins/ — Plugin system
  • wiki/ — Persistent project wiki: ingest, ask, file, and vault management
  • hooks.py — Lifecycle hook dispatch
  • compaction.py — Hierarchical conversation summarization via LLM, with a pre-compaction transcript archive
  • agents/tool_offload.py — Offloads cleared tool results to /cleared/ so they stay readable
  • agents/tool_verdicts.py — System One compaction: a Tev1 decision model picks which tool results are stale (opt-in)
  • tui/gc_tuning.py — Garbage-collection tuning that keeps collection pauses out of the UI
  • plans.py — Plan management and persistence
  • onboarding.py — Interactive first-run setup
  • doctor.py — System diagnostics
  • migrate.py — Configuration migration

Optional Dependencies

The base install is kept lean. Heavier features are extras:

# Real-browser automation: /browser-use and the LinkedIn scraper (~330 MB)
pip install novacode-cli[browser]

# The local server the async agents run on
pip install novacode-cli[agents-server]

# Voice I/O (STT + TTS + VAD) — ~2 GB extra
pip install novacode-cli[voice]

# Orpheus TTS — very natural LLM-based local TTS
pip install novacode-cli[voice-orpheus]

# Parakeet STT — NVIDIA local speech-to-text via sherpa-onnx
pip install novacode-cli[voice-parakeet]

# Pocket TTS — lightweight local TTS
pip install novacode-cli[voice-pocket]

Async subagents

The nine async subagents (code review, test generation, documentation updates and the rest) talk Agent Protocol to a LangGraph server, which NOVA launches itself. Their graphs live in novacode_cli/agents/async_agents/. One optional extra provides the server:

uv sync --extra agents-server   # once: installs langgraph-cli, the dev server

With that extra installed, NOVA runs the server itself, with no Docker involved:

  • On demand. Nothing is started at boot. NOVA reserves a port and offers the async tools; the server comes up on the first start_async_task (a few seconds) and stops when NOVA exits. A session that never delegates never pays for it.
  • In your project. The agents read, search and run commands in the workspace NOVA was opened in, not in NOVA's own repo.

A server you started yourself is used only if you declare the directory it works in with NOVA_ASYNC_AGENT_ROOT=<its directory> and that is the current project; otherwise NOVA launches its own. Without the extra, NOVA falls back to the in-process subagents.

Control it from inside the TUI with /agent-server:

/agent-server status     is a server running, which port, which log
/agent-server start      launch one now (blocking, first run can take a minute)
/agent-server stop       stop this session's server
/agent-server restart    stop, then start on a fresh port
/agent-server logs       the last 20 lines of the server log

--no-agent-server turns the automatic launch off for a run, and --agent-server-port N pins the port instead of picking a free one.

Which model each agent runs on

/model covers four roles. The list opens with a Roles section; the row marked target is where the next model pick goes. Choosing a role row retargets the picker instead of closing it, so the flow is: pick the role, then pick the model.

RoleCoversTakes effect
Main agentthe agent you talk toimmediately (hot-swapped)
Subagentsin-process delegation via the task toolon the next dispatch
Async agentsthe nine graphs on the LangGraph serveron the next dispatch
Dynamic agentsagents discovered in the agent directories, which is also what an /eval fan-out dispatcheson the next dispatch

Dynamic describes where an agent definition comes from; Async describes execution on the agent server. These can overlap: a custom agent.md with async: true remains available in-process and can also be served as a background agent. The Dynamic model applies to its in-process dispatch; Async applies to the server dispatch. This agent server is separate from Telegram remote access.

Dynamic inherits Subagents → Main when unset, unless the agent's own model: overrides it. Async follows Async role → explicit server environment → Main. If an async per-run model cannot be built, the current server middleware logs a warning and falls back to its graph default; the role picker therefore shows the requested model, which can differ from the model actually used after a fallback.

Any role you leave unset keeps its previous behaviour, which is what every role did before this existed, so an untouched setup behaves exactly as before: the subagents and the dynamic agents inherit the main agent's model, and so do the async agents. A discovered agent can also name its own model in agent.md frontmatter, and that wins over the dynamic role:

---
name: custom-agent
model: anthropic:claude-sonnet-4-5-20250929
---

The roles live in ~/.nova/Nova.config.json, one key per role, and the panel above the transcript reports each task's real model rather than assuming the session one.

Which model the async agents run on

Provider-agnostic: any provider NOVA supports can run them. In order of precedence:

  1. the Async agents role set in /model;
  2. ASYNC_AGENT_PROVIDER / ASYNC_AGENT_MODEL in the environment;
  3. otherwise, the main agent's own model.

So with nothing configured, the async agents run on whatever the session runs on, and a /model change applies to the next dispatch.

VariableMeaning
ASYNC_AGENT_PROVIDERollama, openai, anthropic, google, openrouter, opencode, nvidia
ASYNC_AGENT_MODELmodel id for that provider
PLAN_SCOUT_MODELper-agent override, plan-scout only; wins over all of the above
the provider's key vare.g. OPENAI_API_KEY, ANTHROPIC_API_KEY; read from the environment or the keychain

Dependencies

This package depends on the deepagents library for core agent functionality, which is automatically installed as a dependency. Core dependencies include LangChain ecosystem (LangGraph, LangSmith), Rich, Textual, prompt-toolkit, and various integration libraries.

License

MIT License — see LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Babitdor/NovaCode

A powerful open-source terminal-based AI coding assistant that runs in your terminal, Built on top of the deepagents library which provides the core agent architecture.

Python

2

469 commits

updated Oct 17, 2026

See the code

README

Nova CLI Banner

NOVA : Agentic Coding Tool

Version License: MIT Python

An open-source, terminal-based AI coding assistant built on LangGraph and the deepagents framework. NOVA runs entirely in your terminal with a Textual TUI, a headless non-interactive mode for scripting and CI, and remote bridges for Discord/Telegram — similar to Claude Code, but extensible and transparent.

Nova CLI Preview

Features

Core Intelligence

  • LangGraph Agent Loop: Deep agent architecture with planning, subagents, filesystem access, and tool-calling — all orchestrated through a shared async event loop
  • Multi-Provider LLM Support: OpenAI, Anthropic, Google Gemini, NVIDIA, OpenRouter, OpenCode, and local Ollama — configure any provider via environment variables, the OS keychain, or the onboarding wizard, and switch with /model. Thinking models round-trip their reasoning_content, so multi-turn tool use works on providers that require it
  • Autonomous Learning System (Hermes): Periodically reviews tool usage patterns, extracts lessons, and autonomously creates reusable skills — the agent improves itself over time without user intervention
  • Memory System: Two-tier persistent memory — auto-maintained markdown files (USER.md/MEMORY.md) plus a LangGraph key/value store (remember/recall) for cross-session facts
  • Context Management: A three-stage pipeline sized to the model's actual context window — older tool results are cleared first (and offloaded to /cleared/ so the agent can read them back instead of losing them), then the conversation is compacted hierarchically, with a hard backstop that always keeps an 8k-token reserve. The pre-compaction transcript is archived to ~/.nova/sessions/<thread>/, and the context meter survives /resume
  • System One Compaction (experimental): Nova can ask Jev or a compatible local/custom decision model whether each old tool result is still needed, and clear only results scored stale. Configure Jev through /auth, or supply a custom System One endpoint and model. Cleared results are offloaded to /cleared/. Off by default; see System One Compaction
  • Native Vision: A multimodal main model sees pasted images directly; a text-only one gets them captioned by an auxiliary vision model. Capability is detected from the model profile and can be overridden with /vision
  • Council Planning: /council <task> has several agents propose plans independently, critique each other anonymously, and vote; a judge picks the top 3 and nothing is implemented until you approve one
  • Research Swarm: /research fans a question out to 7 research personas (web researcher, fact checker, literature reviewer, market analyst, financial analyst, technical researcher, synthesizer) and merges their findings
  • Plan Mode with Stored Plans: Read-only investigation, then a plan you approve. A plan you approve is saved to the project's .nova/plans/; a plan Nova approves on its own (auto-approve) goes to the global ~/.nova/plans/<project>/ archive
  • Steering Instructions: Persistent user-defined directives injected into every model call — set once, always respected
  • Inline Verification Loop: After each task, an out-of-band LLM call grades the output against a rubric — on a failing verdict, the agent is automatically re-driven with feedback (up to 3 retries). Fail-open by design
  • Prompt-Template Hill Climbing: When reviews repeatedly flag the same class of misunderstanding, the system proposes a targeted rewrite of the relevant .jinja template, A/B tests it against the current version using verifier pass/fail as the quality signal, and promotes or discards it. Packaged templates are never modified — all overrides live in ~/.nova/prompt_history/
  • Threshold Auto-Tuner: Reads the durable trace data Hermes already records and nudges review-trigger thresholds toward the observed working style — more real work ⇒ review sooner; more browsing ⇒ review less. Damped convergence with hard floor/ceiling bounds
  • Cron / Heartbeat Scheduler: Proactive scheduled tasks via standard 5-field cron expressions — fired jobs go on the same queue as remote bridges, so they run like any prompt. Manage with /cron
  • Webhook Ingress Server: Let external systems (GitHub, Linear, or any signed sender) trigger a Nova run without a human relaying through Discord/Telegram. Per-source HMAC-SHA256 secrets, timing-safe verification, binds to 127.0.0.1 by default. Manage with /webhook
  • Reasoning Effort Control: Dynamically adjust LLM reasoning effort (/effort low|medium|high|off) — hot-swaps the model without restarting. Supports OpenAI o-series, Gemini 2.5/3, and Claude 3.7 Sonnet
  • Self-Evolution Log: Track the agent's own growth over time (/evolution) — skills unlocked and levelled up at the completion of complex tasks, persisted in durable store
  • Autonomous Goal Mode: Set a persistent goal (/goal <text>) that is injected into every turn, with an optional acceptance rubric (/goal rubric <criteria>) graded by deepagents' RubricMiddleware. The agent runs autonomously toward the goal (capped at 5 turns by default) and stops when it declares GOAL ACHIEVED
  • Side Questions: Ask a question on an ephemeral thread without touching the main conversation (/btw <question>)
  • Refinement Loop: /refine runs a refinement audit trail over the session's work, with history and rollback <id> subcommands
  • Headless Mode: Run a single prompt non-interactively and exit (nova -p "...", or pipe the prompt on stdin) with text, json, or stream-json output — built for scripting and CI. --max-turns caps the run; --deny-tools auto-rejects tool approvals (fail-closed)

UI & Interaction

  • Textual TUI: Modern terminal UI with chat messages, modals, animations, keyboard shortcuts, condensed tool groups, and click-to-copy
  • Built to Stay Smooth: Status ticks repaint in place instead of reflowing the screen, rendered Markdown is cached per width, static data stays out of checkpoints, subagent graphs compile on first use, the skill listing is cached across restarts, and garbage collection is tuned to run while you are idle. A watchdog logs any UI freeze over 1s to ~/.nova/logs/freeze.log
  • Multi-line Prompt: The input grows with its content; shift+enter inserts a newline
  • Parallel Session Panes: Run several sessions side by side (/session new, ctrl+n, alt+<n>) and switch between them
  • Cross-project Agent Messages: Address another live tab with @tab:<session-id> <message> or @<unique-title> <message>. Tab addresses appear in @ autocomplete. Requests queue while the recipient is busy; linked final replies appear in collapsed Markdown panels in both transcripts. Expand a panel to read it, use Attach to prompt to append it to your draft, or Open tab to navigate to the peer. Attachment never submits the draft or stops your current task. Agents can use list_sessions, send_session_message, read_session_messages, and reply_session_message. Each recipient keeps its own project and tool approvals. Only the explicit message is shared. Communication currently covers tabs in one Nova window; pending messages are held in memory. Use the explicit @tab: form when a title also names a file or subagent. Peer messages are agent prompts; slash-command text inside them is context rather than a CLI command.
  • Docked Todo Checklist: The todo list stays on screen and can be clicked to collapse/expand
  • Condensed Tool UI: Consecutive tool calls grouped into collapsible sections — full diffs shown for code edits; reads, searches, and other calls stay compact
  • Syntax-Highlighted Diffs: Diff previews are syntax-highlighted per line (Pygments, keyed off the file extension) — token colours overlay the +/- marker colour, so added/removed lines stay visually distinct
  • Modal Animations: Entrance effects (fade/slide/zoom) for all modal dialogs, pulsing borders, and a shimmer status bar
  • Web Chat UI: Launch a local browser-based chat interface via /chat — dark-themed, Claude-inspired, with Markdown rendering and code highlighting
  • Nova Cowork Desktop App: Launch a desktop companion app via /cowork (alias /desktop) for a native window onto the same agent
  • Local Voice I/O (optional): Speak prompts and hear Nova's prose replies, fully offline — Faster-Whisper (STT), Silero VAD (utterance endpointing), and Piper (TTS). Push-to-talk (ctrl+g) or hands-free always-listening (ctrl+l); code blocks are stripped before speaking. One-command install: uv tool install -e .[voice], or uv pip install -e '.[voice]' for uv run; manage with /voice. Swappable TTS/STT providers: cloud (ElevenLabs / Deepgram), Orpheus — an optional, very natural LLM-based local TTS (/voice settings tts orpheus; uv pip install -e '.[voice-orpheus]' + the CPU llama-cpp-python wheel; ~2GB model, slower than Piper), Parakeet — NVIDIA's local STT via sherpa-onnx (/voice settings stt parakeet; uv pip install -e '.[voice-parakeet]'), or Pocket TTS — Kyutai's lightweight local TTS (/voice settings tts pocket; uv pip install -e '.[voice-pocket]')

Tools & Capabilities

  • 50+ Built-in Tools: File operations, shell commands, web search (Tavily + DuckDuckGo), docs search, HTTP fetch, subagent delegation, semantic code search, project graph queries, wiki management, plan mode, artifacts, background tasks, daemons, a persistent Python kernel, and more. Rarely used tools are deferred behind tool_search, so they cost no context until needed
  • Artifacts: Create, update, and list durable artifacts (create_artifact, update_artifact, list_artifacts) that persist across resume — browse them with /artifacts
  • Background Tasks: Long-running shell jobs are monitored and reported back when they finish; inspect them with list_background_tasks, get_task_status, get_task_logs, terminate_task, restart_task, or the /tasks panel
  • Daemons: Start, stop, and tail long-lived background processes (daemon) — dev servers, watchers, and the like
  • Persistent Python Kernel: Run Python in a long-lived kernel that keeps state between calls (python_kernel)
  • Multi-Model Oracle: Ask several models the same question and have a judge synthesize the best answer (oracle)
  • Web Scraping: GitHub trending repos, Hacker News headlines, LinkedIn jobs, Reddit posts — no external API keys required
  • Semantic Code Search: Find code by description or meaning, not just exact text matches (code_search, find_related_code)
  • LSP Integration: Language Server Protocol support for go-to-definition, find references, rename, diagnostics, and more
  • Project Graph: Visualize and query your codebase architecture — 5000+ nodes, community detection, dependency analysis, blast radius tracking

Extensibility

  • MCP Support: Extend capabilities with Model Context Protocol servers (14 curated presets, plus any custom server) — tools eagerly discovered with server-prefixed names to avoid collisions Presets: Playwright, Serena, Context7, Apify, CUA Driver, Sequential Thinking, Chrome DevTools, Firecrawl, Tavily, Exa, and Perplexity. Perplexity requires an API key; select it in /mcp to configure it.
  • Skills System: 50+ built-in skills with progressive disclosure — domain-specific workflows loaded on demand. Install skills from any public GitHub repo
  • Plugin System: Python entry-point based plugins that can register slash commands, add middleware at defined slots, and extend the agent
  • Custom Subagents: 4 built-in in-process specialists (code exploration, refactoring, bug fixing, browser automation), plus the 7 research-swarm personas and any agents you define yourself. Longer, self-contained jobs go to the async agents below
  • Async Subagents: 9 background agents on a LangGraph server that Nova launches itself, on demand, in your project directory (no Docker needed) — documentation updates, code reviews, test generation, dependency audits, refactoring, plan scouting, security audits, test runs, web research; results are automatically reported when the agent is idle. Without a usable server Nova falls back to the in-process subagents
  • Wiki System: Persistent project wiki at .nova/wiki/ — ingest web clippings (/ingest), ask questions with wiki context (/ask), file conversation knowledge as wiki pages (/file), and browse the vault (/wiki)

Sandbox & Safety

  • Sandbox Execution: Run code safely in sandboxes — OS (workspace-confined), Docker, Modal, Runloop, Daytona, LangSmith (hardware-virtualized microVMs)
  • Security-First: Automatic .gitignore enforcement, command injection detection, URL sanitization, and input validation
  • File Recovery: Automatic snapshots before destructive operations — restore deleted or overwritten files via /restore or agent tools (list_trash, restore_file)
  • Human-in-the-Loop (HITL): Configurable interrupt system requiring user approval before destructive or external operations
  • Path Approval: Path-based operation approval for filesystem access outside the project root

Infrastructure

  • Session Management: Save, restore, auto-save, and resume sessions. Compact conversation history via /compact. Run several sessions in parallel panes (/session new) and resume a saved session for the current path with /resume <id>
  • Remote Bridges: Discord and Telegram integration for remote agent interaction. Telegram accepts photos and image files: send one in a session's topic with a caption telling Nova what to do. Without a caption, Nova describes the image. Images join that session's conversation context; images received during a task are queued for a new turn. Images are limited to 20 MB and 7680 pixels per dimension. Telegram also accepts voice notes — they're transcribed with your configured /voice STT provider and sent to the agent as an ordinary prompt (the transcript is echoed back so you can see what was heard). In a Telegram forum each session gets its own topic, and a question Nova asks you is deleted from the chat once you answer it
  • Vixie Desktop Companion: Background server for desktop notifications and system tray integration
  • Hooks System: Lifecycle hooks at key points (pre/post tool call, on message, on error) — shell commands or Python scripts
  • Process Manager: Subprocess lifecycle, health checks, and cleanup for dev servers and background tasks
  • LangSmith Tracing: Built-in LangSmith integration for debugging, monitoring, and evaluating agent runs
  • Doctor Command: System diagnostics to verify your environment, API keys, and dependencies
  • Onboarding System: First-run setup that checks what you enter before saving it: an API key is tested against the provider and an Ollama host must answer with a model installed, so a typo shows up on the setup screen, not on your first prompt. Keys go to the OS keychain
  • Configuration Migration: Migrate from legacy directory structure to Claude Code-compatible layout

Quick Start (Two Commands)

git clone https://github.com/Babitdor/NovaCode.git
cd NovaCode
uv sync

Run it:

uv run nova

Headless (non-interactive) — for scripting and CI:

# Run a single prompt and exit
uv run nova -p "summarize the changes in this repo"

# Machine-readable output, capped at 10 turns, no tool approvals
uv run nova -p "summarize the changes in this repo" --output-format json --max-turns 10 --timeout 120 --deny-tools

# Explicitly allow unattended tool approvals for an execution task
uv run nova -p "run the test suite and report failures" --auto-approve --output-format json --timeout 300

# Stream JSON lines, including provisional text updates
uv run nova -p "explain src/main.py" --output-format stream-json --include-partial-messages --timeout 120

# Or pipe the prompt on stdin
echo "explain src/main.py" | uv run nova -p

The one-shot -p mode accepts UTF-8 text (up to 1 MiB): close stdin and read the result on stdout. Diagnostics, native writes, and inherited subprocess output go to stderr. JSON records include schema_version: 1; the terminal result includes exit_code. Partial text events are provisional: a text_discard event invalidates the current preview, and committed assistant events remain authoritative.

--print does not enable auto-approve or silently trust a directory. Existing policy and session allowances still apply; actions requiring a human are rejected and reported with exit code 3. Pass --auto-approve explicitly when unattended execution is intended. --deny-tools rejects approval requests, but does not disable all tools or guarantee a read-only run. For an unapproved workspace, approve it interactively first or explicitly pass --trust-workspace to grant folder-only trust.

Exit codes: 0 success, 1 execution/startup/incomplete-stream error, 2 observed turn limit, 3 human input required, 124 timeout, 130 cancellation, 141 closed output pipe. Invalid CLI options use argparse's exit code 2. --max-turns counts observed main-agent rounds; it is not an exact API-call or spend limit. --timeout covers asynchronous startup and execution; cleanup gets a bounded grace period. A caller needing a strict wall-clock limit should also enforce a process timeout. This mode does not accept interactive replies or multiple JSON requests on stdin.

Persistent pipe mode — for the Nova Remote App:

nova --mode pipe
# Alias: nova --headless

Wait for the JSON ready event, then send JSON lines such as {"type":"prompt","id":"mobile-1","content":"Investigate failing tests"}. The process stays alive for multiple prompts and streams structured text, tool, approval, and completion events. cancel stops work; shutdown exits cleanly. Use an approved project as the child process's working directory, an absolute binary, and shell: false. See the protocol and bridge guide and Node process adapter. For the Nova Remote App setup, pairing, project registry, relay, and multi-session integration sequence, see the Remote App integration guide.

Optional — voice I/O adds STT, TTS, and VAD (~2 GB extra):

uv run nova
/voice test     # verify it works
ctrl+g          # push-to-talk

No need to install anything globally. uv run nova always runs the latest code from the repo — no stale snapshots, no PATH issues, no "which Python".

If you want a global nova command that works from any directory, add the repo's .venv to your PATH:

# Windows PowerShell:
$env:Path += ";$pwd\.venv\Scripts"
# Or add `B:\Summer Project 2026\Nova-Code\nova-code-cli\.venv\Scripts` to your system PATH

Then just type nova anywhere.

Alternative: Install with pip

# 1. Clone the repository
git clone https://github.com/Babitdor/NovaCode.git
cd NovaCode

# 2. Create a virtual environment
python -m venv .venv

# 3. Activate the virtual environment
# On Windows (PowerShell):
.venv\Scripts\Activate.ps1
# On Windows (Command Prompt):
.venv\Scripts\activate.bat
# On macOS/Linux:
source .venv/bin/activate

# 4. Upgrade pip
pip install --upgrade pip

# 5. Install dependencies
pip install -e .

Verify Installation

# Check if nova is installed
nova --version

# Run system diagnostics
nova doctor

# Start the CLI
nova

Update Nova

nova update --check  # check now without installing
nova update          # update the Nova installation running this command

The TUI checks in the background at startup and hourly. When an update is available, a notification and a transcript notice tell you to exit and run nova update, then restart. /update checks immediately from the TUI. Set NOVA_DISABLE_UPDATE_CHECK=1 to disable background checks; manual checks still work. Checks use a one-hour cache and stay quiet when offline.

Repo and Git installs compare commits against the tracked branch (Git package installs use main), so pushing code can trigger a notification without changing the package version. Package-index installs check the published package version. For a stable release workflow, bump the version and publish the package for each release; repo users can receive changes directly from Git.

Source checkouts must have no local changes and track the matching origin branch. Updates fetch and merge with --ff-only, then refresh dependencies with uv or pip. uv tool installations use uv tool upgrade; other package installs use the running Python environment. Pinned Git refs, forks, and archive installs remain managed through their original installer. Nova settings, sessions, MCPs, and skills remain in their existing directories.

On Windows, uv-managed updates run in a separate process after nova update and its launcher exit. Installer progress and the final result appear live in the same terminal. When no update is needed, Nova displays NovaCode is up to date. Close other Nova sessions before updating. If an older updater reports Failed to install entrypoint or Windows could not move Nova's launcher, run this directly from PowerShell after closing Nova to install the corrected updater:

uv tool upgrade novacode-cli --reinstall

API Keys Setup

Configure your preferred LLM provider by setting environment variables:

# OpenAI (default)
export OPENAI_API_KEY="your-openai-api-key"

# Or Anthropic
export ANTHROPIC_API_KEY="your-anthropic-api-key"

# Or Google Gemini / NVIDIA / OpenRouter
export GOOGLE_API_KEY="your-google-api-key"
export NVIDIA_API_KEY="your-nvidia-api-key"
export OPENROUTER_API_KEY="your-openrouter-api-key"

# Optional: Web search (Tavily)
export TAVILY_API_KEY="your-tavily-api-key"

Option 2: .env File

Create a .env file in your project root or home directory:

# .env file
OPENAI_API_KEY=your-openai-api-key
ANTHROPIC_API_KEY=your-anthropic-api-key
TAVILY_API_KEY=your-tavily-api-key

Option 3: Configuration File (Secure Keychain)

# Store keys securely via OS keychain
nova secrets set openai_api_key
nova secrets set anthropic_api_key

Troubleshooting

IssueSolution
Python version mismatchpython --version → specify version: uv venv --python 3.11
Virtual env not activating (Windows)Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser then retry
Package installation failsuv cache clean && uv sync --reinstall
Missing dependenciesuv sync --all-extras
Import errorsuv pip install -e . --force-reinstall

Development Setup

# Install development dependencies
uv sync --all-extras

# Run tests
pytest tests/

# Format and lint code
make format
make lint

# Type checking
mypy novacode_cli/

CLI Reference

Top-Level Subcommands

CommandDescription
nova initInitialize project or global configuration
nova listList all available agents
nova helpShow help information
nova reset --agent <name>Reset an agent's memory/store
nova skillsManage agent skills (list, create, add, remove, find, update)
nova mcpManage MCP servers (add, remove, list, install)
nova configView or edit configuration (show, set, get)
nova secretsManage API keys securely (set, list, delete)
nova doctorValidate configuration and connections
nova pathsManage approved file system paths (list, revoke, clear)
nova migrateMigrate to new directory structure

Flags

FlagDefaultDescription
--agent"nova-agent"Agent identifier for separate memory stores
--auto-approveoffAuto-approve tool usage (disables HITL)
--sandboxos (Linux/macOS), none (Windows)Sandbox provider: none, os, modal, daytona, runloop, docker, langsmith
--no-sandboxoffRun shell commands unconfined on the host (disables OS/Docker sandbox)
--sandbox-idNoneReuse an existing sandbox (skips create/cleanup)
--sandbox-setupNonePath to setup script to run in sandbox after creation
--sandbox-vcpusNoneNumber of virtual CPUs (LangSmith sandbox only)
--sandbox-mem-bytesNoneMemory in bytes (LangSmith sandbox only, e.g. 8589934592 for 8GB)
--sandbox-fs-capacity-bytesNoneFilesystem capacity in bytes (LangSmith sandbox only)
--sandbox-snapshotNoneSnapshot name to boot from (LangSmith only)
--sandbox-snapshot-idNoneSnapshot ID to boot from (LangSmith only)
--portsNonePort forwarding for Docker sandbox (format: PORT or HOST:CONTAINER, comma-separated)
--no-splashoffDisable the startup splash screen
--continue / -coffContinue last session (optionally specify session ID)
--resume / -roffInteractively select and resume a session
--print / -poffRun a single prompt non-interactively and exit (pass the prompt as the value, or omit it to read from stdin)
--output-formattextHeadless output format: text, json, or stream-json
--max-turnsNoneHeadless only: cap the number of agent turns
--deny-toolsoffHeadless only: auto-reject tool approvals (fail-closed) instead of prompting
--timeoutunlimitedHeadless deadline in seconds, including asynchronous startup
--include-partial-messagesoffAdd provisional text events to stream-json output
--trust-workspaceoffHeadless only: explicitly grant current-folder trust
--version—Show version number and exit

Shell commands in the TUI

Enter !command to stream output in the chat. Nova records the output and reports the result to the agent. Enter !!command to open an interactive terminal view for prompts, menus, and other commands that need keyboard input. Press Ctrl+G or Shift+Tab to return to chat while the command keeps running; use /tasks to inspect or stop it.

Interactive Slash Commands

CommandDescription
/helpShow interactive help
/exit / /quit / /qExit the CLI
/clearClear conversation history and reset session
/tokensDisplay token usage for the session
/contextDisplay current context window status
/costShow session token spend
/verboseToggle verbose mode (show internal agent context)
/steerSet persistent steering instructions for the agent
/goalSet a persistent goal injected into every turn (/goal rubric <criteria> for an acceptance rubric; status / clear)
/btwAsk a side question on an ephemeral thread without touching the main conversation
/saveSave current session
/compactCompact conversation history with optional focus
/sessionsList, select, or delete saved sessions
/uiInspect the optional UI panels; use patch, preview, commit, rollback, or reset
/tabsSession tabs: launch opens the approved project picker; resume picks a saved session to reopen as a tab; resume <id> accepts an exact ID or unique prefix. list / close manage tabs (ctrl+n, alt+<n>)
/resumeResume a saved session for this path (/resume <id>)
/restoreRestore a previous file version from snapshots
/filesShow file operation summary for the session
/imagesManage tracked image references
/artifactsOpen the artifacts list
/tasksOpen the selected tab's background tasks panel (t: terminate, r: restart, l: logs)
/logShow workspace log files
/serversShow active server processes
/testsRun test suites
/killKill a process by PID
/notificationsReview and manage notifications
/remoteManage remote sandbox connections
/reindexRebuild semantic code search index
/copyCopy the last response (or the whole chat)
/themeSwitch color theme
CommandDescription
/initGenerate/update project documentation and graph
/mcpInteractive MCP server management menu
/modelSwitch the model for the main agent, the subagents, the async agents or the dynamic agents
/hooksManage lifecycle hooks (list, add, remove, enable, disable)
/skillsInteractive skills manager
/agentsCustom agent management (view, create, delete)
/plugins / /pluginNova plugin management (list, enable, disable)
/middlewareList active middleware (/reload-plugins to reload)
/reload-pluginsReload plugin registrations
/planInvoke plan-mode agent for investigation & approval (approved plans are saved to .nova/plans/)
/agent-serverControl the local LangGraph server for async agents — status, start, stop, restart, logs
/traceLangSmith tracing management (status, enable, projects)
/ralphAutonomous looping mode (background task execution)
/council <task>Plan a task with the council: agents propose independently, critique anonymously, vote, and a judge picks the top 3 for you to approve
/council view [n]Show the selected plans, or plan n in full
/council approve <n>Approve plan n and hand it to the coding agent (nothing is implemented before this)
/council revise <notes>Re-plan with your changes
/council historyPast council runs (kept in .nova/council/)
/chatLaunch local browser-based chat UI
/cowork / /desktopLaunch the Nova Cowork desktop app (/cowork [task])
/trelloBrowser-based task board server
/researchMulti-agent research swarm (academic/market/stocks/technical/general)
/dreamRun memory consolidation
/browser-useAI-powered browser automation
/createLaunch the Skills & Agents web UI for browsing, editing, and creating skills/agents
/skill:<name>Directly invoke a skill by name (e.g., /skill:api-testing)
/cronManage scheduled (heartbeat) tasks — list, add, remove, fire now
/webhookManage webhook ingress server — start, stop, register sources, status
/promptManage evolving system-prompt templates — status, rollback, accept, reject
/refineRefinement audit trail (/refine history, /refine rollback <id>)
/voiceLocal voice I/O — status, on/off, mode ptt|listen, test (ctrl+g talk, ctrl+l listen)
/effortSet reasoning effort level — low, medium, high, or off (hot-swaps model)
/visionConfigure image handling — status, set the auxiliary vision model, or force the main model multimodal/text-only
/evolutionView the self-evolution log — skills unlocked (🧬) and levelled up (⬆️)
/learningToggle Nova's autonomous learning loop (/learning on|off|status)
/ingestIngest captured sources (Obsidian Web Clipper) into synthesized wiki pages
/askAsk a question informed by wiki context — searches wiki and answers with relevant knowledge
/fileFile recent conversation knowledge as a wiki page under a topic path
/wikiList all synthesized pages in the project wiki vault

In Telegram, send /tab to pick an approved project, then confirm the launch in that topic. The new tab gets its own topic named NovaCode · <session name>; chat there to work in that project. Existing topics adopt the session name on reconnect, preserving their history. Names are synchronized when topics are attached, with long names shortened to Telegram's 128-character limit. Use /tab close to choose a tab to close. Telegram photos and image documents are delivered to the session belonging to their topic.

In the main session's Telegram topic, slash commands use the normal TUI handlers, including /skills, /model, /settings, and plugin commands. Interactive panels show numbered choices: /choose N selects an action, /set N value fills a field, /input N value submits it, /panel N changes pages, and /back closes the panel. Only the requester in that topic can operate its controls. Commands received during a task wait until it finishes. Invoke skills with /skill:name arguments or /name arguments; skill invocation also works in child-session topics, using that session's workspace. Child topics use the shared CLI handlers for other commands; TUI-only management panels are available in the main topic.

Type / in Telegram to open its native command autocomplete menu. Nova publishes commands and enabled skills for the configured chat on connection and refreshes after skill management or plugin reload. Telegram allows up to 100 menu entries; commands take priority, followed by skills. Names with hyphens appear with underscores (for example /api_testing). Skills outside the menu remain available with /skill:name. The menu is shared by all topics in that chat.

Each TUI tab shows its own Tasks footer. Open /tasks (or Ctrl+B with an empty prompt) to select and terminate a background command. You can also ask Nova to list or stop its background tasks; task IDs apply only within that session.

Nova saves an incoming prompt before model execution, checkpoints active sessions every five seconds, and saves again when a turn ends. Atomic recovery snapshots preserve the last complete conversation after a crash. Resume with nova --continue or choose a session with /sessions. Abrupt termination can lose progress since the last completed save and tokens the model has not yet committed to its history.

On restore, Nova rebuilds a continuation from saved history and session memory. The loaded history is limited to approximately 30,000 tokens, including tool-call arguments and retained reasoning; unpaired tool calls and results are excluded. /context estimates the newly loaded context, including the continuation briefing, current instructions, memory, and tool schemas. It does not reuse the previous request's token total: provider usage becomes available after the next model call.

The local TUI supports optional notes, workspace files, and activity panels. Ask Nova to customize them, or use /ui patch with a JSON object, then /ui preview and /ui commit. Panel order follows the panels list. Layouts are saved per workspace under ~/.nova/ui/. /ui rollback restores the saved layout. Use /ui reset, Ctrl+Shift+Backspace, or start with nova --safe-ui for recovery. Custom panel shortcuts use F6–F12; custom panel commands use /ui-<name>. Conversation, input, approvals, and session controls stay protected. This first version uses registered components; it does not load generated Python widgets.

Example: /ui patch {"panels":[{"id":"notes","type":"notes","title":"Notes","text":"Current task"}],"width":28}

External histories can be viewed or imported through /sessions, /import codex --last, or /import claude <id-or-file>. Switch the loaded reference with /context imported full|compact|relevant [query]; compare histories using /compare claude:<id> codex:<id>. Startup also supports nova --import claude --latest. See session import and adapter plugins.

The Active subagents panel shows running tasks with their model and elapsed time. It disappears when no tasks are active; Alt+S collapses or expands it.

Built-in Tools

ToolDescription
lsList files and directories
read_fileRead contents of a file
write_fileCreate or overwrite a file
edit_fileMake targeted edits to existing files
globFind files matching a pattern (e.g., **/*.py)
grepSearch for text patterns across files
shellExecute shell commands (local mode)
executeExecute commands in remote sandbox (sandbox mode)
taskDelegate work to subagents for parallel execution
write_todosCreate and manage task lists for complex work
thinkStructured reasoning and reflection before acting
web_searchSearch the web using Tavily API
duckduckgo_searchWeb search using DuckDuckGo (no API key required)
docs_searchSearch official documentation sites
fetch_urlFetch and convert web pages to markdown (covers all HTTP methods)
github_trendingScrape GitHub trending repositories by language/time range
hacker_newsScrape Hacker News front page headlines
linkedin_jobsSearch LinkedIn job listings (Playwright-based, no login)
reddit_postsScrape Reddit posts by subreddit, user, or search query
package_infoGet package version and dependency info (PyPI / npm)
read_memory / write_memoryRead and write persistent markdown agent memories
remember / recallStore and fetch durable cross-session facts by key
list_memories / forgetList and delete stored durable memory facts
list_trashList file snapshots available for recovery
restore_fileRestore a deleted or overwritten file from snapshots
create_artifactCreate a durable artifact (markdown, code, etc.) that persists across resume
update_artifactUpdate an existing artifact's title, type, or content
list_artifactsList all artifacts in the session
list_background_tasksList agent-launched background shell jobs
get_task_statusGet a background task's status, runtime, and exit code
get_task_logsRead the recent output of a background task
terminate_taskStop a running background task
restart_taskRestart a background task
daemonStart, stop, and tail long-lived background processes
python_kernelRun Python in a persistent kernel that keeps state between calls
oracleAsk several models the same question and have a judge synthesize the answer
query_project_graphQuery the project graph for architectural information
code_searchSemantic code search by description or symbol name
find_related_codeFind code semantically similar to a known location
start_async_taskStart a background task on a remote LangGraph server
check_async_taskCheck status and result of a background task
update_async_taskSend updated instructions to a running background task
cancel_async_taskCancel a running background task
list_async_tasksList all tracked background tasks
speakSpeak a short summary aloud via TTS
skill_manageCreate, refine, or remove reusable skills
wiki_readRead a wiki page by path
wiki_searchSearch the project wiki for pages matching a query
wiki_update_indexAdd or update an entry in the wiki index
wiki_writeWrite or overwrite a wiki page
enter_plan_modeSwitch to read-only investigation mode before coding
exit_plan_modePresent a plan for user approval and exit plan mode
ask_user_questionAsk the user a multiple-choice question and wait for response

Note: Potentially destructive operations require user approval. Use --auto-approve to skip prompts.

Trello Task Board

NOVA includes a browser-based task board for managing and processing tasks visually. Start it with /trello.

/trello              Start the task board server and open browser
/trello stop         Stop the task board server
/trello status       Show current task board state

Task Lifecycle

StatusDescription
LoadedTask added, waiting to be processed
ProcessingAgent is currently working on the task
DoneTask completed by the agent

Add tasks from Telegram

  1. Configure your Telegram bot and group with /remote once. The group must have Topics enabled, and the bot needs permission to manage topics.
  2. Open /trello and turn on Telegram in the board header.
  3. Click Open topic when the connection is ready. Nova creates a dedicated Trello topic, separate from the session topics.
  4. Send a text message or /add <task> in that topic. It becomes a card in Loaded. Use /status to see board counts.

Only authorized Telegram users can add cards. Turning the toggle off pauses intake and keeps the topic and existing cards. Telegram task intake does not change your tool approval mode.

Move a card to Processing, or enable Auto-advance, to run it. In the TUI, execution waits until the board's owning tab is selected and idle. Keep Nova and the board running: cards are held in memory and are not restored after a restart. This topic accepts text tasks; use a session topic for images.

Web Chat UI

Launch a local browser-based chat interface with /chat:

/chat              Start the chat server and open browser
/chat stop         Stop the chat server
/chat status       Show chat server status
  • Dark-themed UI: Claude-inspired design with red accents
  • Markdown Rendering: Full Markdown + syntax highlighting via marked + highlight.js
  • Typing Indicator: Animated bouncing dots while the agent responds
  • Same Agent: Connects to the same LangGraph agent — no separate config

Web Scraping Tools

Built-in tools that work with public data — no API keys required:

ToolData Source
github_trendingGitHub trending repositories
hacker_newsHacker News front page
linkedin_jobsLinkedIn job listings (Playwright)
reddit_postsReddit posts by subreddit/user/search

Standalone CLI scripts also available in scripts/scraper/.

Autonomous Learning System (Hermes)

NOVA includes Hermes, an autonomous learning system that runs in the background:

  • Self-Review: Every ~10 tool calls, Hermes reviews tool usage patterns and extracts lessons
  • Self-Improving Memory: Automatically maintains two memory tiers:
    • USER.md — User model: communication style, preferences, workflows, recurring frustrations
    • MEMORY.md — Cross-session memory: architecture decisions, reusable patterns, key facts
  • Skill Creation: Analyzes repeated successful tool sequences and autonomously creates reusable skills with deterministic naming and refinement
  • Skill Debate: skill_debate.py — Multi-perspective skill evaluation that compares new skills against existing ones, flags overlap, and suggests merges
  • Skill Manager: skill_manager.py — Orchestrates skill creation from review feedback, failure-grounded refinement, and background curation
  • Tool Usage Tracker: tracker.py — Counts tool calls, maintains per-tool stats, and tracks skill invocations to drive refinement decisions
  • Review Runner: review.py — Decides when to review (signal-based: failure bursts, substantive windows, hard cap) and runs out-of-band LLM reviews
  • Curator: curator.py — Archives unused skills and flags overlapping ones to keep the skill library lean
  • Evolution Logger: evolution.py — Tracks skill unlocks and level-ups, persisted in durable store, viewable via /evolution
  • No Interruption: Reviews run out-of-band in the background — no pause in agent operation
  • Live Indicator: Visible indicator in the TUI status line when Hermes is reviewing

Loop Engineering Enhancements

Hermes has been extended with five self-improving subsystems, each closing a different feedback loop:

EnhancementModuleWhat It Does
1. Inline Verification Loopcore/verification_loop.py, hermes/verifier.pyAfter each task, an out-of-band LLM call grades the output against a rubric. On a failing verdict, the agent is re-driven with feedback (up to 3 retries). Fail-open: any grading error yields a pass
2. Prompt-Template Hill Climbinghermes/prompt_evolution.pyWhen reviews repeatedly flag the same class of misunderstanding, proposes a targeted rewrite of the relevant .jinja template, A/B tests it using verifier pass/fail as the quality signal, and promotes or discards it. Packaged templates are never modified — overrides live in ~/.nova/prompt_history/
3. Cron / Heartbeat Schedulerremote/scheduler.py, commands/cron_handler.pyProactive scheduled tasks via standard 5-field cron expressions. Fired jobs go on the same queue as remote bridges, so they run like any prompt. Manage with /cron
4. Threshold Auto-Tunerhermes/tuner.pyReads durable trace data and nudges review-trigger thresholds toward the observed working style. Damped convergence (0.2 weight) with hard floor/ceiling bounds — can never starve reviews or burn tokens
5. Webhook Ingress Serverremote/webhook_server.py, remote/webhook_adapters.py, commands/webhook_handler.pyLet external systems (GitHub, Linear, or any signed sender) trigger a Nova run. Per-source HMAC-SHA256 secrets, timing-safe verification, binds to 127.0.0.1 by default. Manage with /webhook

All enhancements share the same design principles:

  • Fail-open: Any failure logs and degrades gracefully — the agent turn is never blocked
  • Durable: State persists in the LangGraph store under named namespaces (hermes/config.py)
  • Background: Run as fire-and-forget asyncio tasks — no pause in agent operation
  • Configurable: All thresholds and bounds are centralized in hermes/config.py

Middleware Stack

Every model call passes through this middleware chain (in order):

LayerModulePurpose
ModelRetryMiddlewaredeepagentsRetry transient model failures (rate limits, 429) with exponential backoff
VisionCaptionMiddlewarebootstrap/vision_router.pyConvert images to text for a text-only main model; pass-through when the main model is multimodal
NovaLearningMiddlewarehermes/middleware.pyHermes learning system — tool usage tracking, review cycles, memory tiers (opt-in)
SecurityMiddlewaresecurity/URL sanitization, unicode attack prevention
BootstrapMiddlewarebootstrap/Environment snapshot injection
SteeringMiddlewarebootstrap/steering.pyInjects persistent user instructions (mid-run steering)
FileTrackerMiddlewaretracking/File-op tracking, result truncation
LoopGuardMiddlewaretracking/loop_guard.pyBreak stuck identical tool-call loops
RubricMiddlewaredeepagentsRubric self-evaluation — dormant unless a rubric is set via /goal rubric
VerdictScorer middlewareagents/tool_verdicts.pyScores old tool results with the System One decision model so the next layer clears only the stale ones (inserted only when tool_verdicts_enabled is on)
ContextEditingMiddlewarelangchain.agents.middlewareClear older tool-call outputs when the window-relative token trigger is reached; cleared results are offloaded to /cleared/ (agents/tool_offload.py)
ShellMiddlewareshell.pyShell tool + sandbox execution
AgentMemoryMiddlewarememory/Agent memory loading (USER.md, MEMORY.md, project NOVA.md)
TaskDisciplineMiddlewareagents/task_discipline.pyTodo recitation appended to the final system message
MCPMiddlewaremcp/middleware.pyMCP tool provisioning (inserted dynamically when MCP servers configured)
GraphContextMiddlewarebootstrap/graph_context.pyInjects project graph legend summary

Project Graph

The project graph (.nova/project-graph.json, ~5000 nodes, ~13000 edges) is built by the /init pipeline. It provides:

  • Community Detection: Tightly coupled module clusters identified via graph analysis
  • Central Hubs: High-degree nodes — files with wide blast radius (e.g., Settings with 502 connections)
  • Dependency Analysis: Cross-module connections and architectural seams
  • Queryable: Ask the agent query_project_graph("Settings") to find connected modules and community structure

Refresh with /init (full rebuild) or /init --update (incremental).

Configuration

Directory Structure

Global Configuration (~/.nova/):

~/.nova/
├── agents/
│   └── default/
│       └── agent.md
├── skills/
│   └── web-research/
│       └── SKILL.md
├── hooks/
│   ├── pre_tool_call.py
│   └── post_tool_call.sh
└── trash/
    └── <session-id>/
        ├── manifest.json
        └── <snapshots>

Project Configuration (in your project root):

my-project/
├── AGENTS.md          # Optional concise instructions; Codex-compatible
├── .nova/
│   ├── NOVA.md        # Project-specific context and conventions
│   ├── config.json    # Project configuration
│   ├── hooks.json     # Project-specific hooks
│   └── skills/        # Project-specific skills
├── .claude/           # Also supported (Claude Code compatible)
└── .nova.config.json  # Project-level config (scoped)

Agent Memory

  • Global (~/.nova/agents/default/agent.md): Your personality, style, and universal preferences
  • Project (NOVA.md, .nova/NOVA.md, CLAUDE.md, .claude/CLAUDE.md, or AGENTS.md): Project-specific instructions are combined when present. /init creates .nova/NOVA.md; project files never grant tool or path approvals.

Keep the project guide short: what the project does, exact test/build commands, protected files, useful examples, and what counts as done. For a debugging request, give Nova the failing test or full error and the relevant file. For a style-sensitive change, point to an example file. For a decision, give the constraints and acceptance criteria. Nova should run the narrowest relevant check and report what it verified before calling the task complete.

Skills

Manage skills with:

# List all skills
nova skills list

# Create a new skill
nova skills create my-skill

# Create a project-specific skill
nova skills create my-skill --project

# View skill details
nova skills info web-research

Installing Skills

nova skills add runs the official Skills CLI (npx --yes skills@latest add) with your arguments unchanged. It requires Node.js (current Skills CLI: Node 22.20+), npm/npx, and Git for repository sources. The first run downloads the CLI; subsequent runs use npm's cache and check for updates. It runs without Nova onboarding or an LLM API key.

# Discover skills and select which ones to install interactively
nova skills add vercel-labs/agent-skills

# List available skills without installing
nova skills add vercel-labs/agent-skills --list

# Select several skills; --skill selects existing names, it does not rename them
nova skills add owner/repo --skill first-skill second-skill

# Install to the shared directory that Nova reads (project scope is the default)
nova skills add owner/repo --agent universal --skill my-skill -y

# Install globally for all projects
nova skills add owner/repo --agent universal --skill my-skill -g -y

# Local folders, GitHub/GitLab URLs, SSH URLs, and owner/repo@skill are supported
nova skills add ./local-skills --agent universal --copy -y
nova skills add owner/repo@my-skill --agent universal -y

# Install every skill to every supported upstream agent
nova skills add owner/repo --all

# Alias
nova add skill owner/repo --list

The official installer controls selection, confirmation, copy/symlink behavior, complete supporting files (including binary assets), errors, and lock files. Nova reads shared skills from .agents/skills/ and ~/.agents/skills/ alongside its existing .nova/skills/ and Claude skill directories. For Nova-only installs, use --agent universal; other --agent choices target the upstream agents. A source without valid skills produces the upstream result; add no longer fabricates a skill from a README. Use nova skills create to author a new skill.

New installs use the upstream lock files and can be maintained with npx skills check, npx skills update, and npx skills remove. Nova's existing update command continues to manage older .nova lock entries. The previous add-only --project flag is unnecessary (project is the default), and --force is replaced by the upstream confirmation/--yes workflow.

System One Compaction

The TUI's CTX meter uses the latest main-model input usage when available and an estimated summary/tail breakdown after compaction or resume. Its percentage uses the selected model's detected context window. SESSION accumulates main-model input and output across tool-loop calls against a configured token budget (1M by default); it is not a provider quota or billing estimate. Compaction preserves SESSION usage, while /clear resets it. Subagents and auxiliary model calls are not included, and historical usage is not restored from saved sessions.

By default the context pipeline clears every tool result older than the token trigger except the newest few. System One compaction replaces that age rule with a judgement: a small decision model is shown a skeleton of the conversation and asked, per result, whether it is still needed. Only results scored below the keep threshold are cleared, and an unjudged result is always kept (the feature fails open).

It is off by default. Open /model → Decisions to select Jev, Tev1, or Custom System One, edit the decision model and endpoint, and toggle Enable System One tool pruning. Save persists the settings and rebuilds the current agent while retaining your chat model and conversation. Cancel discards the changes.

To use hosted Jev, open /auth, select Jev (System One compaction), and save your TypeSafe API key. The Decisions tab's Manage API key button opens the same manager without discarding your draft. Keys use Nova's existing credential store as TYPESAFE_API_KEY. Saving a key does not change the decision model or enable pruning; those settings belong to the Decisions tab. Create keys in the TypeSafe console; the official API reference describes the request format.

For environment-based authentication, set TYPESAFE_API_KEY and configure:

{
  "tool_verdicts_enabled": true,
  "tool_verdict_endpoint": "https://api.typesafe.ai/v1/systemone",
  "tool_verdict_model": "jev-latest"
}

Local and custom models remain optional. Set their full System One endpoint and the model name accepted by that server in ~/.nova/Nova.config.json. There is no model allowlist: Kev1 and future compatible models work through the same interface. For example, the existing local Tev1 setup is:

{
  "tool_verdicts_enabled": true,
  "tool_verdict_endpoint": "http://localhost:11434/v1/systemone",
  "tool_verdict_model": "tev1:4b",
  "tool_verdict_keep_threshold": 0.5
}
KeyMeaningDefault
tool_verdicts_enabledMaster switchfalse
tool_verdict_endpointSystem One endpointhttp://localhost:11434/v1/systemone
tool_verdict_modelDecision model (tev1:4b separates answers cleanly; the 0.8B size does not)tev1:4b
tool_verdict_keep_thresholdMinimum probability a result is still needed for it to survive0.5

If a custom endpoint requires authentication, use Custom System One (optional API key) in /auth, or set SYSTEM_ONE_API_KEY. Local endpoints can run without a real key. TypeSafe credentials are sent only to the exact official Jev endpoint; custom endpoints use the separate custom credential. Configure the endpoint/model and toggle pruning in Decisions. Hand-edited configuration applies after restarting Nova; set tool_verdicts_enabled to false to disable it.

This feature decides which tool outputs to offload during context management. /compact summary generation continues to use your active session model. Thresholds should be evaluated separately for each decision model.

Why it is opt-in: the current scorer budgets about 2,000 tokens and considers only the newest 12 results, including when Jev is selected. Measured on six real sessions with Tev1, the default age rule cleared more (70 results / 72,682 chars against 49 / 18,364) with fewer regretted clears (0.19 against 0.44 per 1k). These measurements do not establish Jev's performance. The flag stays so each model can be tried live and re-measured.

Tool discovery

Nova keeps less-used tool schemas out of the model's prompt and loads them with search_tools. Search covers every currently available tool, including core and already loaded tools, plus specialist subagents. Use a capability description, an exact name, a partial name, or a wildcard such as playwright_*.

search_tools(query="*", limit=20, offset=0) browses the catalog; increase offset to retrieve later pages. Results load the tools for the next model call and indicate whether a subagent uses task or start_async_task. Search covers tools registered for the current session.

Built-in Subagents

NOVA has two kinds of subagent. In-process specialists run inside the session, behind its approvals and sandbox, and answer in the same turn. Async agents run in the background and report back when they finish.

In-process Specialists

SubagentDescriptionAuto-loaded Skills
general-purposeAny delegated task; the default—
code-explorerNavigate, understand, and query large codebasescodebase-explorer/, graphify/
refactoring-specialist-agentCode smells, technical debt, design patternsimprove-codebase-architecture/
bug-fix-agentSystematic bug diagnosis and fixsystematic-debugging/
browser-automation-agentWeb testing, forms, screenshots, data extraction; drives a real browser through the Playwright MCP tools, and the desktop through cua-driveragent-browser/, browser-use/, web-research/

Their graphs are compiled on first use, so unused ones cost nothing at start-up.

Longer, self-contained jobs (review, documentation, tests, security audits, research) are async agents, below. Domain know-how such as frontend, backend or Docker work is a skill the main agent loads on demand.

Research Swarm

Dispatched by /research; kept out of the everyday roster and loaded on demand.

SubagentDescription
web-researcherBroad web search and source gathering
fact-checkerVerifies claims against independent sources
literature-reviewerAcademic papers and prior work
market-analystMarkets, competitors, and trends
financial-analystStocks and financial data
technical-researcherLibraries, APIs, and technical trade-offs
research-synthesizerMerges the findings into one report

Async Background Agents (Remote LangGraph)

SubagentDescription
documentation-update-agentAuto-synchronize project docs and changelogs with git commits
code-review-agentReview uncommitted/recent changes asynchronously
test-generation-agentGenerate/maintain test suites in the background
dependency-audit-agentAudit dependencies for updates and security vulnerabilities
refactoring-agentAnalyze and improve code quality in the background
plan-scout-agentRead-only directory scans dispatched during plan mode
security-audit-agentFull security audit (OWASP Top 10, secrets, auth flaws); read-only
test-runner-agentRun the test suite and report failures with likely causes; test-runner commands only
research-agentWeb research with sourced findings

Async agents read, search and report; the ones that write (documentation, tests, refactoring) do so unattended, so give them a self-contained task. Work that needs your approval along the way belongs with an in-process specialist, because approvals do not reach the server.

Start any with start_async_task(), check status with check_async_task(). When Nova has a local server planned or a usable external server, the async tools stay visible to the model without a tool search. The local server starts on the first dispatch. Otherwise Nova uses its in-process subagents.

The dynamic subagents panel shows only active tasks. Completed, failed and stopped rows disappear, and the panel hides when no tasks remain active. Background tasks remain visible across foreground turns while they are running.

Hooks System

Lifecycle hooks for customizing agent behavior:

HookWhen It FiresUse Case
pre_tool_callBefore a tool is executedValidate inputs, log, modify params
post_tool_callAfter a tool completesProcess results, log, trigger notifications
on_messageWhen a message is receivedFilter content, add context
on_errorWhen an error occursCustom error handling, recovery
# List all hooks
/hooks list

# Add a hook
/hooks add pre_tool_call my_hook --command "echo 'Tool called'"

# Add a hook from a file
/hooks add post_tool_call logger --file hooks/logger.py

# Enable/disable hooks
/hooks enable my_hook
/hooks disable my_hook

Hooks can be Python scripts (full access to internals), shell commands, or any executable.

MCP Integration

Extend the agent with Model Context Protocol servers:

# Add from preset
nova mcp add google-drive --preset google-drive
nova mcp add gmail --preset gmail
nova mcp add google-docs --preset google-docs
nova mcp add playwright --preset playwright

# Custom HTTP transport
nova mcp add my-server --transport http --url https://example.com/mcp

# Custom stdio transport
nova mcp add my-server --transport stdio --command "python -m my_mcp_server"

Available Presets: google-drive, gmail, google-docs, playwright, serena, context7, apify, cua-driver, sequential-thinking, chrome-devtools, firecrawl, tavily, exa, perplexity

Google MCP setup: Open /mcp, select Google Drive, Gmail, or Google Docs, and install the preset. These use the community-maintained Google Workspace MCP server, launched through uvx workspace-mcp with only the selected service's core tools. uv must be installed.

Create a Google Cloud OAuth client using the upstream quick-start guide, enable the Drive, Gmail, and Docs APIs you intend to use, and download its client JSON. Register http://localhost:8001/oauth2callback for Drive, http://localhost:8002/oauth2callback for Gmail, and http://localhost:8003/oauth2callback for Docs. Supply the JSON file's full path when Nova prompts; the same file can serve all three presets. Google consent is completed through the server's authentication flow after restarting the session. Nova stores the file path in MCP configuration; the client secret remains in your JSON file. No Google account is connected merely by adding a catalog preset.

MCP Management:

nova mcp list              # List all configured servers
nova mcp remove my-server  # Remove a server

Sandbox Execution

NOVA supports multiple sandbox providers for safe code execution:

# OS sandbox (default on Linux/macOS — host files, shell confined to workspace)
nova --sandbox os

# Docker (opt-in on Windows, with workspace binding)
nova --sandbox docker

# Modal (cloud)
nova --sandbox modal

# Runloop (cloud)
nova --sandbox runloop

# Daytona (cloud)
nova --sandbox daytona

# LangSmith Sandboxes (hardware-virtualized microVMs)
nova --sandbox langsmith

# Force unconfined local execution
nova --no-sandbox

# Reuse an existing sandbox
nova --sandbox-id <id>

# Port forwarding (Docker)
nova --sandbox docker --ports 8080:8080

# LangSmith sandbox resource config
nova --sandbox langsmith --sandbox-vcpus 2 --sandbox-mem-bytes 8589934592

The default sandbox image is python:3.11-slim.

Plugin System

NOVA supports Python entry-point based plugins that can register slash commands and add middleware at defined slots. Plugins are discovered via the nova.plugins entry point group and can contribute:

  • Slash Commands: Custom interactive commands
  • Middleware: Add behavior at named slots in the middleware stack
  • Skills: Domain-specific workflows
# List plugins
/plugins

# Enable/disable a plugin
/plugins enable my-plugin
/plugins disable my-plugin

File Recovery

NOVA automatically snapshots files before destructive operations:

  • Files targeted by rm shell commands — captured before deletion
  • Files overwritten by write_file — previous content saved
  • Files modified by edit_file — pre-edit content saved
# Interactive restore
/restore

# Restore by index
/restore 1

# Restore by path
/restore src/utils.py

Agent tools: list_trash() to see snapshots, restore_file("path") to restore.

Snapshots stored in ~/.nova/trash/<session-id>/. Files over 10 MB skipped.

Vixie Desktop Companion

NOVA includes Vixie, a background desktop companion server:

  • Desktop Notifications: Task completion and status alerts
  • System Tray Integration: Quick access to Nova status
  • WebSocket Server: Real-time event streaming

Testing

# Run unit tests
make test

# Run all tests (including integration)
make test_all

# Run with coverage
make test_cov

# Run specific test file
make test TEST_FILE=tests/unit_tests/test_specific.py

# Watch mode
make test_watch

Test suite includes:

DirectoryWhat it tests
tests/test_hermes/Hermes learning system — middleware, memory, skill discovery, verifier, tuner, prompt evolution
tests/test_tui_app.pyTextual TUI — animations, chat, modals, tool groups
tests/test_workdir_grep.pySandbox-backed grep path-rebased execution
tests/test_notifications.pyNotification system integration
tests/test_context_breakdown_tokens.pyToken budget and context optimization
tests/test_backends/Filesystem backend virtual-path operations
tests/test_remote_cron.pyCron scheduler — expression parsing, job lifecycle, tick loop
tests/test_webhook_server.pyWebhook ingress — signature verification, adapter parsing, server lifecycle

Makefile Commands

CommandDescription
make testRun unit tests (ignores shell/process/e2e tests)
make test_integrationRun integration tests
make test_allRun all tests
make test_watchWatch mode with ptw
make test_covRun tests with coverage (term-missing report)
make runRun uv run nova
make syncSync dependencies (uv sync)
make lockLock dependencies (uv lock)
make treeShow dependency tree (uv tree)
make outdatedShow outdated packages (uv tree --outdated)
make add PACKAGE=<name>Add a dependency (uv add)
make add-dev PACKAGE=<name>Add a dev dependency
make remove PACKAGE=<name>Remove a dependency
make reinstallFull reinstall of novacode-cli + deepagents
make run_reinstallReinstall then run nova
make lintCheck formatting and linting
make formatAuto-format code
make cleanClean caches

Architecture

User Input → CLI Entry (main.py) → Agent Loop (core/agent_loop.py) → UI Renderer

Core Flow

  1. CLI Entry (main.py → cli_main()) — parses args, initializes SessionState, runs optional onboarding, then enters the Textual TUI (or the headless runner with -p)
  2. Agent Loop (core/agent_loop.py → iterate_agent_events()) — the single canonical async generator driving the LangGraph agent stream
  3. UI Events (ui_events.py) — dataclass instances decoupled from rendering; the TUI, the headless runner, and the remote bridges all consume the same event types
  4. Middleware Stack — wraps every model call (ModelRetry → VisionCaption → NovaLearning → Security → Bootstrap → Steering → FileTracker → LoopGuard → Rubric → ContextEditing → Shell → AgentMemory → TaskDiscipline)

Module Structure

Core:

  • main.py — Entry point, CLI loop, argument parsing
  • cli_session.py — Session management, auto-save, display helpers
  • input.py — prompt_toolkit input handling, completers, image paste, keybindings
  • core/agent_loop.py — Canonical async generator driving the LangGraph agent stream
  • core/verification_loop.py — Inline verification wrapper around iterate_agent_events (Enhancement 1)

Agent:

  • agents/core_agent.py — Agent creation, configuration, middleware wiring
  • agents/default_subagents/ — the in-process specialists, the research personas, and the client specs for the async agents
  • agents/async_agents/ — the nine async agent graphs and their langgraph.json
  • agents/server_launcher.py — launches the async agents' server on demand, in the session's project
  • agents/plan_agent/ — Plan mode agent with planning middleware

Commands:

  • commands/ — 20+ CLI command handlers (commands/__init__.py aggregates via CommandRegistry)
  • commands/chat_handler.py — /chat command — local web chat UI
  • commands/cron_handler.py — /cron command — scheduled task management (Enhancement 3)
  • commands/webhook_handler.py — /webhook command — webhook ingress server management (Enhancement 5)
  • commands/prompt_handler.py — /prompt command — evolving prompt template management (Enhancement 2)

Configuration:

  • config/config.py — Settings hub (502 connections), color scheme, model factory, console init
  • config/nova_config.py — Persistent JSON config (~/.nova/Nova.config.json)
  • config/model_create.py — Model instantiation for all providers
  • config/model_manager.py — Model provider management

Context & Memory:

  • context/ — Context budget tracking, eviction, optimization, growth monitoring
  • memory/store.py — Durable LangGraph key/value store with stdlib-fallback
  • prompts/ — Jinja2 template rendering

Learning (Hermes):

  • hermes/middleware.py — NovaLearningMiddleware (thin orchestrator)
  • hermes/tracker.py — ToolUsageTracker: counters, per-tool stats, skill invocation tracking
  • hermes/review.py — ReviewRunner: signal-based review scheduling, out-of-band LLM review
  • hermes/skill_manager.py — SkillManager: create-from-review, failure-grounded refinement
  • hermes/skill_discovery.py — Skill spec parsing/writing, effectiveness checks, refinement
  • hermes/curator.py — Archive unused skills, flag overlapping ones
  • hermes/skill_debate.py — Multi-perspective skill evaluation and merge suggestions
  • hermes/evolution.py — Skill unlock/level-up tracking, viewable via /evolution
  • hermes/memory_tiers.py — USER.md / MEMORY.md auto-maintenance
  • hermes/config.py — Centralized thresholds, bounds, and store namespace constants
  • hermes/verifier.py — Inline output verifier (Enhancement 1)
  • hermes/prompt_evolution.py — Prompt-template hill climbing with A/B testing (Enhancement 2)
  • hermes/tuner.py — Threshold auto-tuner via hill-climbing inward (Enhancement 4)

UI (Rich console):

  • ui/ui_elements.py — Token tracking, help, diff rendering, todos
  • ui/execution.py — Tool execution orchestration and approval flow
  • ui/streaming.py — Real-time output streaming
  • ui/tool_processing.py — Tool call formatting and display
  • ui/hitl_approval.py — Human-in-the-loop approval UI
  • ui/subagent_tracking.py — Subagent progress visualization

TUI (Textual):

  • tui/app.py — NovaApp: chat messages, modals, keyboard shortcuts, condensed tool groups, history, parallel session panes
  • tui/animations.py — Fade/slide/zoom, pulsing borders, shimmer, thinking dots

Headless:

  • headless/runner.py — Non-interactive single-prompt runner (nova -p)
  • headless/output.py — text / json / stream-json output formatting

Tools:

  • tools/ — HTTP fetch, search, web scraping, package info, git, LSP, browser, memory, reflection, project graph, code search, plan mode, artifacts, background jobs, daemons, Python kernel, oracle

Integrations:

  • integrations/ — Sandbox providers and workdir backend
  • mcp/ — MCP client, config, middleware, presets
  • remote/ — Discord and Telegram bridges, cron scheduler, webhook ingress server
  • remote/scheduler.py — Cron / heartbeat scheduler (Enhancement 3)
  • remote/webhook_server.py — Webhook ingress HTTP server (Enhancement 5)
  • remote/webhook_adapters.py — Per-source payload adapters with timing-safe signature verification

Infrastructure:

  • session/ — Session persistence, restore, summarization, prompt building
  • sessions/ — Parallel session supervisor, worker, lease, and worktree management
  • states/slices/ — 6 state slices (UISettings, AgentRuntime, RemoteBridge, BackgroundTask, Notifications, Wiki)
  • states/Session.py — SessionState composite dataclass
  • artifacts/ — Durable artifact registry and serving
  • daemons/ — Long-lived background process registry
  • cowork/ — Nova Cowork desktop app launcher, broker middleware, and policy
  • server/ — Local HTTP server, event adapter, and session manager
  • audio/ — Voice I/O: capture, VAD, STT/TTS providers, speakable-text extraction
  • server_runner/ — Dev server and test runner lifecycle
  • process_manager.py — Subprocess lifecycle, health checks, cleanup
  • tracking/ — File tracking, run logging, LangSmith, workspace anchoring, loop guard

Safety & Recovery:

  • errors/ — Error taxonomy (14 categories) and recovery handlers
  • security/ — Unicode security and input validation
  • git_safety.py — Dangerous command detection and injection prevention
  • file_ops.py — File operation tracking, diff, approval previews
  • recovery.py — File recovery snapshots
  • path_approval.py — Path-based operation approval

Specialized:

  • bootstrap/ — Environment snapshots, project graph context, steering instructions
  • init/ — Project initialization (detect → extract → generate → graph)
  • skills/ — Skill loading, creation, locking, system prompt generation
  • hitl/ — Human-in-the-loop interrupt configuration
  • bootstrap/vision_router.py — Vision captioning middleware (converts images to text for a text-only main model; passes images straight through when the main model is multimodal — see config/model_capabilities.py and the /vision command)
  • vixie/ — Desktop companion server (notifications, system tray)
  • plugins/ — Plugin system
  • wiki/ — Persistent project wiki: ingest, ask, file, and vault management
  • hooks.py — Lifecycle hook dispatch
  • compaction.py — Hierarchical conversation summarization via LLM, with a pre-compaction transcript archive
  • agents/tool_offload.py — Offloads cleared tool results to /cleared/ so they stay readable
  • agents/tool_verdicts.py — System One compaction: a Tev1 decision model picks which tool results are stale (opt-in)
  • tui/gc_tuning.py — Garbage-collection tuning that keeps collection pauses out of the UI
  • plans.py — Plan management and persistence
  • onboarding.py — Interactive first-run setup
  • doctor.py — System diagnostics
  • migrate.py — Configuration migration

Optional Dependencies

The base install is kept lean. Heavier features are extras:

# Real-browser automation: /browser-use and the LinkedIn scraper (~330 MB)
pip install novacode-cli[browser]

# The local server the async agents run on
pip install novacode-cli[agents-server]

# Voice I/O (STT + TTS + VAD) — ~2 GB extra
pip install novacode-cli[voice]

# Orpheus TTS — very natural LLM-based local TTS
pip install novacode-cli[voice-orpheus]

# Parakeet STT — NVIDIA local speech-to-text via sherpa-onnx
pip install novacode-cli[voice-parakeet]

# Pocket TTS — lightweight local TTS
pip install novacode-cli[voice-pocket]

Async subagents

The nine async subagents (code review, test generation, documentation updates and the rest) talk Agent Protocol to a LangGraph server, which NOVA launches itself. Their graphs live in novacode_cli/agents/async_agents/. One optional extra provides the server:

uv sync --extra agents-server   # once: installs langgraph-cli, the dev server

With that extra installed, NOVA runs the server itself, with no Docker involved:

  • On demand. Nothing is started at boot. NOVA reserves a port and offers the async tools; the server comes up on the first start_async_task (a few seconds) and stops when NOVA exits. A session that never delegates never pays for it.
  • In your project. The agents read, search and run commands in the workspace NOVA was opened in, not in NOVA's own repo.

A server you started yourself is used only if you declare the directory it works in with NOVA_ASYNC_AGENT_ROOT=<its directory> and that is the current project; otherwise NOVA launches its own. Without the extra, NOVA falls back to the in-process subagents.

Control it from inside the TUI with /agent-server:

/agent-server status     is a server running, which port, which log
/agent-server start      launch one now (blocking, first run can take a minute)
/agent-server stop       stop this session's server
/agent-server restart    stop, then start on a fresh port
/agent-server logs       the last 20 lines of the server log

--no-agent-server turns the automatic launch off for a run, and --agent-server-port N pins the port instead of picking a free one.

Which model each agent runs on

/model covers four roles. The list opens with a Roles section; the row marked target is where the next model pick goes. Choosing a role row retargets the picker instead of closing it, so the flow is: pick the role, then pick the model.

RoleCoversTakes effect
Main agentthe agent you talk toimmediately (hot-swapped)
Subagentsin-process delegation via the task toolon the next dispatch
Async agentsthe nine graphs on the LangGraph serveron the next dispatch
Dynamic agentsagents discovered in the agent directories, which is also what an /eval fan-out dispatcheson the next dispatch

Dynamic describes where an agent definition comes from; Async describes execution on the agent server. These can overlap: a custom agent.md with async: true remains available in-process and can also be served as a background agent. The Dynamic model applies to its in-process dispatch; Async applies to the server dispatch. This agent server is separate from Telegram remote access.

Dynamic inherits Subagents → Main when unset, unless the agent's own model: overrides it. Async follows Async role → explicit server environment → Main. If an async per-run model cannot be built, the current server middleware logs a warning and falls back to its graph default; the role picker therefore shows the requested model, which can differ from the model actually used after a fallback.

Any role you leave unset keeps its previous behaviour, which is what every role did before this existed, so an untouched setup behaves exactly as before: the subagents and the dynamic agents inherit the main agent's model, and so do the async agents. A discovered agent can also name its own model in agent.md frontmatter, and that wins over the dynamic role:

---
name: custom-agent
model: anthropic:claude-sonnet-4-5-20250929
---

The roles live in ~/.nova/Nova.config.json, one key per role, and the panel above the transcript reports each task's real model rather than assuming the session one.

Which model the async agents run on

Provider-agnostic: any provider NOVA supports can run them. In order of precedence:

  1. the Async agents role set in /model;
  2. ASYNC_AGENT_PROVIDER / ASYNC_AGENT_MODEL in the environment;
  3. otherwise, the main agent's own model.

So with nothing configured, the async agents run on whatever the session runs on, and a /model change applies to the next dispatch.

VariableMeaning
ASYNC_AGENT_PROVIDERollama, openai, anthropic, google, openrouter, opencode, nvidia
ASYNC_AGENT_MODELmodel id for that provider
PLAN_SCOUT_MODELper-agent override, plan-scout only; wins over all of the above
the provider's key vare.g. OPENAI_API_KEY, ANTHROPIC_API_KEY; read from the environment or the keychain

Dependencies

This package depends on the deepagents library for core agent functionality, which is automatically installed as a dependency. Core dependencies include LangChain ecosystem (LangGraph, LangSmith), Rich, Textual, prompt-toolkit, and various integration libraries.

License

MIT License — see LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request