Skip to content

Engineering4AI/nanoclaw

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

26 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🦞 NanoClaw

Your personal AI assistant - like Hermes or OpenClaw, but distilled to its essentials.
~2,000 lines of TypeScript. No dashboard. No bloat. Just the loop.

Bun 1.x+ License Lines of code

User: "summarize the errors in app.log from the last 10 minutes"
Bot:  [reads file] [runs grep] β†’ "Found 3 ERROR lines: connection timeout (Γ—2), OOM at 14:32"

NanoClaw in action


Why NanoClaw?

Most agent runtimes ship hundreds of abstractions, dozens of providers, and dashboards you never open. NanoClaw is a design: the fewest moving parts that still make a capable, recoverable personal assistant.

NanoClaw OpenClaw Hermes Agent
Lines of code ~2,000 ~500,000–800,000 ~10,000–15,000
Runtime Bun + TypeScript TS Β· Swift Β· Kotlin Β· more Python
Chat platforms 3 (TG Β· Slack Β· Discord) 20+ (WhatsApp Β· Signal Β· iMessage Β· WeChat Β· IRC Β· …) 6 (TG Β· Discord Β· Slack Β· WhatsApp Β· Signal Β· CLI)
Install bun install npm install -g openclaw + onboard wizard curl … | bash installer
Config Single .env file JSON5 config + openclaw onboard wizard hermes setup wizard + hermes config set
Per-peer concurrency βœ… single-slot pending buffer (newest wins) βœ… βœ…
Voice ❌ βœ… wake word + talk mode (macOS Β· iOS Β· Android) ❌ (memo transcription only)
Subagents ❌ βœ… multi-agent routing βœ… spawn isolated subagents
Self-improvement ❌ ❌ βœ… (DSPy + GEPA)
Skills marketplace ❌ βœ… ClawHub βœ… agentskills.io
Companion apps ❌ βœ… macOS menu bar Β· iOS Β· Android ❌
Deployment Local process Daemon (launchd/systemd) Β· Docker Local Β· Docker Β· SSH Β· Modal (serverless)
Hack-friendly βœ… read in an afternoon Needs weeks to orient Moderate (~10k LOC)

Features

πŸ”„ Agent Loop

Engine

β€’ Streaming tool-call loop
β€’ Parallel tool dispatch
β€’ Retry backoff + token guard

πŸ›  Kernel Tools

Tools

β€’ File read / write / edit
β€’ Shell execution
β€’ Web fetch + web search

πŸ”Œ Provider Abstraction

Providers

β€’ Anthropic + OpenAI
β€’ OpenAI-compatible endpoints
β€’ OpenRouter + local Ollama

πŸ” Safety & Permissions

Safety

β€’ Prompt / auto / read-only modes
β€’ Denied-command prefix matching
β€’ Blocks credential path reads

♻️ State & Recovery

Resilience

β€’ Isolated OS process per run
β€’ External coordination state
β€’ JSONL + SQLite restart recovery


Getting Your API Tokens

You need two tokens: one for the LLM, one for the chat platform.

LLM (pick one)

Provider Where to get it Env var
OpenRouter (recommended) openrouter.ai/keys - free tier available, access to all models OPENROUTER_API_KEY
Anthropic console.anthropic.com/keys ANTHROPIC_API_KEY
OpenAI platform.openai.com/api-keys OPENAI_API_KEY

Chat platform (pick one)

Platform Steps
Discord discord.com/developers/applications - New Application - Bot - Reset Token. Enable Message Content Intent. Invite bot with bot + applications.commands scopes.
Telegram Message @BotFather on Telegram - /newbot - copy the token.
Slack api.slack.com/apps - Create App - Socket Mode on - add chat:write + im:history scopes - install to workspace. You need both SLACK_BOT_TOKEN (xoxb-) and SLACK_APP_TOKEN (xapp-).

Quick Start

git clone https://github.com/Engineering4AI/nanoclaw
cd nanoclaw
bun install                    # core deps
bun install grammy             # + Telegram adapter
# bun install @slack/bolt      # + Slack adapter
# bun install discord.js       # + Discord adapter

cp .env.example .env
# edit .env β€” set your API key + bot token

bun src/main.ts

That's it. First run bootstraps ~/.nanoclaw/config.yaml and workspace files automatically.


Configuration

Everything lives in .env β€” no code changes needed:

# LLM (default: OpenRouter)
OPENROUTER_API_KEY=sk-or-...
NANOCLAW_MODEL=anthropic/claude-sonnet-4-6
NANOCLAW_PROVIDER=openai_compatible
NANOCLAW_BASE_URL=https://openrouter.ai/api/v1

# Platform (pick one)
DISCORD_TOKEN=your-discord-bot-token
# TELEGRAM_TOKEN=your-telegram-bot-token
# SLACK_BOT_TOKEN=xoxb-...
# SLACK_APP_TOKEN=xapp-...

# Agent behavior
NANOCLAW_PERMISSION_MODE=default   # default | auto | plan

# Cron jobs (optional) β€” semicolon-separated: SCHEDULE|PROMPT[|label]
# NANOCLAW_CRON=30m|check disk usage and warn if above 90%|disk;1h|summarize today's errors in ~/app.log|logs

Switch to Anthropic directly:

ANTHROPIC_API_KEY=sk-ant-...
NANOCLAW_PROVIDER=anthropic
NANOCLAW_MODEL=claude-opus-4-8

Architecture

flowchart TD
    TG[Telegram] & SL[Slack] & DC[Discord] --> R

    subgraph Gateway
        R["Router\n(1 lock / peer)"]
        SS[(SessionStore\nbun:sqlite)]
        R <--> SS
    end

    R --> AL

    subgraph AgentLoop["Agent Loop"]
        AL["stream LLM response"] --> TD{tool_use?}
        TD -->|yes| PD["parallel dispatch\n(Promise.all)"]
        TD -->|no| OUT[return text]
        PD --> AL
        AL --> CP["compact @ 80% context"]
        AL --> JP[(JSONL\npersistence)]
    end

    PD --> TR

    subgraph ToolRegistry["Tool Registry"]
        TR["permission_check"] --> PH[pre_hook]
        PH --> EX["execute\n(read Β· write Β· edit Β· bash Β· fetch Β· search)"]
        EX --> POH[post_hook]
        POH --> RS["result ≀ 50 KB"]
    end

    RS --> PD
Loading

File Layout

src/
  main.ts                      # entry point β€” reads env, starts gateway
  config.ts                    # Config interface + YAML load
  permissions.ts               # PermissionPolicy, 3 modes, sensitive-path guard
  hooks.ts                     # pre/post hook registry

  providers/
    base.ts                    # Provider ABC, StreamResponse, ToolUse, ToolResult
    anthropic.ts               # AnthropicProvider β€” backoff on 429/529
    openai.ts                  # OpenAIProvider β€” converts tool schema to OpenAI format
    index.ts                   # getProvider() factory

  tools/
    index.ts                   # Tool type, executeParallel(), buildRegistry()
    files.ts                   # read_file, write_file, edit_file
    shell.ts                   # run_bash (120s timeout)
    web.ts                     # web_fetch (HTML stripped), web_search (DuckDuckGo)

  agent/
    loop.ts                    # run() β€” the agent loop
    compactor.ts               # compact when estimated tokens > 80% context window
    session.ts                 # JSONL append-only persistence per session_id

  memory/
    workspace.ts               # bootstrap AGENTS.md/USER.md, build system prompt

  gateway/
    index.ts                   # GatewayConfig, start()
    session.ts                 # SessionStore β€” bun:sqlite-backed
    router.ts                  # onMessage β†’ lock β†’ agent loop β†’ chunk β†’ deliver
    adapters/
      base.ts                  # ChannelAdapter abstract class
      telegram.ts              # grammy polling
      slack.ts                 # @slack/bolt socket mode
      discord.ts               # discord.js intents

  ui/
    App.tsx                    # React Ink root β€” gateway log + active sessions view
    SessionPanel.tsx           # Per-session message stream
    StatusBar.tsx              # Model Β· permission mode Β· uptime

Persistent Memory

NanoClaw ships with two workspace files that persist across sessions:

  • ~/.nanoclaw/workspace/AGENTS.md β€” operating instructions, task notes, agent persona. Injected as system prompt prefix.
  • ~/.nanoclaw/workspace/USER.md β€” user profile, preferences. Injected after AGENTS.md.

Edit these files to shape how the agent behaves. No vector store, no database β€” just files.


Intentionally Not Included

Feature Add it when...
Multi-agent board You have >1 agent profile needing coordination
MCP servers You hit a tool gap the 6 kernel tools can't cover
Dashboard / TUI Gateway is the interface; the Ink UI is optional
Skills / macros AGENTS.md handles this at minimal scale
Trajectory recording You need RL training data

The One Rule

Each agent run is an OS process. Coordination state lives outside the process.

Session JSONL survives crashes. SQLite session store survives gateway restarts. A restart picks up where it left off. This constraint keeps everything else simple.

About

Minimal personal AI assistant: gateway agent for Telegram, Slack & Discord. ~2,000 lines of TypeScript, no bloat.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors