Skip to content

Latest commit

 

History

History
159 lines (125 loc) · 4.86 KB

File metadata and controls

159 lines (125 loc) · 4.86 KB

AGENTS.md - Clawlet

AI agent instructions for working in the Clawlet codebase.

Project Overview

Clawlet is a self-hosted AI assistant with a dual-loop cognitive architecture. Fast triage path for instant replies, deep worker for async task processing, consolidation cycle for memory management. Runs in Docker.

  • Language: TypeScript
  • Runtime: Node.js 22
  • Lines of Code Target: ~1,200–1,500 (guidance, not hard limit)
  • Files Target: ≤ 10 source files
  • Dependencies Target: ≤ 10 npm packages

Build Commands

npm install
npm run build           # TypeScript → dist/
npm run dev             # Development with hot reload
npm start               # Production start

Lint/Format Commands

npm run typecheck       # Type check (no emit)
npm run lint            # ESLint
npm run lint:fix        # Auto-fix lint issues
npm run format          # Prettier
npm run format:check    # Check formatting

Test Commands

npm test                # Run all tests
npx vitest run src/agent.test.ts    # Single test file
npx vitest run -t "test name"      # Single test by name
npx vitest --watch                  # Watch mode

Code Style Guidelines

File Organization

  • Maximum 10 source files in src/
  • Each file has a single responsibility
  • Target file sizes: 50-500 lines
  • Keep it readable in one sitting

Naming Conventions

  • Files: kebab-case.ts
  • Functions: camelCase
  • Types: PascalCase
  • Constants: UPPER_SNAKE_CASE
  • Database tables: snake_case

TypeScript Guidelines

  • Strict mode enabled
  • Explicit return types on exported functions
  • Avoid any — use unknown with type guards
  • All types in src/types.ts
  • Use import type for type-only imports

Import/Export Style

  • Use explicit named exports
  • Group imports: builtins → npm → local
  • One blank line between import groups
  • No barrel files

Code Structure

// 1. Imports (grouped)
import { readFile } from 'fs/promises';
import OpenAI from 'openai';
import type { Message } from './types.js';

// 2. Constants
const MAX_RETRIES = 3;

// 3. Exported functions
export async function init(): Promise<void> { ... }

// 4. Private functions
function helper(): void { ... }

SQL/Database

  • Parameterized queries only
  • Idempotent migrations (CREATE TABLE IF NOT EXISTS)
  • SQLite exclusively — 7 tables: episodic, semantic, personality, agenda, work_log, meta, schedules

Testing

  • Unit tests co-located: foo.ts → foo.test.ts
  • Mock external services (OpenRouter, filesystem)
  • Keep tests fast (< 100ms per test)

Dependencies

Current allowed dependencies:

  • openai — OpenRouter client
  • better-sqlite3 — SQLite driver
  • express — HTTP server
  • ws — WebSocket server
  • yaml — YAML parsing
  • ulid — Unique IDs
  • glob — File pattern matching
  • cron-parser — Cron expression parsing for scheduled tasks

Configuration

  • Environment: .env file only
  • User rules: config/rules.yaml (all fields overridable by env vars)
  • Personality: config/personality.yaml

Architecture

Three independent loops:

  1. Queue processor — polls incoming/ every 100ms → processFastPath()
  2. Deep worker — polls agenda every 1s → tool-calling loop with coherence check
  3. Consolidation — every N minutes → extract facts, compact, review agenda, reflect

Dual-tier LLM:

  • Fast (llama-3.1-8b): triage, coherence checks
  • Deep (claude-sonnet-4): reasoning, tools, consolidation

File Structure

src/
├── agent.ts          # Dual-loop logic: fast path, deep worker, consolidation (~590 lines)
├── memory.ts         # SQLite store, 7-table schema, JSONL log, decay (~250 lines)
├── schedule.ts       # Cron-based scheduled tasks, CRUD (~95 lines)
├── agenda.ts         # Working memory CRUD with cap + domain (~90 lines)
├── queue.ts          # File-based message queue (~60 lines)
├── server.ts         # Express + WebSocket + schedule API (~185 lines)
├── llm.ts            # Dual-tier OpenRouter client (~60 lines)
├── tools.ts          # 7 tools for deep worker (~70 lines)
├── types.ts          # Shared interfaces (~165 lines)
└── index.ts          # Entry point (~28 lines)

Pre-commit Checklist

  1. npm run typecheck passes
  2. npm run lint passes
  3. npm test passes
  4. npm run build succeeds
  5. wc -l src/*.ts ≤ ~1,500 lines
  6. ls src/*.ts | wc -l ≤ 10 files

Design Principles

  1. Fits in your head — Understand entire codebase in 15 minutes
  2. Queue everything — Debug with ls and cat
  3. Separate conversation from cognition — Fast replies, async deep work
  4. All intelligence in the cloud — Local process is a thin orchestrator
  5. Observe, don't control — Dashboard is a window, not a control plane
  6. Complexity budget is law — Fork instead of bloat