Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,17 @@ DISCORD_ALLOWED_USER=your_discord_user_id_here
# TIMEOUT_MS=300000
# LOG_LEVEL=info # debug, info, warn, error
# TIMEZONE=Asia/Tokyo

# Autonomous heartbeat
# HEARTBEAT_ENABLED=true
# HEARTBEAT_CHANNEL_ID=123456789
# HEARTBEAT_MIN_INTERVAL_MS=1800000 # 30 minutes
# HEARTBEAT_MAX_INTERVAL_MS=7200000 # 2 hours
# HEARTBEAT_IDLE_THRESHOLD_MS=600000 # 10 minutes

# Event triggers (morning/evening/weekly)
# TRIGGER_ENABLED=true
# TRIGGER_CHANNEL_ID=123456789
# TRIGGER_MORNING_HOUR=8
# TRIGGER_EVENING_HOUR=22
# TRIGGER_WEEKLY_DAY=0 # 0=Sun, 1=Mon, ..., 6=Sat
23 changes: 12 additions & 11 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ bun run check:fix # Biome auto-fix
bun run typecheck # Type check only (tsc --noEmit)
bun run test # Run tests (vitest run)
bun run test:watch # Test watch mode
bun vitest run tests/sessions.test.ts # Run a single test
bun vitest run tests/settings.test.ts # Run a single test
```

Docker: `docker compose up thor -d --build`
Expand All @@ -29,19 +29,20 @@ thor is a wrapper that invokes Claude Code from Discord chat. Designed for singl

| Layer | Files | Role |
|-------|-------|------|
| Chat | `index.ts` | Discord client, message routing |
| Agent | `agent-runner.ts`, `base-runner.ts` | Abstract interface for AI CLI |
| CLI Adapter | `claude-code.ts` | Claude Code adapter implementation |
| Process | `persistent-runner.ts`, `runner-manager.ts`, `process-manager.ts` | Persistent process management, queue, circuit breaker |
| Scheduler | `scheduler.ts`, `schedule-cli.ts` | Cron/one-shot schedules, JSON persistence |
| Skills | `skills.ts` | Load skills from `workspace/skills/` |
| Config | `config.ts`, `constants.ts`, `settings.ts`, `sessions.ts` | Environment variables, constants, runtime settings, session management |
| Entry | `index.ts` | Bootstrap, Discord client setup, Brain/Scheduler wiring |
| Discord | `discord-client.ts`, `agent-response.ts`, `slash-commands.ts` | Message routing, streaming response, slash commands |
| Brain | `brain/brain.ts`, `brain/heartbeat.ts`, `brain/triggers.ts` | Priority queue, autonomous heartbeat/triggers |
| Agent | `agent-runner.ts`, `sdk-runner.ts`, `system-prompt.ts` | Agent SDK runner, system prompt construction |
| MCP | `mcp/server.ts`, `mcp/discord-tools.ts`, `mcp/schedule-tools.ts` | MCP tools for Discord and scheduler operations |
| Scheduler | `scheduler.ts`, `schedule-handler.ts`, `scheduler-discord.ts` | Cron/one-shot schedules, slash command handler, Discord bridge |
| Config | `config.ts`, `constants.ts`, `settings.ts` | Environment variables, constants, runtime settings |

### Key Data Flows

- `index.ts` receives Discord messages → forwards to AI CLI via `processPrompt()`
- Detects `!discord` / `!schedule` / `SYSTEM_COMMAND:` in AI output and executes them autonomously
- `persistent-runner.ts` runs Claude Code as a persistent process using `--input-format=stream-json`
- `index.ts` boots Discord client → `discord-client.ts` routes messages via `routeMessage()`
- `agent-response.ts` streams AI responses to Discord with live editing
- `SYSTEM_COMMAND:` in AI output triggers `system-commands.ts` (e.g., restart)
- MCP tools (`discord-tools.ts`, `schedule-tools.ts`) provide Discord/scheduler access to the AI agent
- Scheduler runs periodic tasks with `node-cron` and sends results to channels

## Development Practices
Expand Down
104 changes: 88 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,37 @@

# thor

thor is a personal AI assistant for Discord.
It uses Claude Code as its backend.
thor is a personal AI assistant for Discord, powered by the Claude Agent SDK.
Designed for single-user use.

## Features

- **Chat** — Talk to Claude directly in Discord. Responses stream in real time.
- **Chat** — Talk to Claude directly in Discord. Responses stream in real time with tool progress visibility.
- **Persistent sessions** — Conversation context is retained per channel. Use `/new` to reset.
- **Brain** — Priority-based task queue. User messages automatically preempt lower-priority tasks (heartbeat, triggers).
- **Autonomous heartbeat** — Periodically checks a `HEARTBEAT.md` checklist in the workspace and acts on pending items. Stays silent when there's nothing to do.
- **Event triggers** — Time-based triggers (morning, evening, weekly reflection) that fire prompts automatically.
- **MCP tools** — The agent can interact with Discord (send messages, read history, list channels) and manage schedules through MCP tools.
- **Scheduler** — Set one-time or recurring tasks with natural language (`in 30 minutes`, `every day 9:00`, cron expressions, etc.).
- **Skills** — Extend thor with custom skill files. List with `/skills`, run with `/skill`.
- **File sending** — thor can send files (images, PDFs, etc.) back to Discord.
- **Startup tasks** — Run agent prompts automatically on bot startup.
- **Personality** — Customize the agent's personality and user context via `SOUL.md` and `USER.md` in the workspace.
- **File sending** — thor can send files (images, PDFs, etc.) back to Discord via `MEDIA:/path/to/file`.

## Architecture

```
Discord messages
Brain (priority queue)
├── USER — chat messages (highest priority, preempts others)
├── EVENT — scheduled triggers
└── HEARTBEAT — autonomous heartbeat (lowest priority)
Agent SDK (sdk-runner.ts)
MCP Server
├── Discord tools (send, channels, history, delete)
└── Schedule tools (create, list, remove, toggle)
```

## Prerequisites

Expand All @@ -31,6 +51,7 @@ cp .env.example .env
Set the following in `.env`:

```bash
WORKSPACE_PATH=./workspace
DISCORD_TOKEN=your_discord_bot_token
DISCORD_ALLOWED_USER=123456789012345678
```
Expand All @@ -50,16 +71,67 @@ Follow the browser authentication prompt. Credentials are stored in a Docker vol
docker compose up thor -d
```

## Core Commands

- `/new` Start a new session
- `/stop` Stop the running task
- `/status` Check current status
- `/settings` Show current settings
- `/restart` Restart the bot
- `/schedule` Manage schedules
- `/skills` List skills
- `/skill` Execute a skill
## Configuration

### Required

| Variable | Description |
|----------|-------------|
| `WORKSPACE_PATH` | Path to the workspace directory |
| `DISCORD_TOKEN` | Discord bot token |
| `DISCORD_ALLOWED_USER` | Your Discord user ID (single user only) |

### Optional

| Variable | Default | Description |
|----------|---------|-------------|
| `AUTO_REPLY_CHANNELS` | — | Comma-separated channel IDs for auto-reply |
| `AGENT_MODEL` | — | Override the agent model |
| `TIMEOUT_MS` | `300000` | Agent timeout in milliseconds |
| `LOG_LEVEL` | `info` | `debug`, `info`, `warn`, `error` |
| `TIMEZONE` | `Asia/Tokyo` | Timezone for schedules and triggers |

### Heartbeat

| Variable | Default | Description |
|----------|---------|-------------|
| `HEARTBEAT_ENABLED` | `false` | Enable autonomous heartbeat |
| `HEARTBEAT_CHANNEL_ID` | — | Channel to send heartbeat results |
| `HEARTBEAT_MIN_INTERVAL_MS` | `1800000` | Minimum interval (30 min) |
| `HEARTBEAT_MAX_INTERVAL_MS` | `7200000` | Maximum interval (2 hours) |
| `HEARTBEAT_IDLE_THRESHOLD_MS` | `600000` | Skip if user active within this time (10 min) |

### Triggers

| Variable | Default | Description |
|----------|---------|-------------|
| `TRIGGER_ENABLED` | `false` | Enable event triggers |
| `TRIGGER_CHANNEL_ID` | — | Channel to send trigger results |
| `TRIGGER_MORNING_HOUR` | `8` | Morning trigger hour |
| `TRIGGER_EVENING_HOUR` | `22` | Evening trigger hour |
| `TRIGGER_WEEKLY_DAY` | `0` | Weekly reflection day (0=Sun … 6=Sat) |

## Workspace Files

Place these files in your `WORKSPACE_PATH` to customize behavior:

| File | Purpose |
|------|---------|
| `USER.md` | User info and preferences (injected into system prompt) |
| `SOUL.md` | Personality and values (injected into system prompt) |
| `HEARTBEAT.md` | Checklist for autonomous heartbeat |

## Slash Commands

| Command | Description |
|---------|-------------|
| `/new` | Start a new session |
| `/stop` | Stop the running task |
| `/status` | Show brain status (busy, queue length, session) |
| `/schedule add` | Add a schedule |
| `/schedule list` | List all schedules |
| `/schedule remove` | Remove a schedule |
| `/schedule toggle` | Enable/disable a schedule |

## Inspired by

Expand Down
35 changes: 35 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading