Skip to main content

AI agent CLI with pluggable tools, powered by free NVIDIA NIM models

Project description

agent-cli

A Claude Code-style AI agent for your terminal, powered by NVIDIA NIM and OpenRouter models. Full-screen TUI (streaming, never blocks), pluggable tools, and long-term chat memory with semantic recall (Postgres + pgvector).

Installation

Requires Python 3.11+. Chat memory (optional) needs Docker; OmniRoute (optional — a self-hosted router across multiple LLM providers) needs Node.js 18+.

Quick install (Linux, macOS, Windows)

pip install linus-cli

That's the whole install — same idea as npm install -g @anthropic-ai/claude-code for Claude Code, just via pip instead of npm. Add your API key afterward:

mkdir -p ~/.agent-cli && cat > ~/.agent-cli/.env <<'EOF'
NVIDIA_API_KEY=your_key_here
EOF

Then run linus from anywhere. Optional extras:

docker compose up -d        # chat memory (Postgres + pgvector) — needs Docker
npm install -g omniroute    # self-hosted multi-provider router — needs Node.js

From source (for development)

git clone https://github.com/linuso71/linuscli.git   # requires repo access — it's private
cd linuscli

python3 -m venv .venv              # Windows: py -m venv .venv
.venv/bin/pip install -e .         # Windows: .venv\Scripts\pip install -e .

cp .env.example .env               # Windows: copy .env.example .env — then paste your API key

Does this run on Windows? The core app (Python + the Textual TUI) is cross-platform and should run natively — I don't have a Windows machine to verify on directly, so this is based on code review rather than a live test, but there's nothing OS-specific in the agent loop, tool system, or config. Two known gaps on native Windows:

  • Clipboard image paste (Ctrl+V) currently only works on Linux (shells out to wl-paste/xclip) — pasted images aren't picked up on Windows yet. Text paste and file attachments both work fine everywhere.
  • run_shell runs whatever command the model writes verbatim, and its instructions assume Unix-style commands (ls, grep, cat, …) — it'll work best in a POSIX-like shell. WSL2 gives the smoothest experience on Windows; native cmd.exe/PowerShell will run the app fine, but shell commands the model writes may not match what's available in your shell.

Usage

linus                        # launch the TUI
linus "what's new in python 3.14?"   # one-shot mode
linus -m meta/llama-4-maverick-17b-128e-instruct "hi"  # override model
linus -m openrouter:qwen/qwen3-coder:free "hi"          # use OpenRouter directly
linus models                 # list models your configured keys can use

TUI commands

Command What it does
/help show help
/new start a new session
/history list saved sessions
/resume <id> continue a past session
/recall <query> semantic search over past conversations
/model pick a model from a searchable list (saved for future sessions)
/model <id> switch chat model directly
/exit quit

Esc cancels the current response. Ctrl+Q quits (Ctrl+C copies selected text in the prompt box instead, matching your terminal's usual behavior).

Sessions

/history (or /resume with no id) opens an interactive picker — type to filter, ↑/↓ to navigate, Enter to resume a past conversation.

Attachments: files and images

Three ways to attach, all shown as removable chips above the input:

  • 📎 button (or /attach) — browse the directory tree and pick a file
  • Paste a file path — a pasted path to an existing file attaches it instead of inserting text
  • Ctrl+V — pastes an image straight from the system clipboard (screenshots; needs wl-paste or xclip, Linux only for now — see the Windows note under Installation); pastes plain text into the prompt otherwise

Text files are inlined into the prompt. Images go to the model as real image input when it supports vision (llama-4-maverick, qwen3.5, the -vl models, …); for text-only models a free NVIDIA vision model (nemotron-3-nano-omni-30b-a3b-reasoning, configurable as vision_model) describes the image first and the description is inlined — so image paste works with every chat model.

One-shot mode: linus -f screenshot.png "why did this build fail?" (repeatable).

Modes: discuss → plan → code

The TUI starts in ⚡ code mode, ready to build (like Claude Code). Click the mode badge next to the input (or press Shift+Tab, or type /mode discuss) to move through the workflow:

Mode Tools available Use it to
💬 discuss web_search, list_dir, read_file, search_code (read-only) talk the idea through — nothing can be modified
📋 plan same read-only tools, plan-focused instructions let the agent explore the project and write a step-by-step plan
⚡ code everything (write, edit, git push) implement the agreed plan

Tool restrictions are enforced twice: restricted tools aren't offered to the model at all, and any hallucinated call is refused at execution. One-shot mode defaults to code; use linus --mode plan "..." to override.

Permissions

Tools are classified by risk: safe (search/read — never confirmed), write (write_file/edit_file), risky (git_push — leaves your machine). The permission badge next to the mode badge cycles three levels (also /permission <level>, or -p in one-shot mode):

Level Behavior
🔒 ask (default) confirm every write and risky tool
⚠ risky file writes run automatically; confirm only risky tools
🔓 auto everything runs without prompts

The ▶ Send button next to the input submits your message; while the agent is working it turns into ■ Cancel (same as pressing Esc).

Built-in tools

  • web_search — DuckDuckGo search (free, no key)
  • git_pushgit add . + commit + push (risky: always confirmed unless auto)
  • list_dir / read_file / search_code — explore files in the directory where you launched linus
  • write_file / edit_file / delete_file — create, edit, and delete files (confirmed at the ask level)
  • run_shell — run a shell command in the current directory (risky: always confirmed unless auto)
  • browser_navigate / browser_snapshot / browser_click / browser_fill / browser_screenshot / browser_close — drive a real headless browser for end-to-end / UI testing (like GitHub Copilot's agent mode)

Browser automation (optional)

Linus can open a real browser, read the page, click, and type — so it can test a web UI end-to-end, not just build it. Enable it once:

.venv/bin/pip install -e ".[browser]"
.venv/bin/playwright install chromium

Then, in code mode: "start the dev server and test the login page in a browser" — linus navigates, snapshots the page (title + interactive elements + text), fills fields, clicks buttons, and can screenshot. If Playwright isn't installed the tools return an install hint instead of failing. Cleanup happens automatically on exit.

Filesystem access is sandboxed to the directory you run linus from — the model cannot read or write anything outside it.

Run it from anywhere

printf '#!/bin/sh\nexec "%s/.venv/bin/python" -m agent_cli.main "$@"\n' "$PWD" > ~/.local/bin/linus
chmod +x ~/.local/bin/linus
mkdir -p ~/.agent-cli && cp .env ~/.agent-cli/.env   # global API key

Then linus works in any directory, with its file tools scoped to that directory. A .env in the current directory overrides the global one (per-project keys/models).

Adding a tool

Drop a file in agent_cli/tools/ (or ~/.agent-cli/tools/ for personal tools — no reinstall needed):

# ~/.agent-cli/tools/weather.py
from agent_cli.tools.base import tool

@tool  # add requires_confirmation=True for side-effectful tools
def get_weather(city: str) -> str:
    """Get the current weather for a city.

    Args:
        city: City name.
    """
    return "sunny, 24°C"

That's it — the schema the model sees is generated from the type hints and docstring, and the file is auto-discovered at startup.

Project memory & context management

Linus manages long sessions the way Claude Code / Codex do:

  • Project memory file — drop a LINUS.md (or AGENTS.md / CLAUDE.md) in your repo with conventions, build commands, and facts. It's found automatically (searching up to the git root) and injected into every session's system prompt.
  • Auto-summarization — when the conversation exceeds a token budget (context_token_budget, default ~16k), older turns are condensed into a summary so per-request cost stays bounded. It cuts only at turn boundaries, so tool-call/result pairs are never split.
  • Subagentsrun_subagent(task) (code mode) delegates broad exploration to an isolated read-only agent that returns just its findings, so the many files it reads never enter the main context.

Two related savers from before: duplicate file reads keep only their newest copy in context, and a call repeated 3× is refused so weak models can't loop.

Prompt caching isn't something linus can enable on the free NVIDIA tier — NIM doesn't expose it. Some OpenRouter models cache automatically server-side (e.g. DeepSeek); linus keeps its system prefix stable across turns so those models benefit where supported, but there's no client-side knob to add.

Configuration

Environment (or .env): NVIDIA_API_KEY, OPENROUTER_API_KEY, DATABASE_URL, AGENT_CHAT_MODEL. In the TUI, /model shows separate NVIDIA and OpenRouter categories. For a direct CLI override, prefix an OpenRouter ID with openrouter:.

Optional ~/.agent-cli/config.toml:

chat_model = "qwen/qwen3-coder-480b-a35b-instruct"
embedding_model = "nvidia/llama-3.2-nv-embedqa-1b-v2"
max_tool_iterations = 10
recall_snippets = 3

Free catalogs rotate over time — run linus models to see what your keys can use and switch with /model or config.

Development

.venv/bin/pip install -e ".[dev]"
.venv/bin/pytest tests/

Architecture

  • agent_cli/agent.py — UI-agnostic async agent loop; yields typed events (TextDelta, ToolCallStarted, …). The TUI and one-shot printer are two consumers of the same stream.
  • agent_cli/tui/ — Textual app. All LLM/tool/DB work runs off the UI event loop, so the input never freezes.
  • agent_cli/memory.py — best-effort memory: if Postgres is down or embedding fails, the CLI warns once and keeps working without recall.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

linus_cli-0.1.0.tar.gz (86.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

linus_cli-0.1.0-py3-none-any.whl (80.4 kB view details)

Uploaded Python 3

File details

Details for the file linus_cli-0.1.0.tar.gz.

File metadata

  • Download URL: linus_cli-0.1.0.tar.gz
  • Upload date:
  • Size: 86.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for linus_cli-0.1.0.tar.gz
Algorithm Hash digest
SHA256 72618d8d3403bec56581b44ae3808e629ed150060d061e5d3ed9fd5d80da5a72
MD5 bf2715e3c86e88861f45a3961e8b8a8c
BLAKE2b-256 6e015fd7368d24317fc9b4364f1c8b8ff58782d7c32b6824489f38ef35441b8e

See more details on using hashes here.

File details

Details for the file linus_cli-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: linus_cli-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 80.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for linus_cli-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2a8e94d69deec8d04fd35d3ab0da8d8c7c6ac7dac4bfbb543bc73ff7e2d46896
MD5 551bcc42483ef77e6a9c56a8eae5001d
BLAKE2b-256 c73f7bc8e5c737490309d75db5bd50eb096c76b12a5174452de4bdef7f5e89db

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page