Version: 2.0 Date: 2026-01-15 Target: Mac OS X 10.0+ (PowerPC & Intel) Language: C89/ANSI C Goal: Maximum vintage OS compatibility with modern Claude API features
CodeOSX is a complete rewrite of LionCode in pure C, designed to run on every version of Mac OS X from 10.0 (Cheetah, 2001) through modern macOS. The architecture prioritizes:
- Universal Compatibility: Single codebase for PowerPC, Intel (i386, x86_64), and future ARM Macs
- Zero Dependencies: Bundled BearSSL (TLS 1.2), SQLite amalgamation, minimal system libraries
- Feature Completeness: Multi-agent system, session persistence, file tools, Git awareness
- Old Compiler Support: C89/ANSI C for GCC 2.95+ (Mac OS X 10.0-10.2)
- All features must work on Mac OS X 10.0+ (no OS-specific feature flags)
- Memory budget: ~100-200KB for code, ~1-5MB for runtime (sessions, buffers)
- Single binary:
codeosxwith agent switching via--agentflag or/agentcommands - CLI/REPL only: No TUI, no GUI, no web UI (for MVP)
- Cross-compilation: Build on modern Mac, run on vintage systems
┌────────────────────────────────────────────────────────────────┐
│ CodeOSX CLI/REPL │
│ - Readline-style input with history │
│ - Markdown rendering (ANSI colors) │
│ - Slash commands (/agent, /save, /load, /quit) │
│ - User question prompts (AskUserQuestion) │
└──────────────────┬─────────────────────────────────────────────┘
│
┌──────────────────▼─────────────────────────────────────────────┐
│ Agent Coordinator │
│ - Main agent (build): Full access, can call subagents │
│ - Subagents: plan (read-only), explore (search-only) │
│ - Agent switching and context passing │
│ - ReAct loop (Reasoning → Action → Observation) │
└──────────────────┬─────────────────────────────────────────────┘
│
┌──────────────────▼─────────────────────────────────────────────┐
│ Session Manager │
│ - SQLite database: ~/.codeosx/sessions.db │
│ - Session CRUD: create, read, update, delete, fork │
│ - Message history: user, assistant, tool_use, tool_result │
│ - Undo/redo via message removal │
└──────────────────┬─────────────────────────────────────────────┘
│
┌──────────────────▼─────────────────────────────────────────────┐
│ Tool Registry │
│ - read_file, write_file, edit_file, list_directory │
│ - bash (fork/exec with timeout) │
│ - grep, find_files │
│ - todos_read, todos_write, todos_add, todos_update │
│ - ask_user (interactive question prompts) │
│ - task (call subagent) │
└──────────────────┬─────────────────────────────────────────────┘
│
┌──────────────────▼─────────────────────────────────────────────┐
│ HTTP Client (BearSSL) │
│ - POST /v1/messages (Claude API) │
│ - TLS 1.2 via BearSSL (~300 source files, 20KB binary) │
│ - Prompt caching support │
│ - Streaming: Initial support for server-sent events (SSE) │
└──────────────────┬─────────────────────────────────────────────┘
│
┌──────────────────▼─────────────────────────────────────────────┐
│ External Dependencies (Bundled) │
│ - BearSSL: TLS 1.2, X.509 validation, embedded CA certs │
│ - SQLite amalgamation: sqlite3.c + sqlite3.h (~200KB) │
│ - JSON parser: Custom minimal parser for Claude responses │
│ - Markdown renderer: ANSI color formatter (from LionCode) │
└────────────────────────────────────────────────────────────────┘
Responsibilities:
- Parse command-line arguments (
--agent,--session,--proxy, etc.) - Initialize configuration from environment variables
- Load or create session
- Start CLI/REPL loop
- Handle signals (SIGINT, SIGTERM)
- Cleanup and shutdown
Key Functions:
int main(int argc, char *argv[]);
void parse_arguments(int argc, char *argv[], config_t *config);
void signal_handler(int signum);
void cleanup_and_exit(int exit_code);Responsibilities:
- Load environment variables (ANTHROPIC_API_KEY, CODEOSX_*)
- Validate API key format
- Parse proxy settings
- Set defaults (model, max_tokens, etc.)
Data Structure:
typedef struct {
char api_key[256];
char api_host[256];
int api_port;
int use_https;
char model[128];
int max_tokens;
int prompt_caching;
int max_iterations;
char history_file[512];
char session_db_path[512];
char current_agent[64]; /* "build", "plan", "explore" */
} config_t;Responsibilities:
- TLS 1.2 connection via BearSSL
- POST requests to Claude API
- HTTP header construction
- Response parsing (chunked encoding, SSE)
- Timeout handling
Key Functions:
int http_init(const config_t *config);
int http_post_json(const char *path, const char *json_body,
char **response_body, size_t *response_len);
void http_cleanup(void);BearSSL Integration:
- Link against
libbearssl.a(built from src/bearssl/) - Embed CA certificates in binary (src/bearssl/certs/)
- Use
br_ssl_client_contextfor TLS connections
Responsibilities:
- Manage main agent and subagent execution
- Implement ReAct loop (max 100 iterations)
- Construct Claude API requests (system prompt + messages + tools)
- Parse API responses (extract tool_use blocks)
- Execute tools and collect results
- Handle agent switching (user-initiated or subagent calls)
Data Structures:
typedef enum {
AGENT_BUILD, /* Full access, can call subagents */
AGENT_PLAN, /* Read-only, can ask user questions */
AGENT_EXPLORE /* Search-only: grep, find_files, read_file */
} agent_type_t;
typedef struct {
agent_type_t type;
char system_prompt[8192];
tool_t *available_tools; /* Subset based on agent type */
int num_tools;
int max_iterations;
} agent_t;Key Functions:
agent_t* agent_create(agent_type_t type, const config_t *config);
int agent_chat(agent_t *agent, const char *user_message,
session_t *session, char **response);
int agent_call_subagent(agent_t *parent, agent_type_t subagent_type,
const char *task, session_t *session, char **result);
void agent_destroy(agent_t *agent);Responsibilities:
- SQLite database operations
- Session CRUD (create, read, update, delete)
- Message history management
- Session forking (create child session from parent)
- Undo/redo via message removal
SQLite Schema:
CREATE TABLE sessions (
session_id TEXT PRIMARY KEY,
parent_session_id TEXT,
title TEXT,
agent_type TEXT,
created_at INTEGER,
updated_at INTEGER
);
CREATE TABLE messages (
message_id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL,
role TEXT NOT NULL, /* 'user', 'assistant' */
content TEXT,
tool_use_json TEXT, /* JSON array of tool_use blocks */
tool_result_json TEXT, /* JSON array of tool_result blocks */
created_at INTEGER,
FOREIGN KEY (session_id) REFERENCES sessions(session_id)
);
CREATE INDEX idx_messages_session ON messages(session_id);
CREATE INDEX idx_messages_created ON messages(created_at);Key Functions:
session_t* session_create(const char *db_path, const char *agent_type);
session_t* session_load(const char *db_path, const char *session_id);
int session_add_user_message(session_t *session, const char *content);
int session_add_assistant_message(session_t *session, const char *content,
const char *tool_use_json, const char *tool_result_json);
int session_fork(session_t *parent, session_t **child);
int session_save(session_t *session);
void session_destroy(session_t *session);Responsibilities:
- Register all available tools
- Filter tools based on agent type
- Dispatch tool execution
- Validate tool inputs (basic type checking)
- Return tool results (JSON string)
Data Structure:
typedef struct {
char name[64];
char description[2048];
char input_schema_json[4096]; /* JSON Schema */
tool_handler_fn handler;
} tool_t;
typedef char* (*tool_handler_fn)(const char *input_json, void *context);Tool List (MVP):
read_file- Read file contentswrite_file- Create/overwrite fileedit_file- String replacementlist_directory- Directory listingbash- Execute shell command (fork/exec with timeout)grep- Regex content searchfind_files- Glob pattern file findingtodos_read- Get task listtodos_write- Replace task listtodos_add- Add tasktodos_update- Update task statusask_user- Prompt user for input (interactive)task- Call subagent
Implements: read_file, write_file, edit_file, list_directory
Safety Features:
- Absolute path enforcement
- Path traversal prevention (reject
..in paths) - File size limits (read_file: 50KB, write_file: 10MB)
- Auto-create parent directories (write_file)
Implements: bash
Implementation via fork/exec:
char* bash_handler(const char *input_json, void *context) {
/* Parse JSON to extract "command" field */
/* Block dangerous patterns */
if (is_dangerous_command(command)) {
return create_error_json("Dangerous command blocked");
}
/* Fork and exec with timeout */
pid_t pid = fork();
if (pid == 0) {
/* Child: exec /bin/sh -c command */
execl("/bin/sh", "sh", "-c", command, NULL);
exit(127);
}
/* Parent: wait with 30s timeout */
int status;
if (waitpid_with_timeout(pid, &status, 30) < 0) {
kill(pid, SIGKILL);
return create_error_json("Command timeout");
}
/* Return stdout, stderr, exit_code as JSON */
return create_result_json(stdout_buf, stderr_buf, exit_code);
}Implements: grep, find_files
grep: Recursive regex search
- Uses POSIX regex (
<regex.h>) - File type filtering (skip binaries)
- Result limit: 100 matches
- Line limit: 500 chars per line
find_files: Glob pattern matching
- Custom glob implementation (POSIX
glob()not on Mac OS X 10.0) - Recursive directory traversal
- Result limit: 100 files
Implements: todos_read, todos_write, todos_add, todos_update
Storage: ~/.codeosx/todos.json
JSON Format:
[
{
"content": "Task description",
"status": "pending|in_progress|completed",
"activeForm": "Present continuous description"
}
]Implements: ask_user
Functionality:
- Display question to user
- Show multiple-choice options
- Read user selection
- Return answer to agent
Input JSON:
{
"questions": [{
"question": "Which approach should we use?",
"header": "Strategy",
"multiSelect": false,
"options": [
{"label": "Option A", "description": "Details..."},
{"label": "Option B", "description": "Details..."}
]
}]
}Responsibilities:
- Read user input (readline-style with history)
- Parse slash commands
- Display agent responses (markdown formatted)
- Show animated thinking indicator
- Handle Ctrl+C, Ctrl+D
Slash Commands:
/agent <build|plan|explore>- Switch active agent/save <session_id>- Save current session/load <session_id>- Load existing session/fork- Fork current session/list- List all sessions/clear- Clear message history (keep session)/quit- Exit
Port from LionCode Python:
- Bold:
**text**→ ANSI bold - Italic:
*text*→ ANSI italic (if supported) - Headers:
# Header→ Bold + newline - Code blocks:
```code```→ Cyan, indented - Inline code:
`code`→ Cyan - Lists:
- itemor1. item→ Proper indentation - Tables: ASCII art with alignment
Minimal JSON parser for Claude API responses:
- Parse
{"type": "text", "text": "..."}blocks - Parse
{"type": "tool_use", "id": "...", "name": "...", "input": {...}}blocks - Extract fields:
json_get_string(),json_get_object(),json_get_array() - No full JSON library needed (reduce code size)
Alternative: Use cJSON (single-file library) if custom parser too complex
Helper functions:
read_file_contents(path, buffer, max_size)- File I/O wrapperwrite_file_contents(path, buffer, size)- Write with error handlingcreate_directories(path)- Recursive mkdiris_absolute_path(path)- Validate pathnormalize_path(path)- Resolve.,..get_timestamp()- Unix timestamp for session created_atgenerate_session_id()- ULID or UUID generation
System Prompt (summary):
You are CodeOSX, a coding agent running on Mac OS X. You help users with software
engineering tasks. You have access to:
- File operations (read, write, edit, list)
- Shell commands (bash)
- Search tools (grep, find_files)
- Task management (todos)
- User interaction (ask_user)
- Subagent calling (task)
Use the ReAct pattern:
1. Thought: Reason about what to do
2. Action: Use a tool
3. Observation: Analyze tool result
4. Repeat until task complete
You can call subagents via the 'task' tool:
- plan agent: For read-only exploration and planning
- explore agent: For fast codebase search
When you need user input, use ask_user tool.
Available Tools: All 13 tools
Permissions: Full access (read, write, execute)
System Prompt (summary):
You are CodeOSX in plan mode. You help users explore codebases and create
implementation plans. You have READ-ONLY access to:
- File reading (read_file, list_directory)
- Search tools (grep, find_files)
- User interaction (ask_user)
You CANNOT modify files or execute commands. Your goal is to analyze code,
understand architecture, and propose plans.
Available Tools:
read_file,list_directory,grep,find_files,ask_user
Permissions: Read-only
System Prompt (summary):
You are CodeOSX in explore mode. You specialize in fast codebase exploration.
Your goal is to quickly find files, search for patterns, and answer questions
about code structure.
You have access to:
- Search tools (grep, find_files)
- File reading (read_file)
Be thorough but efficient. Return findings concisely.
Available Tools:
grep,find_files,read_file
Permissions: Read-only
Task Tool:
{
"name": "task",
"description": "Call a subagent to perform a specialized task...",
"input_schema": {
"type": "object",
"properties": {
"subagent_type": {"type": "string", "enum": ["plan", "explore"]},
"description": {"type": "string"},
"prompt": {"type": "string"}
},
"required": ["subagent_type", "prompt"]
}
}Implementation:
- Build agent calls task tool with
subagent_type: "explore" - Agent coordinator creates new explore agent
- Subagent executes with own ReAct loop (limited tools)
- Subagent returns result as string
- Result returned to build agent as tool_result
Session Handling:
- Subagent runs in same session (messages appended)
- OR: Subagent runs in temporary child session (cleaner history)
Location: ~/.codeosx/sessions.db
Tables:
-- Sessions table
CREATE TABLE sessions (
session_id TEXT PRIMARY KEY, -- ULID or UUID
parent_session_id TEXT, -- NULL or parent session ID
title TEXT NOT NULL, -- User-friendly title
agent_type TEXT NOT NULL, -- 'build', 'plan', 'explore'
created_at INTEGER NOT NULL, -- Unix timestamp
updated_at INTEGER NOT NULL, -- Unix timestamp
FOREIGN KEY (parent_session_id) REFERENCES sessions(session_id)
);
-- Messages table
CREATE TABLE messages (
message_id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL,
role TEXT NOT NULL, -- 'user' or 'assistant'
content TEXT, -- Text content (can be NULL if only tool use)
tool_use_json TEXT, -- JSON array of tool_use blocks
tool_result_json TEXT, -- JSON array of tool_result blocks
created_at INTEGER NOT NULL,
FOREIGN KEY (session_id) REFERENCES sessions(session_id)
);
-- Indexes
CREATE INDEX idx_messages_session ON messages(session_id);
CREATE INDEX idx_messages_created ON messages(created_at);
CREATE INDEX idx_sessions_parent ON sessions(parent_session_id);
CREATE INDEX idx_sessions_updated ON sessions(updated_at DESC);Create Session:
session_t* session = session_create(db_path, "build");
/* Auto-generates session_id, sets created_at, title="New Session" */Add Messages:
session_add_user_message(session, "Read the README file");
session_add_assistant_message(session,
"I'll read the README for you.",
"[{\"type\":\"tool_use\",\"id\":\"1\",\"name\":\"read_file\",\"input\":{...}}]",
"[{\"type\":\"tool_result\",\"tool_use_id\":\"1\",\"content\":\"...\"}]"
);Fork Session:
session_t *child;
session_fork(parent_session, &child);
/* Creates new session with parent_session_id set, copies message history */Load Session:
session_t* session = session_load(db_path, "01ARZ3NDEKTSV4RRFFQ69G5FAV");
/* Loads session metadata and all messages from DB */Save Session (auto-save after each turn):
session_save(session); /* Commits pending messages to DB */Targets:
all- Build codeosx for current platformuniversal- Build universal binary (PPC + Intel)clean- Remove build artifactsinstall- Install to /usr/local/bintest- Run basic testsbearssl- Build BearSSL librarysqlite- Build SQLite amalgamation
Example Makefile (simplified):
CC = gcc
CFLAGS = -std=c89 -Wall -Wextra -O2 -I./src -I./src/bearssl/inc -I./src/sqlite
LDFLAGS = -L./build -lbearssl -lsqlite3 -lm
SOURCES = src/main.c src/config.c src/http_client.c src/agent.c \
src/session.c src/cli.c src/markdown.c src/json.c src/util.c \
src/tools/registry.c src/tools/filesystem.c src/tools/shell.c \
src/tools/search.c src/tools/todos.c src/tools/ask_user.c
OBJECTS = $(SOURCES:.c=.o)
all: bearssl sqlite codeosx
bearssl:
cd src/bearssl && $(MAKE) && cp build/libbearssl.a ../../build/
sqlite:
$(CC) $(CFLAGS) -c src/sqlite/sqlite3.c -o build/sqlite3.o
ar rcs build/libsqlite3.a build/sqlite3.o
codeosx: $(OBJECTS)
$(CC) $(OBJECTS) $(LDFLAGS) -o build/codeosx
universal:
$(MAKE) clean
$(MAKE) CC="gcc -arch ppc -arch i386 -arch x86_64"
clean:
rm -rf build/*.o build/codeosx src/**/*.o
install: codeosx
cp build/codeosx /usr/local/bin/
chmod +x /usr/local/bin/codeosx
test: codeosx
./build/codeosx --test-connectionFor PowerPC (Mac OS X 10.0-10.5):
CC="gcc -arch ppc" makeFor Intel i386 (Mac OS X 10.4-10.6):
CC="gcc -arch i386" makeFor Intel x86_64 (Mac OS X 10.6+):
CC="gcc -arch x86_64" makeUniversal Binary (PPC + Intel):
make universalC89 Compliance:
- No
//comments (use/* */) - No variable declarations mid-block
- No inline functions
- No
long long(uselongorint64_tif available)
Test on Modern Mac:
gcc -std=c89 -pedantic -Wall -Wextra src/*.cPOST /v1/messages:
Host: api.anthropic.com
Content-Type: application/json
x-api-key: sk-...
anthropic-version: 2023-06-01
Request Body:
{
"model": "claude-sonnet-4-5-20250929",
"max_tokens": 4096,
"system": [
{"type": "text", "text": "System prompt...", "cache_control": {"type": "ephemeral"}}
],
"messages": [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": [
{"type": "text", "text": "I'll use a tool"},
{"type": "tool_use", "id": "1", "name": "read_file", "input": {"path": "/tmp/file"}}
]},
{"role": "user", "content": [
{"type": "tool_result", "tool_use_id": "1", "content": "File contents..."}
]}
],
"tools": [
{
"name": "read_file",
"description": "Read file contents",
"input_schema": {
"type": "object",
"properties": {"path": {"type": "string"}},
"required": ["path"]
}
}
]
}Cache Control Markers:
- Last item in
systemarray:{"cache_control": {"type": "ephemeral"}} - Last tool in
toolsarray: Same marker - Last user message: Same marker
Benefits:
- Reduce latency (cache hits ~0.3s vs ~2s)
- Reduce cost (90% discount on cached tokens)
- Better for long sessions
| Component | Estimated Size |
|---|---|
| BearSSL | 20 KB |
| SQLite amalgamation | 200 KB (compiled ~100 KB) |
| Main executable | 50 KB |
| Total Binary | ~170 KB |
| Resource | Estimated Size |
|---|---|
| BearSSL buffers | ~16 KB |
| SQLite in-memory cache | ~1 MB |
| Session message history | ~100 KB - 2 MB |
| Tool result buffers | ~50 KB |
| Total Runtime | ~1-5 MB |
Compatible with:
- Mac OS X 10.0 (default ~128 MB RAM)
- Mac OS X 10.4 (default ~256 MB RAM)
See separate document: CODEOSX_TESTING.md
All file tools:
int validate_path(const char *path) {
if (!is_absolute_path(path)) return 0;
if (strstr(path, "..") != NULL) return 0;
if (strstr(path, "~") != NULL) return 0; /* Expand ~ first */
return 1;
}Bash tool:
- Block dangerous patterns:
rm -rf /,mkfs,dd if=,/dev/, fork bombs - Use
execve()instead ofsystem()(no shell interpretation) - Timeout enforcement (30s default)
- Never log API key
- Validate format (starts with
sk-ant-) - Store in environment variable only
read_file: 50 KB maxwrite_file: 10 MB max- Prevent DoS via large file attacks
| Feature | OpenCode | LionCode | CodeOSX (MVP) |
|---|---|---|---|
| Language | TypeScript | Python 2.7 | C89/ANSI C |
| Runtime | Bun/Node | Python 2.7 | Native binary |
| Min OS | macOS 10.13+ | Mac OS X 10.7+ | Mac OS X 10.0+ |
| Binary Size | ~50 MB | ~1 MB (Python) | ~170 KB |
| Dependencies | 100+ npm packages | 0 (stdlib only) | 0 (bundled) |
| TLS | Native Node/Bun | Python ssl | BearSSL |
| Multi-agent | ✅ 7 agents | ❌ Single agent | ✅ 3 agents |
| Session Persist | ✅ JSON files | ❌ None | ✅ SQLite |
| Session Fork | ✅ Yes | ❌ No | ✅ Yes |
| File Tools | ✅ Read/Write/Edit/Glob/Grep | ✅ Read/Write/Edit/List/Grep/Find | ✅ Same |
| Bash Tool | ✅ Persistent shell | ✅ One-shot | ✅ One-shot + timeout |
| Todo Tools | ✅ Yes | ✅ Yes | ✅ Yes |
| Ask User | ✅ Yes (TUI/GUI) | ❌ No | ✅ Yes (CLI) |
| LSP | ✅ Yes | ❌ No | ❌ Not MVP |
| MCP | ✅ Yes | ❌ No | ❌ Not MVP |
| Git Integration | ✅ Deep | ❌ No | |
| Web UI | ✅ Yes | ❌ No | ❌ Not MVP |
| TUI | ✅ Rich TUI | ✅ Basic CLI | ✅ CLI/REPL |
| Plugin System | ✅ Yes | ❌ No | ❌ Not MVP |
| Prompt Caching | ✅ Yes | ✅ Yes | ✅ Yes |
| Streaming | ✅ Full SSE | ❌ No |
-
Git Integration (if libgit2 compatible with 10.0+)
- Repository detection
- Commit creation
- Branch management
- Worktree awareness
-
Streaming Responses
- Server-Sent Events (SSE) parsing
- Incremental display of agent responses
- Animated typing effect
-
Configuration File
.codeosx.jsonor~/.codeosx/config.json- Custom agent prompts
- Custom tool definitions (via external commands)
-
Export/Import Sessions
- Export to JSON
- Import from OpenCode sessions
- Share sessions (encrypt with password)
-
Performance Optimizations
- SQLite connection pooling
- Message history pruning (auto-compaction)
- BearSSL session resumption
-
Advanced Features
- LSP integration (if feasible on old OS)
- MCP support (may require newer OS)
- Multi-provider support (OpenAI, etc.)
-
libgit2 Compatibility:
- Can libgit2 compile on Mac OS X 10.0 with GCC 2.95?
- Alternative: Ship pre-compiled libgit2 for each OS version?
- Fallback: Shell out to
gitcommand (if installed)
-
SQLite Amalgamation Compatibility:
- Test SQLite 3.x on Mac OS X 10.0-10.3
- Verify no POSIX 2008 dependencies
-
BearSSL Compatibility:
- Confirm BearSSL compiles with GCC 2.95 (C89 mode)
- Test TLS 1.2 handshake on old OS
-
C89 Compliance Testing:
- Audit all code for C99/C11 features
- Test with
-std=c89 -pedantic
-
Universal Binary Creation:
- Can we build PPC + Intel + ARM in single binary?
- Or ship separate binaries per architecture?
See CODEOSX_IMPLEMENTATION_PLAN.md for detailed phase breakdown.