OpenNova v0.4.0 is a lightweight CLI AI coding agent built from scratch in Python.
English | 简体中文
Quickstart (Chinese) | Tutorial (Chinese) | API Reference (Chinese)
OpenNova runs in your terminal and combines a small core with practical coding-agent workflows:
- Multi-provider runtime for OpenAI, Anthropic, and DeepSeek
- Textual TUI with split-pane chat, streaming output, session resume, and slash commands
- Session management: save, resume, and list sessions (JSONL persistence)
- Context compression: LLM-driven summarization for long conversations
- Plan + act workflows for decomposing larger tasks before execution
- Tool + skill extensibility for local tools and trusted project plugins
- MCP integration for external tool servers
- Built-in safety guardrails for risky commands and protected paths
The current release adds stronger plan/skill/security foundations, OS process sandboxing, and a more polished Textual workbench:
- Workbench TUI: two-column chat plus a wider Tools / Plan / Todos side panel with keyboard tab switching
- Plan mode upgrades: persisted plan markdown, per-step refresh, live status writeback, and todo mirroring
- Skills upgrades: namespaced discovery, argument substitution, hooks, path activation, and ranking
- Security hardening: parameter-level permission rules, command/network/MCP policies, secret redaction, audit logs, and process sandbox support
- Session management:
/resume <id>,/sessions— conversations persist to JSONL - Context compression: LLM summarizes old messages when context exceeds 55% token utilization, keeping long conversations within budget
- Textual TUI: structured chat blocks, copy overlay, history navigation, real-time streaming, and side-panel details
- Expanded built-in tools: file ops, shell execution, git, task tracking, TodoWrite, plan mode, sub-agents, skills, web, project guide init, code search, Python diagnostics/symbols, MCP resources, worktrees
- ReAct runtime with streaming responses and tool execution
- Plan mode with approval flow inside the TUI
- Diff/patch editing pipeline
- Context, working memory, and project memory components
- MCP stdio and SSE transport support
- Skill auto-discovery and bundled example skills
- Interactive user-question prompts in TUI and task runs
- Real HTTP-backed
web_fetchbehavior
Note: web_search is present as a tool surface, but in this runtime it reports that search is not configured instead of fabricating results.
- Python 3.11+
- uv package manager
# Clone the repository
git clone https://github.com/Wardell-Stephen-CurryII/OpenNova.git
cd OpenNova
# Install dependencies into the project environment
uv sync
# Initialize configuration
uv run opennova initIf you want an installed CLI instead of the local development flow, you can also run uv tool install . and then use opennova directly. The examples below use uv run opennova ... so they always match the checked-out source tree.
Edit ~/.opennova/config.yaml or set environment variables:
default_provider: deepseek
default_model: deepseek-v4-pro
providers:
openai:
api_key: ${OPENAI_API_KEY}
default_model: gpt-4o
anthropic:
api_key: ${ANTHROPIC_API_KEY}
default_model: claude-sonnet-4
deepseek:
api_key: ${DEEPSEEK_API_KEY}
default_model: deepseek-v4-pro
agent:
max_iterations: 20
auto_confirm: false
show_thinking: true
compression:
enabled: true
threshold: 0.55
keep_last_pairs: 6
max_tool_result_tokens: 8000
security:
permission_mode: auto # request | auto | full
sandbox_mode: true
command_timeout: 30
allow_network: true
auto_confirm_safe: true
allowed_paths: []
blocked_commands: []
strict_shell_parsing: false
read_only: false
max_file_size: 104857600
mcp:
enabled: true
servers:
- name: filesystem
transport: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "./src"]
skills:
enabled: true
dirs: []
exclude: []Or use environment variables:
export OPENAI_API_KEY=your_key_here
export ANTHROPIC_API_KEY=your_key_here
export DEEPSEEK_API_KEY=your_key_here# Textual TUI (default interactive interface, including Windows IME support)
uv run opennova
# Explicit Textual TUI mode
uv run opennova run --tui# Open the TUI session picker
uv run opennova --resume
# Continue the most recent saved session in the TUI
uv run opennova --continue# Execute a task directly
uv run opennova run "Read the README.md file"
# Run in plan mode
uv run opennova run --plan "Refactor the authentication module"
# Use a specific model
uv run opennova run -m gpt-4o "Create a new Python module"
# Choose the approval mode for this run
uv run opennova --permission-mode request
uv run opennova --permission-mode full run "Run the trusted migration"Inside the Textual TUI:
| Command | Description |
|---|---|
/plan <task> |
Generate a plan, show it, and ask whether to execute it now |
/act <task> |
Execute directly (default mode) |
/tools |
List available tools |
/skills |
List loaded skills |
/skill <name> [args] |
Invoke a loaded skill directly |
/reload-skills |
Reload skills from disk |
/model |
Show current model info |
/init [--force] |
Let the model analyze the repo and generate OPENNOVA.md for long-term project memory |
/config |
Show current configuration |
/permissions |
Show the active approval mode and persisted tool rules |
/permissions mode request|auto|full |
Switch approval mode for this run |
/permissions <tool> allow|deny|ask |
Update a persisted tool permission rule |
/plugins [trust|untrust|test name|lock|drift|warnings|audit [--policy strict]] |
Manage, lock, validate, warn, and audit local project plugins |
/hooks |
Show loaded hook counts |
/automations |
List local scheduled automations |
/automations once <name> <run_at> <prompt> |
Schedule a one-shot local automation |
/automations interval <name> <seconds> <prompt> |
Schedule a recurring local automation |
/automations pause|resume|delete|run-now <id> |
Manage local automations |
/automations daemon start|stop|status|tick|run |
Control the local automation daemon |
/diagnostics [path] |
Run Python syntax diagnostics |
/status |
Show runtime/session status |
/todos |
Show the current TodoWrite task board |
/checkpoint |
Show checkpoint/rollback status |
/checkpoint list|diff|restore [--preview] <id> |
List, preview, or restore checkpoint snapshots |
/checkpoint diff --session <session> <id> |
Inspect checkpoint diff from .opennova/exports/<session>.md |
/checkpoint diff --from-transcript <path> <id> |
Inspect checkpoint diff from an exported transcript |
write_file checkpoint metadata |
Existing-file overwrites automatically create a checkpoint and return checkpoint_id |
edit_file checkpoint metadata |
Edit and multi-edit operations also create restore checkpoints for existing files |
/export [dir] |
Export the current transcript to Markdown, including tool checkpoint/diff details |
| automation retry/archive | Local daemon retry events can be archived by an injected callback |
| automation backoff/archive summary | Retry delay and archive summaries are available for daemon productization |
| transcript checkpoint lookup | Exported transcripts can be indexed by checkpoint_id for later diff lookup |
| transcript session lookup | /checkpoint diff --session resolves checkpoint diffs by session id |
| plugin startup warnings | /plugins warnings --policy strict reports lockfile drift and policy risks |
| diagnostics events | Diagnostics, hover, definition, and references can be wrapped in unified event payloads |
| diagnostics server manager | A lightweight server lifecycle facade tracks pyright/ruff server argv and process metadata |
| plugin startup warnings | Drift and strict policy warnings can be generated without blocking startup |
| automation status archive | Daemon status can include archive summaries for productized status panels |
/history [n] |
Show recent conversation history |
/resume <id> |
Resume a previous session |
/sessions |
List saved sessions |
/clear |
Clear current conversation state |
/help |
Show help message |
/exit |
Exit OpenNova |
OpenNova ships with a broader tool surface than the original README listed.
| Tool | Description |
|---|---|
read_file |
Read file contents with optional line range |
write_file |
Write content to a file |
create_file |
Create a new file |
delete_file |
Delete a file with confirmation |
list_directory |
List directory contents |
execute_command |
Execute shell commands through guardrails |
git_commit |
Create a git commit with staged changes |
git_status |
Show working tree status |
git_diff |
Show changes between commits or working tree |
git_log |
Show commit history |
git_branch |
List or manage branches |
task_create |
Create a new task in the task list |
task_list |
List all tracked tasks |
task_get |
Get task details by ID |
task_update |
Update task status or properties |
task_stop |
Stop a running background task |
task_output |
Get output from a completed task |
todo_write |
Replace the current structured task board for multi-step work |
enter_plan_mode |
Enter plan mode for architectural design |
exit_plan_mode |
Exit plan mode after plan approval |
agent |
Delegate work to a sub-agent |
send_message |
Send a message to a running sub-agent |
skill |
Invoke a loaded skill by name |
ask_user_question |
Ask the user to choose from 2-4 options during a run |
web_fetch |
Fetch a real HTTP/HTTPS page and return extracted content |
web_search |
Search interface placeholder; reports unconfigured when no backend is available |
init_project_guide |
Create or regenerate OPENNOVA.md project guide |
glob_files |
Find files using glob patterns while respecting project ignores |
grep_code |
Search code content without relying on shell commands |
python_diagnostics |
Run lightweight Python syntax diagnostics |
python_symbols |
List Python symbols with qualified names |
python_definition |
Find Python symbol definitions |
python_references |
Find Python symbol references |
list_mcp_resources |
List resources exposed by connected MCP servers |
read_mcp_resource |
Read a resource from a connected MCP server |
enter_worktree |
Create and enter an isolated git worktree |
exit_worktree |
Remove a git worktree |
Tip: OPENNOVA.md is generated by the model during /init and remains manually maintainable. The agent automatically reads it as project context during task execution.
OpenNova includes several example skills:
| Skill | Description |
|---|---|
code_review |
Review code for quality and best practices |
generate_docs |
Generate documentation/docstrings |
git_helper |
Git command assistance |
analyze_project |
Analyze project structure |
Custom skills now use the Claude Code-style markdown package format. Create a directory such as ~/.opennova/skills/my_skill/ and put a SKILL.md file inside it:
---
name: my_skill
description: Summarize a target file or feature area.
when_to_use: Use when the user wants a reusable project-specific analysis prompt.
allowed-tools: read_file, list_directory
arguments: [target]
argument-hint: <file-or-area>
---
Analyze the requested target carefully.
Target: $ARGUMENTS
Summarize:
- what it does
- key risks
- likely extension pointsSkills are markdown prompts loaded from these directory layouts:
~/.opennova/skills/<skill-name>/SKILL.md.opennova/skills/<skill-name>/SKILL.md- configured skill directories with the same
<skill-name>/SKILL.mdstructure
OpenNova supports Model Context Protocol (MCP) servers for extended capabilities:
mcp:
enabled: true
servers:
- name: filesystem
transport: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]Supported transports:
- stdio: launch a subprocess and communicate over stdin/stdout
- sse: connect to an HTTP SSE endpoint
OpenNova automatically compresses conversation context when token usage exceeds 55% of the model's context window:
- LLM-driven summarization: Old messages are summarized into a concise paragraph using the active LLM provider
- Safe cut points: Compression never splits incomplete assistant+tool pairs
- Session persistence: Compression markers are saved to JSONL, enabling compact session resume
- Tool result truncation: Large tool outputs (>8000 tokens) are truncated (head 20% + tail 80%)
- Configurable: Adjust threshold, keep-last-pairs count, and truncation limits in config
When a session resumes, only messages after the last compression boundary are loaded — older context is replaced by the summary.
Conversations are automatically persisted to ~/.opennova/sessions/ as JSONL files:
# Inside the TUI
/resume <session_id> # Resume a previous session
/sessions # List all saved sessionsEach session file records every message, tool call, and compression boundary. When resuming, compression markers allow the agent to restore context compactly.
opennova/
├── providers/ # LLM provider implementations
├── tools/ # Built-in tools and tool registry (17 tools)
├── runtime/ # Agent runtime, loop, and state
├── cli/ # Textual TUI and shared CLI helpers
├── diff/ # Diff/patch system
├── memory/ # Context management, compression, working/project memory
├── planning/ # Plan data structures and planner
├── security/ # Guardrails and sandboxing
├── session/ # Session persistence (JSONL)
├── mcp/ # MCP transports and connectors
├── skills/ # Skill system and examples
└── main.py # CLI entry point
OpenNova includes several safety mechanisms:
- Three approval modes:
requestasks for every allowed tool call,autoasks only for risky calls, andfullskips approval prompts - Dangerous command detection for destructive shell commands
- Path sandboxing for file access limits
- Protected paths for system directories such as
/etcand/usr - Confirmation prompts for risky operations
- Sensitive file detection for files like
.envand.pem - Optional network policy (
security.allow_network) to block tool/network access - Strict shell parsing mode (
security.strict_shell_parsing) to reject shell syntax fallback
full only bypasses approval prompts. Hard blocks, explicit deny rules, plan approval,
network/path restrictions, and the OS process sandbox remain active.
# Run tests
LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 PYTHONUTF8=1 uv run pytest
# Run tests with coverage
LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 PYTHONUTF8=1 uv run pytest --cov=opennova
# Type check
uv run mypy src/opennova
# Format code
uv run ruff format src/
# Lint
uv run ruff check src/This project is licensed under the MIT License. See the LICENSE file for the full text.
Xingwang Lin (@Wardell-Stephen-CurryII)