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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@ src/test/fixtures/workspace/.vscode/tasktree.json

.playwright-mcp/
website/_site/

.commandtree/
12 changes: 9 additions & 3 deletions .vscode-test.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { defineConfig } from '@vscode/test-cli';
import { cpSync, mkdtempSync } from 'fs';
import { tmpdir } from 'os';
import { join } from 'path';
import { join, resolve } from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __dirname = dirname(fileURLToPath(import.meta.url));

// Copy fixtures to a temp directory so tests run in full isolation
const testWorkspace = mkdtempSync(join(tmpdir(), 'commandtree-test-'));
cpSync('./src/test/fixtures/workspace', testWorkspace, { recursive: true });

const userDataDir = resolve(__dirname, '.vscode-test/user-data');

export default defineConfig({
files: ['out/test/e2e/**/*.test.js', 'out/test/providers/**/*.test.js'],
version: 'stable',
Expand All @@ -19,8 +25,8 @@ export default defineConfig({
slow: 10000
},
launchArgs: [
'--disable-extensions',
'--disable-gpu'
'--disable-gpu',
'--user-data-dir', userDataDir
],
coverage: {
include: ['out/**/*.js'],
Expand Down
12 changes: 0 additions & 12 deletions .vscode/commandtree.json

This file was deleted.

2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
{
/* Multi-line comment for test */
"name": "Debug Python",
"type": "python",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/main.py"
}
Expand Down
18 changes: 13 additions & 5 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,22 @@
"mochaExplorer.ui": "tdd",
"mochaExplorer.require": [],
"typescript.tsserver.experimental.enableProjectDiagnostics": true,
"typescript.reportStyleChecksAsErrors": true,
"eslint.lintTask.enable": true,
"eslint.run": "onType",
"eslint.probe": ["typescript"],
"eslint.validate": ["typescript"],
"eslint.probe": [
"typescript"
],
"eslint.validate": [
"typescript"
],
"eslint.useFlatConfig": true,
"eslint.workingDirectories": ["."],
"eslint.workingDirectories": [
"."
],
"eslint.debug": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
"source.fixAll.eslint": "explicit",
"commandtree.enableAiSummaries": "explicit"
}
}
}
1 change: 1 addition & 0 deletions .vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ src/**
test-fixtures/**
out/test/**
node_modules/**
!node_modules/node-sqlite3-wasm/**
scripts/**
.too_many_cooks/**
.claude/**
Expand Down
183 changes: 183 additions & 0 deletions Agents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# CLAUDE.md - CommandTree Extension

## Too Many Cooks

You are working with many other agents. Make sure there is effective cooperation
- Register on TMC immediately
- Don't edit files that are locked; lock files when editing
- COMMUNICATE REGULARLY AND COORDINATE WITH OTHERS THROUGH MESSAGES

## Coding Rules

- **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!
- **No string literals** - Named constants only, and it ONE location
- **Functional style** - Prefer pure functions, avoid classes where possible
- **No suppressing warnings** - Fix them properly
- **No REGEX** It is absolutely ⛔️ illegal
- **Don't run long runnings tasks** like docker builds, tests. Ask the user to do it!!
- **Expressions over assignments** - Prefer const and immutable patterns
- **Named parameters** - Use object params for functions with 3+ args
- **Keep files under 450 LOC and functions under 20 LOC**
- **No commented-out code** - Delete it
- **No placeholders** - If incomplete, leave LOUD compilation error with TODO

### Typescript
- **TypeScript strict mode** - No `any`, no implicit types, turn all lints up to error
- **Ignoring lints = ⛔️ illegal** - Fix violations immediately
- **No throwing** - Only return `Result<T,E>`

### CSS
- **Minimize duplication** - fewer classes is better
- **Don't include section in class name** - name them after what they are - not the section they sit in

## Testing

⚠️ NEVER KILL VSCODE PROCESSES

#### Rules
- **Prefer e2e tests over unit tests** - only unit tests for isolating bugs
- DO NOT USE GIT
- Separate e2e tests from unit tests by file. They should not be in the same file together.
- Prefer adding assertions to existing tests rather than adding new tests
- Test files in `src/test/suite/*.test.ts`
- Run tests: `npm test`
- NEVER remove assertions
- FAILING TEST = ✅ OK. TEST THAT DOESN'T ENFORCE BEHAVIOR = ⛔️ ILLEGAL
- Unit test = No VSCODE instance needed = isolation only test

### Automated (E2E) Testing

**AUTOMATED TESTING IS BLACK BOX TESTING ONLY**
Only test the UI **THROUGH the UI**. Do not run command etc. to coerce the state. You are testing the UI, not the code.

- Tests run in actual VS Code window via `@vscode/test-electron`
- Automated tests must not modify internal state or call functions that do. They must only use the extension through the UI.
* - ❌ Calling internal methods like provider.updateTasks()
* - ❌ Calling provider.refresh() directly
* - ❌ Manipulating internal state directly
* - ❌ Using any method not exposed via VS Code commands
* - ❌ Using commands that should just happen as part of normal use. e.g.: `await vscode.commands.executeCommand('commandtree.refresh');`
* - ❌ `executeCommand('commandtree.addToQuick', item)` - TAP the item via the DOM!!!

### Test First Process
- Write test that fails because of bug/missing feature
- Run tests to verify that test fails because of this reason
- Adjust test and repeat until you see failure for the reason above
- Add missing feature or fix bug
- Run tests to verify test passes.
- Repeat and fix until test passes WITHOUT changing the test

**Every test MUST:**
1. Assert on the ACTUAL OBSERVABLE BEHAVIOR (UI state, view contents, return values)
2. Fail if the feature is broken
3. Test the full flow, not just side effects like config files

### ⛔️ FAKE TESTS ARE ILLEGAL

**A "fake test" is any test that passes without actually verifying behavior. These are STRICTLY FORBIDDEN:**

```typescript
// ❌ ILLEGAL - asserts true unconditionally
assert.ok(true, 'Should work');

// ❌ ILLEGAL - no assertion on actual behavior
try { await doSomething(); } catch { }
assert.ok(true, 'Did not crash');

// ❌ ILLEGAL - only checks config file, not actual UI/view behavior
writeConfig({ quick: ['task1'] });
const config = readConfig();
assert.ok(config.quick.includes('task1')); // This doesn't test the FEATURE

// ❌ ILLEGAL - empty catch with success assertion
try { await command(); } catch { /* swallow */ }
assert.ok(true, 'Command ran');
```

## Critical Docs

[VSCode Extension API](https://code.visualstudio.com/api/)
[SCode Extension Testing API](https://code.visualstudio.com/api/extension-guides/testing)

## Project Structure

```
CommandTree/
├── src/
│ ├── extension.ts # Entry point, command registration
│ ├── CommandTreeProvider.ts # TreeDataProvider implementation
│ ├── config/
│ │ └── TagConfig.ts # Tag configuration from commandtree.json
│ ├── discovery/
│ │ ├── index.ts # Discovery orchestration
│ │ ├── shell.ts # Shell script discovery
│ │ ├── npm.ts # NPM script discovery
│ │ ├── make.ts # Makefile target discovery
│ │ ├── launch.ts # launch.json discovery
│ │ └── tasks.ts # tasks.json discovery
│ ├── models/
│ │ └── TaskItem.ts # Task data model and TreeItem
│ ├── runners/
│ │ └── TaskRunner.ts # Task execution logic
│ └── test/
│ └── suite/ # E2E test files
├── test-fixtures/ # Test workspace files
├── package.json # Extension manifest
├── tsconfig.json # TypeScript config
└── .vscode-test.mjs # Test runner config
```

## Commands

| Command ID | Description |
|------------|-------------|
| `commandtree.refresh` | Reload all tasks |
| `commandtree.run` | Run task in new terminal |
| `commandtree.runInCurrentTerminal` | Run in active terminal |
| `commandtree.debug` | Launch with debugger |
| `commandtree.filter` | Text filter input |
| `commandtree.filterByTag` | Tag filter picker |
| `commandtree.clearFilter` | Clear all filters |
| `commandtree.editTags` | Open commandtree.json |

## Build Commands

See [text](package.json)

## Adding New Task Types

1. Create discovery module in `src/discovery/`
2. Export discovery function: `discoverXxxTasks(root: string, excludes: string[]): Promise<TaskItem[]>`
3. Add to `discoverAllTasks()` in `src/discovery/index.ts`
4. Add category in `CommandTreeProvider.buildRootCategories()`
5. Handle execution in `TaskRunner.run()`
6. Add E2E tests in `src/test/suite/discovery.test.ts`

## VS Code API Patterns

```typescript
// Register command
context.subscriptions.push(
vscode.commands.registerCommand('commandtree.xxx', handler)
);

// File watcher
const watcher = vscode.workspace.createFileSystemWatcher('**/pattern');
watcher.onDidChange(() => refresh());
context.subscriptions.push(watcher);

// Tree view
const treeView = vscode.window.createTreeView('commandtree', {
treeDataProvider: provider,
showCollapseAll: true
});

// Context for when clauses
vscode.commands.executeCommand('setContext', 'commandtree.hasFilter', true);
```

## Configuration

Settings defined in `package.json` under `contributes.configuration`:
- `commandtree.excludePatterns` - Glob patterns to exclude
- `commandtree.sortOrder` - Task sort order (folder/name/type)
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
# Changelog

## 0.5.0

### Added

- **GitHub Copilot AI Summaries** — discovered commands are automatically summarised in plain language by GitHub Copilot, displayed in tooltips on hover
- Security warnings: commands that perform dangerous operations (e.g. `rm -rf`, force-push) are flagged with a warning in the tree view
- `commandtree.enableAiSummaries` setting to toggle AI summaries (enabled by default)
- `commandtree.generateSummaries` command to manually trigger summary generation
- Content-hash change detection — summaries only regenerate when scripts change

### Fixed

- Terminal execution no longer throws when xterm viewport is uninitialised in headless environments

## 0.4.0

### Added

- SQLite storage for summaries and embeddings via `node-sqlite3-wasm`
- Automatic migration from legacy JSON store to SQLite on activation
- File watcher re-summarises scripts when they change, with user notification

### Fixed

- Corrected homepage link to commandtree.dev in package.json and README
Expand Down
47 changes: 38 additions & 9 deletions Claude.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ You are working with many other agents. Make sure there is effective cooperation
## Coding Rules

- **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!
- **No string literals** - Named constants only, and it ONE location
- DO NOT USE GIT
- **Functional style** - Prefer pure functions, avoid classes where possible
- **No suppressing warnings** - Fix them properly
- **No REGEX** It is absolutely ⛔️ illegal
- **No REGEX** It is absolutely ⛔️ illegal, and no text matching in general
- **Don't run long runnings tasks** like docker builds, tests. Ask the user to do it!!
- **Expressions over assignments** - Prefer const and immutable patterns
- **Named parameters** - Use object params for functions with 3+ args
Expand All @@ -22,6 +24,8 @@ You are working with many other agents. Make sure there is effective cooperation

### Typescript
- **TypeScript strict mode** - No `any`, no implicit types, turn all lints up to error
- **Regularly run the linter** - Fix lint errors IMMEDIATELY
- **Decouple providers from the VSCODE SDK** - No vscode sdk use within the providers
- **Ignoring lints = ⛔️ illegal** - Fix violations immediately
- **No throwing** - Only return `Result<T,E>`

Expand All @@ -35,7 +39,6 @@ You are working with many other agents. Make sure there is effective cooperation

#### Rules
- **Prefer e2e tests over unit tests** - only unit tests for isolating bugs
- DO NOT USE GIT
- Separate e2e tests from unit tests by file. They should not be in the same file together.
- Prefer adding assertions to existing tests rather than adding new tests
- Test files in `src/test/suite/*.test.ts`
Expand Down Expand Up @@ -95,8 +98,21 @@ assert.ok(true, 'Command ran');

## Critical Docs

### Vscode SDK
[VSCode Extension API](https://code.visualstudio.com/api/)
[SCode Extension Testing API](https://code.visualstudio.com/api/extension-guides/testing)
[VSCode Extension Testing API](https://code.visualstudio.com/api/extension-guides/testing)
[VSCODE Language Model API](https://code.visualstudio.com/api/extension-guides/ai/language-model)
[Language Model Tool API](https://code.visualstudio.com/api/extension-guides/ai/tools)
[AI extensibility in VS Cod](https://code.visualstudio.com/api/extension-guides/ai/ai-extensibility-overview)
[AI language models in VS Code](https://code.visualstudio.com/docs/copilot/customization/language-models)

### Website

https://developers.google.com/search/blog/2025/05/succeeding-in-ai-search
https://developers.google.com/search/docs/fundamentals/seo-starter-guide

https://studiohawk.com.au/blog/how-to-optimise-ai-overviews/
https://about.ads.microsoft.com/en/blog/post/october-2025/optimizing-your-content-for-inclusion-in-ai-search-answers

## Project Structure

Expand All @@ -109,11 +125,25 @@ CommandTree/
│ │ └── TagConfig.ts # Tag configuration from commandtree.json
│ ├── discovery/
│ │ ├── index.ts # Discovery orchestration
│ │ ├── shell.ts # Shell script discovery
│ │ ├── npm.ts # NPM script discovery
│ │ ├── make.ts # Makefile target discovery
│ │ ├── launch.ts # launch.json discovery
│ │ └── tasks.ts # tasks.json discovery
│ │ ├── shell.ts # Shell scripts (.sh, .bash, .zsh)
│ │ ├── npm.ts # NPM scripts (package.json)
│ │ ├── make.ts # Makefile targets
│ │ ├── launch.ts # VS Code launch configs
│ │ ├── tasks.ts # VS Code tasks
│ │ ├── python.ts # Python scripts (.py)
│ │ ├── powershell.ts # PowerShell scripts (.ps1)
│ │ ├── gradle.ts # Gradle tasks
│ │ ├── cargo.ts # Cargo (Rust) tasks
│ │ ├── maven.ts # Maven goals (pom.xml)
│ │ ├── ant.ts # Ant targets (build.xml)
│ │ ├── just.ts # Just recipes (justfile)
│ │ ├── taskfile.ts # Taskfile tasks (Taskfile.yml)
│ │ ├── deno.ts # Deno tasks (deno.json)
│ │ ├── rake.ts # Rake tasks (Rakefile)
│ │ ├── composer.ts # Composer scripts (composer.json)
│ │ ├── docker.ts # Docker Compose services
│ │ ├── dotnet.ts # .NET projects (.csproj)
│ │ └── markdown.ts # Markdown files (.md)
│ ├── models/
│ │ └── TaskItem.ts # Task data model and TreeItem
│ ├── runners/
Expand Down Expand Up @@ -179,5 +209,4 @@ vscode.commands.executeCommand('setContext', 'commandtree.hasFilter', true);

Settings defined in `package.json` under `contributes.configuration`:
- `commandtree.excludePatterns` - Glob patterns to exclude
- `commandtree.showEmptyCategories` - Show empty category nodes
- `commandtree.sortOrder` - Task sort order (folder/name/type)
Loading