---
license: mit
model_name: Shadowclaw v1.0 (Testing)
binary_size: 100-200 KiB
llm_integration: Ollama (localhost:11434)
build: make
dependencies: gcc, libcurl, bc, cJSON
persistence: shadowclaw.bin
---
# Shadowclaw v3.4 (Testing)
____ _ _ _
/ ___|| |__ __ _ __| | _____ _____| | __ ___ __
\___ \| '_ \ / _` |/ _` |/ _ \ \ /\ / / __| |/ _` \ \ /\ / /
___) | | | | (_| | (_| | (_) \ V V / (__| | (_| |\ V V /
|____/|_| |_|\__,_|\__,_|\___/ \_/\_/ \___|_|\__,_| \_/\_/
**Shadowclaw** is a minimal, single‑binary agent harness written in C. It follows the *OpenClaw* philosophy: self‑hosted, tool‑using, persistent memory, and minimal dependencies. The core memory management uses **Tsoding's "shadow header" trick** (like `stb_ds` but for a growable arena). All data (conversation history, tool definitions, results) lives inside a single `realloc`‑ed memory block with a hidden header. The agent communicates with a local LLM (Ollama) via curl, can execute shell commands, read/write files, perform HTTP GET, and evaluate simple math expressions. State is automatically saved to disk after every interaction.
**Niche edge use cases:**
RPi Zero/IoT: offline sensor scripts (shell + persistent shadow.bin)
Air-gapped systems: USB-stick local LLM agent (file/HTTP/math)
Embedded routers: 100-200KB network automation (low-mem Linux)
Low-power edge nodes: self-hosted persistent AI, no cloud.
---
## Features
- **🧠 Local LLM integration** – works with any Ollama model (default: `tinyllama:1.1b`).
- **🔧 Built‑in tools** – `file_read`, `file_write`, `http_get`, `math`, `list_dir`, `shell` (disabled by default), and more.
- **⏰ Cron jobs** – schedule recurring tasks using `@every N[s/m/h]`, `@hourly`, `@daily`, `@weekly`.
- **🌐 Webhooks** – trigger HTTP POST calls on tool execution or cron events.
- **🎓 Dynamic skills** – create reusable multi‑step workflows without recompiling.
- **💾 Core memory** – persistent key‑value storage (JSON) that survives across sessions.
- **📜 Soul file** – Markdown export of all memories (conversation, skills, crons, webhooks, core memory).
- **🎨 Colored TUI** – optional GNU readline support for line editing and history.
- **⚡ Thread‑safe** – cron jobs run in a separate thread, tool calls are queued.
- **🛡️ Security** – path sandboxing, domain allowlist, shell opt‑in, dry‑run mode.
---
## 📦 Requirements
- **Linux / macOS / WSL** (tested on Ubuntu 22.04, Kali)
- **Ollama** (running locally) – optional, the agent can run in `--no-llm` mode
- **Dependencies**:
- `libcurl` (HTTP requests)
- `libpthread` (threading)
- `libreadline` (optional, for TUI enhancements)
- `gcc` or `clang` with C99 support
---
## Installation + Launch
*Put all files into a single folder on your system*
```bash
cd ~/shadowclaw (The folder you put the files in)
make clean && make
./start.sh
```
## Setup your local Ollama model
*Shadowclaw is set to use qwen2.5:0.5b as a default, to change this:*
Find line 633 in the shadowclaw.c file:
```bash
static const char *ollama_endpoint = "http://localhost:11434";
static const char *ollama_model = "qwen2.5:0.5b"; (Change this to desired model)
static long llm_connect_timeout = 15;
```
Also line 16 in the start.sh file:
```bash
OLLAMA_ENDPOINT="${OLLAMA_ENDPOINT:-http://localhost:11434}"
OLLAMA_MODEL="${OLLAMA_MODEL:-qwen2.5:0.5b}" (Change this to desired model)
```
---
### First start
- The agent creates `shadowclaw.bin` (binary state) and a folder `shadowclaw_data/` containing `shadowsoul.md`.
- If Ollama is not reachable, it automatically falls back to `--no-llm` mode.
- A default heartbeat cron job (`@every 120s`) is added automatically to keep the soul file updated.
---
## Interactive Commands
Shadowclaw understands both natural language (sent to the LLM) and slash commands.
| Command | Description |
|---------|-------------|
| `/help` | Show help and list all commands. |
| `/tools` | List available built‑in tools. |
| `/state` | Show arena memory usage and soul file stats. |
| `/clear` | Erase conversation history (keeps system prompt and core memory). |
| `/exit` | Quit the agent. |
| `/loop [args]` | Schedule a recurring task. Examples:
`/loop 30m http_get https://example.com`
`/loop daily math "1+1"` |
| `/crons` | List all scheduled cron jobs. |
| `/webhooks` | Show registered webhooks. |
| `/skills` | List dynamic skills. |
| `/compact` | Manually compact the arena (remove deleted blobs). |
| `/soul` | Display information about `shadowsoul.md`. |
---
## 🛠️ Tools
Tools are invoked by the LLM during the “plan” phase. Each tool is described in the LLM prompt with its parameters and an example.
| Tool | Description | Example args |
|------|-------------|---------------|
| `file_read` | Read a file (max 10 MB, path must be inside CWD). | `notes.txt` |
| `file_write` | Write content to a file (overwrites). | `output.txt Hello world` |
| `http_get` | HTTP GET to an allowed domain (see `allowed_domains` in source). | `https://example.com/data` |
| `math` | Evaluate arithmetic expression. | `(2+3)*4` |
| `list_dir` | List directory contents. | `.` or `/home/user` |
| `webhook_add` | Register a webhook (JSON: `{"url":"...","event":"..."}`). | `{"url":"http://...","event":"tool:http_get"}` |
| `cron_add` | Add a cron job (JSON: `{"schedule":"...","tool":"...","args":"..."}`). | `{"schedule":"@every 30m","tool":"math","args":"1+1"}` |
| `cron_list` | List all cron jobs. | (none) |
| `cron_remove` | Remove cron jobs containing a substring in their JSON representation. | `@every` |
| `skill_add` | Create a dynamic skill (JSON with `name`, `desc`, `steps` array, optionally `interpreter_command`). | See below. |
| `skill_run` | Run a skill by name. | `weather London` |
| `list_skills` | List all available skills. | (none) |
| `update_core_memory` | Merge JSON object into core memory. | `{"user_name":"Alice","preferences":{"theme":"dark"}}` |
| `recall` | Search conversation history for a keyword. | `project` |
| `heartbeat` | Internal (used by cron). | (none) |
> **Security:** The `shell` tool is compiled out by default. To enable it, add `-DENABLE_SHELL_TOOL` to `CFLAGS` and understand the risks.
---
## Dynamic Skills
Skills are sequences of tool calls stored in the arena as `BLOB_KIND_SKILL`. Example creation:
```json
{
"name": "weather",
"desc": "Get weather for a city",
"steps": [
{"tool": "http_get", "args": "https://wttr.in/{0}"},
{"tool": "file_write", "args": "/tmp/weather.txt {result}"}
]
}
```
Placeholders supported:
- `{args}` – the whole argument string passed to `skill_run`
- `{0}`, `{1}`, … – positional arguments (split by spaces)
- `{result}` – output of the previous step
Skills can also delegate to an external interpreter command (e.g., a Python script) via the optional `interpreter_command` field.
---
## Soul File
All persistent memories are written to `shadowclaw_data/shadowsoul.md` in Markdown format. It contains:
- `## Core Memory` – JSON key‑value store.
- `## Skills` – list of registered skills (JSON).
- `## Cron Jobs` – all scheduled jobs.
- `## Webhooks` – registered webhooks.
- `## Conversation Log` – user, assistant, tool calls, and results.
The file is updated every 5 writes (write‑behind) and immediately after important events.
---
## ⚙️ Configuration via Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `SHADOWCLAW_CONNECT_TIMEOUT` | 10 | Seconds to wait for Ollama connection. |
| `SHADOWCLAW_TOTAL_TIMEOUT` | 120 | Total LLM request timeout (increased on retries). |
| `SHADOWCLAW_RETRY_ATTEMPTS` | 3 | Number of retries with exponential backoff. |
---
## 📁 Project Structure
```
shadowclaw/
├── shadowclaw.c # Main program, arena, tools, cron, LLM
├── interpreter.c # Local command interpreter (used in --no-llm mode)
├── interpreter.h # Header for interpreter
├── cJSON.c / cJSON.h # JSON library
├── Makefile # Build instructions
├── start.sh # Helper startup script (checks dependencies)
└── README.md # This file
```
## 📄 License
MIT License.