Skip to content
therezorPublic

About

A self-hosted AI agent in one Rust binary: a web UI, local models, and every tool call in a container you own.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

87 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

██████╗  █████╗ ██████╗ ██╗  ██╗██╗    ██╗██╗██████╗ ███████╗
██╔══██╗██╔══██╗██╔══██╗██║ ██╔╝██║    ██║██║██╔══██╗██╔════╝
██║  ██║███████║██████╔╝█████╔╝ ██║ █╗ ██║██║██████╔╝█████╗
██║  ██║██╔══██║██╔══██╗██╔═██╗ ██║███╗██║██║██╔══██╗██╔══╝
██████╔╝██║  ██║██║  ██║██║  ██╗╚███╔███╔╝██║██║  ██║███████╗
╚═════╝ ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═╝ ╚══╝╚══╝ ╚═╝╚═╝  ╚═╝╚══════╝

DarkWire

Your models. Your machine. Your wire.

An agent with a real shell and real file tools, running local models on your own hardware — Ollama, LM Studio, llama.cpp, vLLM.
Cloud providers are opt-in, not assumed.

licence install build telemetry runs release

curl -fsSL https://raw.githubusercontent.com/therezor/darkwire/main/install.sh | sh
darkwire serve

Prints a URL and a one-time code. Open it, pick a model — done.
One binary, browser UI compiled in. No runtime, no package manager, nothing to install alongside it.

Want more than one agent? Make them in Agents: a system prompt, the tools each may call, the container each runs in, and which of the others it may hand work to.

Get started · Docs · Security

A terminal recording: darkwire chat is launched, asked what is in the workspace, calls the ls tool, and streams back an answer with a code block — finishing in 2 steps.
DarkWire's chat view: a streaming answer with a highlighted code block, the session sidebar, and the context budget under the composer.

What it does

Acts Reads files, edits them, runs commands, browses the web from a sandbox.
Four ways in Browser, terminal, REST API, Telegram. Same conversations, same database.
Remembers Plain markdown in your project, which you read, edit and commit.

Built for long, tool-heavy work on infrastructure you control — recon and pen-test runs, codebase surgery, research sweeps, scheduled chores.

Why DarkWire

  • You hold every key. Permission is per tool, per agent — allow | ask | deny — and a tool absent from the map is not refused at call time, it is never offered to the model at all. Nothing is granted implicitly, ever.
  • A small prompt is a fast prompt. On a local model the prompt is not a bill, it is wall-clock: whatever changed since the last step gets re-processed before the first token comes back, and one tool-using turn is five or ten requests over the same history. So the volatile half of the prompt is kept tiny, tool registry entries are rebuilt once per turn rather than once per step, and exec reaches every program in a container from one ~40 token schema where a tool per program costs 60–80 each, per request.
  • Nothing leaves the box. A repo-wide grep for telemetry|analytics|posthog|sentry|mixpanel returns exactly one hit — the test that forbids them. Binds 127.0.0.1; a public bind with auth off refuses to start.
  • No hidden preamble. All eight prompt templates are yours to edit, and systemPrompt replaces the built-in text rather than being bolted underneath something you cannot see.
  • Security you can audit in an afternoon. Every guard lives in one package behind a 95% coverage gate, each explaining the attack it closes and why the obvious approach fails.

The competition

  • More private than ChatGPT — nothing leaves the box. Zero telemetry, and fully offline against Ollama.
  • More contained than Claude Code — exec runs in a digest-pinned container, caps dropped, egress default-deny unless the agent asks for more.
  • Leaner on tokens than OpenClaw — one exec schema reaches every program in the container, in ~40 tokens, where a tool per program costs 60–80 each, per request.

See it

A tool call, expanded

A ls tool card, expanded to show the files it returned.

An approval, before anything runs

An approval prompt for exec, showing the argv it would run, with Once, This session and Deny.

Where the context window went

The context inspector, breaking a session's token usage into system prompt, tool registry entries, session and live state.

The workspace, browsable and editable

The file browser, listing the workspace tree.

More in Web UI. Generated from the real app, not staged.

Loadout

Skills A folder in the workspace. The agent opens the sheet when it applies; ~20 tokens to index.
Memory One markdown file per topic, read and written by key, committed beside the project.
Environments Bound the blast radius. exec runs in a digest-pinned container with caps dropped and root read-only, and no image, capability or uid an agent's config could reach.
MCP servers stdio, Streamable HTTP or SSE, with OAuth. Each agent picks which of their tools it may call.
Extensions Tools, channels, providers, prompt sections, commands. Approval is a digest over every byte.
Subagents One agent hands work to another as an ask_<id> tool.
Telegram The same sessions from a phone. Answers only the ids you list.
Scheduled jobs Cron and one-shot. A heartbeat is a job, not a second system.
REST + WebSocket One port, with an OpenAPI 3.1 doc generated from the schemas the server validates against.

Security

Assume the model is compromised.

It reads web pages, command output and files an attacker may have written. Everything it asks for is an untrusted request.

Guard What it stops
Workspace jail Path traversal. /etc/passwd addresses <workspace>/etc/passwd; paths are rebuilt, then realpath'd.
Argv-only exec Command injection. The argv vector is spawned directly — no shell, so no string to interpret.
Environments Blast radius. exec runs in a digest-pinned container whose definition fixes caps, user and network.
Per-tool permission An agent doing what you did not enable. Absent means not enabled; ask shows you the arguments first.
guardedFetch SSRF and DNS rebinding. Resolved addresses are pinned into the dispatcher — no second lookup to differ. Every web_fetch and web_search request goes through it.
Nonce fencing Prompt injection. Every tool result is fenced with a fresh per-turn nonce, and the model is told it is data.
Credential vault Key theft at rest. AES-256-GCM, 0600, key in the OS keychain. Nothing reads a credential back out over HTTP.
Auth Guessing. argon2id, and two asymmetric throttle scopes so a botnet cannot spread its attempts out.

Security states each guard's limits — including the one that matters: a workspace is an organisational boundary, not a security boundary, wherever host exec is enabled. That is what containers are for. SECURITY.md is how to report a vulnerability.

What is not built yet

The schemas and seams ship; the implementations do not, and nothing in the UI advertises them — a settings screen naming a feature you cannot open is one an operator checks twice.

Feature Ships today Missing
Heartbeat delivery The decide/run/evaluate triad, as a scheduled job's payload targets reaching a channel
Session search Keyset pagination and filters Text search over message content

Two smaller ones, so nothing here reads as more finished than it is: only the openai-chat wire adapter ships, so the one registry entry naming another wire — anthropic — is refused at construction rather than falling back, and reaching it today means an endpoint that speaks openai-chat or an extension that contributes the wire; and the translation layer is complete while English is the only shipped locale — adding one is a folder plus a line.


Docs

Getting started · CLI · Configuration · Prompts · Providers · Tools & permissions · Skills · Memory · Environments · Extensions · Web UI · API · Architecture · Security · Development

Contributing

pnpm check runs the first CI job. CONTRIBUTING.md has the other three, Development the reasoning behind them.

Running from source
git clone https://github.com/therezor/darkwire.git
cd DarkWire
pnpm install
pnpm build                                  # the web bundle the binary embeds
cargo build --release -p darkwire            # → target/release/darkwire

Needs pnpm 11 (corepack enable) and rustup; the compiler version is pinned in rust-toolchain.toml. pnpm build is not optional — rust-embed compiles packages/web/dist into the binary, so a missing bundle is a compile error rather than a server that comes up without a UI.

License

MIT

About

A self-hosted AI agent in one Rust binary: a web UI, local models, and every tool call in a container you own.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages