Nava Claw
An autonomous AI agent that trades on-chain, remembers what it learns, and runs on a schedule. Built for crypto traders, DeFi degens, and anyone who wants an agent that can actually do things, sign transactions, execute swaps, manage positions, and grow smarter over time.
Nava-Claw is a TypeScript monorepo that ships as a single server: plug in a model provider, point it at a chain, give it skills, and let it run.
Overview
What You Get
- Multi-chain execution. Protocol-specific execution skills (e.g.,
verified-swapfor Uniswap) handle calldata generation, Nava verification, and broadcast internally. Add a new protocol by creating a skill, no code changes required. - Nava verification. Every on-chain action passes through the Nava arbiter before execution. Safety rails you don’t have to think about.
- Skills on demand. Drop a
SKILL.mdfile into./skills/and the agent learns a new capability on the fly. Skills are listed in a compact catalog; the agent reads them viacatwhen needed, not injected into the prompt. Hot-reloaded, no restart needed. - Cron and heartbeat. Schedule recurring jobs with cron expressions. Skills can declare their own schedules in frontmatter.
- Memory. Typed
memorytool with search, recall, and observe actions. Backed by Postgres + pgvector for persistent semantic search, or zero-config in-memory mode for development. Memory is accessed on demand, not injected into every prompt. - Channels. Talk to your agent via Telegram or Slack. Channel plugins are composable and easy to extend.
- Any model. Claude, GPT, Gemini, Ollama, OpenRouter. Swap providers without changing your agent config.
Architecture
nava-claw/
├── apps/
│ └── server/ @nava-claw/server HTTP server, boot sequence, graceful shutdown
├── packages/
│ ├── shared/ @nava-claw/shared Logging (tslog), common utilities
│ ├── config/ @nava-claw/config Config loader, validation, execution context
│ ├── models/ @nava-claw/models Multi-provider discovery (OpenAI, Anthropic, Google, Ollama, etc.)
│ ├── memory/ @nava-claw/memory Postgres + pgvector search, cron store, in-memory fallback
│ ├── skills/ @nava-claw/skills Skill loader, watcher, frontmatter parsing
│ ├── channels/ @nava-claw/channels Channel plugins (Telegram, Slack), routing, delivery
│ ├── pipeline/ @nava-claw/pipeline Command queue, agent runner, text chunking
│ ├── heartbeat/ @nava-claw/heartbeat Cron tool, scheduled skills, heartbeat runner
│ ├── tools/ @nava-claw/tools Payload store, MCP client, tool assembly
│ └── trading/ @nava-claw/trading Generic sign + execute pipeline, Nava verification
└── skills/ Skill definitions (SKILL.md files)
Data flow: Inbound message (channel) enters the pipeline (model call, tools) and produces an outbound reply (channel). The heartbeat triggers jobs on cron schedules. On-chain execution is handled by protocol-specific skills that bundle calldata generation, Nava verification, and broadcast into self-contained scripts. Skills are read on demand via bash. Memory is queried via the memory tool.
Setup
Prerequisites
- Node.js 22+ (
nvm install 22) - pnpm (
npm install -g pnpm) - Foundry (optional, for on-chain reads via
cast-read) - Docker (optional, for Postgres persistence; omit
DATABASE_URLfor in-memory mode)
Quick Start
The fastest path is the interactive setup wizard, which handles deps, builds, provider config, channels, skills, and generates config.json + .env for you.
Claude Code
git clone --recursive git@github.com:navalabs-dev/nava-claw.git && cd nava-claw
Open a Claude Code session and run:
/setup
Cursor
Open the project in Cursor and ask:
Set up nava-claw
Cursor picks up the setup rule automatically.
Manual
git clone --recursive git@github.com:navalabs-dev/nava-claw.git && cd nava-claw
pnpm install && pnpm build
cp .env.example .env # Fill in your API keys and secrets
# Create config.json (see Configuration)
pnpm --filter @nava-claw/server start
The server starts on http://localhost:4747. Health check at /health.
Docker (with Postgres Persistence)
cp .env.example .env # Fill in your API keys
# Create config.json (see Configuration)
docker compose up
This starts Postgres (pgvector) + the app. Memory, cron jobs, and sessions persist across restarts. To run without persistence, just omit DATABASE_URL from .env and run the server directly.
Development
pnpm build # Build all packages (TypeScript project references)
pnpm check # Type-check without emitting
pnpm test # Run all tests (Vitest)
pnpm clean # Clean build artifacts
API Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /health | Health check ({ status: "ok", uptime }) |
| GET | /ready | Readiness probe (503 if not ready) |
Configuration
Nava-Claw uses two config sources: secrets in .env and everything else in config.json.
Environment Variables
See .env.example for the full list. Key ones:
| Variable | Required | Description |
|---|---|---|
ANTHROPIC_API_KEY | At least one provider key | Anthropic API key |
OPENAI_API_KEY | At least one provider key | OpenAI API key |
TELEGRAM_BOT_TOKEN | If using Telegram | Bot token from @BotFather |
SLACK_BOT_TOKEN | If using Slack | Bot token from Slack app |
PRIVATE_KEY | If trading | Hex-encoded private key for signing |
WALLET_ADDRESS | If trading | Corresponding wallet address |
RPC_URL | If trading | Chain RPC endpoint |
UNISWAP_API_KEY | If using Uniswap | From https://hub.uniswap.org |
NAVA_API_KEY | If trading | Nava arbiter API key |
DATABASE_URL | For persistence | Postgres connection string (omit for in-memory) |
EXECUTION_MODE | No | direct (default) or dry-run |
PORT | No (default: 4747) | HTTP server port |
LOG_LEVEL | No (default: info) | debug, info, warn, error |
config.json
{
"port": 4747,
"agents": [
{
"id": "default",
"name": "Nava",
"provider": "anthropic",
"model": "claude-sonnet-4-6",
"identity": "You are Nava, an autonomous trading agent..."
}
],
"providers": {
"anthropic": {
"baseUrl": "https://api.anthropic.com",
"apiKey": { "env": "ANTHROPIC_API_KEY" },
"api": "anthropic-messages",
"models": [
{ "id": "claude-sonnet-4-6", "name": "Sonnet 4.6", "contextWindow": 1000000, "supportsToolUse": true }
]
}
},
"channels": {
"telegram": {
"enabled": true,
"accounts": {
"default": { "botToken": { "env": "TELEGRAM_BOT_TOKEN" } }
}
}
},
"chain": { "id": 42161, "name": "Arbitrum One" },
"tools": {
"bash": {
"enabled": true,
"allow": {
"commands": ["curl", "cast-read", "cat", "jq", "grep", "head", "echo"],
"paths": ["./skills"]
}
},
"typed": true
}
}
Secrets use the { "env": "VAR_NAME" } pattern. Never hardcode keys in config.
Supported Chains
| Chain | ID | Notes |
|---|---|---|
| Ethereum Mainnet | 1 | Highest liquidity, higher gas |
| Base | 8453 | Coinbase L2, low fees, growing DeFi |
| Arbitrum One | 42161 | Fast, low cost, most common for Uniswap |
| Polygon | 137 | Uniswap + Polymarket |
| Hyperliquid | 999 | Perpetuals and spot trading |
| Sepolia | 11155111 | Testnet, no real funds |
Writing Skills
Skills are markdown files that teach the agent new behaviors. Drop a SKILL.md into ./skills/<name>/ and it’s live on the next heartbeat cycle.
Directory Structure
skills/
core/ Auto-enabled (cast-read, testnet, mcporter)
reference/ Supplementary docs (Uniswap Trading API, Uniswap driver)
Skill Format
---
name: my-strategy
description: My custom trading strategy
tags: trading
schedule: "0 */2 * * *" # Optional: runs every 2 hours
---
# My Strategy
Describe what the agent should do...
How Skills Work
- Skills are listed in a compact catalog; the agent reads them via
catwhen needed, not injected into the prompt. - Hot-reloaded, no restart needed.
- Skills can declare their own schedules in frontmatter using cron expressions.
- The heartbeat runner triggers scheduled skills on their cron schedule.
- Protocol-specific execution skills (e.g.,
verified-swapfor Uniswap) bundle calldata generation, Nava verification, and broadcast into self-contained scripts.
Channels
Talk to your Nava-Claw agent via Telegram or Slack. Channel plugins are composable and easy to extend.
Telegram
- Create a bot via @BotFather and get the bot token.
- Set
TELEGRAM_BOT_TOKENin.env. - Enable in
config.json:
{
"channels": {
"telegram": {
"enabled": true,
"accounts": {
"default": { "botToken": { "env": "TELEGRAM_BOT_TOKEN" } }
}
}
}
}
Slack
- Create a Slack app and get the bot token.
- Set
SLACK_BOT_TOKENin.env. - Enable in
config.json:
{
"channels": {
"slack": {
"enabled": true,
"accounts": {
"default": { "botToken": { "env": "SLACK_BOT_TOKEN" } }
}
}
}
}