Release 0.1.0: MIT license, changelog, multi-arch Docker image without CLI builds
- LICENSE (MIT), CHANGELOG for 0.1.0, README overhaul - docker-compose.release.yml pulling the registry image - Dockerfile cross-compiles the server with cargo-zigbuild for amd64 and arm64; the terminal client is no longer built into the image - Server, install script and settings point to a source install of the terminal client when no prebuilt binaries are available (/info: cli_builds) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d14c609576
commit
ed9942829a
15 files changed
+384
-109
No files matched your search
@@ -5,35 +5,38 @@
|
||||
<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.
|
||||
<b>A self-hosted coding agent for your browser and terminal: any model, your tools, your rules.</b><br>
|
||||
Run Claude, Gemini, OpenRouter, opencode or your own models as coding agents with files, shell, MCP and subagents,<br>
|
||||
approve what they do from any device, automate recurring work, and see exactly what every request costs.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img alt="Version 0.1.0" src="https://img.shields.io/badge/version-0.1.0-d69e2e?style=flat-square">
|
||||
<img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-689d6a?style=flat-square">
|
||||
<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">
|
||||
<img alt="Docker: amd64 and arm64" src="https://img.shields.io/badge/docker-amd64%20%7C%20arm64-1d63ed?style=flat-square&logo=docker&logoColor=white">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#install">Install</a> ·
|
||||
<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="#terminal-client">Terminal client</a> ·
|
||||
<a href="#automations">Automations</a> ·
|
||||
<a href="#integrations">Integrations</a> ·
|
||||
<a href="#users-and-security">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>
|
||||
<a href="#development">Development</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%">
|
||||
<img src="docs/images/chat.png" alt="A CodeCraft session: the agent edits a file, a permission card shows the command and asks before running it, 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>
|
||||
@@ -41,47 +44,84 @@
|
||||
<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.
|
||||
<h3>Any model</h3>
|
||||
Anthropic natively, plus everything that speaks the OpenAI API: Gemini, OpenRouter, opencode, fal.ai, Ollama, vLLM, llama.cpp. Mix them in one chat, with automatic fallback.
|
||||
</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.
|
||||
<h3>Real tools</h3>
|
||||
Files, shell, web, an interactive browser, LSP diagnostics, 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.
|
||||
<h3>You decide</h3>
|
||||
Permission cards with diffs, questions from agents and MCP servers, per-tool rules. On your phone, with push 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.
|
||||
<h3>Every token counted</h3>
|
||||
Tokens, cache hits, prefill and output speed, and cost per request – per chat, per day and per model.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<br>
|
||||
|
||||
## Install
|
||||
|
||||
You need Docker with Compose. The image is published for **amd64 and arm64**.
|
||||
|
||||
```sh
|
||||
mkdir codecraft && cd codecraft
|
||||
curl -fsSLO https://git.familie-zink.org/zink/codecraft/raw/branch/main/docker-compose.release.yml
|
||||
curl -fsSL --create-dirs -o docker/seccomp-sandbox.json \
|
||||
https://git.familie-zink.org/zink/codecraft/raw/branch/main/docker/seccomp-sandbox.json
|
||||
curl -fsSL -o .env https://git.familie-zink.org/zink/codecraft/raw/branch/main/.env.example
|
||||
$EDITOR .env # workspace path, provider keys, time zone
|
||||
docker compose -f docker-compose.release.yml up -d
|
||||
docker compose -f docker-compose.release.yml logs codecraft # one-time setup code for the first admin
|
||||
```
|
||||
|
||||
Open `http://localhost:8787`, enter the setup code and create the admin account. Then add a
|
||||
provider under *Settings → Providers & models* – or put the keys into `.env` and reference
|
||||
them in the config as `${NAME}`.
|
||||
|
||||
**Update:** `docker compose -f docker-compose.release.yml pull && docker compose -f docker-compose.release.yml up -d`.
|
||||
Pin a version with `CODECRAFT_VERSION=0.1.0` in `.env`. Admins see a notice when a new release is out.
|
||||
|
||||
**From source:** `git clone https://git.familie-zink.org/zink/codecraft.git && cd codecraft`,
|
||||
`cp .env.example .env`, then `docker compose up -d --build`.
|
||||
|
||||
All state – configuration, database, backups, the agent's home directory – lives in the Docker
|
||||
volume `codecraft-data`; recreating the container keeps it. Your projects are mounted from
|
||||
`WORKSPACE`. The port is bound to `127.0.0.1`: put a TLS reverse proxy in front of it (with
|
||||
WebSocket support) and set `auth.public_url` – installing the app and push notifications
|
||||
require HTTPS.
|
||||
|
||||
## 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.
|
||||
CodeCraft runs on your server, next to your projects. You talk to it from a browser, the
|
||||
installed app or the terminal client; 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.
|
||||
1. **Pick a folder and a task.** The start screen asks what you want to do – build, plan,
|
||||
craft something, model a part for 3D printing – and where: a new folder, an existing one
|
||||
or a git repository.
|
||||
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.
|
||||
|
||||
Every change can be reviewed hunk by hunk, rewound to a checkpoint, or isolated in a git
|
||||
worktree. Sessions can be pinned, archived and filed into folders; <kbd>Ctrl</kbd>+<kbd>K</kbd>
|
||||
opens the command palette, and prompt templates with placeholders save typing.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td width="50%" valign="top">
|
||||
<td width="40%" 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>
|
||||
<sub><b>Mobile:</b> answer questions and approve changes from your phone. Share links and text from other apps into a chat.</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 width="60%" valign="top">
|
||||
<img src="docs/images/settings.png" alt="Settings: providers with model counts and their status (reachable, API key rejected)" width="100%"><br>
|
||||
<sub><b>Settings:</b> providers, models, prices, MCP, permissions, users, templates and backups – all in the UI.</sub>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -92,11 +132,13 @@ installed app; the agent keeps working when you close the tab.
|
||||
|---|---|
|
||||
| **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. |
|
||||
| **craft** | Study a target – a website, app, game or old program – and build your own version, check it visually and refine. Websites are captured at several screen widths in a headless browser and compared with the build. *Clean room* uses only what a visitor sees; *deep mode* may read the 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.
|
||||
The agent keeps notes about a project in `.codecraft/memory.md`; your personal memory applies to
|
||||
every project.
|
||||
|
||||
## Models
|
||||
|
||||
@@ -105,76 +147,108 @@ output limit, reasoning effort, extra request options and prices per million tok
|
||||
|
||||
- **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.
|
||||
writes documentation in the background on another.
|
||||
- **Fallback:** if a host is unreachable or its budget is used up, the request goes to the
|
||||
model's fallback.
|
||||
- **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.
|
||||
process one at a time; waiting time is shown and never counted as model latency.
|
||||
- **Status:** every five minutes each provider's model list is fetched (no tokens used), so
|
||||
you see at a glance which hosts answer and which keys are rejected.
|
||||
|
||||
## Users
|
||||
## Terminal client
|
||||
|
||||
`codecraft` is a full-screen terminal client in the style of Claude Code and opencode. The agent
|
||||
loop, the tools and the chat history run **on your machine**, in the current folder. Signed in to
|
||||
a CodeCraft server, it uses the server's models, keys, budgets, modes, rules, skills, MCP tools and
|
||||
your theme, and the server counts usage and costs. Without a server, a guided setup connects
|
||||
Anthropic, OpenAI, Gemini, OpenRouter, opencode or a local model server (Ollama, LM Studio,
|
||||
llama.cpp, vLLM – detected automatically); both can be mixed.
|
||||
|
||||
```sh
|
||||
cargo install --locked --git https://git.familie-zink.org/zink/codecraft codecraft-cli
|
||||
codecraft login # server URL, user name, password → creates an API token
|
||||
codecraft # start in the current folder; /help lists the commands
|
||||
```
|
||||
|
||||
There are no prebuilt binaries yet, so the client is installed from source (needs a Rust
|
||||
toolchain). A server that has binaries in `CODECRAFT_CLI_DIR` (`codecraft-linux-x86_64`,
|
||||
`codecraft-linux-aarch64`) also offers `curl -fsSL https://<your-server>/cli/install.sh | sh`
|
||||
and `codecraft update`.
|
||||
|
||||
## Automations
|
||||
|
||||
An automation is a Markdown file with a cron schedule in its front matter
|
||||
(`.codecraft/jobs/<name>.md`). Each run is a normal chat session, so you can read and continue
|
||||
it; if it needs a permission, you get a push notification. Ask an agent in any chat to set one
|
||||
up, start from a template (dependency check, security review of recent commits, test suite
|
||||
health, daily summary, TODO report, documentation freshness) or write the file yourself.
|
||||
|
||||
**Webhooks** start an automation from outside, e.g. on every push: the request is checked with a
|
||||
shared secret or a Gitea/GitHub HMAC signature, and its JSON payload is handed to the agent.
|
||||
|
||||
## Integrations
|
||||
|
||||
- **API tokens** (*Settings → Account*) with full or read-only scope for scripts and the terminal client.
|
||||
- **Prometheus:** set `server.metrics_token` and scrape `GET /metrics` with
|
||||
`Authorization: Bearer <token>` – requests, errors, tokens, cost and time per model, provider
|
||||
status, sessions, pending permissions.
|
||||
- **JSON logs:** `CODECRAFT_LOG_FORMAT=json` writes one JSON object per line.
|
||||
- **Backups:** daily at 03:00 into `/data/backups` (the last 30 are kept), optionally copied to
|
||||
any S3-compatible bucket (AWS, MinIO, Garage, Backblaze B2, Hetzner). *Settings → Audit*
|
||||
shows them, creates one on demand and downloads them.
|
||||
- **Health:** `GET /api/health` for monitoring, with version and commit.
|
||||
|
||||
## Users and security
|
||||
|
||||
- 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.
|
||||
- Every user works in `<workspace>/<username>`; admins can share additional folders. Sessions
|
||||
are private and can be shared read-only. An audit log records sign-ins, permissions and
|
||||
configuration changes.
|
||||
- Shell commands of non-admin users run in a **bubblewrap sandbox**: read-only system, only
|
||||
their folders writable, own home and processes, no server environment. It needs the security
|
||||
options in the compose file; without them non-admins cannot run shell commands.
|
||||
- The browser tool reaches the internet and `localhost`, never addresses in private networks.
|
||||
|
||||
## 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%">
|
||||
<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 of the last 14 days" 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.
|
||||
shows totals, cost per day by model, tokens per day, an activity heatmap of the last 14 days,
|
||||
and tables per model, provider, mode, user and session – each chart also as a table. Turn on
|
||||
the daily cost summary to get a push notification every evening.
|
||||
|
||||
## 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
|
||||
[`config.example.toml`](config.example.toml) on first start. The settings pages edit it in
|
||||
place and keep 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` |
|
||||
| `[server]` | workspace, default and small model, currency, auto-compaction, subagent limit, `metrics_token` |
|
||||
| `[providers.<name>]` | `kind = "anthropic" \| "openai"`, `base_url`, `api_key`, `max_concurrency`, `models` (with prices and `fallback`) |
|
||||
| `[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 |
|
||||
| `[sandbox]` | shell sandbox for non-admins (`auto`, `always`, `off`) |
|
||||
| `[backup]`, `[backup.s3]` | daily backups, retention, S3 target |
|
||||
| `[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
|
||||
Pick a **base theme** in *Settings → General* and switch **light / dark / auto** there or with
|
||||
the theme 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:
|
||||
@@ -224,33 +298,44 @@ 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
|
||||
|
||||
# terminal client
|
||||
cargo run -p codecraft-cli
|
||||
```
|
||||
|
||||
Tests: `cd server && cargo test` · type check: `cd web && npx tsc --noEmit`.
|
||||
Tests: `cargo test --workspace` · type check: `cd web && npx tsc --noEmit`.
|
||||
|
||||
```
|
||||
core/ shared crate: types, config, providers, permissions, prompts
|
||||
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)
|
||||
tools/ built-in tools (files, shell, web, browser, 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
|
||||
jobs.rs automations and webhooks
|
||||
auth.rs users, sessions, API tokens, OpenID Connect
|
||||
cli/ terminal client (ratatui)
|
||||
web/ React + Vite PWA
|
||||
src/components chat, composer, cards, settings, statistics
|
||||
src/themes CSS themes
|
||||
src/i18n English (reference) and German
|
||||
```
|
||||
|
||||
The Docker build cross-compiles the server with
|
||||
[cargo-zigbuild](https://github.com/rust-cross/cargo-zigbuild), so a multi-arch image builds
|
||||
quickly on either architecture:
|
||||
`docker buildx build --platform linux/amd64,linux/arm64 -t <registry>/codecraft:<version> --push .`
|
||||
|
||||
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:
|
||||
Early, but in daily use. See the [changelog](CHANGELOG.md). Planned next:
|
||||
|
||||
- Per-user sandboxes for shell commands
|
||||
- File checkpoints and undo, background shells, `@file` mentions
|
||||
- Prebuilt terminal client binaries (Linux, macOS, Windows)
|
||||
- MCP OAuth, resources and prompts
|
||||
- Hooks before/after tool calls
|
||||
- Image generation tools (fal.ai) and the OpenAI Responses API
|
||||
- The OpenAI Responses API
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE) © Richard Zink. The theme palettes keep the licenses listed under [Themes](#themes).
|
||||
Reference in new issue
Block a user