Architecture

2 min read

A technical overview of how nclaw is structured internally.

Overview

Telegram  -\
Scheduler -->  Claude Code CLI  -->  Telegram
Webhook   -/

Project Structure

PathPurpose
cmd/nclaw/main.goEntrypoint: config init, DB setup, bot creation, scheduler start
internal/config/Viper-based config (env prefix NCLAW_, .env support, optional config.yaml)
internal/handler/Telegram message handling, file attachments, reply context, sendfile processing
internal/claude/Claude Code CLI wrapper using go-binwrapper (fluent builder API), plus OAuth token refresh
internal/model/GORM models: ScheduledTask, TaskRunLog
internal/db/Database operations (SQLite with WAL mode)
internal/scheduler/Task scheduling via gocron, command parsing from Claude replies

Key Patterns

Claude CLI Integration

The claude package wraps the CLI binary with a fluent builder. The handler calls:

claude.New().
    Dir(dir).
    SkipPermissions().
    AppendSystemPrompt(prompt).
    Continue(query)

This continues the session in a per-chat directory.

OAuth Token Refresh

Before each CLI invocation, claude.EnsureValidToken() proactively refreshes the OAuth token if it expires within 5 minutes. Credentials are read from ~/.claude/.credentials.json using field-preserving JSON round-tripping. Refresh failures are logged as warnings and do not block the CLI call.

Scheduled Tasks

Claude’s replies are scanned for nclaw:schedule code blocks containing JSON commands (create, pause, resume, cancel). Tasks support cron, interval, and one-time schedules. Tasks persist in SQLite and reload on startup.

Tech Stack

TechnologyPurpose
Go 1.25Primary language
github.com/go-telegram/botTelegram bot framework
github.com/nickalie/go-binwrapperBinary wrapper for Claude CLI
github.com/spf13/viperConfiguration management
gorm.io/gorm + SQLiteDatabase
github.com/go-co-op/gocron/v2Task scheduling
github.com/stretchr/testifyTesting