Skip to content

douglascorrea/syscall-agent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

syscall-agent

syscall-agent is a compact coding agent written in pure C. It talks to OpenRouter, keeps durable memory in Markdown, and exposes local tools that lean on OS primitives such as fork, execvp, mmap, rename, kqueue, inotify, getaddrinfo, non-blocking sockets, and process-table syscalls.

The goal is a small single-binary agent that can inspect code, edit files, perform network lookups, run bounded local commands, and stay usable from both plain CLI mode and a responsive Pi-style TUI.

Important

This is a local coding agent with powerful filesystem and optional process execution tools. Run it in a repository or disposable workspace you trust.

Highlights

  • Pure C implementation with one generated binary.
  • OpenRouter chat-completions backend.
  • Tool-calling loop with file, web, memory, process, watch, network, and Termux tools.
  • Runtime tool catalog, auth status, host diagnostics, and local skill-pack tools.
  • Optional syscall-backed command execution with resource limits.
  • Atomic file writes via mkstemp + rename.
  • mmap range reads for large files and logs.
  • Persistent MEMORY.md with append locking.
  • Interactive --tui mode inspired by Pi Agent.
  • Android Termux install path and Termux:API device integrations.
  • Focused regression tests for TUI commands, agent events, tools, and security checks.

Requirements

  • macOS, Linux, or Android through Termux
  • C compiler with C11 support
  • make
  • libcurl
  • OpenRouter API key

On macOS, libcurl is usually already available. On Debian/Ubuntu:

sudo apt-get install build-essential libcurl4-openssl-dev

On Android, install Termux from F-Droid or GitHub, then inside Termux:

pkg update
pkg upgrade
pkg install git clang make libcurl

Full Android setup, storage, and Termux:API instructions are in docs/termux-install.md.

Build

make

The binary is written to:

build/agent

Run the test suite:

make test

Quick Start

export OPENROUTER_API_KEY=sk-or-...

./build/agent "summarize this repository"
./build/agent -s 20 -m anthropic/claude-3.5-sonnet "find the largest C file and explain it"
echo "what changed recently?" | ./build/agent

Open the TUI:

./build/agent --tui

Enable subprocess tools:

./build/agent --allow-exec "run the tests and summarize failures"

Configuration

Variable Purpose
OPENROUTER_API_KEY Required OpenRouter API key.
OPENROUTER_MODEL Default model when -m/--model is not set.
BRAVE_SEARCH_API_KEY Optional Brave Search key; otherwise web search falls back to DuckDuckGo HTML.
SYSTEM_PROMPT_PATH Override SYSTEM_PROMPT.md.
MEMORY_PATH Override MEMORY.md.
LLA_ALLOW_EXEC=1 Enable subprocess tools.
LLA_ALLOW_UNSAFE_EXEC=1 Allow unsandboxed profile=none; implies exec tools.
SYSCALL_AGENT_AUTH_PROVIDER Descriptive provider label shown by auth status tools. Defaults to openrouter.
SYSCALL_AGENT_SKILLS_DIR Optional directory containing local name/SKILL.md skill packs.

Flags:

--tui                 open the interactive terminal UI
-s, --steps N         max agent-loop iterations (default 10)
-m, --model NAME      OpenRouter model id (default openai/gpt-4o-mini)
--system PATH         path to SYSTEM_PROMPT.md
--memory PATH         path to MEMORY.md
--allow-exec          enable exec_command, spawn_bg, bg_read, bg_kill, bg_list
--allow-unsafe-exec   also allow profile=none; implies --allow-exec
-v, --verbose         trace tool calls to stderr in plain CLI mode
-h, --help            show help

TUI

The TUI is intentionally small and terminal-native. It uses full-width accent borders, muted status/footer lines, padded user blocks, and compact tool or reasoning panels.

In TUI mode, model responses use OpenRouter streaming. Assistant text appears as it arrives. Tool-call deltas appear in real time when /verbose tools or /verbose all is enabled, and reasoning deltas appear in real time when /verbose reasoning or /verbose all is enabled.

Slash commands:

Command Behavior
/model Open a live OpenRouter model picker backed by GET /api/v1/models.
/models Open the same model picker.
/model N Select a built-in quick choice by list index.
/model provider/model-id Set any OpenRouter model id directly.
/verbose normal Show only user and assistant conversation text.
/verbose tools Also show tool calls and tool results.
/verbose reasoning Also show model reasoning fields when returned.
/verbose reasioning Accepted alias for the original requested spelling.
/verbose all Show tools and reasoning output.
/tools Show tool families visible to the model.
/skills List local skill packs from configured skill roots.
/auth Show auth-provider status without printing secrets.
/sysinfo Show host OS, architecture, cwd, CPU count, and page size.
/new Clear the visible transcript.
/exit Leave the TUI.

Model picker controls:

Key Behavior
Type text Filter models by id, name, or description.
Up/Down Move through the filtered list.
PageUp/PageDown Jump through the filtered list.
Enter Select the highlighted model for the current session.
Esc Close the picker without changing the model.
Ctrl-R Refresh the OpenRouter model catalog.

Reasoning display supports OpenRouter-style reasoning, reasoning_content, and reasoning_details fields when the selected model returns them, including streamed choices[].delta.reasoning_details chunks.

Tools

Always available:

Tool Capability
list_tools List every currently visible tool and one-line description.
read_file Read up to 256 KB from a local file.
search_files Recursively search filenames by glob or substring.
search_web Brave Search or DuckDuckGo HTML search.
fetch_url HTTP/HTTPS GET with raw response output.
web_fetch HTTP/HTTPS GET with HTML stripped to text.
save_memory Append durable notes to MEMORY.md.
auth_status Report configured auth surfaces without exposing secrets.
system_info Inspect host OS, architecture, cwd, CPU count, and page size.
disk_usage Inspect filesystem capacity and inode counts via statvfs.
env_get Read allowlisted configuration environment variables with secret redaction.
which Locate executables on PATH without invoking a shell.
file_digest Compute an FNV-1a 64-bit checksum for change detection.
grep_text Search one text file for literal matching lines.
list_skills List local name/SKILL.md skill packs.
read_skill Read a local skill pack by safe skill name.
stat Inspect metadata without reading file content.
list_dir List directory entries with type, size, and mtime.
write_file Atomic file replacement using a same-directory temp file.
read_file_range mmap-backed byte-range read for large files.
dns_lookup Resolve A and AAAA records through getaddrinfo.
tcp_check Non-blocking TCP reachability probe with duration.
watch_path Wait for file or directory changes.
list_processes List top processes by RSS.
termux_info Detect Termux/Android environment and command availability.
termux_api_status Check Termux:API helper command availability and setup hints.
termux_storage_status Check Android shared-storage symlinks from termux-setup-storage.
termux_battery_status Read Android battery state through Termux:API.
termux_wifi_info Read current Wi-Fi connection details through Termux:API.
termux_clipboard_get Read Android clipboard text through Termux:API.
termux_clipboard_set Set Android clipboard text through Termux:API.
termux_notification Show an Android notification through Termux:API.
termux_vibrate Vibrate the Android device for a bounded duration.
termux_wake_lock Acquire or release Termux's wake lock.

Termux tools degrade gracefully outside Termux or when the relevant termux-* command is missing. They invoke fixed Termux commands through argv-only execvp, never through a shell. See docs/termux-install.md for Android setup.

Gated by --allow-exec:

Tool Capability
exec_command Run an argv-only command, capture stdout/stderr, enforce rlimits.
spawn_bg Start a background command and return a handle.
bg_read Read buffered background output by offset.
bg_kill Terminate a background process.
bg_list List background processes owned by this agent.
delegate_codex Delegate to the official Codex CLI using its own supported auth.
delegate_copilot Delegate to the official GitHub Copilot CLI using its own supported auth.

exec_command and spawn_bg never invoke a shell. The model must provide an argv array, so shell metacharacters are ordinary arguments unless the chosen executable is itself a shell.

Delegation tools are also gated by --allow-exec. They invoke official local CLIs (codex exec and copilot -p) through argv-only fork/execvp, so users can use Codex OAuth or GitHub Copilot subscription authentication without syscall-agent reading or reusing private tokens. Delegation is read-only by default. mode=workspace-write requires --allow-unsafe-exec.

Auth Surfaces

Model calls currently go through OpenRouter with OPENROUTER_API_KEY. The agent also reports other common coding-agent auth surfaces so operators can see what is configured on the machine:

Surface Behavior
OpenRouter Used for model requests through OPENROUTER_API_KEY.
OpenAI API Detected through OPENAI_API_KEY for future provider work.
Codex CLI OAuth Detected by auth_status; usable through delegate_codex when the official codex CLI is installed and logged in.
GitHub/Copilot Detected by auth_status; usable through delegate_copilot when the official copilot CLI is installed and logged in.

syscall-agent does not print, scrape, or repurpose ChatGPT/Codex OAuth or GitHub Copilot subscription tokens. That keeps provider integration on the documented side of the boundary while leaving room for official support later.

Skills

Skill packs are simple directories containing SKILL.md. The agent searches:

$SYSCALL_AGENT_SKILLS_DIR
./skills
~/.syscall-agent/skills

Use list_skills to discover available packs and read_skill to load one into the conversation. In the TUI, /skills shows the same roots.

Execution Safety

Every subprocess gets these resource limits:

Limit Value
CPU time 30 seconds
Address space 512 MB
Output file size 256 MB
Open files 256
Captured stdout/stderr 256 KB per stream

OpenRouter SSE streaming is only enabled for the interactive TUI. Plain CLI mode keeps the one-shot response path unless a future flag enables stream printing.

Sandbox profiles:

Profile macOS behavior Linux behavior
readonly Read filesystem, write only tmp/devnull paths, no network. Fails closed until Linux sandboxing is implemented.
default Read filesystem, process spawning, write only tmp/devnull paths, no network. Fails closed until Linux sandboxing is implemented.
network default plus outbound network. Fails closed until Linux sandboxing is implemented.
build Filesystem writes allowed for build loops, no network. Fails closed until Linux sandboxing is implemented.
none No sandbox; requires --allow-unsafe-exec. No sandbox; requires --allow-unsafe-exec.

HTTP tools accept only http:// and https:// URLs. write_file masks mode bits to regular permission bits so tool calls cannot request setuid/setgid outputs.

Memory

The agent reads SYSTEM_PROMPT.md and MEMORY.md at startup. MEMORY.md is created on first use and appended through save_memory.

Override paths:

./build/agent --system prompts/system.md --memory state/MEMORY.md "use this context"

Repository Layout

src/
  main.c                 CLI entry and flag parsing
  agent.c                tool-calling loop and event emission
  openrouter.c           OpenRouter request/response handling
  openrouter_models.c    OpenRouter model catalog fetch/parse/filter helpers
  tui.c                  raw terminal UI
  tools.c                shared tool registration and dispatch
  tools_meta.c           tool catalog, auth, host diagnostics, skills, grep/checksum
  tools_termux.c         Android Termux detection and Termux:API wrappers
  tools_fs.c             stat, list_dir, write_file, read_file_range
  tools_proc.c           exec, background process, process listing
  tools_watch.c          kqueue/inotify path watching
  tools_net.c            DNS and TCP probes
  os_compat_*.c          platform-specific syscall shims
  memory.c               Markdown memory loading/appending
  http.c                 libcurl wrapper
vendor/
  cJSON.c                vendored JSON parser
tests/
  *_test.c               focused regression tests

Development

make clean
make
make test

Useful smoke checks:

./build/agent --help
./build/agent -m openai/gpt-4o-mini -s 3 "Reply with OK only"
./build/agent --tui

The research notes behind the current roadmap live in docs/research/2026-05-16-roadmap.md.

About

A compact coding agent written in pure C with OpenRouter, syscall-backed tools, memory, and a Pi-style TUI.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors