Skillshub nix-agent-tool-design

nix Agent Tool Design

install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/Mind-Dragon/atoolix/nix-agent-tool-design" ~/.claude/skills/comeonoliver-skillshub-nix-agent-tool-design && rm -rf "$T"
manifest: skills/Mind-Dragon/atoolix/nix-agent-tool-design/SKILL.md
source content

*nix Agent Tool Design

A single

run(command="...")
tool with Unix-style commands outperforms a catalog of typed function calls.

Credit: This design was authored by the backend lead at Manus and is implemented in the open-source agent-clip runtime by @epiral. This skill packages that knowledge for use in OpenCode, OpenClaw, and Pinix.


Core Philosophy

Unix and LLMs made the same architectural decision 50 years apart: everything is text.

  • Unix: text streams, pipes, exit codes,
    --help
    , stderr
  • LLMs: tokens in, tokens out — they only understand and produce text

This convergence means the Unix terminal interface is the LLM's native tool interface. Don't invent a new one.


Principle 1: Single
run
Tool

Replace a catalog of typed function calls with one tool:

run(command="...")

All capabilities exposed as CLI subcommands. The LLM composes strings instead of switching between unrelated API schemas.

Why it works:

  • LLMs have seen billions of shell commands in training data — they already know CLI
  • Command selection = string composition in one namespace
  • Function selection = context-switching between N unrelated APIs
  • Reduces "which tool?" cognitive load; agent focuses on "what do I need?"

Example reduction:

# Function-calling (3 calls):
read_file(path="/var/log/app.log")
search_text(text=<file>, pattern="ERROR")
count_lines(text=<matches>)

# CLI (1 call):
run(command="cat /var/log/app.log | grep ERROR | wc -l")

Principle 2: Chain Parser (
parseChain
)

Support four Unix chain operators so a single tool call = a complete workflow:

OperatorBehavior
|
Pipe: stdout of previous → stdin of next
&&
And: next only if previous succeeded (exit 0)
||
Or: next only if previous failed (exit ≠ 0)
;
Seq: next regardless of result

Examples:

curl -sL $URL -o data.csv && cat data.csv | head 5    # download → inspect
cat access.log | grep "500" | sort | head 10           # read → filter → sort → top 10
cat config.yaml || echo "config not found, using defaults"  # try A, fall back to B

Principle 3: Progressive
--help
Discovery (3 levels)

Never stuff full documentation into the system prompt. Use progressive disclosure:

Level 0 — Tool description → command list (injected at conversation start)

Available commands:
  cat    — Read a text file. For images use 'see'. For binary use 'cat -b'.
  see    — View an image (auto-attaches to vision)
  ls     — List files in current topic
  write  — Write file. Usage: write <path> [content] or stdin
  grep   — Filter lines matching a pattern (supports -i, -v, -c)
  memory — Search or manage memory
  clip   — Operate external environments (sandboxes, services)

Level 1 —

command
with no args → usage string

run(command="memory")
→ [error] memory: usage: memory search|recent|store|facts|forget

Level 2 —

command subcommand
with missing args → specific parameters

run(command="memory search")
→ [error] memory: usage: memory search <query> [-t topic_id] [-k keyword]

Requirement: Every command and subcommand MUST have complete help output. A good help message means one-shot success. A missing one means a blind guess.


Principle 4: Error Messages as Navigation

Every error must contain: what went wrong + what to do instead.

# Traditional (useless to agents):
cat: binary file (standard output)

# Agent-optimized:
[error] cat: binary image file (182KB). Use: see photo.png
[error] unknown command: foo — Available: cat, ls, see, write, grep, memory, clip
[error] clip "sandbox" not found. Use 'clip list' to see available clips

Production lesson: Silent stderr caused 10 blind retries to find the right package manager. Always surface stderr on failure.

# WRONG:
if stdout != "": discard stderr

# RIGHT:
always attach stderr on failure:
output + "\n[stderr] " + stderr

Principle 5: Consistent Output Format

Append

[exit:N | Xms]
to every tool result:

file1.txt
file2.txt
dir1/
[exit:0 | 12ms]

Exit code semantics (LLMs already know these):

  • exit:0
    — success
  • exit:1
    — general error
  • exit:127
    — command not found

Duration signals cost:

  • 12ms
    — cheap, call freely
  • 3.2s
    — moderate
  • 45s
    — expensive, use sparingly

Consistent format = agent internalizes pattern over the conversation. Inconsistency makes every call feel like the first.


Principle 6: Two-Layer Architecture (CRITICAL)

Raw command output ≠ what the LLM should receive. Two hard LLM constraints drive this:

  • Constraint A: Context window is finite and expensive
  • Constraint B: LLMs cannot process binary data (produces meaningless high-entropy tokens that degrade surrounding attention)
┌─────────────────────────────────────────────────┐
│  Layer 2: LLM Presentation Layer                │  ← Designed for LLM constraints
│  Binary guard | Truncation+overflow | Meta      │
├─────────────────────────────────────────────────┤
│  Layer 1: Unix Execution Layer                  │  ← Pure Unix semantics
│  Command routing | pipe | chain | exit code     │
└─────────────────────────────────────────────────┘

CRITICAL: Layer 1 must be raw, lossless, metadata-free. If you truncate in Layer 1,

grep
only searches the first 200 lines. If you add
[exit:0]
in Layer 1, it becomes grep data. Processing only happens in Layer 2.

Layer 2 Mechanisms

A. Binary Guard

Null byte detected → binary
UTF-8 validation failed → binary  
Control character ratio > 10% → binary

→ [error] binary image (182KB). Use: see photo.png
→ [error] binary file (1.2MB). Use: cat -b file.bin

B. Overflow Mode

Output > 200 lines or > 50KB?
  → Truncate to first 200 lines (rune-safe)
  → Write full output to /tmp/cmd-output/cmd-{n}.txt
  → Return:
    [first 200 lines]
    --- output truncated (5000 lines, 245.3KB) ---
    Full output: /tmp/cmd-output/cmd-3.txt
    Explore: cat /tmp/cmd-output/cmd-3.txt | grep <pattern>
             cat /tmp/cmd-output/cmd-3.txt | tail 100
    [exit:0 | 1.2s]

The agent already knows

grep
,
head
,
tail
— overflow mode turns large data into a familiar navigation problem.

C. Metadata Footer

[exit:0 | 1.2s]

Appended after the pipe chain completes. Never in Layer 1.

D. stderr Attachment

output + "\n[stderr] " + stderr

Always on failure. Never drop it when stdout is non-empty.


When NOT to Use CLI

Typed APIs may be better when:

  • Strongly-typed interactions — DB queries, GraphQL, schema validation required
  • High security — CLI string concatenation has injection risk; use typed params + sandbox isolation
  • Native multimodal — Pure audio/video binary stream processing

Safety boundaries are external (not iteration limits):

  • Sandbox isolation (e.g., BoxLite containers)
  • API spending caps
  • User cancellation with graceful shutdown

Production War Stories

StoryRoot CauseFixLesson
PNG caused 20 iterations of thrashingNo binary guard in Layer 2
isBinary()
+
Use: see photo.png
Return garbage = agent goes blind
10 blind retries to find package managerSilent stderr when stdout non-emptyAlways attach stderr on failurestderr is most needed when commands fail
5,000-line log overwhelmed contextNo overflow modeTruncate + write to /tmp + give explore commandsA map beats the entire territory

Implementation Reference

Original implementation by @epiral:

RepoDescription
epiral/agent-clipThe agent as a Pinix Clip — full Go implementation of these principles
epiral/pinixDecentralized runtime platform that hosts Clips (BoxLite micro-VMs, Edge Clips)
FileResponsibility
internal/tools.go
Command routing, single
run
entry point
internal/chain.go
Pipe/&&/||/; chain parser
internal/loop.go
Two-layer agentic loop
internal/fs.go
Binary guard
internal/clip.go
stderr handling
internal/browser.go
Vision auto-attach
internal/memory.go
Semantic memory commands