Super l# PLANCKCLAW — Design Specification for Claude Code
================================================================================ LEVEL 1 — CAPABILITIES
Smallest possible autonomous AI agent binary on Linux x86-64. Target: < 8 KB. The agent follows Unix philosophy: do one thing well, delegate the rest to existing tools on the host machine.
C1 — Receive messages from a human via an interaction bridge (Discord by default). C2 — Discover available tools dynamically from a claw bridge. C3 — Send a prompt (with tool definitions) to a brain bridge (Anthropic Claude by default). C4 — Dispatch tool calls to the claw bridge, relay results back to the brain. C5 — Send the final response back via the interaction bridge. C6 — Maintain persistent memory between sessions: conversation history and an injectable personality/context file. C7 — Run continuously as a long-lived daemon process, listening for incoming messages.
- No embedded TLS (delegated to environment tools)
- No multi-channel (single interaction bridge)
- No hot-reload of bridges (restart to swap)
- No multi-bridge of the same type (one interact, one brain, one tools)
- No cron/webhook triggers (reactive daemon only)
- No web interface or dashboard
- No sophisticated error handling (basic retry, clean crash otherwise)
- No multi-user (single owner)
- Linux x86-64 only
- Agent relies on host tools (curl, websocat, jq) for network transport/TLS
- API keys (Anthropic, Discord Bot Token) provided via environment variables
- Local filesystem is the only storage system
================================================================================ LEVEL 2 — COMPONENTS
The agent itself is a minimalist Unix filter. Network complexity (TLS, HTTP, WebSocket, polling) is delegated to external processes via pipes. The agent only: reads, thinks, writes, remembers.
┌──────────────────┐ │ Discord API │ └───┬──────────▲───┘ │ │ ┌───▼──────────┴───┐ │ BRIDGE INTERACT │ │ (shell script) │ └───┬──────────▲───┘ │ │ interact_in interact_out │ │ ┌───▼──────────┴───┐ ┌──────────────────┐ │ AGENT ├──────────────► BRIDGE CLAW │ │ (~7KB x86-64) ◄──────────────┤ (shell script) │ └───┬──────────▲───┘ └──────────────────┘ │ │ claw_in / claw_out brain_in brain_out │ │ ┌───▼──────────┴───┐ │ BRIDGE BRAIN │ │ (shell script) │ └───┬──────────▲───┘ │ │ ┌───▼──────────┴───┐ │ Anthropic API │ └──────────────────┘
FILESYSTEM: memory/soul.md, memory/history.jsonl, memory/summary.md
The core. The ONLY compiled component. A pure router. Responsibilities: - Main loop: read interact_in → discover tools → build payload → write brain_in → read brain_out → if tool_use: dispatch to claw bridge → loop → write interact_out - Build JSON payload for LLM (inject soul.md + recent history + message + tools) - Parse LLM JSON response (extract text, detect tool_use) using structural JSON parser - Write each exchange to history.jsonl (append-only) - Read soul.md at startup and keep in memory - Read summary.md at startup and keep in memory - Trigger compaction when history exceeds threshold
What it does NOT do: no networking, no TLS, no tool execution, no hardcoded tool definitions.
A shell script (~180 lines) that: - Connects to Discord Gateway via websocat (WebSocket) - Handles Identify, Heartbeat, and MESSAGE_CREATE events - Extracts message text and channel_id with jq - Writes to interact_in (format: channel_id\tmessage\n) - Reads from interact_out and sends responses via Discord REST API with curl - Ignores bot messages (prevents loops)
Dependencies: websocat, jq, curl. Swappable for any other platform.
A shell script (~85 lines) that: - Reads complete JSON payload from brain_in (delimited by \n\n) - Sends it to https://api.anthropic.com/v1/messages via curl - Returns raw JSON response on brain_out (delimited by \n\n) - On failure after retries: returns {"error":"timeout"}\n\n
Dependencies: curl. Swappable for any other LLM provider.
A shell script (~45 lines) that: - On "list_tools\n": returns tools JSON array (Claude-compatible) on claw_out - On "{name}\t{input}\n": executes the tool, returns result on claw_out - Default tools: get_time (date +%s), system_status (/proc/*) - Delimiter: \n\n
Dependencies: none (uses shell builtins and /proc). Extensible by adding case branches.
Not a software component — a file convention: - memory/history.jsonl — One JSON line per message, append-only - memory/soul.md — System prompt, read once at startup, human-editable - memory/summary.md — Cumulative summary, written by LLM during compaction - config.env — Environment variables for tokens and settings
WHY shell scripts for bridges, not all in asm? curl already handles TLS, HTTP/2, certs, retries, redirects. Reimplementing in asm would be thousands of lines for zero functional gain. The "smallest binary" constraint applies to the compiled binary, not the shell ecosystem around it.
WHY FIFOs for IPC? Simplest IPC mechanism on Unix. Zero extra syscalls beyond read() and write(). Zero complex serialization. Makes the agent testable in isolation (pipe text manually).
WHY JSONL for history, not Markdown like OpenClaw? The agent must build a JSON payload for the Claude API. If history is already JSON, no parsing/conversion needed — the agent concatenates lines. In asm, every parsing operation avoided saves hundreds of instructions.
WHY separate Discord bridge and LLM bridge? So you can replace one without touching the other. Want to switch from Discord to Telegram? Rewrite only the Discord bridge. Want to switch from Claude to GPT? Rewrite only the LLM bridge. The compiled agent never changes.
================================================================================ LEVEL 3 — INTERACTIONS
/tmp/planckclaw/interact_in Bridge Interact → Agent (incoming messages)
/tmp/planckclaw/interact_out Agent → Bridge Interact (responses)
/tmp/planckclaw/brain_in Agent → Bridge Brain (JSON payloads)
/tmp/planckclaw/brain_out Bridge Brain → Agent (JSON responses)
/tmp/planckclaw/claw_in Agent → Bridge Claw (discovery + tool calls)
/tmp/planckclaw/claw_out Bridge Claw → Agent (tool defs + results)
All created by the launcher with umask 077 (owner-only, protects API keys in transit).
TIME BRIDGE DISCORD AGENT BRIDGE LLM
──── ────────────── ───── ──────────
t0 websocat receives
MESSAGE_CREATE from
Discord Gateway
t1 jq extracts channel_id
and content
Escape \n and \t
t2 write fifo_in:
"123456789\tHello\n"
t3 read fifo_in (blocking)
parse: channel_id=123456789
msg="Hello"
t4 --- BUILD PROMPT ---
soul.md (in memory)
summary.md (in memory)
last HISTORY_KEEP lines
from history.jsonl
Build JSON payload
t5 write fifo_llm_req:
{complete JSON}\n\n
t6 read fifo_llm_req
curl POST to
api.anthropic.com
t7 <── JSON response
write fifo_llm_res:
{raw JSON}\n\n
t8 read fifo_llm_res
JSON parser: navigate to
content[0].text
t9 --- PERSIST ---
append history.jsonl:
{"role":"user","content":"Hello"}
{"role":"assistant","content":"..."}
t10 --- COMPACTION CHECK ---
if history.jsonl > HISTORY_MAX lines:
trigger compaction sequence
t11 write fifo_out:
"123456789\tLLM response\n"
t12 read fifo_out
parse: channel_id, response
Unescape \\n → \n
curl POST to Discord
REST API sendMessage
t13 loop back to t0
When history.jsonl exceeds HISTORY_MAX lines (200), the agent summarizes old exchanges to free space while preserving context.
TIME AGENT BRIDGE LLM
──── ───── ──────────
c0 history.jsonl has 200+ lines.
Split into two zones:
LINES 0..159 (old) → to compact
LINES 160..199 (recent) → keep as-is
c1 Read memory/summary.md
(existing summary, may be empty)
c2 Build a special compaction prompt:
{
model: claude-haiku-4-5-20241022,
max_tokens: 2048,
system: "You are a memory compaction assistant.
Summarize the following conversation, preserving:
key facts about the user, their preferences,
decisions made, ongoing projects, and important
context. Be concise but complete. Output only the
summary, no preamble.",
messages: [{
role: "user",
content: "EXISTING SUMMARY:\n[summary.md]\n\n
CONVERSATION TO SUMMARIZE:\n[lines 0..159]"
}]
}
c3 write fifo_llm_req
read, curl, response
c4 write fifo_llm_res
c5 read fifo_llm_res
Write response to memory/summary.md
(overwrite, not append)
c6 Rewrite history.jsonl:
keep only lines 160..199
(the last 40)
After compaction, the normal prompt structure becomes:
system: [soul.md contents]
---
CONVERSATION SUMMARY:
[summary.md contents]
messages: [last 40 exchanges from history.jsonl]
+ current message
fifo_in and fifo_out (Discord <-> Agent):
{channel_id}\t{text}\n
- channel_id: decimal ASCII integer (e.g. 1234567890123456789)
- \t: tab character (0x09), separator
- text: UTF-8 content, literal \n replaced by \\n, literal \t replaced by \\t
- \n: message delimiter (0x0A)
Example: 1234567890123456789\tHello how are you?\n
fifo_llm_req and fifo_llm_res (Agent <-> LLM):
{compact JSON on a single line}\n\n
- The double newline (\n\n) is the message delimiter.
- JSON is always compact (single line, never pretty-printed).
- This works because curl returns compact JSON by default.
Situation Behavior
───────── ────────
Bridge LLM: curl fails (timeout, 5xx) Bridge writes {"error":"timeout"}\n\n
on fifo_llm_res. Agent detects "error"
field and writes apology on fifo_out.
Bridge LLM: curl fails 3x in a row Bridge writes {"error":"fatal"}\n\n.
Agent writes "Temporarily unavailable"
and continues listening on fifo_in.
Bridge Discord: WebSocket disconnects sleep 5 with exponential backoff
(max 60s), reconnect.
Agent: history.jsonl corrupted Agent reads line by line, ignores
unparseable lines. Graceful degradation.
Agent: soul.md missing Agent uses hardcoded default system
prompt: "You are a helpful personal
assistant."
A process dies Others block on FIFO (natural behavior).
Launcher can monitor with wait and restart.
================================================================================ LEVEL 4 — CONTRACTS
STARTUP: 1. Read env var PLANCKCLAW_DIR (default: "./memory") 2. Read env var HISTORY_MAX (default: "200") 3. Read env var HISTORY_KEEP (default: "40") 4. Open and read $PLANCKCLAW_DIR/soul.md entirely into memory - If missing → use hardcoded default: "You are a helpful personal assistant." 5. Open and read $PLANCKCLAW_DIR/summary.md entirely into memory - If missing → empty string 6. Open FIFOs: - /tmp/planckclaw/interact_in (O_RDONLY) - /tmp/planckclaw/interact_out (O_WRONLY) - /tmp/planckclaw/brain_in (O_WRONLY) - /tmp/planckclaw/claw_in (O_WRONLY) - brain_out and claw_out opened on-demand to avoid deadlock 7. Enter MAIN LOOP
MAIN LOOP (infinite): 8. read() on interact_in → buffer (blocking) 9. Parse: channel_id, message (separated by \t, terminated by \n) 10. Discovery: write "list_tools\n" to claw_in, read tools JSON array from claw_out until \n\n 11. Read last HISTORY_KEEP lines from history.jsonl 12. Build JSON payload with dynamic tools definitions 13. write() payload to brain_in, terminated by \n\n 14. read() response from brain_out until \n\n (blocking) 15. Parse response JSON: - If stop_reason == "tool_use": a. Extract tool_use_id, name, input from response b. write "{name}\t{input}\n" to claw_in c. read result from claw_out until \n\n d. Build follow-up payload (assistant content + tool_result) e. write to brain_in, read brain_out → loop until text response - If "error" field → response = "I'm temporarily unavailable." - Otherwise → extract content[0].text 16. Append 2 lines to history.jsonl 17. If line count > HISTORY_MAX → Trigger COMPACTION 18. write() response to interact_out: channel_id\tresponse\n 19. Go to step 8
All allocated in .bss (zero binary cost — zeroed by kernel at load).
Name Size Purpose
──── ──── ───────
MAX_MSG_IN 4096 Max incoming message (fifo_in)
MAX_JSON_OUT 65536 Max JSON payload to LLM
MAX_JSON_IN 65536 Max JSON response from LLM
MAX_SOUL 8192 Max soul.md size
MAX_SUMMARY 8192 Max summary.md size
MAX_HISTORY 32768 Max history block injected in prompt
MAX_LINE 4096 Max single line in history.jsonl
Number Name Usage
────── ──── ─────
0 sys_read Read FIFOs and files
1 sys_write Write FIFOs and files
2 sys_open Open files and FIFOs
3 sys_close Close file descriptors
8 sys_lseek Seek in history.jsonl
21 sys_access Check file existence (F_OK)
60 sys_exit Termination
NO fork(). NO exec(). NO mmap(). NO brk(). NO sysinfo(). NO clock_gettime(). Zero dynamic allocation. Tool execution is delegated to the claw bridge.
Normal prompt (compact, single line):
{"model":"claude-haiku-4-5-20241022","max_tokens":1024,"system":"[SOUL.MD CONTENTS]\\n---\\nCONVERSATION SUMMARY:\\n[SUMMARY.MD CONTENTS]","messages":[{"role":"user","content":"msg1"},{"role":"assistant","content":"rep1"},{"role":"user","content":"current_msg"}]}
Construction rules: - Always compact JSON (single line, never pretty-printed) - "system" field = soul.md + "\n---\nCONVERSATION SUMMARY:\n" + summary.md (if summary.md is empty, omit the separator and summary part) - "messages" field = array of last HISTORY_KEEP exchanges from history.jsonl + current message as last element - Special characters in content are JSON-escaped: " → " newline → \n tab → \t backslash → \\
Compaction prompt (compact, single line):
{"model":"claude-haiku-4-5-20241022","max_tokens":2048,"system":"You are a memory compaction assistant. Summarize the following conversation, preserving: key facts about the user, their preferences, decisions made, ongoing projects, and important context. Be concise but complete. Output only the summary, no preamble.","messages":[{"role":"user","content":"EXISTING SUMMARY:\\n[summary.md]\\n\\nCONVERSATION TO SUMMARIZE:\\n[lines 0..N-HISTORY_KEEP from history.jsonl]"}]}
Success response from Anthropic API (compact, single line):
{"id":"msg_01X","type":"message","role":"assistant","content":[{"type":"text","text":"The actual LLM response here"}],"model":"claude-haiku-4-5-20241022","stop_reason":"end_turn"}
The agent's JSON parser must structurally navigate: → find key "content" → enter array → enter first object → find key "text" → extract string value (handling " escapes)
This is NOT a search for the string "text:" — it is structural navigation that knows its depth level and context. This is important for injection safety.
Error response (from bridge, not from API):
{"error":"timeout"}
{"error":"fatal"}
Agent checks: if root-level key "error" exists → use default error message.
interact_in and interact_out (Bridge Interact <-> Agent):
{channel_id}\t{text_with_escaped_newlines}\n
Escaping rules:
Literal newline in message → \\n (two chars: backslash, n)
Literal tab in message → \\t (two chars: backslash, t)
Literal backslash in message → \\\\ (two chars: backslash, backslash)
Example input: 1234567890123456789\tHello how are you?\n
Example output: 1234567890123456789\tI'm fine thanks!\\nHow about you?\n
brain_in and brain_out (Agent <-> Brain Bridge):
{compact JSON}\n\n
Double newline (\n\n) = message delimiter.
JSON is always on a single line (compact).
claw_in and claw_out (Agent <-> Tools Bridge):
Discovery request: __list_tools__\n
Discovery response: [{tool JSON array}]\n\n
Tool call request: {name}\t{input_json}\n
Tool call response: {result_text}\n\n
The tools JSON array is Claude-compatible and injected verbatim into the
brain payload. The agent does not parse or interpret tool definitions.
Interface: Env vars: DISCORD_BOT_TOKEN, DISCORD_CHANNEL_ID FIFO read: /tmp/planckclaw/interact_out FIFO write: /tmp/planckclaw/interact_in Network: wss://gateway.discord.gg (WebSocket via websocat) https://discord.com/api/v10 (REST via curl) Dependencies: websocat, jq, curl
RECEPTION subprocess (WebSocket → fifo_in):
STARTUP:
1. curl GET https://discord.com/api/v10/gateway
→ extract "url" field
2. Open websocat to {url}/?v=10&encoding=json
IDENTIFY:
3. On receiving opcode 10 (Hello):
→ extract heartbeat_interval from d.heartbeat_interval
4. Send Identify payload:
{"op":2,"d":{"token":"$TOKEN","intents":512,"properties":{"os":"linux","browser":"planckclaw","device":"planckclaw"}}}
(intents 512 = GUILD_MESSAGES, bit 9)
LOOP:
5. Read JSON messages from WebSocket (one per line from websocat)
6. For each message:
a. If op=10 (Hello) → already handled
b. If op=11 (Heartbeat ACK) → noop
c. If op=1 or heartbeat_interval elapsed:
→ Send {"op":1,"d":$last_sequence}
d. If op=0 and t="MESSAGE_CREATE":
- Extract .d.channel_id, .d.content, .d.author.id, .d.author.bot
- IGNORE if .d.author.bot == true (prevent loops)
- IGNORE if .d.channel_id != $DISCORD_CHANNEL_ID
- Escape \n → \\n and \t → \\t in content
- Write "{channel_id}\t{content}\n" to fifo_in
e. Store .s (sequence number) for next heartbeat
7. Back to 5
ERROR/DISCONNECT:
- If websocat closes: sleep 5, back to STARTUP
- Exponential backoff: 5s, 10s, 20s, max 60s, reset on success
SEND subprocess (fifo_out → REST):
LOOP:
1. Read fifo_out line by line
2. Parse: channel_id, response (separated by \t)
3. Unescape \\n → newline and \\t → tab
4. curl POST https://discord.com/api/v10/channels/{channel_id}/messages
-H "Authorization: Bot $DISCORD_BOT_TOKEN"
-H "Content-Type: application/json"
-d '{"content":"$response"}'
5. If response > 2000 chars (Discord limit):
→ Split into chunks of 1990 chars
→ Send sequentially
6. Back to 1
ERROR:
- HTTP 429 (rate limit): read Retry-After header, sleep, retry
- Other errors: log to stderr, continue
Interface: Env var: ANTHROPIC_API_KEY FIFO read: /tmp/planckclaw/brain_in FIFO write: /tmp/planckclaw/brain_out Dependencies: curl
LOOP: 1. Read brain_in until empty line (\n\n) → store in variable $payload 2. curl POST https://api.anthropic.com/v1/messages 3. If success (HTTP 200): → write JSON response + \n\n to brain_out 4. If failure after retries: → write {"error":"timeout"}\n\n to brain_out 5. Back to 1
Interface: Env vars: (none required) FIFO read: /tmp/planckclaw/claw_in FIFO write: /tmp/planckclaw/claw_out Dependencies: none (shell builtins + /proc)
LOOP: 1. Read claw_in line by line 2. If line == "list_tools": → write tools JSON array + \n\n to claw_out 3. If line == "{name}\t{input}": → execute tool, write result + \n\n to claw_out 4. Back to 1
Default tools: get_time → date +%s system_status → /proc/uptime, /proc/meminfo, /proc/loadavg
#!/bin/sh
. ./config.env
umask 077
mkdir -p /tmp/planckclaw memory
mkfifo /tmp/planckclaw/interact_in
mkfifo /tmp/planckclaw/interact_out
mkfifo /tmp/planckclaw/brain_in
mkfifo /tmp/planckclaw/brain_out
mkfifo /tmp/planckclaw/claw_in
mkfifo /tmp/planckclaw/claw_out
[ -f memory/soul.md ] || echo "You are a helpful personal assistant." > memory/soul.md
[ -f memory/history.jsonl ] || touch memory/history.jsonl
[ -f memory/summary.md ] || touch memory/summary.md
./bridge_brain.sh &
./bridge_claw.sh &
./planckclaw &
./bridge_discord.sh &
wait
export DISCORD_BOT_TOKEN="MTI3..."
export DISCORD_CHANNEL_ID="1234567890123456789"
export ANTHROPIC_API_KEY="sk-ant-..."
export PLANCKCLAW_DIR="./memory"
export HISTORY_MAX="200"
export HISTORY_KEEP="40"
memory/soul.md — Free-form UTF-8 text. Example:
You are Planck, a minimalist personal assistant.
You respond in French by default.
You are concise and direct.
You remember previous conversations through your summary.
memory/summary.md — Free-form UTF-8, written by LLM during compaction. Overwritten each time. Example:
The user's name is Marc. He works in tech.
He is interested in minimalist AI agents and x86-64 assembly.
He prefers responses in French, concise.
Current project: building the smallest possible AI agent (planckclaw).
memory/history.jsonl — One JSON object per line. Always in user/assistant pairs.
{"role":"user","content":"Hello"}
{"role":"assistant","content":"Hi! How are you?"}
{"role":"user","content":"Can you explain Unix FIFOs?"}
{"role":"assistant","content":"FIFOs (named pipes) are..."}
planckclaw/
├── planckclaw.asm # Agent — x86-64 NASM assembly source
├── Makefile # nasm + ld → planckclaw binary (~7 KB)
├── planckclaw.sh # Launcher (6 FIFOs, 4 processes)
├── bridge_discord.sh # Bridge Interact — Discord (websocat + jq + curl)
├── bridge_brain.sh # Bridge Brain — Anthropic API (curl)
├── bridge_claw.sh # Bridge Claw — tool discovery + execution
├── config.env.example # Config template
├── memory/
│ ├── soul.md # Persistent system prompt
│ ├── summary.md # Cumulative summary (generated)
│ └── history.jsonl # Raw history (generated)
└── README.md
ASM = nasm
LDFLAGS = -s -n
TARGET = planckclaw
all: $(TARGET)
$(TARGET): planckclaw.o
ld $(LDFLAGS) -o $@ $
planckclaw.o: planckclaw.asm
$(ASM) -f elf64 -o $@ $
size: $(TARGET)
wc -c $(TARGET)
size $(TARGET)
clean:
rm -f planckclaw.o $(TARGET)
.PHONY: all size clean
ld flags: -s : strip symbols (saves ~1-2 KB) -n : no page alignment (allows more compact ELF binary)
Component Requires Default on Linux?
───────── ──────── ─────────────────
Agent nothing (static bin) N/A — this is our binary
Bridge Interact websocat, jq, curl curl: yes. jq: usually. websocat: MUST INSTALL
Bridge Brain curl yes
Bridge Claw nothing (sh + /proc) yes
Launcher sh, mkfifo, mkdir yes (POSIX)
websocat install: cargo install websocat or download static binary (~3 MB) from GitHub releases.
The agent implements a STRUCTURAL JSON parser, not pattern matching. This is critical for injection safety.
The parser is a state machine with these states: STATE_ROOT — expecting { to start object STATE_KEY — inside object, expecting "key" STATE_COLON — expecting : after key STATE_VALUE — expecting value (string, number, object, array, bool, null) STATE_STRING — inside a "string", handling " escapes STATE_ARRAY — inside [...], tracking index STATE_OBJECT — inside {...}, tracking depth
The parser tracks: - Current nesting depth (incremented on { or [, decremented on } or ]) - Current array index (incremented on , within arrays) - A "path target" to match against (e.g., content.0.text)
Navigation algorithm for extracting content[0].text: 1. Enter root object (depth 0) 2. Scan keys at depth 0 until key == "content" 3. Enter array (depth 1) 4. Enter first element at index 0 (depth 2, it's an object) 5. Scan keys at depth 2 until key == "text" 6. Extract the string value (handling " and \\ escapes) 7. Return extracted string
For error detection: 1. Enter root object (depth 0) 2. Scan keys at depth 0. If key == "error" → return error flag 3. If key == "content" → proceed with normal extraction
This parser does NOT need to handle: - Numbers (we never extract numeric values) - Booleans or null (we never extract these) - Nested objects beyond depth 3 - Unicode escape sequences \uXXXX (pass through as-is) - Pretty-printed JSON (input is always compact single-line)
Estimated size: ~500-700 bytes of x86-64 assembly.
================================================================================ IMPLEMENTATION NOTES FOR CLAUDE CODE
PRIORITY ORDER: 1. bridge_brain.sh (simplest, can test API connectivity) 2. bridge_claw.sh (test tool discovery and execution) 3. bridge_discord.sh (test Discord connectivity) 4. planckclaw.asm (the core — pure router) 5. planckclaw.sh (launcher with 6 FIFOs) 6. Makefile (trivial) 7. config.env.example (trivial) 8. README.md (document everything)
TESTING STRATEGY: - Test bridge_brain.sh independently: echo '{"model":"claude-haiku-4-5-20251001","max_tokens":64,"messages":[{"role":"user","content":"Say hello"}]}' > /tmp/planckclaw/brain_in and read from brain_out - Test bridge_claw.sh independently: echo 'list_tools' > /tmp/planckclaw/claw_in and read from claw_out - Test agent independently by piping text to interact_in manually and reading from interact_out, with both bridges running - Test bridge_discord.sh independently by monitoring interact_in output
ASM TIPS: - Use section .bss for all buffers (zero binary cost) - Use section .data for constant strings (system prompt default, JSON templates, FIFO paths) - Use section .text for code - All syscalls via: mov rax, SYSCALL_NUM; syscall - String operations: use rep movsb, rep stosb, repne scasb - The JSON builder can use a "template + fill" approach: pre-store JSON skeleton in .data with placeholder markers, copy to buffer, then memcpy variable content at marker positions
BINARY SIZE TARGET: < 8 KB If the binary exceeds 8 KB, optimize: - Remove any unused code paths - Shorten constant strings - Combine similar subroutines - Use shorter instruction encodings where possible