---
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 v1.3 (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.
---
## Repository Structure
```
shadowclaw/
├── shadowclaw.c # main program: arena, tools, LLM glue, event loop
├── Makefile # simple build file
├── cJSON.c # lightweigt JSON parser (from cJSON library)
└── cJSON.h # cJSON header
```
---
## Features
- **Growable shadow arena** – all objects stored in one contiguous block with hidden headers.
- **Persistent memory** – saves and loads full arena to/from `shadowclaw.bin`.
- **Tool use** – shell, file I/O, HTTP GET, math (via `bc`).
- **Ollama integration** – talk to any model running locally.
- **Blob storage** – system prompts, user messages, assistant replies, tool calls, results.
- **Tiny footprint** – stripped binary ≈ 100–200 KiB.
---
## Requirements
- Linux (developed on Debian, should work on most Unix‑likes)
- `gcc`, `make`, `libcurl4-openssl-dev`, `bc`
- [Ollama](https://ollama.com/) running locally (default `http://localhost:11434`) with a model pulled (e.g. `llama3.2`)
Install build dependencies on Debian/Ubuntu:
```bash
sudo apt update
sudo apt install build-essential libcurl4-openssl-dev bc
```
---
## Define your model:
- **Change Ollama endpoint/model**: edit `ollama_endpoint` and `ollama_model` in `shadowclaw.c`.
Find this line (507) in the shadowclaw.c file:
```bash
// --------------------------------------------------------------------
// Main (with slash commands from v1.2.2)
// --------------------------------------------------------------------
int main(int argc, char **argv) {
const char *state_file = "shadowclaw.bin";
const char *ollama_endpoint = "http://localhost:11434";
const char *ollama_model = "qwen2.5:0.5b"; // change as needed
```
Adjust the model endpoint in "ollama_model = "qwen2.5:0.5b";" to meet your model.
- **Add new tools**: extend the `tools` array in `shadowclaw.c` with a name and a function that takes a `const char*` argument and returns a `char*` (must be `malloc`ed, the caller will `free` it).
---
## How It Works
### Shadow Arena
All dynamic data lives in a single `realloc`‑ed block.
A `ShadowHeader` is stored **immediately before** the user‑visible pointer.
This header holds capacity, used length, a magic number, and a dirty flag.
```
+-------------------+---------------------+
| ShadowHeader | payload (blobs) |
+-------------------+---------------------+
^
`- pointer returned to user
```
### Blob Format
Each item (system prompt, user message, tool result, etc.) is stored as:
```
+------------+------+------+-----------------+
| BlobHeader | kind | id | payload (bytes) |
+------------+------+------+-----------------+
```
- `BlobHeader` contains the payload size, kind, and a 64‑bit ID.
- The payload is arbitrary data (null‑terminated strings for most kinds).
### Persistence
-The whole arena (header + payload) is written to `shadowclaw.bin` with `fwrite`.
-On startup, if the file exists and has a valid magic number, it is loaded back.
-All conversations and tool results are automatically saved to `shadowclaw.bin` and reloaded on restart.
---
# Updated 3/3/2026: Shadowclaw v1.3
### Built‑in Slash Commands
Type any of these commands directly at the `>` prompt – they are handled without invoking the LLM.
| Command | Description |
|-----------|-------------|
| `/help` | Show this help message. |
| `/tools` | List all available tools (shell, file I/O, HTTP, math, `list_dir`). |
| `/state` | Display current arena memory statistics (capacity, used bytes, dirty flag). |
| `/clear` | Clear the conversation history while retaining the system prompt. |
| `/chat` | Remind you that you are already in chat mode (the default behaviour). |
| `/exit` | Quit Shadowclaw. |
## Build
```bash
cd /Home/User/Shadowclaw # The folder you have the files located.
```
```bash
make clean && make
```
## Run
```bash
./shadowclaw
```
Use the slash commands above to get started – even without Ollama running, you can explore the built‑in features.
When your agent is running you should be able to use /help and see (example):
```bash
┌──(kali㉿user)-[~/shadowclaw]
└─$ ./shadowclaw
ShadowClaw ready. Type your message (Ctrl-D to exit)
/help
Shadowclaw commands:
/help Show this help
/tools List available tools
/state Show arena memory stats
/clear Clear conversation history (keeps system prompt)
/chat Remind you that chat mode is active
/exit Exit Shadowclaw
```
## Notes
-If Ollama is not running, you’ll see LLM call failed.
-Tool arguments can be a JSON array – they will be joined with spaces (useful if your model outputs "args":["arg1","arg2"]).
-All conversations and tool results are saved in shadowclaw.bin and reloaded on restart.
---
## How Tool Arguments Work
Shadowclaw processes tool calls by parsing JSON, where the args value is passed as a string to the function, executing it, and appending the result as a kind 5 blob for the next prompt. It supports a fallback where the model outputs args as an array (e.g., [arg1, arg2]), allowing for flexible input handling when standard JSON encoding fails.
-Tool Call Flow: The agent parses the JSON block, executes the tool, and appends the result.
-Result Visibility: The tool output is visible to the model in the next prompt.
-Fallback Mechanism: If JSON parsing fails, Shadowclaw interprets args as an array.
-Alternative Tooling: In some scenarios, tool calls can be handled as a single string to avoid parsing errors.
This system helps in handling malformed JSON, which occasionally occurs with certain LLM providers, ensuring the tool call succeeds.
```json
{"tool":"write_file","args":["notes.txt","Hello world"]}
```
Shadowclaw automatically **joins the array elements with spaces**, so the tool receives a single string `"notes.txt Hello world"`. This makes the agent robust to different model behaviours to ensure:
- **Simplicity** – most tools only need a single string argument (a command, a filename, a URL).
- **Flexibility** – if a tool needs multiple pieces of information (like `write_file` needing a filename **and** content), we use a simple delimiter (newline). The LLM can learn this pattern from the system prompt.
- **Lightweight Design** – no complex argument schemas, no extra JSON nesting. The entire tool call is tiny.
- **Args are always a single string** to keep things simple.
- **Multiple values are encoded with delimiters** (like newline) – the tool and LLM agree on the format.
- **Shadowclaw’s niche** is minimalism: a single binary with persistent memory, running anywhere, with just enough tools to be genuinely useful.
You can easily add new tools by editing the `tools` array – each new function opens up more automation possibilities for your unique environment.
---
## Niche Use Cases
Shadowclaw is designed for **minimal, self‑contained AI agents** running on resource‑constrained or air‑gapped systems.
Its toolset is deliberately small but powerful enough to automate many tasks without spawning heavy processes.
| Tool | What it does | Example args | Unique Niche Use |
|------|--------------|--------------|------------------|
| `shell` | Executes any shell command | `"ls -la /home"` | Automate system maintenance, run scripts, control services on a headless Raspberry Pi or embedded Linux device. |
| `read_file` | Reads a file from disk | `"/etc/passwd"` | Inspect configuration files, read logs, retrieve data for the LLM to analyse – all without a web interface. |
| `write_file` | Writes content to a file (args: `filename\ncontent`) | `"notes.txt\nBuy milk"` | Create notes, write configuration files, save results – perfect for offline data logging. |
| `http_get` | Fetches a URL (via libcurl) | `"https://api.example.com/data"` | Retrieve weather, fetch RSS feeds, call local REST APIs – even on devices with no browser, just a network stack. |
| `math` | Evaluates an expression using `bc` | `"2 + 2 * 5"` | Let the LLM do arithmetic, unit conversions, or simple calculations without relying on external tools. |
| `list_dir` | Lists directory contents | `"/home/user"` | Explore filesystem, find documents, check available storage – all natively, without forking a shell. |
---
## Niche Use Case Examples:
### 1. Raspberry Pi Zero / IoT Sensor Node
- **Tool used:** `shell` + `write_file`
- **Flow:** LLM asks to read a temperature sensor via a shell script, then logs the value to a file.
- **Why Shadowclaw?** Runs in <200KB RAM, no Python, no bloat. Persistent memory keeps the last readings.
### 2. Air‑Gapped Engineering Workstation
- **Tool used:** `http_get` + `math` + `read_file`
- **Flow:** Engineer asks for a component value calculation; LLM fetches a local datasheet via HTTP, reads a config file, does the math, and writes a report.
- **Why Shadowclaw?** No cloud, no internet required. All data stays on the machine.
### 3. Embedded Router Automation
- **Tool used:** `shell` + `list_dir`
- **Flow:** Network admin asks for a list of active interfaces; LLM runs `ifconfig` and parses the output, then suggests a config change.
- **Why Shadowclaw?** Tiny binary fits in router storage (often just a few MB). Uses curl for local API calls.
### 4. Low‑Power Field Logger
- **Tool used:** `write_file` + `math`
- **Flow:** A solar‑powered device collects environmental data; Shadowclaw can process and store it locally, then answer queries about trends.
- **Why Shadowclaw?** No database needed – just a binary and a single file (`shadowclaw.bin`) for persistence.
---
## Credits
- **Tsoding** – for the “insane shadow data trick” (the header‑before‑data arena idea).
- **cJSON** – Dave Gamble and contributors – the minimal JSON parser used.
- **Ollama** – HTTP requests via curl.
- **Vibe Code** - xAI Grok 4.20 and Deepseek AI
- **Openclaw**
- **webXOS**
---
## License
This project is released under the open sourced MIT License.
cJSON is also MIT licensed.