Files
codecraft/README.md
T
Richard ZinkandClaude Opus 5.5 5b569b6835 Add security hardening, Ghidra, recreate skill, checkpoints, shells, web search and themes
- Sandbox (bubblewrap) for non-admin shell/git, MCP per-user rights, hard budgets and quotas,
  login rate limiting, audit log and backups
- Ghidra headless decompilation (ARM64 natives built from source), binary_info tool,
  clean room / deep workflow per session
- Recreate skill and commands for analysing and re-building old software
- File checkpoints with rewind/restore, background shells (bash_output, kill_shell)
- web_search tool (DuckDuckGo, SearXNG, Brave, Tavily)
- In-app dialogs and toasts instead of browser dialogs
- 15 base themes (trilium-themes palettes plus Nord, VS Code, GitHub, Catppuccin, One,
  Dracula, Rose Pine, Everforest, Kanagawa) with light/dark/auto switcher and license notes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 19:12:30 +01:00

257 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<p align="center">
<img src="web/public/icon.svg" width="112" height="112" alt="CodeCraft icon: angle brackets with a slash on a dark tile">
</p>
<h1 align="center">CodeCraft</h1>
<p align="center">
<b>A self-hosted coding agent for your browser: any model, your tools, your rules.</b><br>
Run Claude, Gemini, opencode Go, fal.ai or your own models as coding agents with files, shell, MCP and subagents,<br>
approve what they do from any device, and see exactly what every request costs.
</p>
<p align="center">
<img alt="Rust backend" src="https://img.shields.io/badge/backend-Rust-b7410e?style=flat-square&logo=rust">
<img alt="React PWA" src="https://img.shields.io/badge/frontend-React%20PWA-2d81ff?style=flat-square&logo=react">
<img alt="Docker" src="https://img.shields.io/badge/deploy-Docker-1d63ed?style=flat-square&logo=docker&logoColor=white">
<img alt="Status: early alpha" src="https://img.shields.io/badge/status-early%20alpha-d69e2e?style=flat-square">
</p>
<p align="center">
<a href="#how-it-works">How it works</a> ·
<a href="#modes">Modes</a> ·
<a href="#models">Models</a> ·
<a href="#users">Users</a> ·
<a href="#statistics">Statistics</a> ·
<a href="#get-started">Get started</a> ·
<a href="#configuration">Configuration</a> ·
<a href="#themes">Themes</a> ·
<a href="#development">Development</a> ·
<a href="#status">Status</a>
</p>
<br>
<p align="center">
<img src="docs/images/chat.png" alt="A CodeCraft session: the agent edits a file, a permission card shows the diff and asks before running a command, the task list shows what is left" width="100%">
<br>
<sub>A session: the agent works through its task list, shows diffs, and asks before anything outside the rules.</sub>
</p>
<table>
<tr>
<td width="25%" valign="top">
<h3>🧠 Any model</h3>
Anthropic natively, plus everything that speaks the OpenAI API: Gemini, opencode Go, fal.ai, OpenRouter, Ollama, vLLM, llama.cpp. Mix them in one chat.
</td>
<td width="25%" valign="top">
<h3>🛠️ Real tools</h3>
Read, write, edit, glob, grep, shell, web fetch, task lists, subagents, skills – and every tool of your MCP servers.
</td>
<td width="25%" valign="top">
<h3>🙋 You decide</h3>
Permission requests with diffs, questions from agents and MCP servers, per-tool rules. On your phone, with notifications.
</td>
<td width="25%" valign="top">
<h3>📊 Every token counted</h3>
Tokens, cache hits, prefill and output speed, and cost per request – per chat and in a dashboard.
</td>
</tr>
</table>
<br>
## How it works
CodeCraft runs on your server, next to your projects. You talk to it from a browser or the
installed app; the agent keeps working when you close the tab.
1. **Pick a folder and a mode.** Every user has their own folder; admins can share more.
2. **Say what you want.** The agent plans with a task list, reads the code and makes changes.
3. **Approve or answer.** Anything outside your rules shows up as a card: allow once, allow
for the session, or reject with feedback. Questions from agents and MCP servers too.
4. **Delegate.** The agent hands work to subagents – in parallel or in the background, on
other models and hosts – and continues while they run.
<table>
<tr>
<td width="50%" valign="top">
<img src="docs/images/mobile.png" alt="CodeCraft on a phone: a session with a question card offering three options" width="100%"><br>
<sub><b>Mobile:</b> answer questions and approve changes from your phone.</sub>
</td>
<td width="50%" valign="top">
<img src="docs/images/settings.png" alt="Settings: providers with models, context sizes and prices per million tokens" width="100%"><br>
<sub><b>Settings:</b> providers, models, prices, MCP, permissions and users – all in the UI.</sub>
</td>
</tr>
</table>
## Modes
| Mode | What it does |
|---|---|
| **build** | Full access: implement, edit, run. |
| **plan** | Read-only: investigate, ask, and propose a step-by-step plan. One click switches to build. |
| **craft** | Study a target, build your own version, check it visually, refine. Websites are captured at several screen widths in a headless browser and compared with the build (similarity per page and width). *Clean room* uses only what a visitor sees; *deep mode* may read the page source. |
| *custom* | Your own modes and subagents – in the UI, the config file or as Markdown in `.codecraft/agents` / `.claude/agents`. |
Projects keep working the way they do in Claude Code and opencode: `AGENTS.md`, `CLAUDE.md`,
slash commands in `.claude/commands` and skills in `.claude/skills` are picked up automatically.
## Models
Every provider is an endpoint with a list of models. Each model can have a context size,
output limit, reasoning effort, extra request options and prices per million tokens.
- **Several models per chat:** switch the model at any time, give modes a fixed model, and
run subagents on other models – e.g. a coding model on one GPU host and a small model that
writes documentation and translations in the background on another.
- **Concurrency limits:** `max_concurrency` per host or model queues requests for servers that
can only process one at a time; `max_parallel` limits instances of a subagent. Waiting time
is shown in the chat and never counted as model latency.
- **Background subagents:** the agent starts them with `background = true`, keeps working,
and receives their result as a message when they finish.
## Users
- Local accounts (Argon2 passwords) and single sign-on via OpenID Connect (Authentik, Authelia,
Keycloak, …) with optional admin and access groups.
- **Admins** manage providers, MCP, permissions, users and shared folders and see all statistics.
**Users** see their own sessions and statistics.
- Every user works in `<workspace>/<username>`; admins can share additional folders with
selected users. Sessions are private and can be shared read-only.
> [!NOTE]
> File tools are confined to a user's folders. Shell commands run in the shared container and
> are **not** sandboxed per user – only give accounts to people you trust with that container.
## Statistics
<p align="center">
<img src="docs/images/stats.png" alt="The statistics dashboard: cost and token tiles, cost per day stacked by model, tokens per day, and an activity heatmap by weekday and hour" width="100%">
</p>
Every model request is stored with input, output and cache tokens, time to first token,
prefill and output speed, and its cost at the price configured at that moment. The dashboard
shows totals, cost per day by model, tokens per day, a weekday × hour heatmap, and tables per
model, provider, mode, user and session – each chart also as a table.
## Get started
```sh
git clone <this repository> codecraft && cd codecraft
cp .env.example .env # workspace path, provider keys, optional first admin
docker compose up -d --build
docker compose logs codecraft # shows the one-time setup code for the first admin
```
All state – configuration, database, the agent's home directory – lives in the Docker volume
`codecraft-data`; rebuilding or recreating the container keeps it. Your projects are mounted
from `WORKSPACE`.
The port is bound to `127.0.0.1` by default. Put a TLS reverse proxy in front of it (enable
WebSocket support) and set `auth.public_url` – installing the PWA requires HTTPS.
## Configuration
One commented TOML file, `/data/config.toml` in the volume, created from
[`config.example.toml`](config.example.toml) on first start. The settings page edits it in
place and keeps your comments. Secrets belong in the environment and are referenced as
`${NAME}`.
| Section | Purpose |
|---|---|
| `[server]` | workspace, default and small model, currency, auto-compaction, subagent limit |
| `[providers.<name>]` | `kind = "anthropic" \| "openai"`, `base_url`, `api_key`, `max_concurrency`, `models` |
| `[mcp.<name>]` | `type = "stdio"` (command, args, env) or `"http"` (url, headers) |
| `[permissions]` | `allow` / `ask` / `deny` per tool (globs like `mcp__*`); `bash_rules` for commands |
| `[agents.<name>]` | modes and subagents: model, tools, `max_parallel`, prompt |
| `[auth]`, `[auth.oidc]` | sign-in, public URL, single sign-on |
| `[craft]` | headless browser, screen widths, clean room |
Compound shell commands (`&&`, `;`, `|`) are only auto-allowed when every part is allowed.
## Themes
Pick a **base theme** in *Settings → Interface* and switch **light / dark / auto** there or with
the ◐ button in the sidebar (auto follows the system preference). Every base theme has a dark and
a light variant. The palettes come from [zink/trilium-themes](https://git.familie-zink.org/zink/trilium-themes)
(MIT, see [`web/src/themes/LICENSE-trilium-themes`](web/src/themes/LICENSE-trilium-themes)), which
in turn are based on:
| Theme | Variants | Palette source | License |
|---|---|---|---|
| Gruvbox | Dark, Light | [morhetz/gruvbox](https://github.com/morhetz/gruvbox) | MIT |
| Ash | Dark, Light | original, Gruvbox-derived ([zink/trilium-themes](https://git.familie-zink.org/zink/trilium-themes)) | MIT |
| Harbor | Dark, Light | [HANCORE-linux/omarchy-harbordark-theme](https://github.com/HANCORE-linux/omarchy-harbordark-theme) | MIT |
| Coffee | Dark, Latte | [megabyte0x/omarchy-coffee-theme](https://github.com/megabyte0x/omarchy-coffee-theme) | MIT |
| Solarized | Dark, Light | [Solarized by Ethan Schoonover](https://ethanschoonover.com/solarized/) | MIT |
| Tokyo Night | Night, Day | [folke/tokyonight.nvim](https://github.com/folke/tokyonight.nvim) | Apache-2.0 |
Further standard themes (palettes re-created from the published colour specifications):
| Theme | Variants | Palette source | License |
|---|---|---|---|
| Nord | Dark, Light (Snow Storm background) | [nordtheme/nord](https://github.com/nordtheme/nord) | MIT |
| VS Code | Dark Modern, Light Modern | [microsoft/vscode](https://github.com/microsoft/vscode) | MIT |
| GitHub | Dark, Light | [primer/github-vscode-theme](https://github.com/primer/github-vscode-theme) | MIT |
| Catppuccin | Mocha, Latte | [catppuccin/catppuccin](https://github.com/catppuccin/catppuccin) | MIT |
| One | One Dark, One Light | [atom/atom](https://github.com/atom/atom) | MIT |
| Dracula | Dracula, Alucard | [dracula/dracula-theme](https://github.com/dracula/dracula-theme) | MIT |
| Rosé Pine | Main, Dawn | [rose-pine/rose-pine-theme](https://github.com/rose-pine/rose-pine-theme) | MIT |
| Everforest | Dark, Light | [sainnhe/everforest](https://github.com/sainnhe/everforest) | MIT |
| Kanagawa | Wave, Lotus | [rebelot/kanagawa.nvim](https://github.com/rebelot/kanagawa.nvim) | MIT |
Colours, syntax highlighting and chart palettes come from CSS variables, one file per variant in
[`web/src/themes`](web/src/themes). To add a base theme `<id>`:
1. Copy `gruvbox-dark.css` / `gruvbox-light.css` to `<id>-dark.css` / `<id>-light.css` and change
the values on `:root[data-theme="<id>-dark"]` / `"<id>-light"`; note source and license in the header.
2. Import both in `themes/index.ts` and add the base theme to `THEMES` in `web/src/theme.ts`.
The variables cover surfaces (`--bg0`–`--bg3`), text (`--fg0`–`--fg3`, `--muted`), accents,
diffs, syntax (`--syntax-*`) and the browser bar colour (`--theme-color`). The chart palettes
(`--series-1`–`8` categorical, `--seq-1`–`6` sequential) live in `themes/base.css` per light/dark
mode and are validated for colour-vision deficiencies.
## Development
Requirements: Rust (edition 2024) and Node ≥ 20.19.
```sh
# backend – writes ./data/config.toml on first start
cd server && CODECRAFT_CONFIG=../data/config.toml cargo run
# frontend with hot reload, proxies /api to 127.0.0.1:8787
cd web && npm install && npm run dev
```
Tests: `cd server && cargo test` · type check: `cd web && npx tsc --noEmit`.
```
server/ Rust (axum, tokio)
runner.rs agent loop: streaming, tools, permissions, subagents, compaction
provider/ Anthropic and OpenAI-compatible streaming clients, concurrency slots
tools/ built-in tools (files, shell, web, agent, craft)
mcp.rs MCP client (stdio, Streamable HTTP, elicitation)
auth.rs users, sessions, OpenID Connect
prompts.rs modes, system prompt, AGENTS.md, commands, skills
web/ React + Vite PWA
src/components chat, composer, cards, settings, statistics
src/themes CSS themes
src/i18n English (reference) and German
```
Translations: copy `web/src/i18n/en.ts`, translate the values and register the language in
`web/src/i18n/index.ts` – the type checker reports missing keys.
## Status
Early alpha. Planned next:
- Per-user sandboxes for shell commands
- File checkpoints and undo, background shells, `@file` mentions
- MCP OAuth, resources and prompts
- Hooks before/after tool calls
- Image generation tools (fal.ai) and the OpenAI Responses API