From c72f23f7b9a62dd62ab075ba96c4012e451e15ce Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 12 Jan 2026 07:03:56 +0000 Subject: [PATCH] docs: add modular .claude.md files for each source directory - Improve main CLAUDE.md with philosophy section, test/typecheck commands, and descriptions in thread properties table - Add src/.claude.md with module structure overview - Add src/commands/.claude.md with command pattern and available commands - Add src/models/.claude.md with type definitions and design notes - Add src/storage/.claude.md with CRUD functions and backup behavior - Add src/utils/.claude.md with color conventions and tree rendering --- CLAUDE.md | 30 ++++++++++----- src/.claude.md | 33 ++++++++++++++++ src/commands/.claude.md | 83 +++++++++++++++++++++++++++++++++++++++++ src/models/.claude.md | 60 +++++++++++++++++++++++++++++ src/storage/.claude.md | 66 ++++++++++++++++++++++++++++++++ src/utils/.claude.md | 71 +++++++++++++++++++++++++++++++++++ 6 files changed, 333 insertions(+), 10 deletions(-) create mode 100644 src/.claude.md create mode 100644 src/commands/.claude.md create mode 100644 src/models/.claude.md create mode 100644 src/storage/.claude.md create mode 100644 src/utils/.claude.md diff --git a/CLAUDE.md b/CLAUDE.md index fdbf398..bb07794 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,20 +5,29 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Build and Development Commands ```bash -npm run build # Compile TypeScript to dist/ +npm run build # Compile TypeScript to dist/ npm run dev -- # Run CLI directly via tsx (e.g., npm run dev -- list) -npm link # Install 'threads' command globally -threads # Run installed CLI +npm run test # Run Jest test suite +npm run typecheck # Type check without emitting +npm link # Install 'threads' command globally +threads # Run installed CLI ``` ## Architecture Threads is a CLI tool for tracking streams of activity through self-reported progress rather than task management. Data is stored in `~/.threads/threads.json` and accessed only through the CLI. +### Philosophy + +- **Self-reported progress over task management**: Users describe what they're doing, not what needs to be done +- **Temperature = momentum**: How actively you're working on something (hot = active focus, frozen = dormant) +- **Threads evolve**: Status, temperature, and details change as work progresses + ### Core Concepts - **Thread**: A stream of activity with status, temperature (momentum), size (scope), and importance - **Progress**: Timestamped notes you report to yourself about a thread +- **Details**: Versioned snapshots of structured information about a thread (latest is current) - **Sub-threads**: Threads can spawn children via `parentId` - **Groups**: Organizational containers for threads - **Dependencies**: Links between threads with why/what/how/when context @@ -35,22 +44,23 @@ src/utils/format.ts # Console output formatting with chalk ### Data Flow -Commands import from `storage` for data operations and `utils` for display. Storage reads/writes `~/.threads/threads.json` on every operation (no in-memory caching). +Commands import from `storage` for data operations and `utils` for display. Storage reads/writes `~/.threads/threads.json` on every operation (no in-memory caching). A backup is created before each write operation. ### Thread Properties -| Property | Values | -|----------|--------| -| status | active, paused, stopped, completed, archived | -| temperature | frozen, freezing, cold, tepid, warm, hot | -| size | tiny, small, medium, large, huge | -| importance | 1-5 | +| Property | Values | Description | +|----------|--------|-------------| +| status | active, paused, stopped, completed, archived | Lifecycle state | +| temperature | frozen, freezing, cold, tepid, warm, hot | Momentum/recency indicator | +| size | tiny, small, medium, large, huge | Scope of work | +| importance | 1-5 | Priority level (5 = highest) | ### Adding New Commands 1. Create `src/commands/.ts` exporting a `Command` object 2. Add export to `src/commands/index.ts` 3. Import and register in `src/index.ts` via `program.addCommand()` +4. Follow the Commander.js pattern: `.argument()` for positional args, `.option()` for flags ## CLI Usage Notes diff --git a/src/.claude.md b/src/.claude.md new file mode 100644 index 0000000..c807886 --- /dev/null +++ b/src/.claude.md @@ -0,0 +1,33 @@ +# src/ - Source Root + +This is the main source directory for the Threads CLI application. + +## Entry Point + +- `index.ts` - CLI entry point using Commander.js + - Imports all commands from `./commands/` + - Creates the root `program` with name, description, version + - Registers each command via `program.addCommand()` + - Calls `program.parse()` to process CLI arguments + +## Module Structure + +| Directory | Purpose | +|-----------|---------| +| `commands/` | CLI command implementations (one per file) | +| `models/` | TypeScript types and interfaces | +| `storage/` | Data persistence layer (JSON file I/O) | +| `utils/` | Formatting and display utilities | + +## Import Conventions + +- Each subdirectory has an `index.ts` that re-exports its public API +- Commands import from `../storage` and `../utils` +- Commands import types from `../models` + +## Adding New Modules + +When adding new functionality: +1. Create the module in the appropriate directory +2. Export from that directory's `index.ts` +3. Import using the directory path (e.g., `from '../storage'`) diff --git a/src/commands/.claude.md b/src/commands/.claude.md new file mode 100644 index 0000000..a55cb1a --- /dev/null +++ b/src/commands/.claude.md @@ -0,0 +1,83 @@ +# commands/ - CLI Commands + +Each file implements a single CLI command. All commands follow the same pattern. + +## Command Pattern + +```typescript +import { Command } from 'commander'; +import { /* storage functions */ } from '../storage'; +import { /* types */ } from '../models'; +import { /* formatters */ } from '../utils'; +import chalk from 'chalk'; + +export const myCommand = new Command('command-name') + .description('What this command does') + .argument('', 'Description of required arg') + .argument('[optional]', 'Description of optional arg') + .option('-f, --flag', 'Boolean flag') + .option('-v, --value ', 'Option with value') + .action((arg1, arg2, options) => { + // Implementation + }); +``` + +## Available Commands + +| Command | Alias | Purpose | +|---------|-------|---------| +| new | - | Create a new thread | +| list | - | List threads with filters | +| show | - | Show thread details | +| progress | p | Add progress note | +| edit-progress | - | Edit or delete progress entries | +| set | - | Update thread properties | +| spawn | - | Create a sub-thread | +| details | - | Add/update thread details | +| group | - | Manage groups | +| tag | - | Add/remove tags | +| depend | - | Manage dependencies | +| archive | - | Archive threads | +| clone | - | Clone a thread | +| merge | - | Merge threads | +| search | - | Search threads | +| overview | - | Show summary view | +| agenda | - | Show prioritized view | +| timeline | - | Show chronological view | +| next | - | Suggest next thread | +| batch | - | Batch operations | +| move-progress | - | Move progress between threads | +| undo | - | Restore from backup | + +## Thread Resolution Pattern + +Most commands accept a thread identifier that can be: +1. Full UUID +2. Partial UUID (prefix match) +3. Exact thread name +4. Partial name (substring match) + +Standard resolution pattern: +```typescript +let thread = getThreadById(identifier); +if (!thread) { + thread = getThreadByName(identifier); +} +if (!thread) { + // Try partial match... +} +``` + +## Output Conventions + +- Use `chalk.green()` for success messages +- Use `chalk.red()` for errors +- Use `chalk.yellow()` for warnings or multiple matches +- Use `chalk.dim()` for secondary information +- Import formatters from `../utils` for consistent thread display + +## Adding a New Command + +1. Create `src/commands/.ts` with the command pattern above +2. Export from `src/commands/index.ts`: `export { myCommand } from './my-command';` +3. Import and register in `src/index.ts`: `program.addCommand(myCommand);` diff --git a/src/models/.claude.md b/src/models/.claude.md new file mode 100644 index 0000000..e9a0f5a --- /dev/null +++ b/src/models/.claude.md @@ -0,0 +1,60 @@ +# models/ - TypeScript Types + +Contains all type definitions for the Threads CLI. No runtime code, only types. + +## Core Types + +### Thread +The main entity - a stream of activity being tracked. + +```typescript +interface Thread { + id: string; // UUID + name: string; // Display name (unique) + description: string; // Brief summary + status: ThreadStatus; // Lifecycle state + importance: Importance; // Priority 1-5 + temperature: Temperature; // Momentum indicator + size: ThreadSize; // Scope of work + parentId: string | null; // For sub-threads + groupId: string | null; // Organizational group + tags: string[]; // User-defined tags + dependencies: Dependency[]; + progress: ProgressEntry[]; + details: DetailsEntry[]; + createdAt: string; // ISO timestamp + updatedAt: string; // ISO timestamp +} +``` + +### Enums + +| Type | Values | +|------|--------| +| `ThreadStatus` | active, paused, stopped, completed, archived | +| `Temperature` | frozen, freezing, cold, tepid, warm, hot | +| `ThreadSize` | tiny, small, medium, large, huge | +| `Importance` | 1, 2, 3, 4, 5 | + +### Supporting Types + +- **ProgressEntry**: `{ id, timestamp, note }` - Timestamped progress notes +- **DetailsEntry**: `{ id, timestamp, content }` - Versioned detail snapshots +- **Dependency**: `{ threadId, why, what, how, when }` - Inter-thread links +- **Group**: `{ id, name, description, createdAt, updatedAt }` - Thread containers +- **ThreadsData**: `{ threads, groups, version }` - Root data structure + +## Usage + +Import types from the models module: +```typescript +import { Thread, ThreadStatus, ProgressEntry } from '../models'; +``` + +## Design Notes + +- All IDs are UUIDs (generated via `uuid` package) +- All timestamps are ISO 8601 strings +- Thread names are unique (case-insensitive matching) +- Progress entries are append-only in normal operation +- Details are versioned; the last entry is the "current" state diff --git a/src/storage/.claude.md b/src/storage/.claude.md new file mode 100644 index 0000000..0c45d3f --- /dev/null +++ b/src/storage/.claude.md @@ -0,0 +1,66 @@ +# storage/ - Data Persistence + +Handles all file I/O for the Threads CLI. Data is stored in `~/.threads/threads.json`. + +## File Locations + +``` +~/.threads/ + threads.json # Main data file + threads.backup.json # Automatic backup (created before each write) +``` + +## Core Functions + +### Data Loading/Saving +- `loadData(): ThreadsData` - Load entire data store +- `saveData(data: ThreadsData): void` - Save with automatic backup + +### Thread CRUD +- `getAllThreads(): Thread[]` +- `getThreadById(id: string): Thread | undefined` +- `getThreadByName(name: string): Thread | undefined` - Case-insensitive +- `findThreads(predicate): Thread[]` - Filter with callback +- `addThread(thread: Thread): void` +- `updateThread(id, updates): Thread | undefined` - Partial update +- `deleteThread(id: string): boolean` + +### Group CRUD +- `getAllGroups(): Group[]` +- `getGroupById(id: string): Group | undefined` +- `getGroupByName(name: string): Group | undefined` - Case-insensitive +- `addGroup(group: Group): void` +- `updateGroup(id, updates): Group | undefined` +- `deleteGroup(id: string): boolean` + +### Backup/Undo +- `getBackupInfo(): BackupInfo` - Check if backup exists +- `loadBackupData(): ThreadsData | undefined` +- `restoreFromBackup(): boolean` - Swap current with backup + +## Design Patterns + +### No Caching +Every read operation loads from disk. This ensures: +- CLI invocations always see current data +- External edits are never lost +- Simple mental model (no cache invalidation) + +### Automatic Backup +Every `saveData()` call copies current file to backup first: +1. Copy `threads.json` to `threads.backup.json` +2. Write new data to `threads.json` + +This enables single-step undo via `threads undo`. + +### Partial Updates +`updateThread()` merges partial updates and auto-sets `updatedAt`: +```typescript +updateThread(id, { temperature: 'hot' }); // Only changes temperature +``` + +## Usage + +```typescript +import { getAllThreads, updateThread, addThread } from '../storage'; +``` diff --git a/src/utils/.claude.md b/src/utils/.claude.md new file mode 100644 index 0000000..117cfb8 --- /dev/null +++ b/src/utils/.claude.md @@ -0,0 +1,71 @@ +# utils/ - Formatting and Display + +Provides consistent formatting for CLI output using chalk for colors. + +## Color Conventions + +### Status Colors +| Status | Color | +|--------|-------| +| active | green | +| paused | yellow | +| stopped | red | +| completed | blue | +| archived | gray | + +### Temperature Colors +| Temperature | Color | +|-------------|-------| +| frozen | bright blue | +| freezing | cyan | +| cold | blue | +| tepid | white | +| warm | yellow | +| hot | red | + +## Format Functions + +### Thread Display +- `formatStatus(status)` - Colored uppercase status +- `formatTemperature(temp)` - Colored temperature label +- `formatSize(size)` - Capitalized size label +- `formatImportance(imp)` - `[*][*][*][ ][ ]` style rating +- `formatImportanceStars(imp)` - Star characters for compact view +- `formatTags(tags)` - Cyan `#tag` labels +- `formatThreadSummary(thread)` - Two-line summary +- `formatThreadDetail(thread)` - Full detail view with progress + +### Tree View +- `TreeChars` - Box-drawing characters (├── └── │) +- `formatThreadTreeLine(thread)` - Compact single-line format +- `formatGroupHeader(group)` - Bold underlined group name +- `buildTree(threads, groups): TreeNode[]` - Build hierarchical structure +- `renderTree(nodes): string[]` - Render tree to output lines + +## TreeNode Structure + +```typescript +interface TreeNode { + type: 'group' | 'thread' | 'ungrouped-header'; + group?: Group; + thread?: Thread; + children: TreeNode[]; +} +``` + +The tree builder: +1. Groups threads by `groupId` +2. Builds parent-child relationships via `parentId` +3. Sorts groups alphabetically +4. Places ungrouped threads at the end + +## Usage + +```typescript +import { formatThreadSummary, buildTree, renderTree } from '../utils'; + +console.log(formatThreadSummary(thread)); + +const tree = buildTree(threads, groups); +renderTree(tree).forEach(line => console.log(line)); +```