Native Rust CLI/runtime for DeepSeek Harness workflows with DeepSeek, OpenAI, Codex, async libSQL/Turso, tools, TUI, and stdio compatibility.
  • Rust 99.6%
  • Nix 0.4%
Find a file
2026-08-27 23:11:48 -07:00
docs feat(runtime): add local session infrastructure 2026-08-27 23:11:48 -07:00
src feat(runtime): add local session infrastructure 2026-08-27 23:11:48 -07:00
.envrc feat: initialize harness-rs CLI foundation 2026-08-21 18:12:24 -07:00
.gitignore feat: initialize harness-rs CLI foundation 2026-08-21 18:12:24 -07:00
AGENTS.md refactor: define application module boundaries 2026-08-21 18:17:05 -07:00
Cargo.lock feat(runtime): add local session infrastructure 2026-08-27 23:11:48 -07:00
Cargo.toml feat(runtime): add local session infrastructure 2026-08-27 23:11:48 -07:00
CLAUDE.md refactor: define application module boundaries 2026-08-21 18:17:05 -07:00
flake.lock feat: initialize harness-rs CLI foundation 2026-08-21 18:12:24 -07:00
flake.nix refactor: define application module boundaries 2026-08-21 18:17:05 -07:00
QUICKSTART.md feat(runtime): add local session infrastructure 2026-08-27 23:11:48 -07:00
README.md feat(runtime): add local session infrastructure 2026-08-27 23:11:48 -07:00

harness-rs

Native Rust CLI/runtime for terminal-first agent harness workflows.

harness-rs combines:

  • a Ratatui/Crossterm chat TUI over typed session events
  • OpenAI and OpenAI-compatible provider integration
  • local-first libSQL/Turso session storage
  • JSON-RPC stdio tools for editor and agent integration
  • safe read-only workspace and host-inspection tools
  • microVM-first execution contracts for mutating or shell-driven work
  • reproducible Nix development and package outputs

Project Status

harness-rs is early foundation software. The CLI, TUI, local persistence, OpenAI-compatible streaming, read-only tools, stdio server, and execution policy contracts are usable. The Firecracker microVM runner is intentionally fail-closed until kernel/rootfs images and the guest runner are implemented.

For current handoff notes, remaining work, and the Linear project link, see docs/handoff.md.

Use the read-only tools today for repository and local file inspection. Treat mutating execution and arbitrary shell work as roadmap items unless you are working on the execution backend itself.

Quick Start

If you are setting up another system, start with QUICKSTART.md.

git clone https://forgejo.kennysheridan.io/kennysheridan/harness-rs.git
cd harness-rs

nix develop
cargo run -- init
cargo run -- config
cargo run -- chat

Without an OpenAI key, provider = auto falls back to the local mock adapter so the CLI, TUI, and persistence path remain testable.

To use OpenAI or an OpenAI-compatible endpoint:

export OPENAI_API_KEY="<token>"
export OPENAI_MODEL="gpt-4o-mini" # optional
cargo run -- run "summarize this repository"

Common commands:

cargo run -- --help
cargo run -- init
cargo run -- config
cargo run -- doctor execution
cargo run -- run "hello"
cargo run -- chat
cargo run -- serve --stdio
cargo run -- skills list

Setup

Requirements

  • Linux or macOS for development; Linux is the primary target for execution isolation.
  • Nix with flakes enabled for the recommended reproducible setup.
  • Git to clone the repository.
  • OpenAI API key only if you want real provider calls.
  • Rust stable if you are not using Nix.
nix develop
cargo fmt
cargo clippy --all-targets --all-features
cargo test --all-targets --all-features

The flake provides stable Rust with rustfmt, clippy, and rust-src, plus native dependency tooling such as pkg-config, openssl, clang, cmake, sqlite, ripgrep, jq, and contributor tools.

You can also run or build directly from the flake:

nix run
nix build
nix flake check

Non-Nix Setup

Use this only when Nix is not available:

rustup toolchain install stable
rustup component add rustfmt clippy rust-src

cargo build
cargo test --all-targets --all-features
cargo run -- --help

Install native dependencies through your platform package manager if Cargo build scripts report missing OpenSSL, libclang, SQLite, CMake, or pkg-config.

Configuration

harness-rs init creates .harness-rs/config.toml if it does not already exist:

[provider]
name = "auto"

[provider.openai]
base_url = "https://api.openai.com/v1"
model = "gpt-4o-mini"
api_key_env = "OPENAI_API_KEY"

[storage]
# Existing local databases continue to use libSQL by default.
local_backend = "libsql-local"

[tools.web]
# Explicit host-side HTTPS fetch capability; disabled by default.
enabled = false
timeout_seconds = 15
max_response_bytes = 1048576

[tools.todo]
# Optional explicit Markdown root. Disabled when omitted.
# root = "/absolute/path/to/Obsidian/Harness-RS"

[execution]
backend = "microvm"

[execution.microvm]
provider = "firecracker"
network_enabled = false
workspace_writable_overlay = false
timeout_seconds = 120
memory_mib = 2048
vcpus = 2

Environment variables override TOML provider values for one-off runs:

export HARNESS_RS_PROVIDER=openai
export OPENAI_BASE_URL="https://api.openai.com/v1"
export OPENAI_MODEL="gpt-4o-mini"
export OPENAI_API_KEY="<token>"

harness-rs config reports the selected provider, model, endpoint, store, and execution policy without printing secret values.

Obsidian todos

Set [tools.todo].root to one explicit Markdown directory to enable the read-only todo index. The scanner does not search home directories, follows no symlinks, ignores hidden app metadata and non-Markdown files, and applies fixed depth, file, task, file-size, and line-size limits. It recognizes - [ ], - [/], and - [x] tasks. The compact TUI sidebar prioritizes in-progress and current-focus work, reports pending and in-progress counts, and Ctrl-R refreshes it; the stdio tool/todo_list tool is advertised only while this root is configured. It returns source-relative path, line number, opaque task ID, normalized text, and status only. The model may use todo_update only in the interactive TUI, with this indexed reference and pending, in_progress, or completed. Every update is revalidated against a fresh bounded index and requires Allow once or Allow always (this project). The latter persists only the todo_update permission in .harness-rs/permissions.json. Stdio rejects this write tool because it cannot approve concurrently.

Remote Session Store

Local state defaults to .harness-rs/harness.db. To use remote Turso/libSQL, set both variables before init, chat, run, or serve --stdio:

export LIBSQL_URL="libsql://<database>.turso.io"
export LIBSQL_AUTH_TOKEN="<token>"
cargo run -- init

LIBSQL_AUTH_TOKEN is required when LIBSQL_URL is set and is never printed by harness-rs config.

Local Turso preview and compatibility canary

[storage].local_backend explicitly selects the local engine. It defaults to libsql-local; turso-local is an opt-in S1/S2 preview that supports init and schema migrations only. Session writes continue to require libsql-local until the adapter is promoted. Remote LIBSQL_URL storage always uses libSQL; combining it with turso-local, or supplying only one remote environment variable, is rejected. turso-local refuses an existing unmarked file; a fresh file receives a sibling .turso-local marker so switching config cannot open a libSQL file in place.

Do not point both engines at one database file. Before trying Turso with a copied, stopped and checkpointed local libSQL database, run:

cargo run -- storage canary --source .harness-rs/harness.db \
  --destination .harness-rs/harness.turso-canary.db

The command refuses to overwrite a destination, reads the source only through libSQL, copies it, then opens only the copy with Turso. Its JSON report includes integrity checks, schema/index comparison, table counts, and migration idempotency. Preserve the original file and rollback by setting local_backend = "libsql-local"; never convert or migrate an active file in place.

Skills

Local skills live under .harness-rs/skills and are not committed by default. Import OpenCode-compatible skills from another machine with:

cargo run -- skills import ~/.config/opencode/skills
cargo run -- skills list

Verifying Installation

Run these checks on a fresh system:

cargo run -- --help
cargo run -- init
cargo run -- config
cargo run -- run "hello from harness-rs"
cargo run -- skills list

With an OpenAI key configured, verify provider streaming and tools:

cargo run -- run "List the top-level files in this repository."
cargo run -- chat

Inside the TUI, try:

/mcp
/models
/files
/largest ~/Downloads 10
/copy last

TUI Usage

cargo run -- chat starts the Ratatui/Crossterm interface.

Key bindings:

  • Enter submits the prompt.
  • Shift-Enter inserts a newline when supported by the terminal.
  • Ctrl-E edits the prompt in $VISUAL, $EDITOR, or nvim.
  • Ctrl-P opens the command palette.
  • Ctrl-B selects a sidebar category; Enter or Space expands or collapses it.
  • Ctrl-T expands or collapses the safe Activity sidebar category.
  • Ctrl-Shift-T switches Activity between compact and bounded sanitized detail views.
  • Ctrl-Y yanks the selected or latest message via OSC52.
  • Esc or Ctrl-C exits.

Useful slash commands:

  • /models or /model opens the searchable model picker.
  • /model <id> switches directly to an OpenAI-compatible model id.
  • /session [id|name], /sessions, /new [name], /rename <name>, and /reset manage sessions.
  • /tokens and /compact show context usage and compact long transcripts.
  • /theme [opencode|midnight|solarized|mono] shows or switches transcript themes.
  • /copy [message-number|last|assistant|user|system|activity|all] yanks transcript content.
  • /mouse [on|off] chooses normal terminal selection or mouse-driven select/right-click yanking.
  • /skills browses imported local skills.
  • /mcp shows runtime metadata, workspace tools, Linux tool availability, and execution policy.
  • /files [path], /read <path>, and /search <text> inspect the workspace safely.
  • /largest [path] [limit] lists the largest regular files under approved user directories.

Tools And Execution

Built-in model tools include:

  • runtime_info for provider, model, cwd, OS/arch, and execution policy metadata.
  • workspace_files for bounded file listing under the configured workspace.
  • workspace_read for bounded reads of workspace files.
  • workspace_search for literal text search with line numbers.
  • linux_exec for argv-only allowlisted read-only commands such as uname, date, pwd, id, selected git inspection commands, and --version checks.
  • host_largest_files for bounded read-only metadata scans under approved user directories such as ~, HOME, $HOME, or ~/Downloads.
  • web_fetch for bounded text fetches from public HTTPS hosts, only when [tools.web].enabled = true.

Workspace paths are confined to --cwd; absolute paths and .. traversal are rejected. Listing and search skip .git, .harness-rs, .agentbrain, .direnv, target, result, and result-*.

Secure Execution

harness-rs treats model-driven execution as a security boundary. Read-only context tools run in-process only when they are path-confined and output-bounded. Read-only Linux inspection runs without a shell through a strict argv allowlist. Web access is a separate, explicit host capability: it is disabled by default and does not depend on or change microVM networking. When enabled, web_fetch allows one HTTPS URL, rejects credentials, localhost, literal IPs, and non-public DNS answers, and manually follows up to four redirects after revalidating and pinning each target. It returns bounded final-URL text without response headers.

Mutating tools, arbitrary shell execution, package installs, tests, generated code execution, and networked execution route through the execution policy. The default backend is microvm, oriented around Firecracker, with network disabled and workspace writes disabled by default. The runner fails closed until images are configured.

See docs/security-execution.md for the detailed architecture and rollout plan. Use cargo run -- doctor execution and docs/microvm-sandboxing.md when bringing up the Firecracker sandbox on a new host.

Stdio Integration

harness-rs serve --stdio exposes newline-delimited JSON-RPC over stdin/stdout.

Example request:

{"jsonrpc":"2.0","id":1,"method":"runtime/status","params":{}}

Available methods include runtime/config/status methods, tools/list, tool/runtime_info, tool/workspace_files, tool/workspace_read, tool/workspace_search, tool/linux_exec, tool/host_largest_files, and tool/web_fetch, and session/prompt. tools/list reports whether web fetch is enabled; calls fail closed while it is disabled.

Project Layout

The project is currently a single Cargo package with explicit module seams:

Module Purpose
app application orchestration and command dispatch
cli command-line parsing
commands slash-command metadata and parser
config configuration discovery, defaults, and validation
execution microVM-first execution contracts and policy types
llm OpenAI-compatible provider and tool-call adapter
protocol typed session and JSON-RPC protocol models
runtime_tools bounded host/runtime inspection tools
session session lifecycle and event streams
skills local skill discovery and import
stdio JSON-RPC stdio server
store async libSQL/Turso persistence
tools path-confined workspace tools
tui Ratatui/Crossterm chat UI

These boundaries can split into workspace crates once the codebase is large enough to justify it.

Documentation

Development

nix develop
cargo fmt
cargo clippy --all-targets --all-features
cargo test --all-targets --all-features
cargo run -- --help

With direnv:

direnv allow

Release-impacting commits should use release-please-compatible Conventional Commits, for example feat(tui): add message copy affordances or fix(runtime): preserve stdio request ids.

Design References

harness-rs borrows Rust systems-design lessons from projects like cuda-oxide: clear boundaries, typed low-level contracts, fail-closed runtime checks, reproducible tooling, and direct verification commands. It does not take a CUDA dependency unless a future GPU-specific harness tool requires one.