Ultra-lightweight and efficient personal AI assistant
Go
325
119 commits
updated Mar 24, 2026
Clawlet is a lightweight personal AI agent with hybrid semantic memory search — a single static binary with no runtime and no CGO.
Bundled SQLite + sqlite-vec. Drop it on any machine and memory search just works.
This project is inspired by OpenClaw and nanobot.
Download from GitHub Releases.
macOS (Apple Silicon):
curl -L https://github.com/mosaxiv/clawlet/releases/latest/download/clawlet_Darwin_arm64.tar.gz | tar xz
mv clawlet ~/.local/bin/
# Initialize
clawlet onboard \
--openrouter-api-key "sk-or-..." \
--model "openrouter/anthropic/claude-sonnet-4.5"
# Check effective configuration
clawlet status
# Chat
clawlet agent -m "What is 2+2?"
~/.clawlet/config.json)Config file: ~/.clawlet/config.json
clawlet currently supports these LLM providers:
openai/<model>, API key: env.OPENAI_API_KEY)openai-codex/<model>, no API key; login: clawlet provider login openai-codex)openrouter/<provider>/<model>, API key: env.OPENROUTER_API_KEY)anthropic/<model>, API key: env.ANTHROPIC_API_KEY)gemini/<model>, API key: env.GEMINI_API_KEY or env.GOOGLE_API_KEY)ollama/<model> or local/<model>, default base URL: http://localhost:11434/v1, API key optional)Minimal config (OpenRouter):
{
"env": { "OPENROUTER_API_KEY": "sk-or-..." },
"agents": { "defaults": { "model": "openrouter/anthropic/claude-sonnet-4-5" } }
}
Agent generation defaults are configurable:
{
"agents": {
"defaults": {
"model": "openrouter/anthropic/claude-sonnet-4-5",
"maxTokens": 8192,
"temperature": 0.7
}
}
}
Minimal config (Local via Ollama):
{
"agents": { "defaults": { "model": "ollama/qwen2.5:14b" } }
}
Minimal config (Local via vLLM using the same ollama/ route):
{
"agents": { "defaults": { "model": "ollama/meta-llama/Llama-3.1-8B-Instruct" } },
"llm": { "baseURL": "http://localhost:8000/v1" }
}
OpenAI Codex (OAuth):
# one-time login
clawlet provider login openai-codex
# headless environment (SSH / container)
clawlet provider login openai-codex --device-code
{
"agents": { "defaults": { "model": "openai-codex/gpt-5.1-codex" } }
}
To enable semantic memory search, add memorySearch to the agent defaults:
{
"env": {
"OPENAI_API_KEY": "sk-..."
},
"agents": {
"defaults": {
"memorySearch": {
"enabled": true,
"provider": "openai",
"model": "text-embedding-3-small"
}
}
}
}
Local embedding (Ollama / OpenAI-compatible local endpoint):
{
"agents": {
"defaults": {
"memorySearch": {
"enabled": true,
"provider": "openai",
"model": "nomic-embed-text",
"remote": {
"baseURL": "http://localhost:11434/v1"
}
}
}
}
}
When enabled:
memory_search and memory_get tools for retrieving past context.MEMORY.md, memory.md, and memory/**/*.md for retrieval.{workspace}/.memory/index.sqlite.When disabled (default):
memorySearch.enabled defaults to false; the search tools are not exposed to the model.memory/MEMORY.md, memory/YYYY-MM-DD.md) are still injected into context as usual.tools.restrictToWorkspace defaults to true (tools can only access files inside the workspace directory)gateway.listen defaults to 127.0.0.1:18790gateway.allowPublicBind defaults to false| Item | Status | Details |
|---|---|---|
| Gateway not publicly exposed | ✅ | Default bind is localhost only. Public bind is rejected unless gateway.allowPublicBind=true is explicitly set. |
Filesystem scoped (no /) | ✅ | File tools block root path, path traversal, encoded traversal, symlink escapes, and sensitive state paths. |
| Exec tool dangerous-command guard | ✅ | exec blocks unsafe shell constructs (command chaining, unsafe expansions, redirection/tee, dangerous patterns), blocks sensitive paths, and passes only allowlisted environment variables to subprocesses. |
Inbound channel messages can include attachments. clawlet can:
Configure under tools.media (the values below are the current default values):
{
"tools": {
"media": {
"enabled": true,
"audioEnabled": true,
"imageEnabled": true,
"attachmentEnabled": true,
"maxAttachments": 4,
"maxFileBytes": 20971520,
"maxInlineImageBytes": 5242880,
"maxTextChars": 12000,
"downloadTimeoutSec": 20
}
}
}
Chat app integrations are configured under channels (examples below).
Uses Telegram Bot API long polling (getUpdates) so no public webhook endpoint is required.
@BotFather and copy the bot token.allowFrom.
@).Example config (merge into ~/.clawlet/config.json):
{
"channels": {
"telegram": {
"enabled": true,
"token": "123456:ABCDEF...",
"allowFrom": ["123456789"]
}
}
}
Then run:
clawlet gateway
Uses WhatsApp Web Multi-Device. No Meta webhook/public endpoint is required.
allowFrom.clawlet channels login --channel whatsappLinked devices.clawlet gateway.Example config (merge into ~/.clawlet/config.json):
{
"channels": {
"whatsapp": {
"enabled": true,
"allowFrom": ["15551234567"]
}
}
}
Then run:
# one-time login (required before gateway)
clawlet channels login --channel whatsapp
# normal runtime
clawlet gateway
Notes:
~/.clawlet/whatsapp-auth/session.db.sessionStorePath if needed.clawlet gateway does not perform QR login; if not linked, it exits with a login command hint.Create the bot and copy the token
Go to https://discord.com/developers/applications, create an application, then Bot → Add Bot. Copy the bot token.
Invite the bot to your server (OAuth2 URL Generator)
In OAuth2 → URL Generator, choose Scopes: bot. For Bot Permissions, the minimal set is View Channels, Send Messages, Read Message History. Open the generated URL and add the bot to your server.
Enable Message Content Intent (required for guild message text) In the Developer Portal bot settings, enable MESSAGE CONTENT INTENT. Without it, the bot won't receive message text in servers.
Get your User ID (for allowFrom)
Enable Developer Mode in Discord settings, then right-click your profile and select Copy User ID.
Configure clawlet
channels.discord.allowFrom is the list of user IDs allowed to talk to the agent (empty = allow everyone).
Example config (merge into ~/.clawlet/config.json):
{
"channels": {
"discord": {
"enabled": true,
"token": "YOUR_BOT_TOKEN",
"allowFrom": ["YOUR_USER_ID"]
}
}
}
clawlet gateway
Uses Socket Mode (no public URL required). clawlet currently supports Socket Mode only.
xapp-...) with connections:writechat:write, reactions:write, app_mentions:read, im:history, channels:historymessage.im, message.channels, app_mentionxoxb-...)channels.slack.enabled=true, and configure botToken + appToken.
Example config (merge into ~/.clawlet/config.json):
{
"channels": {
"slack": {
"enabled": true,
"botToken": "xoxb-...",
"appToken": "xapp-...",
"groupPolicy": "mention",
"allowFrom": ["U012345"]
}
}
}
Then run:
clawlet gateway
| Command | Description |
|---|---|
clawlet onboard | Initialize a workspace and write a minimal config. |
clawlet status | Print the effective configuration (after defaults and routing). |
clawlet agent | Run the agent in CLI mode (interactive or single message). |
clawlet gateway | Run the long-lived gateway (channels + cron + heartbeat). |
clawlet channels status | Show which chat channels are enabled/configured. |
clawlet cron list | List scheduled jobs. |
clawlet cron add | Add a scheduled job. |
clawlet cron remove | Remove a scheduled job. |
clawlet cron toggle | Enable/disable a scheduled job. |
clawlet cron run | Run a job immediately. |
clawlet cron add formats--message is required, and exactly one of --every, --cron, or --at must be set.
# Every N seconds
clawlet cron add --message "summarize my inbox" --every 3600
# Cron expression (5-field)
clawlet cron add --message "daily standup notes" --cron "0 9 * * 1-5"
# Run once at a specific time (RFC3339)
clawlet cron add --message "remind me" --at "2026-02-10T09:00:00Z"
# Deliver to a chat (requires both --channel and --to)
clawlet cron add --message "ping" --every 600 --channel slack --to U012345
Pre-built images are available on GitHub Container Registry:
# docker-compose.yml
services:
clawlet:
image: ghcr.io/mosaxiv/clawlet:latest
volumes:
- ~/.clawlet:/root/.clawlet
command: gateway
restart: unless-stopped
docker compose up -d
# Build the image
docker build -t clawlet .
# Initialize config (first time only)
docker run -v ~/.clawlet:/root/.clawlet --rm clawlet onboard
# Edit config on host to add API keys
vim ~/.clawlet/config.json
# Run the gateway
docker run -v ~/.clawlet:/root/.clawlet clawlet gateway
# Or run a single command
docker run -v ~/.clawlet:/root/.clawlet --rm clawlet agent -m "Hello"
docker run -v ~/.clawlet:/root/.clawlet --rm clawlet status
Go
97.1%
Shell
1.5%
Go Template
1.3%
Ultra-lightweight and efficient personal AI assistant
Go
325
119 commits
updated Mar 24, 2026
Clawlet is a lightweight personal AI agent with hybrid semantic memory search — a single static binary with no runtime and no CGO.
Bundled SQLite + sqlite-vec. Drop it on any machine and memory search just works.
This project is inspired by OpenClaw and nanobot.
Download from GitHub Releases.
macOS (Apple Silicon):
curl -L https://github.com/mosaxiv/clawlet/releases/latest/download/clawlet_Darwin_arm64.tar.gz | tar xz
mv clawlet ~/.local/bin/
# Initialize
clawlet onboard \
--openrouter-api-key "sk-or-..." \
--model "openrouter/anthropic/claude-sonnet-4.5"
# Check effective configuration
clawlet status
# Chat
clawlet agent -m "What is 2+2?"
~/.clawlet/config.json)Config file: ~/.clawlet/config.json
clawlet currently supports these LLM providers:
openai/<model>, API key: env.OPENAI_API_KEY)openai-codex/<model>, no API key; login: clawlet provider login openai-codex)openrouter/<provider>/<model>, API key: env.OPENROUTER_API_KEY)anthropic/<model>, API key: env.ANTHROPIC_API_KEY)gemini/<model>, API key: env.GEMINI_API_KEY or env.GOOGLE_API_KEY)ollama/<model> or local/<model>, default base URL: http://localhost:11434/v1, API key optional)Minimal config (OpenRouter):
{
"env": { "OPENROUTER_API_KEY": "sk-or-..." },
"agents": { "defaults": { "model": "openrouter/anthropic/claude-sonnet-4-5" } }
}
Agent generation defaults are configurable:
{
"agents": {
"defaults": {
"model": "openrouter/anthropic/claude-sonnet-4-5",
"maxTokens": 8192,
"temperature": 0.7
}
}
}
Minimal config (Local via Ollama):
{
"agents": { "defaults": { "model": "ollama/qwen2.5:14b" } }
}
Minimal config (Local via vLLM using the same ollama/ route):
{
"agents": { "defaults": { "model": "ollama/meta-llama/Llama-3.1-8B-Instruct" } },
"llm": { "baseURL": "http://localhost:8000/v1" }
}
OpenAI Codex (OAuth):
# one-time login
clawlet provider login openai-codex
# headless environment (SSH / container)
clawlet provider login openai-codex --device-code
{
"agents": { "defaults": { "model": "openai-codex/gpt-5.1-codex" } }
}
To enable semantic memory search, add memorySearch to the agent defaults:
{
"env": {
"OPENAI_API_KEY": "sk-..."
},
"agents": {
"defaults": {
"memorySearch": {
"enabled": true,
"provider": "openai",
"model": "text-embedding-3-small"
}
}
}
}
Local embedding (Ollama / OpenAI-compatible local endpoint):
{
"agents": {
"defaults": {
"memorySearch": {
"enabled": true,
"provider": "openai",
"model": "nomic-embed-text",
"remote": {
"baseURL": "http://localhost:11434/v1"
}
}
}
}
}
When enabled:
memory_search and memory_get tools for retrieving past context.MEMORY.md, memory.md, and memory/**/*.md for retrieval.{workspace}/.memory/index.sqlite.When disabled (default):
memorySearch.enabled defaults to false; the search tools are not exposed to the model.memory/MEMORY.md, memory/YYYY-MM-DD.md) are still injected into context as usual.tools.restrictToWorkspace defaults to true (tools can only access files inside the workspace directory)gateway.listen defaults to 127.0.0.1:18790gateway.allowPublicBind defaults to false| Item | Status | Details |
|---|---|---|
| Gateway not publicly exposed | ✅ | Default bind is localhost only. Public bind is rejected unless gateway.allowPublicBind=true is explicitly set. |
Filesystem scoped (no /) | ✅ | File tools block root path, path traversal, encoded traversal, symlink escapes, and sensitive state paths. |
| Exec tool dangerous-command guard | ✅ | exec blocks unsafe shell constructs (command chaining, unsafe expansions, redirection/tee, dangerous patterns), blocks sensitive paths, and passes only allowlisted environment variables to subprocesses. |
Inbound channel messages can include attachments. clawlet can:
Configure under tools.media (the values below are the current default values):
{
"tools": {
"media": {
"enabled": true,
"audioEnabled": true,
"imageEnabled": true,
"attachmentEnabled": true,
"maxAttachments": 4,
"maxFileBytes": 20971520,
"maxInlineImageBytes": 5242880,
"maxTextChars": 12000,
"downloadTimeoutSec": 20
}
}
}
Chat app integrations are configured under channels (examples below).
Uses Telegram Bot API long polling (getUpdates) so no public webhook endpoint is required.
@BotFather and copy the bot token.allowFrom.
@).Example config (merge into ~/.clawlet/config.json):
{
"channels": {
"telegram": {
"enabled": true,
"token": "123456:ABCDEF...",
"allowFrom": ["123456789"]
}
}
}
Then run:
clawlet gateway
Uses WhatsApp Web Multi-Device. No Meta webhook/public endpoint is required.
allowFrom.clawlet channels login --channel whatsappLinked devices.clawlet gateway.Example config (merge into ~/.clawlet/config.json):
{
"channels": {
"whatsapp": {
"enabled": true,
"allowFrom": ["15551234567"]
}
}
}
Then run:
# one-time login (required before gateway)
clawlet channels login --channel whatsapp
# normal runtime
clawlet gateway
Notes:
~/.clawlet/whatsapp-auth/session.db.sessionStorePath if needed.clawlet gateway does not perform QR login; if not linked, it exits with a login command hint.Create the bot and copy the token
Go to https://discord.com/developers/applications, create an application, then Bot → Add Bot. Copy the bot token.
Invite the bot to your server (OAuth2 URL Generator)
In OAuth2 → URL Generator, choose Scopes: bot. For Bot Permissions, the minimal set is View Channels, Send Messages, Read Message History. Open the generated URL and add the bot to your server.
Enable Message Content Intent (required for guild message text) In the Developer Portal bot settings, enable MESSAGE CONTENT INTENT. Without it, the bot won't receive message text in servers.
Get your User ID (for allowFrom)
Enable Developer Mode in Discord settings, then right-click your profile and select Copy User ID.
Configure clawlet
channels.discord.allowFrom is the list of user IDs allowed to talk to the agent (empty = allow everyone).
Example config (merge into ~/.clawlet/config.json):
{
"channels": {
"discord": {
"enabled": true,
"token": "YOUR_BOT_TOKEN",
"allowFrom": ["YOUR_USER_ID"]
}
}
}
clawlet gateway
Uses Socket Mode (no public URL required). clawlet currently supports Socket Mode only.
xapp-...) with connections:writechat:write, reactions:write, app_mentions:read, im:history, channels:historymessage.im, message.channels, app_mentionxoxb-...)channels.slack.enabled=true, and configure botToken + appToken.
Example config (merge into ~/.clawlet/config.json):
{
"channels": {
"slack": {
"enabled": true,
"botToken": "xoxb-...",
"appToken": "xapp-...",
"groupPolicy": "mention",
"allowFrom": ["U012345"]
}
}
}
Then run:
clawlet gateway
| Command | Description |
|---|---|
clawlet onboard | Initialize a workspace and write a minimal config. |
clawlet status | Print the effective configuration (after defaults and routing). |
clawlet agent | Run the agent in CLI mode (interactive or single message). |
clawlet gateway | Run the long-lived gateway (channels + cron + heartbeat). |
clawlet channels status | Show which chat channels are enabled/configured. |
clawlet cron list | List scheduled jobs. |
clawlet cron add | Add a scheduled job. |
clawlet cron remove | Remove a scheduled job. |
clawlet cron toggle | Enable/disable a scheduled job. |
clawlet cron run | Run a job immediately. |
clawlet cron add formats--message is required, and exactly one of --every, --cron, or --at must be set.
# Every N seconds
clawlet cron add --message "summarize my inbox" --every 3600
# Cron expression (5-field)
clawlet cron add --message "daily standup notes" --cron "0 9 * * 1-5"
# Run once at a specific time (RFC3339)
clawlet cron add --message "remind me" --at "2026-02-10T09:00:00Z"
# Deliver to a chat (requires both --channel and --to)
clawlet cron add --message "ping" --every 600 --channel slack --to U012345
Pre-built images are available on GitHub Container Registry:
# docker-compose.yml
services:
clawlet:
image: ghcr.io/mosaxiv/clawlet:latest
volumes:
- ~/.clawlet:/root/.clawlet
command: gateway
restart: unless-stopped
docker compose up -d
# Build the image
docker build -t clawlet .
# Initialize config (first time only)
docker run -v ~/.clawlet:/root/.clawlet --rm clawlet onboard
# Edit config on host to add API keys
vim ~/.clawlet/config.json
# Run the gateway
docker run -v ~/.clawlet:/root/.clawlet clawlet gateway
# Or run a single command
docker run -v ~/.clawlet:/root/.clawlet --rm clawlet agent -m "Hello"
docker run -v ~/.clawlet:/root/.clawlet --rm clawlet status
Go
97.1%
Shell
1.5%
Go Template
1.3%