Synchronous client over libcurl + vendored cJSON. Single public
header (include/clawdforge.h) with an opaque cf_client_t and the
full surface: /healthz, /run, /files, /admin/tokens.
- C11, no GNU extensions; -Wall -Wextra -Wpedantic clean
- Hidden visibility on the shared lib + CF_API export attribute
- Static + shared lib via CMake; relocatable pkg-config (${pcfiledir})
- Errors via out-param cf_error_t; every output struct has a _free()
- Multipart upload streams from disk via curl_mime_filedata
- 15 in-process socket-loop tests; valgrind + ASan clean
LAN-only HTTP service that runs claude -p subprocess on behalf of Sulkta apps.
Bearer token + IP allowlist gated. SQLite-backed token registry + run audit log.
- POST /run run a prompt, return parsed result
- POST /files upload a file, get a file_token to attach to /run
- POST /admin/tokens mint per-app tokens (admin-bootstrap-token gated)
- GET /admin/tokens list, DELETE /admin/tokens/<name> revoke
- GET /healthz liveness + claude --version smoke
Container = node:22 + npm-installed @anthropic-ai/claude-code + uvicorn/FastAPI
wrapper. Persistent volumes for /data (sqlite + run staging) and /root/.claude
(subscription auth — survives container rebuilds; auth via 'docker exec -it
clawdforge claude /login' once). Compose binds 192.168.0.5:8800 only — no
public proxy.
First consumer = cauldron (about to land).