Local-first agentic assistant — terminal UI and pluggable agent runtime
Project description
Citnega
Citnega is a local-first agentic assistant — a full-featured terminal UI backed by a production-grade agent runtime. It runs conversations, calls tools in parallel, compiles plans, and routes tasks to specialists, all from a single citnega command.
pip install citnega
citnega
Features
- Terminal UI built on Textual — keyboard-driven, themeable, no browser required
- Pluggable framework adapters — swap between
direct(built-in), Google ADK, LangGraph, or CrewAI without changing application code - Parallel tool execution — independent tool calls fan out concurrently via
asyncio.TaskGroup - Plan mode — draft → approve → execute multi-step plans with a structured compiler and scheduler
- Persistent knowledge base — full-text search, tagging, and session-scoped KB retrieval
- Workspace overlay — drop custom agents, tools, workflows, and skills into a workfolder; they override built-ins by name
- Conversation compaction — automatic summarisation keeps context within token budget
- Policy enforcement — file path bounds, network controls, approval gates, per-tool overrides
- Circuit breaker per model provider with configurable thresholds and cooldown
Installation
# Core (direct adapter, built-in tools)
pip install citnega
# With Google ADK support
pip install "citnega[adk]"
# With LangGraph
pip install "citnega[langgraph]"
# With CrewAI
pip install "citnega[crewai]"
# Everything
pip install "citnega[all]"
Requires Python 3.11+.
Quick Start
# Launch the TUI
citnega
# New session directly
citnega --session my-project
# Headless CLI
citnega-cli run --session my-session --prompt "Summarise the latest changes in this repo"
# List sessions
citnega-cli session list
TUI keyboard shortcuts
| Key | Action |
|---|---|
Enter |
Send message |
↑ / ↓ |
Browse input history |
/ |
Start a slash command |
Ctrl+K |
Open command palette |
Ctrl+Y |
Copy last response |
Ctrl+L |
Clear chat |
Ctrl+C |
Quit |
Slash commands
| Command | Description |
|---|---|
/model [id] |
Show or switch the active model |
/mode [name] |
Switch session mode (chat, plan, explore, …) |
/think [on|off|auto] |
Toggle extended thinking |
/compact |
Compact conversation history |
/sessions |
List all sessions |
/new |
Start a new session |
/rename <name> |
Rename current session |
/setworkfolder <path> |
Point to a workfolder |
/createtool |
Scaffold a new custom tool |
/createagent |
Scaffold a new custom agent |
/createworkflow |
Scaffold a new workflow |
/help |
List all commands |
Configuration
Config lives in the platform app-home directory:
| Platform | Path |
|---|---|
| macOS | ~/Library/Application Support/citnega/config/ |
| Linux | ~/.local/share/citnega/config/ |
| Windows | %APPDATA%\citnega\config\ |
Key files:
settings.toml— runtime, session, model, logging, workspace, policy settingsmodels.yaml— model registry (providers, priorities, thinking flags)
All settings can also be set via environment variables with the CITNEGA_ prefix:
CITNEGA_RUNTIME__DEFAULT_MODEL_ID=gpt-4o citnega
CITNEGA_NEXTGEN__PLANNING_ENABLED=true citnega
Minimal settings.toml
[runtime]
default_model_id = "gpt-4o"
local_only = false
[workspace]
workfolder_path = "/home/you/my-citnega-workspace"
Workfolder
A workfolder is a directory that extends Citnega with your own agents, tools, and workflows. Workfolder callables override built-ins of the same name.
my-workspace/
├── agents/ # custom agent modules
├── tools/ # custom tool modules
├── workflows/ # YAML or Python workflow definitions
├── skills/ # SKILL.md bundles
└── memory/ # runtime state (sessions, KB, logs, artifacts)
├── db/
├── sessions/
├── kb/
└── logs/
Set the path via /setworkfolder in the TUI, or in settings.toml:
[workspace]
workfolder_path = "/absolute/path/to/workspace"
Custom tool example
# my-workspace/tools/summarise.py
from citnega.packages.protocol.interfaces.tool import ITool, ToolResult
class SummariseTool(ITool):
name = "summarise"
description = "Summarise a block of text in one paragraph."
async def invoke(self, input, ctx):
text = input.get("text", "")
# ... call your model / logic here
return ToolResult(output=summary)
Built-in Tools
| Tool | Description |
|---|---|
read_file |
Read a file from disk |
write_file |
Write or create a file |
edit_file |
Apply targeted edits to a file |
list_dir |
List directory contents |
search_files |
Full-text search across a file tree |
run_shell |
Execute a shell command |
git_ops |
Git status, diff, log, commit, push |
web_search |
Search the web (requires provider) |
read_kb |
Retrieve from the persistent knowledge base |
write_kb |
Save a note or document to the KB |
repo_map |
Generate a structural map of a repository |
quality_gate |
Run linters and type-checkers |
test_matrix |
Discover and run test suites |
Architecture
apps/
tui/ — Textual TUI (ChatScreen, widgets, controllers)
cli/ — Typer CLI (citnega-cli)
packages/
bootstrap/ — Dependency composition and startup
runtime/ — CoreRuntime, ApplicationService, SessionManager
adapters/ — Framework adapters (direct, ADK, LangGraph, CrewAI)
agents/ — Built-in agents (conversation, planner, specialist)
tools/ — Built-in tools
planning/ — PlanCompiler, PlanScheduler, TaskClassifier
execution/ — ExecutionEngine (parallel batch runner)
strategy/ — StrategySpec, SkillLoader, MentalModelCompiler
capabilities/ — CapabilityRegistry and descriptors
model_gateway/ — Provider abstraction, retry, circuit breaker
context/ — Context assembly pipeline (handlers, token budget)
kb/ — Knowledge base (SQLite FTS5)
workspace/ — Workfolder loader and overlay
config/ — Pydantic settings, TOML loaders
protocol/ — Shared interfaces, events, models (no deps)
The protocol package defines all interfaces and events; every other package depends on it but not on each other, enforcing a clean dependency graph.
Development
git clone https://github.com/8prabhat/citnega.git
cd citnega
uv sync --all-extras
uv run citnega
Tests
uv run pytest # full suite
uv run pytest tests/unit/ # unit tests only
uv run pytest tests/integration/ # integration tests
uv run pytest --cov --cov-report=term-missing
Linting
uv run ruff check .
uv run mypy packages apps --ignore-missing-imports
uv run lint-imports --config import-linter.ini
Release
Tag a version to trigger automated PyPI publishing via GitHub Actions:
git tag v0.6.0
git push origin v0.6.0
The release.yml workflow builds the wheel, runs tests, and publishes to PyPI using trusted publishing (OIDC — no API token required).
License
MIT © 2025 Citnega contributors
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file citnega-0.6.0.tar.gz.
File metadata
- Download URL: citnega-0.6.0.tar.gz
- Upload date:
- Size: 533.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
104554f0f917e60cf2e6d9c5b732820aca8deedbd2e7288c1a79e9194ae453bb
|
|
| MD5 |
622df79ba90b63d5c33feee140a0fc2c
|
|
| BLAKE2b-256 |
77b42e73a222d55ffb46f807f70df20935faac090caea3d1ddcb71adfac3a7c9
|
File details
Details for the file citnega-0.6.0-py3-none-any.whl.
File metadata
- Download URL: citnega-0.6.0-py3-none-any.whl
- Upload date:
- Size: 567.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
502b6b329e68044c14871b1157f9ab857db25d89c751ff4975f8383a9bc2a646
|
|
| MD5 |
4935c3c86fe138887259cccd79995706
|
|
| BLAKE2b-256 |
63c248ba1260da87b0ef75fd8f1fd82c3c284ee45edeb1dff43a47f2ca90e897
|