this repo has no description
1---
2description: Use Bun instead of Node.js, npm, pnpm, or vite.
3globs: "*.ts, *.tsx, *.html, *.css, *.js, *.jsx, package.json"
4alwaysApply: false
5---
6
7## Issue Tracking with bd (beads)
8
9**IMPORTANT**: This project uses **bd (beads)** for ALL issue tracking. Do NOT use markdown TODOs, task lists, or other tracking methods.
10
11### Why bd?
12
13- Dependency-aware: Track blockers and relationships between issues
14- Git-friendly: Auto-syncs to JSONL for version control
15- Agent-optimized: JSON output, ready work detection, discovered-from links
16- Prevents duplicate tracking systems and confusion
17
18### Quick Start
19
20**Check for ready work:**
21```bash
22bd ready --json
23```
24
25**Create new issues:**
26```bash
27bd create "Issue title" -t bug|feature|task -p 0-4 --json
28bd create "Issue title" -p 1 --deps discovered-from:bd-123 --json
29bd create "Subtask" --parent <epic-id> --json # Hierarchical subtask (gets ID like epic-id.1)
30```
31
32**Claim and update:**
33```bash
34bd update bd-42 --status in_progress --json
35bd update bd-42 --priority 1 --json
36```
37
38**Complete work:**
39```bash
40bd close bd-42 --reason "Completed" --json
41```
42
43### Issue Types
44
45- `bug` - Something broken
46- `feature` - New functionality
47- `task` - Work item (tests, docs, refactoring)
48- `epic` - Large feature with subtasks
49- `chore` - Maintenance (dependencies, tooling)
50
51### Priorities
52
53- `0` - Critical (security, data loss, broken builds)
54- `1` - High (major features, important bugs)
55- `2` - Medium (default, nice-to-have)
56- `3` - Low (polish, optimization)
57- `4` - Backlog (future ideas)
58
59### Workflow for AI Agents
60
611. **Check ready work**: `bd ready` shows unblocked issues
622. **Claim your task**: `bd update <id> --status in_progress`
633. **Work on it**: Implement, test, document
644. **Discover new work?** Create linked issue:
65 - `bd create "Found bug" -p 1 --deps discovered-from:<parent-id>`
665. **Complete**: `bd close <id> --reason "Done"`
676. **Commit together**: Always commit the `.beads/issues.jsonl` file together with the code changes so issue state stays in sync with code state
68
69### Auto-Sync
70
71bd automatically syncs with git:
72- Exports to `.beads/issues.jsonl` after changes (5s debounce)
73- Imports from JSONL when newer (e.g., after `git pull`)
74- No manual export/import needed!
75
76### Managing AI-Generated Planning Documents
77
78AI assistants often create planning and design documents during development:
79- PLAN.md, IMPLEMENTATION.md, ARCHITECTURE.md
80- DESIGN.md, CODEBASE_SUMMARY.md, INTEGRATION_PLAN.md
81- TESTING_GUIDE.md, TECHNICAL_DESIGN.md, and similar files
82
83**Best Practice: Use a dedicated directory for these ephemeral files**
84
85**Recommended approach:**
86- Create a `history/` directory in the project root
87- Store ALL AI-generated planning/design docs in `history/`
88- Keep the repository root clean and focused on permanent project files
89- Only access `history/` when explicitly asked to review past planning
90
91### CLI Help
92
93Run `bd <command> --help` to see all available flags for any command.
94For example: `bd create --help` shows `--parent`, `--deps`, `--assignee`, etc.
95
96### Important Rules
97
98- Use bd for ALL task tracking
99- Always use `--json` flag for programmatic use
100- Link discovered work with `discovered-from` dependencies
101- Check `bd ready` before asking "what should I work on?"
102- Store AI planning docs in `history/` directory
103- Run `bd <cmd> --help` to discover available flags
104- Do NOT create markdown TODO lists
105- Do NOT use external issue trackers
106- Do NOT duplicate tracking systems
107- Do NOT clutter repo root with planning documents
108
109---
110
111## Claude Models
112
113This project uses **two Claude models**:
114
115### Opus 4.5 (Main Agent)
116- Model ID: `claude-opus-4-5-20251101`
117- Letta handle: `openai/claude-opus-4-5-20251101` (via LiteLLM proxy)
118- Used for: Main conversational agent, tool execution, user interactions
119
120### Haiku 4.5 (Detection)
121- Model ID: `claude-haiku-4-5-20251001`
122- Config: `HAIKU_MODEL` environment variable
123- Used for: Fast classification of user messages (overwhelm, brain dump, self-bullying)
124- Called via LiteLLM at `LITELLM_URL`
125
126The detection flow in `src/detect.ts`:
1271. Regex pre-filter triggers Haiku only when patterns detected
1282. Haiku classifies: `overwhelm`, `brainDump`, `selfBullying`, `urgency`
1293. If brain dump detected, Haiku parses and saves tasks/ideas to DB
1304. Detection context prepended to message for Opus to respond appropriately
131
132Do NOT use Sonnet unless explicitly requested.
133
134### Letta Agent Creation Workaround
135
136Due to a Letta bug with BYOK model handles, agents must be created in two steps:
137
1381. Create agent with `letta/letta-free` model
1392. Update agent's `llm_config` to use Claude:
140 ```typescript
141 await client.agents.update(agentId, {
142 llm_config: {
143 handle: 'openai/claude-opus-4-5-20251101',
144 model: 'claude-opus-4-5-20251101',
145 model_endpoint_type: 'openai',
146 model_endpoint: 'http://litellm:4000',
147 context_window: 200000,
148 temperature: 0.7,
149 },
150 });
151 ```
152
153### Letta Tool Registration (Critical!)
154
155Custom tools require careful registration. Letta's "auto-extraction from Python source" is unreliable.
156
157**1. json_schema format** - Use Letta's flat format, NOT OpenAI's nested format:
158```typescript
159// WRONG (OpenAI format)
160json_schema: {
161 type: 'function',
162 function: { name, description, parameters }
163}
164
165// CORRECT (Letta format)
166json_schema: {
167 name: 'tool_name',
168 description: 'What it does',
169 parameters: {
170 type: 'object',
171 properties: { /* ... */ },
172 required: ['arg1']
173 }
174}
175```
176
177**2. Always pass json_schema explicitly** - Both on create AND update:
178```typescript
179// When creating
180await client.tools.create({
181 source_code: pythonCode,
182 description: '...',
183 json_schema: { name, description, parameters }, // Required!
184});
185
186// When updating existing tools
187await client.tools.update(toolId, {
188 source_code: pythonCode,
189 description: '...',
190 json_schema: { name, description, parameters }, // Also required!
191});
192```
193
194**3. Python function signatures** - Use explicit typed parameters:
195```python
196# WRONG - Letta won't know what args to pass
197def my_tool(**kwargs):
198 pass
199
200# CORRECT - Explicit parameters
201def my_tool(text: str, priority: int = None):
202 pass
203```
204
205**4. Tool attachment timing** - Attach AFTER agent creation:
206```typescript
207// Tools must be attached after agent is created
208// (tool_ids in create() doesn't work with letta-free)
209const agent = await client.agents.create({ /* ... */ });
210for (const toolId of toolIds) {
211 await client.agents.tools.attach(toolId, { agent_id: agent.id });
212}
213```
214
215**5. Handle existing tools** - Check by name and update instead of failing:
216```typescript
217const existingTools = new Map<string, string>();
218for await (const tool of client.tools.list()) {
219 existingTools.set(tool.name, tool.id);
220}
221// Then update if exists, create if not
222```
223
224### LiteLLM tools=None Bug (Pinned Version)
225
226LiteLLM's `main-latest` image has a bug where `filter_web_search_deployments` throws a `TypeError` when Letta sends `tools=null` during summarization requests.
227
228**Symptom:** Agent crashes during memory compaction/summarization with:
229```
230TypeError: argument of type 'NoneType' is not iterable
231```
232
233**Fix:** Pin to version `v1.80.9.dev6` which includes the fix:
234```yaml
235# docker-compose.yml
236litellm:
237 # Using specific version that includes fix for tools=None bug
238 # https://github.com/BerriAI/litellm/commit/7c2e2111c0cc3372ca0ce911d0b6d45c22794d7f
239 image: ghcr.io/berriai/litellm:litellm_embedding_header_forwarding-v1.80.9.dev6
240```
241
242**When to update:** Once LiteLLM releases a stable version with this fix merged, update to that version.
243
244---
245
246## Tiny Wins Tools
247
248The bot includes tools for tracking small accomplishments in `src/tools/wins.ts`:
249
250| Tool | Purpose | Key Parameters |
251|------|---------|----------------|
252| `record_tiny_win` | Log an accomplishment | `content` (required), `category`, `magnitude` |
253| `delete_tiny_win` | Remove a mistaken entry | `id` (required) |
254| `get_wins_by_day` | Query wins for a specific day | `period` ("today", "yesterday", "YYYY-MM-DD"), `category` |
255| `get_wins_summary` | Get overview with streaks | `days` (1-30), `category`, `limit` |
256
257**Categories:** `task`, `habit`, `self_care`, `social`, `work`, `creative`, `other`
258
259**Magnitudes:** `tiny`, `small`, `medium`, `big`
260
261**Database:** Wins are stored in the `wins` table with timestamps (`createdAt`).
262
263---
264
265## Code Quality (MANDATORY)
266
267**CRITICAL**: All code changes MUST pass these checks before completion:
268
269```bash
270bun run check # Runs all checks: typecheck, lint, format, test
271```
272
273### Individual Commands
274
275```bash
276bun run typecheck # TypeScript strict checking with tsgo
277bun run lint # ESLint with strict rules
278bun run format:check # Prettier format verification
279bun test # Run all tests
280```
281
282### Auto-fix Commands
283
284```bash
285bun run fix # Auto-fix lint and format issues
286bun run lint:fix # Fix ESLint issues only
287bun run format # Fix Prettier issues only
288```
289
290### Subagent Handoff Protocol
291
292**Before completing ANY task**, subagents MUST:
293
2941. Run `bun run check` and ensure ALL checks pass
2952. Fix any errors found (use `bun run fix` for auto-fixable issues)
2963. Re-run `bun run check` to verify fixes
2974. Only mark task complete when all checks pass
298
299**If checks fail and cannot be fixed:**
300- Document the specific errors in the task completion message
301- Do NOT mark task as complete
302- Escalate to orchestrator for resolution
303
304### Configuration Files
305
306- `tsconfig.json` - Strict TypeScript (all strict flags enabled)
307- `eslint.config.js` - ESLint flat config with typescript-eslint strict
308- `.prettierrc` - Prettier (120 chars, semicolons, single quotes)
309
310---
311
312## Bun Runtime
313
314Default to using Bun instead of Node.js.
315
316- Use `bun <file>` instead of `node <file>` or `ts-node <file>`
317- Use `bun test` instead of `jest` or `vitest`
318- Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
319- Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
320- Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
321- Use `bunx <package> <command>` instead of `npx <package> <command>`
322- Bun automatically loads .env, so don't use dotenv.
323
324## APIs
325
326- `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
327- `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
328- `Bun.redis` for Redis. Don't use `ioredis`.
329- `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
330- `WebSocket` is built-in. Don't use `ws`.
331- Prefer `Bun.file` over `node:fs`'s readFile/writeFile
332- Bun.$`ls` instead of execa.
333
334## Testing
335
336Use `bun test` to run tests.
337
338```ts#index.test.ts
339import { test, expect } from "bun:test";
340
341test("hello world", () => {
342 expect(1).toBe(1);
343});
344```
345
346## Frontend
347
348Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
349
350Server:
351
352```ts#index.ts
353import index from "./index.html"
354
355Bun.serve({
356 routes: {
357 "/": index,
358 "/api/users/:id": {
359 GET: (req) => {
360 return new Response(JSON.stringify({ id: req.params.id }));
361 },
362 },
363 },
364 // optional websocket support
365 websocket: {
366 open: (ws) => {
367 ws.send("Hello, world!");
368 },
369 message: (ws, message) => {
370 ws.send(message);
371 },
372 close: (ws) => {
373 // handle close
374 }
375 },
376 development: {
377 hmr: true,
378 console: true,
379 }
380})
381```
382
383HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
384
385```html#index.html
386<html>
387 <body>
388 <h1>Hello, world!</h1>
389 <script type="module" src="./frontend.tsx"></script>
390 </body>
391</html>
392```
393
394With the following `frontend.tsx`:
395
396```tsx#frontend.tsx
397import React from "react";
398import { createRoot } from "react-dom/client";
399
400// import .css files directly and it works
401import './index.css';
402
403const root = createRoot(document.body);
404
405export default function Frontend() {
406 return <h1>Hello, world!</h1>;
407}
408
409root.render(<Frontend />);
410```
411
412Then, run index.ts
413
414```sh
415bun --hot ./index.ts
416```
417
418For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`.
419