nova ❯man nova

A coding agent that verifies its own work.

NovaCode is an open-source, terminal-based AI coding assistant built on LangGraph and the deepagents framework. It runs entirely in your terminal with a Textual TUI, a headless non-interactive mode for scripting and CI, and remote bridges for Discord and Telegram.

Version 1.0.23 · MIT licensed · Python 3.11+. Runs locally, brings your own model. NovaCode does not retrain your model. What changes are prompts, skills, and thresholds on disk, readable and deletable.

  • ~30 core tools · ~85 total
  • 12 async background agents
  • 8 model providers
  • 20 MCP presets
  • 7 sandbox providers
  • 50+ built-in skills

Core flow

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

    main.py to cli_main(): parses args, initializes SessionState, runs optional onboarding, then enters the TUI or the headless runner.

  2. Agent Loop

    core/agent_loop.py to 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, headless runner, and remote bridges all consume the same event types.

  4. Middleware

    Wraps every model call: retry, vision, learning, security, bootstrap, steering, file tracking, loop guard, rubric, context editing, shell, memory, task discipline.

Key design principles

One canonical agent loop

iterate_agent_events() drives a LangGraph agent stream and yields ui_events dataclasses. Bug fixes and features belong here so every renderer benefits.

SessionState is a composite

Six state slices (UISettings, AgentRuntimeState, RemoteBridgeState, BackgroundTaskState, NotificationState, WikiState) with properties that delegate to slices. Zero callers change when a slice is added.

Deepagents is monkey-patched

Three patches at import time: validate_path (Windows path normalization), perform_string_replacement (UTF-8 BOM tolerance), and create_sub_agent (graph compile caching).

Heavy imports are blocked

A meta-path finder makes import transformers/torch raise ImportError (305 MB / ~13 s to 145 MB / ~2.4 s). Set NOVA_ALLOW_TRANSFORMERS=1 to opt out.

What ships in the box

ComponentCountDescription
Core tools~30Bound to the model on every call; the rest are deferred behind search_tools
Total tools~85Full roster (~117k chars of schemas), loaded on demand
In-process subagents5general-purpose, code-explorer, refactoring-specialist, bug-fix, browser-automation
Research personas7Dispatched by /research, loaded on demand
Async agents12Background LangGraph graphs: docs, review, tests, audits, research
Model providers8OpenAI, Anthropic, Google, NVIDIA, OpenRouter, OpenCode, OpenCode Zen, Ollama
MCP presets20Playwright, Serena, Context7, Apify, CUA Driver, and more
Sandbox providers7os, docker, modal, runloop, daytona, langsmith, none
Built-in skills50+Progressive disclosure, loaded on demand
Slash commands80+In-TUI commands for every feature

nova ❯cat INSTALL.md

Two commands and you are running.

Python 3.11 or newer. Nothing is installed globally.

git clone https://github.com/Babitdor/NovaCode.git
cd NovaCode && uv sync
uv run nova
git clone https://github.com/Babitdor/NovaCode.git
cd NovaCode; uv sync
uv run nova
uv tool install "novacode-cli @ git+https://github.com/Babitdor/NovaCode.git"
nova

Prerequisites

RequirementMinimumNotes
Python3.11+Required. python --version to check.
uvlatestPackage manager. Install from astral.sh/uv if missing.
GitanyFor cloning the repository and for nova skills add.
API key1At least one model provider key, or a local Ollama host.
Node.jsoptionalOnly for installing skills from GitHub via the Skills CLI.

Verify installation

nova --version
nova doctor          # validate config + connections
nova               # start the TUI

nova doctor runs six checks: configuration file, secrets, LLM provider connection, Tavily connection, file permissions, and the voice stack. It returns exit code 0 when everything passes.

Update Nova

nova update --check  # check without installing
nova update          # update the running installation

The TUI checks in the background at startup and hourly. Installation detection covers source checkout, uv-tool, git, and package installs. On Windows, uv-managed updates run in a separate detached process because nova.exe locks the package directory. Set NOVA_DISABLE_UPDATE_CHECK=1 to disable background checks.

Onboarding

First-run setup 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. Keys go to the OS keychain. A typo shows up on the setup screen, not on your first prompt.

nova ❯nova --help

CLI reference.

Every subcommand, flag, and environment variable, with defaults.

Entry point chain

LayerResponsibility
pyproject.tomlRegisters nova = "novacode_cli.entrypoint:cli_main"
entrypoint.pyThin forwarder (--version, update, skills install), then calls main.py:cli_main()
main.py:main()Path approval, keychain hydration, Vixie server, SQLite store/checkpointer, model creation, agent build, TUI launch
os._exit()Exits with session_state.headless_exit_code

Subcommands

CommandDescription
nova initInitialize project or global configuration
nova listList all available agents
nova helpShow help information
nova resetReset an agent's memory/store (--agent <name>)
nova skillsManage agent skills (list, create, add, remove, find, update, info)
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 the new directory structure
nova updateUpdate Nova or check for new code (--check)

Flags

FlagDefaultDescription
--agent"nova-agent"Agent identifier for separate memory stores
--auto-approveoffAuto-approve tool usage (disables HITL)
--sandboxos / noneSandbox provider: none, os, modal, daytona, runloop, docker, langsmith
--no-sandboxoffRun shell commands unconfined on the host
--sandbox-idNoneReuse an existing sandbox
--sandbox-setupNonePath to a setup script for the sandbox
--sandbox-vcpusNoneVirtual CPUs (LangSmith only)
--sandbox-mem-bytesNoneMemory in bytes (LangSmith only)
--sandbox-fs-capacity-bytesNoneFilesystem capacity (LangSmith only)
--sandbox-snapshotNoneSnapshot name (LangSmith only)
--sandbox-snapshot-idNoneSnapshot ID (LangSmith only)
--portsNonePort forwarding for the Docker sandbox
--no-splashoffDisable the startup splash screen
--continue / -coffContinue last session (optionally a session ID)
--resume / -roffInteractively select and resume a session
--print / -poffRun a single prompt non-interactively and exit
--output-formattextHeadless output: text, json, or stream-json
--max-turnsNoneHeadless only: cap agent turns
--deny-toolsoffHeadless only: auto-reject tool approvals (fail-closed)
--safe-uioffStart with the default UI, skipping saved customizations
--import—Import a conversation (codex, claude, nova, or adapter)
--latestoffImport the selected provider's latest session
--import-session—Source session ID or transcript file path
--import-modecompactImport mode: compact, full, relevant
--no-agent-serveroffDo not launch a local LangGraph server for async subagents
--agent-server-portNonePort for the local agent server
--version—Show version number and exit

Environment variables

VariablePurpose
OPENAI_API_KEYOpenAI API key
ANTHROPIC_API_KEYAnthropic API key
GOOGLE_API_KEYGoogle Gemini API key
NVIDIA_API_KEYNVIDIA API key
OPENROUTER_API_KEYOpenRouter API key
OPENCODE_API_KEYOpenCode Go gateway key
OPENCODE_ZEN_API_KEYOpenCode Zen key
TAVILY_API_KEYTavily web search key
NOVA_ALLOW_TRANSFORMERSSet to 1 to allow transformers/torch import
NOVA_DISABLE_UPDATE_CHECKSet to 1 to disable background update checks
NOVA_ASYNC_AGENT_ROOTDirectory for an external async agent server
ASYNC_AGENT_PROVIDERProvider for async agents
ASYNC_AGENT_MODELModel for async agents
PLAN_SCOUT_MODELPer-agent override for plan-scout
TYPESAFE_API_KEYTypeSafe API key for System One compaction
SYSTEM_ONE_API_KEYCustom System One endpoint API key
LANGSMITH_TRACINGEnable LangSmith tracing
LANGSMITH_API_KEYLangSmith API key

Credential storage

Keys go to the OS keychain (via the keyring library) with a permission-restricted JSON fallback. The endpoint and project are paired with the key as non-secret metadata in Nova.config.json. Enumeration and deletion are supported, and secrets are never logged or interpolated into exception messages.

nova secrets set openai_api_key
nova secrets set anthropic_api_key
nova secrets list
nova secrets delete openai_api_key

get_provider_auth_status() resolves credential readiness into a ProviderAuthStatus with states: CONFIGURED, MISSING, NOT_REQUIRED, MANAGED, UNKNOWN.

nova ❯nova config show

Config file.

Configuration lives in ~/.nova/Nova.config.json, with project config under .nova/.

nova config show           # view all settings
nova config get <key>      # get one setting
nova config set <key> <val> # set a setting

Configuration modules

config/ holds 14 modules:

ModuleResponsibility
config.pySettings hub, color scheme, model factory, console init
nova_config.pyPersistent JSON config at ~/.nova/Nova.config.json
model_create.pyModel instantiation for all providers
model_manager.pyModel provider management
model_catalog.pyModel lineup per provider
model_capabilities.pyStatic capability registry (which models accept images)
provider_auth.pyProvider credential readiness
credentials.pyCredential storage (keychain + JSON fallback)
role_models.pyPer-role model selection (main, subagent, async, dynamic)
google_oauth_auth.pyGoogle OAuth authentication
openai_chatgpt_auth.pyOpenAI ChatGPT plan sign-in
opencode_gateway.pyOpenCode Go gateway integration

Key directories

PathContents
~/.nova/Global config, agents, skills, hooks, daemons, plans, plugins, trash
~/.nova/store.dbDurable LangGraph key/value store
~/.nova/Nova.config.jsonPersistent configuration
~/.nova/logs/Application log, freeze log
~/.nova/ui/Saved UI layouts, per workspace
.nova/Project context, config, hooks, skills, wiki, plans, council
.nova/NOVA.mdProject-specific context and conventions

Model providers

ProviderKey variableNotes
OpenAIOPENAI_API_KEYDefault; also supports ChatGPT plan sign-in
AnthropicANTHROPIC_API_KEYClaude models
GoogleGOOGLE_API_KEYGemini models; also supports OAuth
NVIDIANVIDIA_API_KEYNVIDIA AI endpoints
OpenRouterOPENROUTER_API_KEYOpenAI-compatible, routed through ChatOpenAI
OpenCodeOPENCODE_API_KEYOpenCode Go gateway
OpenCode ZenOPENCODE_ZEN_API_KEYOpenCode Zen gateway
Ollama—Local models; live list from ollama list

The model catalog draws from two sources: provider profile data (LangChain packages ship auto-generated _profiles.py listing every model with capability flags) for OpenAI, Anthropic, Google, and NVIDIA; and a live list for Ollama and OpenCode Go. The curated MODEL_PRESETS list is unioned into every result and ordered first.

Per-role model selection

/model covers four roles:

RoleCoversTakes effect
Main agentThe agent you talk toImmediately (hot-swapped)
SubagentsIn-process delegation via taskOn the next dispatch
Async agentsGraphs on the LangGraph serverOn the next dispatch
Dynamic agentsAgents discovered in agent directoriesOn the next dispatch

Any role left unset inherits the main agent's model. Reasoning effort changes without a restart via /effort low|medium|high|off.

nova ❯nova

The TUI.

The only interactive UI. Chat messages, modals, animations, and keyboard shortcuts.

The Textual TUI provides a scrollable transcript, multi-line input that grows with content (shift+enter for a newline), modal dialogs with entrance animations, keyboard shortcuts, condensed tool groups, syntax-highlighted diffs, click-to-copy, parallel session panes, a docked todo checklist, a status bar with shimmer animation, and pulsing borders on active elements.

Screens

ScreenPurpose
ChatMain conversation view
Model pickerSwitch models for main agent, subagents, async agents, dynamic agents
AuthManage API keys and provider credentials
WikiBrowse the project wiki vault
Settings/ConfigurationAdjust settings
Artifacts viewerBrowse and open artifacts
Tasks panelBackground task monitoring
Subagents panelRunning subagent tasks with model and elapsed time
NotificationsReview and manage notifications

Key bindings

KeyAction
shift+enterInsert a newline in the input
ctrl+nNew parallel session
alt+<n>Switch to session n
ctrl+gPush-to-talk (voice)
ctrl+lHands-free listening (voice)
ctrl+shift+backspaceReset UI to default
alt+sCollapse/expand the subagents panel
F6–F12Custom panel shortcuts

Performance features

  • status ticks repaint in place
  • rendered Markdown cached per width
  • static data stays out of checkpoints
  • subagent graphs compile on first use
  • skill listing cached across restarts
  • garbage collection tuned to run while idle
  • a watchdog logs any UI freeze over 1s

UI panels

Optional notes, workspace files, and activity panels are customizable via /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.

nova ❯/help

Slash commands.

All slash commands are registered via CommandRegistry and invoked through a single dispatch. Plugin commands are registered last, so built-ins always win on collision.

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
/steerSet persistent steering instructions
/goalSet a persistent goal (rubric, status, clear)
/btwAsk a side question on an ephemeral thread
/saveSave current session
/compactCompact conversation history with optional focus
/sessionsList, select, or delete saved sessions
/uiInspect UI panels (patch, preview, commit, rollback, reset)
/sessionParallel sessions: new / list / close
/resumeResume a saved session (/resume <id>)
/restoreRestore a previous file version from snapshots
/filesShow file operation summary
/imagesManage tracked image references
/artifactsOpen the artifacts list
/tasksOpen the background tasks panel
/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 the semantic code search index
/copyCopy the last response (or the whole chat)
/themeSwitch color theme
/initGenerate/update project documentation and graph
/mcpInteractive MCP server management menu
/modelSwitch the model for main agent, subagents, async agents, or dynamic agents
/hooksManage lifecycle hooks (list, add, remove, enable, disable)
/skillsInteractive skills manager
/agentsCustom agent management (view, create, delete)
/plugins / /pluginPlugin management (list, enable, disable)
/middlewareList active middleware (/reload-plugins to reload)
/reload-pluginsReload plugin registrations
/planInvoke the plan-mode agent for investigation and approval
/agent-serverControl the local LangGraph server (status, start, stop, restart, logs)
/traceLangSmith tracing management
/ralphAutonomous looping mode (background task execution)
/councilPlan a task with the council (propose, critique, vote, judge)
/chatLaunch the local browser-based chat UI
/cowork / /desktopLaunch the Nova Cowork desktop app
/trelloBrowser-based task board server
/researchMulti-agent research swarm
/dreamRun memory consolidation
/browser-useAI-powered browser automation
/createLaunch the Skills & Agents web UI
/skill:<name>Directly invoke a skill by name
/cronManage scheduled (heartbeat) tasks
/webhookManage the webhook ingress server
/promptManage evolving system-prompt templates
/refineRefinement audit trail (history, rollback <id>)
/voiceLocal voice I/O management
/effortSet reasoning effort level (low, medium, high, off)
/visionConfigure image handling
/evolutionView the self-evolution log
/learningToggle the autonomous learning loop (on, off, status)
/ingestIngest captured sources into wiki pages
/askAsk a question informed by wiki context
/fileFile recent conversation knowledge as a wiki page
/wikiList all synthesized pages in the project wiki vault
/updateCheck for updates immediately
/importImport external conversations (codex, claude, nova)
/compareCompare histories (/compare claude:<id> codex:<id>)

Command categories

CategoryCommands
Session/save, /sessions, /session, /resume, /clear, /compact
Model & reasoning/model, /effort, /learning, /verbose, /vision
Planning & research/plan, /council, /research, /goal, /steer
Extensibility/skills, /agents, /plugins, /mcp, /hooks, /middleware
Integrations/webhook, /cron, /chat, /cowork, /trello, /browser-use
Knowledge/wiki, /ingest, /ask, /file, /dream

Council system

/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. Past council runs are kept in .nova/council/.

Research swarm

/research fans a question out to 7 research personas: web researcher, fact checker, literature reviewer, market analyst, financial analyst, technical researcher, synthesizer.

nova ❯nova -p "..."

Headless mode.

Run a single prompt non-interactively and exit. Built for scripting and CI.

# Basic: run a prompt, print the response
uv run nova -p "summarize the changes in this repo"

# JSON output, capped at 10 turns, approvals denied
uv run nova -p "run the test suite and report failures" \
  --output-format json \
  --max-turns 10 \
  --deny-tools

# Stream JSON events
uv run nova -p "explain the architecture" --output-format stream-json

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

Output formats

FormatDescription
textFinal answer only (default)
jsonA single result object
stream-jsonNewline-delimited JSON events

Exit codes

CodeMeaning
0Success
1Error during execution
2Max-turns hit

Runner behavior

headless/runner.py drives a single prompt through the UI-agnostic event stream (iterate_agent_events) to completion with no human present.

  • prompt from headless_prompt, format from headless_output_format
  • tool interrupts use evaluate_tool_actions unless --deny-tools
  • a None verdict (ask the user) is converted to an approve
  • question/plan interrupts resolve to the default response
  • counts turns, accumulates text, tracks usage, enforces max-turns
  • autosaves the run as a resumable session; never fails on a save error

Headless runs are the exception to the approval rule: --deny-tools rejects everything, so a pipeline fails closed instead of hanging on a prompt nobody is there to answer.

nova ❯search_tools *

Tools.

50+ built-in tools across 22 modules. Rarely used tools are deferred behind search_tools, so they cost no context until needed.

File operations

ToolDescription
lsList files and directories
read_fileRead the contents of a file
write_fileCreate or overwrite a file
edit_fileMake targeted edits to existing files
globFind files matching a pattern
grepSearch for text patterns across files

Shell & execution

ToolDescription
shellExecute shell commands (local mode)
executeExecute commands in a remote sandbox
python_kernelRun Python in a persistent kernel that keeps state between calls
daemonStart, stop, and tail long-lived background processes

Web & search

ToolDescription
web_searchSearch the web using the Tavily API
duckduckgo_searchWeb search using DuckDuckGo (no API key)
docs_searchSearch official documentation sites
fetch_urlFetch and convert web pages to markdown
github_trendingScrape GitHub trending repositories
hacker_newsScrape the Hacker News front page
linkedin_jobsSearch LinkedIn job listings (Playwright-based)
reddit_postsScrape Reddit posts
package_infoGet package version and dependency info (PyPI / npm)

Code intelligence

ToolDescription
code_searchSemantic code search by description or symbol name
find_related_codeFind code semantically similar to a known location
query_project_graphQuery the project graph for architectural information
search_toolsSearch and load deferred tools by capability

Memory & knowledge

ToolDescription
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
memory_searchSearch topic memory by meaning
wiki_read / wiki_search / wiki_write / wiki_update_indexWiki management

Agent & delegation

ToolDescription
taskDelegate work to subagents for parallel execution
write_todosCreate and manage task lists for complex work
thinkStructured reasoning and reflection before acting
ask_user_questionAsk the user a multiple-choice question
oracleAsk several models the same question and have a judge synthesize
speakSpeak a short summary aloud via TTS
skill_manageCreate, refine, or remove reusable skills
sleep_desktopPut the desktop to sleep (overnight sessions)

Async agents

ToolDescription
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 task
cancel_async_taskCancel a running background task
list_async_tasksList all tracked background tasks

Background tasks

ToolDescription
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

Artifacts & plans

ToolDescription
create_artifactCreate a durable artifact (markdown, code, etc.)
update_artifactUpdate an existing artifact
list_artifactsList all artifacts in the session
enter_plan_modeSwitch to read-only investigation mode
exit_plan_modePresent a plan for user approval

File recovery

ToolDescription
list_trashList file snapshots available for recovery
restore_fileRestore a deleted or overwritten file from snapshots

UI & desktop

ToolDescription
ui_inspect / ui_patch / ui_preview / ui_commit / ui_rollbackUI panel management

Tool search

Only core tools are bound to the model on every call. search_tools finds the rest on demand. 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.

search_tools("playwright browser automation")
search_tools("*")            # browse the catalog

MCP tools (serena, playwright, cua-driver, etc.) are discovered by MCPMiddleware and attached to the main agent. They are granted to subagents selectively via MCP_TOOLS_BY_SUBAGENT.

nova ❯/agents

Subagents.

In-process specialists, a research swarm, and 12 async background agents.

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 extractionagent-browser, browser-use, web-research

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

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

12 graphs on a remote LangGraph server that Nova launches itself, on demand. No Docker needed. 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.

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
research-agentWeb research with sourced findings
general-purpose-asyncScoped coding, investigation, testing, research, or analysis
bug-investigation-agentTrace a reported bug to a likely root cause
performance-audit-agentInvestigate performance and resource bottlenecks

By default, Nova launches its own langgraph dev server on an ephemeral port (gated on the opt-in agents-server extra). Nothing is started at boot: 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. A server that will not come up leaves the session as it was (in-process subagents), never blocks it. Users can create async agents by setting async: true in an agent.md frontmatter.

Agent-to-agent mailbox

The orchestrator can message its subagents by name and read replies via the send_agent_message and read_agent_messages tools.

nova ❯memory_search

Memory system.

A three-tier model: Episodic, Semantic, and Procedural.

The three tiers

Episodic

hermes/tracker.py: the durable, time-ordered record of what the agent actually did. Tool history, counters, per-tool stats, and per-skill effectiveness. Stored in the durable store at ~/.nova/store.db.

Semantic

agent.md (user model), memories/INDEX.md (topic pointers), memories/<topic>.md (topic facts), and HABITS.md. Files are written newest-first and compacted past 12,000 chars.

Procedural

Skills are the procedural memory: reusable workflows the agent can invoke. Created and refined by Hermes, stored in ~/.nova/skills/.

Durable store

A single sync SqliteStore at ~/.nova/store.db (with a stdlib-sqlite3 fallback), wrapped by a DualModeStore for both sync and async access. All Hermes namespaces live under the ("nova", ...) prefix.

AgentMemoryMiddleware

  • loads memory into the system prompt at before_agent
  • always injects agent.md, memories/INDEX.md, HABITS.md, learning overview
  • per-turn retrieval: lexical overlap scoring, top-3 topic bodies
  • hot-reloads memory files when they change on disk
  • prompt-cache split: the retrieval block sits after the cache breakpoint

Memory tools

ToolDescription
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
memory_searchSearch topic memory by meaning

nova ❯/skills

Skills system.

50+ built-in skills with progressive disclosure. Install from any public GitHub repo.

A skill is a playbook (SKILL.md) with YAML frontmatter (name, description required; version, tags optional) and a Markdown body with canonical sections: When to Use, Quick Reference, Procedure, Pitfalls, Verification. Optional supporting files, scripts, and even an executable skill.py entry point can ship alongside.

Skill loading

Skills are loaded from multiple sources in precedence order (later overrides earlier):

  1. User skills

    ~/.nova/skills/

  2. Shared global

    ~/.agents/skills/

  3. Claude skills

    ~/.claude/skills/

  4. Plugin skills

    ~/.nova/plugins/<name>/skills/

  5. Project skills

    .agents/skills/, .nova/skills/, .claude/skills/

Caching uses a directory signature (name, mtime, size) per skill, so only changed directories are re-parsed. A disk cache at ~/.nova/cache/skill_index.json enables cross-process reuse.

Skill retrieval

Hybrid search fuses BM25 (exact terms) with static Model2Vec embeddings (paraphrases) by reciprocal rank. The embedding model is minishlab/potion-code-16M.

FunctionBehavior
search(query, k=5)Top-k skills
suggest(query, k=3)Skills that stand out (z-score ≥ 4.5, cosine ≥ 0.4)

RefreshingSkillsMiddleware is tiered:

TierBehavior
ListingOnly most-used skills within a char budget (1% of window)
SuggestionsEach new user message matched against the whole library; top picks added as Internal context
skills_searchA tool for needs that surface mid-task

Also provides mid-session refresh when watched skill directories change.

Skill versioning

Every mutation snapshots the prior SKILL.md first: .history/<version>.md inside the skill dir, .history/manifest.json as the version log, skills-archive/ for soft-deleted skills, and origin.json for provenance. restore() rolls back to any version.

Skill management commands

nova skills list              # list all skills
nova skills create my-skill   # create a new skill
nova skills create my-skill --project  # project-specific skill
nova skills info web-research # view skill details
nova skills add owner/repo    # install from GitHub
nova skills remove <name>     # remove a skill
nova skills find <query>      # search for skills
nova skills update <name>     # update from source

nova skills add runs the official Skills CLI (npx --yes skills@latest add) with your arguments unchanged. It requires Node.js, npm/npx, and Git for repository sources.

nova ❯/mcp

MCP integration.

Extend the agent with Model Context Protocol servers. Tools are eagerly discovered with server-prefixed names to avoid collisions.

Available presets

  • playwright
  • serena
  • context7
  • apify
  • cua-driver
  • brave-search
  • memory
  • postgres
  • google-drive
  • fetch
  • time
  • sqlite
  • stripe
  • everything
  • sequential-thinking
  • chrome-devtools
  • firecrawl
  • tavily
  • exa
  • perplexity

Perplexity requires an API key. Select it in /mcp to configure it.

Management

nova mcp add brave-search --preset brave-search
nova mcp add my-server --transport http --url https://example.com/mcp
nova mcp add my-server --transport stdio --command "python -m my_mcp_server"
nova mcp list
nova mcp remove my-server

MCPMiddleware is inserted dynamically when MCP servers are configured. It calls list_servers() on every model turn, so it is skipped entirely when there are no servers. Tools are eagerly discovered before building the agent graph.

nova ❯/plugins

Plugin system.

Python entry-point based plugins that register slash commands and add middleware at defined slots.

Plugins are discovered via the nova.plugins entry point group and tracked in ~/.nova/plugins/manifest.json with an enabled list (read/written atomically).

Plugin capabilities

Slash commands

Custom interactive commands registered into the TUI command palette.

Middleware

Add behavior at named slots in the middleware stack.

Skills

Domain-specific workflows bundled with the plugin.

Lifecycle hooks

before_agent_setup and after_agent_setup.

Middleware slots

SlotTarget
earlyPrepend at position 0
before_securityBefore SecurityMiddleware
before_bootstrapBefore BootstrapMiddleware
before_steeringBefore SteeringMiddleware
before_shellBefore ShellMiddleware
before_memoryBefore AgentMemoryMiddleware
tailAppend at the end

Plugin management

/plugins                    # list plugins
/plugins enable my-plugin   # enable a plugin
/plugins disable my-plugin  # disable a plugin
/reload-plugins             # reload plugin registrations

nova ❯/learning

Autonomous learning.

Hermes is Nova's learning and memory subsystem. It runs out-of-band and never blocks the agent's task turn.

The system is orchestrated by NovaLearningMiddleware (hermes/middleware.py), a thin orchestrator that delegates to four focused modules:

ToolUsageTracker

Episodic tier: counter, tool history, skill stats.

ReviewRunner

Periodic review lifecycle: trigger, OOB invoke, content persistence.

SkillManager

Skill lifecycle: create, cleanup, refine.

EvolutionEngine

Task-completion skill evolution.

The review loop

Trigger logic (hermes/review.py, ReviewRunner.should_review()). A review fires when any of these hold (and a review wasn't just done):

  • Failure burst: ≥ FAILURE_BURST (default 3) failed tool calls in the current window
  • Substantive threshold: count ≥ REVIEW_THRESHOLD (default 10) AND the window contains real work
  • Hard cap: count ≥ 2× threshold (so all-trivial windows can't defer forever)
  • Clean win: real substantive work, zero failures, past the floor

OOB model invocation: the review runs as a separate, out-of-band model call — it is NEVER injected into the agent's task turn.

Content persistence: after the OOB review, the parsed content is applied:

Review outputApplied to
<user_model> blocksagent.md
<lesson topic="..."> blocksmemories/<topic>.md + INDEX pointer
<habit> blocksHABITS.md

Post-review actions: every review runs cleanup_legacy_skills_once() and maybe_create_from_review(); every 5th review runs maybe_refine_skills() (one high-failure skill per cycle); every 10th review runs maybe_curate(), ThresholdTuner.run_tuning_pass(), and PromptEvolutionEngine.maybe_auto_evolve().

What Hermes learns

  1. User model

    User preferences, communication style, merged into agent.md.

  2. Topic lessons

    Cross-session facts/lessons organized by topic.

  3. Good habits

    Reusable practices that worked well, stored in HABITS.md.

  4. Skills

    Episode-grounded skills created from review <skill> blocks.

  5. Prompt templates

    A/B-tested rewrites of system prompt templates.

  6. Verification memory

    Per-repo failure patterns that make the inline verifier smarter.

Self-evolution engine

Fires at task completion:

  1. Slice

    The task's episodic window.

  2. Score

    Complexity via a deterministic heuristic (no LLM).

  3. Invoke

    If complex enough (≥ 8), runs an OOB model call returning <skill> (new) or <level_up skill="name"> (improvement).

  4. Debate

    New skills go through one adversarial critic round before freezing.

Loop engineering enhancements

EnhancementModuleWhat it does
Inline Verification Loopcore/verification_loop.py, hermes/verifier.pyAfter each task, an OOB 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 by design.
Prompt-Template Hill Climbinghermes/prompt_evolution.pyProposes targeted .jinja rewrites, A/B tests them using verifier pass/fail as the quality signal, and promotes or discards. Packaged templates are never modified — overrides live in ~/.nova/prompt_history/.
Cron / Heartbeat Schedulerremote/scheduler.py, commands/cron_handler.pyProactive scheduled tasks via standard 5-field cron expressions.
Threshold Auto-Tunerhermes/tuner.pyNudges review-trigger thresholds toward the observed working style. Damped convergence (0.2 weight) with hard floor/ceiling bounds.
Webhook Ingress Serverremote/webhook_server.py, remote/webhook_adapters.pyExternal systems trigger a Nova run with per-source HMAC-SHA256 secrets.

Key design principles

  • Never block the turn: all learning runs OOB or in background tasks.
  • Fail-open: any learning failure logs and continues; never breaks the agent.
  • Durable persistence: all learning state survives restarts via the LangGraph BaseStore.
  • Bounded: every loop has hard caps (max retries, max lessons per review, etc.).

nova ❯/goal rubric

Verification loop.

Code written isn't the same as a task finished. Nova checks the result against what you asked for.

The loop

  1. Task

    The user's request.

  2. Understand

    Read the codebase, find the relevant code.

  3. Plan

    Decide what to change.

  4. Edit

    Write the code.

  5. Test

    Run the tests.

  6. Verify

    Grade the result. Fail? Back to plan.

When verification passes, the run is done, and the verdict and the diff that earned it are stored. When it fails, the failure comes back as feedback and the loop runs again, up to three attempts, then reports honestly instead of guessing.

Grader criteria

Five criteria scored by a separate model call:

  • responded to the request
  • wrote files
  • no errors
  • tests pass
  • did not modify tests to pass
CriterionWhat it means
Responded to requestDid the run address what the user actually asked for?
Wrote filesDid the run actually modify the codebase, or just talk about it?
No errorsDid the run complete without errors, exceptions, or failures?
Tests passDo the existing tests still pass after the changes?
Did not modify testsDid the run change the tests to make them pass instead of fixing the code?

Turning it on

# Grade each finished run (costs one extra model call per turn)
/learning on

# Hold a specific piece of work to your own criteria
/goal rubric <what counts as done>

Off by default. The inline verifier lives in core/verification_loop.py and hermes/verifier.py. It is fail-open by design: a verification failure never breaks the run.

nova ❯/remote

Remote bridges.

The bridge runs as background asyncio tasks inside the same event loop as the CLI. A remote message executes like any local prompt.

PlatformTypeNotes
DiscordInteractive chatMessages over 2000 chars are split into chunks
TelegramInteractive chatMessages over 4096 chars are split; supports voice notes
CronOne-way event sourceScheduled tasks via 5-field cron expressions
WebhookOne-way event sourceHMAC-SHA256 signed ingress from external systems

Security

  • only allowlisted channel/chat IDs receive responses
  • /remote allow <ID> manages the allowlist
  • unauthorised messages are silently ignored (no acknowledgement leaked)

Lifecycle

/remote start discord --token TOKEN --channel ID
/remote start telegram --token TOKEN --chat ID
/remote stop               # gracefully shut down all bridges
/remote status             # show what is running

Voice notes (Telegram)

Telegram accepts voice notes: they are transcribed with the 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.

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.

nova cron add "0 9 * * *" "review open PRs"
nova cron list
nova cron remove <id>

Webhook ingress server

Let 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.

nova webhook add <name> --secret <secret>
nova webhook list
nova webhook remove <name>

Streaming

Response chunks are captured from the agent's output and sent back to the originating platform. For Discord, messages longer than 2,000 characters are split. For Telegram the limit is 4,096. Edit-in-place streaming creates a single "live" reply message and edits it in place on subsequent calls.

nova ❯/voice

Voice I/O.

Speak prompts and hear Nova's prose replies, fully offline.

ComponentDefault providerDescription
STTFaster-WhisperLocal, open-source (CUDA/CPU)
VADSilero VADUtterance endpointing
TTSPiperLocal, lightweight

Providers

KindProviderNotes
STTFaster-WhisperLocal, CUDA/CPU
STTDeepgramCloud, high-accuracy
STTElevenLabsCloud STT
STTParakeetNVIDIA Parakeet via sherpa-onnx
TTSPiperLightweight local TTS
TTSElevenLabsCloud TTS
TTSDeepgramCloud TTS
TTSOrpheusLLM-based TTS (~2GB, slower)
TTSPocket TTSKyutai's lightweight local TTS

Voice modes

Two modes: push-to-talk (ctrl+g, press to start recording, release to stop) and hands-free (ctrl+l, always-listening with VAD). Code blocks are stripped before speaking. The speak tool speaks a short summary aloud.

Voice management

/voice test              # verify it works
/voice on/off            # toggle voice I/O
/voice mode ptt|listen   # switch mode
/voice settings tts orpheus   # switch TTS provider
/voice settings stt parakeet  # switch STT provider

nova ❯/middleware

Middleware stack.

Every model call passes through this chain. The base stack is order-sensitive, outermost to innermost.

#MiddlewarePurpose
0AsyncServerOnDemandMiddlewareStarts the LangGraph agent server on first start_async_task
1ModelRetryMiddlewareRetries transient failures (429, 5xx, timeout) with exponential backoff
2VisionCaptionMiddlewareConverts images to text for text-only models; pass-through for multimodal
3NovaLearningMiddlewareHermes learning loop (periodic review, skill creation)
4SecurityMiddlewareScreens URL args for deceptive Unicode/punycode spoofing
5BootstrapMiddlewareWorkspace bootstrap
6SteeringMiddlewareLive steering instructions from /steer
7FileTrackerMiddlewareFile-op tracking, result truncation
8LoopGuardMiddlewareBreaks identical-repeat tool loops (threshold 3)
9RubricMiddlewareSelf-evaluation against /goal rubric criteria; dormant without rubric
10ContextEditingMiddlewareClears old tool results when the token limit is reached
11ShellMiddlewareShell execution with sandbox support
12AgentMemoryMiddlewareInjects NOVA.md/CLAUDE.md project memory into the system prompt
13TaskDisciplineMiddlewareTodo list discipline (appended last, in the final system message)

Additional middleware

Appended after the base stack:

  • RefreshingSkillsMiddleware — tiered listing + per-turn suggestions
  • SkillCurationMiddleware — clamps loaded skills to the user-enabled set
  • CodeInterpreterMiddleware — QuickJS eval bridge for dynamic subagent dispatch
  • RepairToolCallsEachStep — repairs malformed tool-call history before every model call
  • ToolSearchMiddleware — deferred loading of ~85 tools and ~90 subagents
  • ModelRouterMiddleware — optional, off by default
  • HardDenyMiddleware — enforces explicit denies even without HITL interrupt
  • extra_middleware — caller-injected (e.g., Cowork's WorkspacePolicy broker)

nova ❯/sessions

Session management.

A composite state object, durable storage, and parallel sessions across git worktrees.

SessionState composite

states/Session.py (741 lines) holds six focused state slices plus cross-cutting identity fields, using __getattr__/__setattr__ for dynamic field routing.

SliceKey fields
UISettingsauto_approve, no_splash, plan_mode_enabled, verbose, active_goal
AgentRuntimeState_agent, _backend, _checkpointer, _store, _tools, _model, _sandbox_type, token_tracker
RemoteBridgeState_remote_message_queue, _remote_bridge_manager, _image_tracker, _seen_message_ids
BackgroundTaskStatebackground_ralph_tasks, trello_server, create_server
NotificationStatenotifications (deque, maxlen 100)
WikiStatewiki_root, wiki_enabled, page_count, last_ingest

Session storage layout

Sessions live in ~/.nova/sessions/<session_id>/:

FileContents
meta.jsonSessionMeta metadata
snapshot.jsonAuthoritative recovery snapshot (v1 format)
recent.jsonlRecent messages, for context injection
archive.jsonlFull message history (not injected)
todos.jsonTask list state
tool_state.jsonLast tool outputs
memory.mdDeclarative memory content
workspace_state.jsonGit + filesystem state
ui_journal.jsonlUI journal (shell commands, background jobs)
imported-context.jsonImported session context

Four-tier persistence

  1. Checkpointer

    LangGraph, SQLite-backed. Persists message history per thread_id. Primary conversation state.

  2. Snapshot

    SessionManager's snapshot.json. The authoritative recovery generation, written atomically.

  3. Store

    Durable key/value at ~/.nova/store.db. SqliteStore, then stdlib fallback, then in-memory.

  4. Semantic files

    memory.md, workspace_state.json, ui_journal.jsonl, skills, worktrees, update cache.

Session lifecycle

  • saves the incoming prompt before execution
  • checkpoints active sessions every five seconds
  • saves again when a turn ends
  • resume with nova --continue or /sessions
  • abrupt termination can lose progress since the last save

Save is serialized via a @serialized_save decorator to prevent concurrent autosave and final-save interleaving. Restoration validates project root, repo hash, and NOVA.md checksum, but never blocks on a mismatch.

Parallel sessions

Parallel sessions run as separate OS processes, each bound to its own git worktree. The child streams ui_events dataclasses to the parent as JSONL; the parent decodes them back and feeds the existing TUI renderer. Up to four run concurrently.

DirectionMessages
Parent to childprompt, interrupt_reply, cancel, shutdown
Child to parentready, ev, interrupt, turn_done, error

Session leases are durable, TTL-based, and cross-process (DEFAULT_TTL = 300s, DEFAULT_RENEW_INTERVAL = 60s). On a lease conflict, a turn runs unleased rather than blocking. Worktrees live under ~/.nova/worktrees/<repo-name>/<slug>, outside the repo.

nova ❯/context

Context management.

A three-stage pipeline sized to the model's actual context window.

  1. Clear

    Older tool results are offloaded to /cleared/ so the agent can read them back.

  2. Compact

    The conversation is summarized hierarchically via LLM.

  3. Reserve

    A hard backstop always keeps an 8k-token reserve.

ContextManager

context/manager.py is a model-aware facade for all context-window operations:

MethodPurpose
window_size()Context window size in tokens
breakdown()Token breakdown against the window
model_config()Model configuration
budget()Process-global context budget
digest()Recent conversation digest

Compaction

Compaction rewrites the whole conversation into one synthetic HumanMessage carrying the summary. The pre-compaction transcript is archived to ~/.nova/sessions/<thread>/.

System One compaction (experimental) asks Jev or a compatible local/custom decision model whether each old tool result is still needed, and clears only results scored stale. Off by default. Configure through /model → Decisions to select Jev, Tev1, or Custom System One.

Context meter

The TUI's CTX meter uses the latest main-model input usage when available and an estimated summary/tail breakdown after compaction or resume. SESSION accumulates main-model input and output across tool-loop calls against a configured token budget (1M by default).

nova ❯open safe.book

Security & safety.

Autonomous doesn't mean uncontrolled. Every tool has a tier, and the tiers are yours to set.

Security middleware

security/middleware.py screens URL-bearing tool arguments for deception: hidden/invisible Unicode (BiDi overrides, zero-width chars, BOM), punycode domain spoofing (xn-- decoding), and mixed-script or confusable domain labels. Policy is warn and sanitize: invisible characters are stripped from the URL in place and the call proceeds; spoofing signals are surfaced as a notice but not blocked.

Human-in-the-loop

hitl/interrupts.py is a configurable interrupt system requiring user approval before destructive or external operations. 11 tool categories have schema-driven interrupt specs:

CategoryTools
Destructiveshell, execute, write_file, edit_file
Externalweb_search, fetch_url, http_request, browser_automate
Code executionrun_tests, start_dev_server
Memorywrite_memory, create_memory_structure
User interactionask_question

File recovery

Automatic snapshots are taken before destructive operations. Files targeted by rm are captured before deletion, files overwritten by write_file have their previous content saved, and files modified by edit_file have the pre-edit content saved. Snapshots live in ~/.nova/trash/<session-id>/. Files over 10 MB are skipped. Restore via /restore or the list_trash and restore_file tools.

Other safety layers

LayerPurpose
path_approval.pyPath-based operation approval for filesystem access outside the project root
git_safety.pyDangerous command detection and injection prevention
errors/taxonomy.py14 error categories for recovery strategies
unicode_security.pyURL safety checking (BiDi, zero-width, BOM, punycode, confusables)
delegated_approval.pyHardDenyMiddleware enforces explicit denies even without HITL

nova ❯--sandbox

Sandbox execution.

Seven providers, from OS-level confinement to hardware-virtualized microVMs.

ProviderDescription
osOS sandbox (default on Linux/macOS — host files, shell confined to workspace)
dockerDocker container (opt-in on Windows, with workspace binding)
modalModal cloud sandbox
runloopRunloop cloud sandbox
daytonaDaytona cloud sandbox
langsmithLangSmith Sandboxes (hardware-virtualized microVMs)
noneNo sandbox (unconfined local execution)

Sandbox flags

nova --sandbox os                    # OS sandbox (default on Linux/macOS)
nova --sandbox docker                # Docker container
nova --sandbox langsmith             # LangSmith microVMs
nova --no-sandbox                    # force unconfined local execution
nova --sandbox-id <id>               # reuse an existing sandbox
nova --sandbox docker --ports 8080:8080
nova --sandbox langsmith --sandbox-vcpus 2 --sandbox-mem-bytes 8589934592

The default sandbox image is python:3.11-slim. The sandbox factory (integrations/sandbox_factory.py) creates the appropriate backend based on the provider type, supporting workspace binding, setup scripts, and resource configuration.

nova ❯/cowork

Infrastructure.

Surfaces beyond the terminal: notifications, a web chat, and a desktop companion app.

Vixie desktop companion

vixie/ is a background server for desktop notifications and system tray integration: task completion and status alerts, quick access to Nova status, a WebSocket server for real-time event streaming, and state mapping (idle, thinking, working, success, error, user_input, planning).

Agent server launcher

The local langgraph dev server that hosts async agent graphs. It reserves a port but does not start at boot; the first start_async_task triggers ensure_started(). Health is confirmed by polling GET /ok and then the first graph. Stop is graceful (SIGTERM to the process group, Ctrl+Break on Windows) then force (SIGKILL / taskkill /T /F). A server that won't come up leaves the session exactly as it was.

Server, Cowork, and tracking

ComponentDescription
server/Local HTTP server with an event adapter, session manager, and WebSocket chat
cowork//cowork launches a desktop companion app: FastAPI on a random localhost port, default-deny workspace access with folder grants
process_manager.pySubprocess lifecycle, health checks, and cleanup for dev servers
daemons/A detached-daemon registry (JSON file-backed pid store) that survives restarts
artifacts/In-memory, session-scoped registry; content rendered in a sandboxed browser context, never executed on the host
tracking/File tracker, loop guard, usage tree with cost estimation, tracing, workspace anchoring

Hooks system

Lifecycle hooks can be Python scripts, shell commands, or any executable.

HookWhen it fires
pre_tool_callBefore a tool is executed (validate inputs, log, modify params)
post_tool_callAfter a tool completes (process results, log, notify)
on_messageWhen a message is received (filter content, add context)
on_errorWhen an error occurs (custom error handling, recovery)

nova ❯tree ~/.nova

Directory structure.

Global configuration (~/.nova/)

~/.nova/
  agents/default/
    agent.md          # user model + preferences
    memories/         # semantic memory tier
      INDEX.md
      <topic>.md
  skills/
    web-research/
      SKILL.md
  hooks/
    pre_tool_call.py
    post_tool_call.sh
  daemons/
    registry.json     # detached daemon registry
  plans/
    <project-slug>/   # global plan archive
  plugins/
    manifest.json     # plugin enable/disable manifest
  trash/
    <session-id>/     # file recovery snapshots
      manifest.json
  store.db            # durable LangGraph key/value store
  Nova.config.json    # persistent configuration
  logs/
    nova.log
  ui/
    <workspace>/       # saved UI layouts

Project configuration

my-project/
  .nova/
    NOVA.md               # project context and conventions
    config.json           # project configuration
    hooks.json            # project-specific hooks
    skills/               # project-specific skills
    wiki/                 # project wiki vault
      index.md
      log.md
      README.md
      Clippings/          # Obsidian Web Clipper inbox
      wiki/               # synthesized pages
    plans/                # approved plans
    council/              # past council runs
    project-graph.json    # project graph
  .claude/                # also supported (Claude Code compatible)
  .nova.config.json       # project-level config (scoped)

nova ❯uv pip install

Optional dependencies.

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

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

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

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

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

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

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

Extras

ExtraPackagesDescription
browserbrowser-use, playwrightReal-browser automation (~330 MB)
agents-serverlanggraph-cli[inmem]Local LangGraph server for async agents
voicefaster-whisper, silero-vad, piper-tts, sounddeviceVoice I/O (~2 GB)
voice-orpheusorpheus-cpp, llama-cpp-pythonOrpheus LLM-based TTS
voice-parakeetsherpa-onnxNVIDIA Parakeet STT
voice-pocketpocket-ttsKyutai Pocket TTS
serverfastapi, uvicornLocal HTTP server

nova ❯nova doctor

Troubleshooting.

Common issues and how to resolve them.

Common issues

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

nova doctor

Runs six checks and returns exit code 0 when all pass (1 on failures):

  1. Configuration

    ~/.nova/config.json exists and is valid JSON with a provider set.

  2. Secrets

    Lists configured secrets via the SecretManager.

  3. LLM connection

    Ollama tests /api/tags and checks allocated context; cloud providers create a model instance.

  4. Tavily

    Tests the search API if a key is configured.

  5. Permissions

    Checks that secrets.json is not readable by others.

  6. Voice stack

    Checks audio imports, PortAudio, and the default input device.

Diagnostics

nova doctor           # validate config + connections
nova --version       # check version
nova paths list      # check approved paths

Any UI freeze over one second is logged to ~/.nova/logs/freeze.log. The application log lives at ~/.nova/logs/nova.log.

Getting help

  • run nova doctor
  • check ~/.nova/logs/freeze.log
  • open an issue on GitHub
  • include nova --version output