|
| 1 | +# CLAUDE.md - CommandTree Extension |
| 2 | + |
| 3 | +## Too Many Cooks |
| 4 | + |
| 5 | +You are working with many other agents. Make sure there is effective cooperation |
| 6 | +- Register on TMC immediately |
| 7 | +- Don't edit files that are locked; lock files when editing |
| 8 | +- COMMUNICATE REGULARLY AND COORDINATE WITH OTHERS THROUGH MESSAGES |
| 9 | + |
| 10 | +## Coding Rules |
| 11 | + |
| 12 | +- **Zero duplication - TOP PRIORITY** - Always search for existing code before adding. Move; don't copy files. Add assertions to tests rather than duplicating tests. AIM FOR LESS CODE! |
| 13 | +- **No string literals** - Named constants only, and it ONE location |
| 14 | +- **Functional style** - Prefer pure functions, avoid classes where possible |
| 15 | +- **No suppressing warnings** - Fix them properly |
| 16 | +- **No REGEX** It is absolutely ⛔️ illegal |
| 17 | +- **Don't run long runnings tasks** like docker builds, tests. Ask the user to do it!! |
| 18 | +- **Expressions over assignments** - Prefer const and immutable patterns |
| 19 | +- **Named parameters** - Use object params for functions with 3+ args |
| 20 | +- **Keep files under 450 LOC and functions under 20 LOC** |
| 21 | +- **No commented-out code** - Delete it |
| 22 | +- **No placeholders** - If incomplete, leave LOUD compilation error with TODO |
| 23 | + |
| 24 | +### Typescript |
| 25 | +- **TypeScript strict mode** - No `any`, no implicit types, turn all lints up to error |
| 26 | +- **Ignoring lints = ⛔️ illegal** - Fix violations immediately |
| 27 | +- **No throwing** - Only return `Result<T,E>` |
| 28 | + |
| 29 | +### CSS |
| 30 | +- **Minimize duplication** - fewer classes is better |
| 31 | +- **Don't include section in class name** - name them after what they are - not the section they sit in |
| 32 | + |
| 33 | +## Testing |
| 34 | + |
| 35 | +⚠️ NEVER KILL VSCODE PROCESSES |
| 36 | + |
| 37 | +#### Rules |
| 38 | +- **Prefer e2e tests over unit tests** - only unit tests for isolating bugs |
| 39 | +- DO NOT USE GIT |
| 40 | +- Separate e2e tests from unit tests by file. They should not be in the same file together. |
| 41 | +- Prefer adding assertions to existing tests rather than adding new tests |
| 42 | +- Test files in `src/test/suite/*.test.ts` |
| 43 | +- Run tests: `npm test` |
| 44 | +- NEVER remove assertions |
| 45 | +- FAILING TEST = ✅ OK. TEST THAT DOESN'T ENFORCE BEHAVIOR = ⛔️ ILLEGAL |
| 46 | +- Unit test = No VSCODE instance needed = isolation only test |
| 47 | + |
| 48 | +### Automated (E2E) Testing |
| 49 | + |
| 50 | +**AUTOMATED TESTING IS BLACK BOX TESTING ONLY** |
| 51 | +Only test the UI **THROUGH the UI**. Do not run command etc. to coerce the state. You are testing the UI, not the code. |
| 52 | + |
| 53 | +- Tests run in actual VS Code window via `@vscode/test-electron` |
| 54 | +- Automated tests must not modify internal state or call functions that do. They must only use the extension through the UI. |
| 55 | + * - ❌ Calling internal methods like provider.updateTasks() |
| 56 | + * - ❌ Calling provider.refresh() directly |
| 57 | + * - ❌ Manipulating internal state directly |
| 58 | + * - ❌ Using any method not exposed via VS Code commands |
| 59 | + * - ❌ Using commands that should just happen as part of normal use. e.g.: `await vscode.commands.executeCommand('commandtree.refresh');` |
| 60 | + * - ❌ `executeCommand('commandtree.addToQuick', item)` - TAP the item via the DOM!!! |
| 61 | + |
| 62 | +### Test First Process |
| 63 | +- Write test that fails because of bug/missing feature |
| 64 | +- Run tests to verify that test fails because of this reason |
| 65 | +- Adjust test and repeat until you see failure for the reason above |
| 66 | +- Add missing feature or fix bug |
| 67 | +- Run tests to verify test passes. |
| 68 | +- Repeat and fix until test passes WITHOUT changing the test |
| 69 | + |
| 70 | +**Every test MUST:** |
| 71 | +1. Assert on the ACTUAL OBSERVABLE BEHAVIOR (UI state, view contents, return values) |
| 72 | +2. Fail if the feature is broken |
| 73 | +3. Test the full flow, not just side effects like config files |
| 74 | + |
| 75 | +### ⛔️ FAKE TESTS ARE ILLEGAL |
| 76 | + |
| 77 | +**A "fake test" is any test that passes without actually verifying behavior. These are STRICTLY FORBIDDEN:** |
| 78 | + |
| 79 | +```typescript |
| 80 | +// ❌ ILLEGAL - asserts true unconditionally |
| 81 | +assert.ok(true, 'Should work'); |
| 82 | + |
| 83 | +// ❌ ILLEGAL - no assertion on actual behavior |
| 84 | +try { await doSomething(); } catch { } |
| 85 | +assert.ok(true, 'Did not crash'); |
| 86 | + |
| 87 | +// ❌ ILLEGAL - only checks config file, not actual UI/view behavior |
| 88 | +writeConfig({ quick: ['task1'] }); |
| 89 | +const config = readConfig(); |
| 90 | +assert.ok(config.quick.includes('task1')); // This doesn't test the FEATURE |
| 91 | + |
| 92 | +// ❌ ILLEGAL - empty catch with success assertion |
| 93 | +try { await command(); } catch { /* swallow */ } |
| 94 | +assert.ok(true, 'Command ran'); |
| 95 | +``` |
| 96 | + |
| 97 | +## Critical Docs |
| 98 | + |
| 99 | +[VSCode Extension API](https://code.visualstudio.com/api/) |
| 100 | +[SCode Extension Testing API](https://code.visualstudio.com/api/extension-guides/testing) |
| 101 | + |
| 102 | +## Project Structure |
| 103 | + |
| 104 | +``` |
| 105 | +CommandTree/ |
| 106 | +├── src/ |
| 107 | +│ ├── extension.ts # Entry point, command registration |
| 108 | +│ ├── CommandTreeProvider.ts # TreeDataProvider implementation |
| 109 | +│ ├── config/ |
| 110 | +│ │ └── TagConfig.ts # Tag configuration from commandtree.json |
| 111 | +│ ├── discovery/ |
| 112 | +│ │ ├── index.ts # Discovery orchestration |
| 113 | +│ │ ├── shell.ts # Shell script discovery |
| 114 | +│ │ ├── npm.ts # NPM script discovery |
| 115 | +│ │ ├── make.ts # Makefile target discovery |
| 116 | +│ │ ├── launch.ts # launch.json discovery |
| 117 | +│ │ └── tasks.ts # tasks.json discovery |
| 118 | +│ ├── models/ |
| 119 | +│ │ └── TaskItem.ts # Task data model and TreeItem |
| 120 | +│ ├── runners/ |
| 121 | +│ │ └── TaskRunner.ts # Task execution logic |
| 122 | +│ └── test/ |
| 123 | +│ └── suite/ # E2E test files |
| 124 | +├── test-fixtures/ # Test workspace files |
| 125 | +├── package.json # Extension manifest |
| 126 | +├── tsconfig.json # TypeScript config |
| 127 | +└── .vscode-test.mjs # Test runner config |
| 128 | +``` |
| 129 | + |
| 130 | +## Commands |
| 131 | + |
| 132 | +| Command ID | Description | |
| 133 | +|------------|-------------| |
| 134 | +| `commandtree.refresh` | Reload all tasks | |
| 135 | +| `commandtree.run` | Run task in new terminal | |
| 136 | +| `commandtree.runInCurrentTerminal` | Run in active terminal | |
| 137 | +| `commandtree.debug` | Launch with debugger | |
| 138 | +| `commandtree.filter` | Text filter input | |
| 139 | +| `commandtree.filterByTag` | Tag filter picker | |
| 140 | +| `commandtree.clearFilter` | Clear all filters | |
| 141 | +| `commandtree.editTags` | Open commandtree.json | |
| 142 | + |
| 143 | +## Build Commands |
| 144 | + |
| 145 | +See [text](package.json) |
| 146 | + |
| 147 | +## Adding New Task Types |
| 148 | + |
| 149 | +1. Create discovery module in `src/discovery/` |
| 150 | +2. Export discovery function: `discoverXxxTasks(root: string, excludes: string[]): Promise<TaskItem[]>` |
| 151 | +3. Add to `discoverAllTasks()` in `src/discovery/index.ts` |
| 152 | +4. Add category in `CommandTreeProvider.buildRootCategories()` |
| 153 | +5. Handle execution in `TaskRunner.run()` |
| 154 | +6. Add E2E tests in `src/test/suite/discovery.test.ts` |
| 155 | + |
| 156 | +## VS Code API Patterns |
| 157 | + |
| 158 | +```typescript |
| 159 | +// Register command |
| 160 | +context.subscriptions.push( |
| 161 | + vscode.commands.registerCommand('commandtree.xxx', handler) |
| 162 | +); |
| 163 | + |
| 164 | +// File watcher |
| 165 | +const watcher = vscode.workspace.createFileSystemWatcher('**/pattern'); |
| 166 | +watcher.onDidChange(() => refresh()); |
| 167 | +context.subscriptions.push(watcher); |
| 168 | + |
| 169 | +// Tree view |
| 170 | +const treeView = vscode.window.createTreeView('commandtree', { |
| 171 | + treeDataProvider: provider, |
| 172 | + showCollapseAll: true |
| 173 | +}); |
| 174 | + |
| 175 | +// Context for when clauses |
| 176 | +vscode.commands.executeCommand('setContext', 'commandtree.hasFilter', true); |
| 177 | +``` |
| 178 | + |
| 179 | +## Configuration |
| 180 | + |
| 181 | +Settings defined in `package.json` under `contributes.configuration`: |
| 182 | +- `commandtree.excludePatterns` - Glob patterns to exclude |
| 183 | +- `commandtree.sortOrder` - Task sort order (folder/name/type) |
0 commit comments