Skip to content

Commit a2596a6

Browse files
Semantic search, AI summaries & security warnings (#4)
# TLDR; Adds AI-powered semantic search and summaries to CommandTree using VS Code's Language Model API, with structured security warning detection via the Tool API. # Details - **Semantic search**: Embeds commands using `all-MiniLM-L6-v2`, stores in SQLite (`.commandtree/`), ranks by cosine similarity with percentage scores - **AI summaries**: Copilot generates human-readable summaries for discovered commands, displayed in tree tooltips - **Security warnings**: Uses VS Code Language Model Tool API (`toolMode: Required`) for structured output — dedicated `security_warning` column in DB, ⚠️ icon on risky commands, warning text in tooltip - **Tagging rewrite**: Tags now stored in SQLite junction table with exact command ID matching (no pattern matching). Managed through UI commands, not JSON config - **New discoverers**: .NET projects (`.csproj`) and Markdown files (`.md`) - **Model selection**: Automatic Copilot model selection with preference ordering - **Test improvements**: Split semantic tests into summaries + semantic search files, removed fake tests (`assert.ok(true)`), added unit tests for similarity, embeddings, model selection - **Removed legacy**: Deleted deprecated `editTags` command, pattern-matching tag config, `tagconfig.provider.test.ts` # How do the tests prove the change works - E2E tests verify semantic search rankings, summary display in tooltips, security warning ⚠️ icons, tag filtering through the VS Code UI (black-box only) - Unit tests isolate cosine similarity math, embedding serialization/deserialization, model selection logic, and DB operations - All tests run in actual VS Code window via `@vscode/test-electron` against a temp fixture workspace
1 parent 0f99c2b commit a2596a6

87 files changed

Lines changed: 7801 additions & 2797 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,5 @@ src/test/fixtures/workspace/.vscode/tasktree.json
3030

3131
.playwright-mcp/
3232
website/_site/
33+
34+
.commandtree/

.vscode-test.mjs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import { defineConfig } from '@vscode/test-cli';
22
import { cpSync, mkdtempSync } from 'fs';
33
import { tmpdir } from 'os';
4-
import { join } from 'path';
4+
import { join, resolve } from 'path';
5+
import { fileURLToPath } from 'url';
6+
import { dirname } from 'path';
7+
8+
const __dirname = dirname(fileURLToPath(import.meta.url));
59

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

14+
const userDataDir = resolve(__dirname, '.vscode-test/user-data');
15+
1016
export default defineConfig({
1117
files: ['out/test/e2e/**/*.test.js', 'out/test/providers/**/*.test.js'],
1218
version: 'stable',
@@ -19,8 +25,8 @@ export default defineConfig({
1925
slow: 10000
2026
},
2127
launchArgs: [
22-
'--disable-extensions',
23-
'--disable-gpu'
28+
'--disable-gpu',
29+
'--user-data-dir', userDataDir
2430
],
2531
coverage: {
2632
include: ['out/**/*.js'],

.vscode/commandtree.json

Lines changed: 0 additions & 12 deletions
This file was deleted.

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
{
2424
/* Multi-line comment for test */
2525
"name": "Debug Python",
26-
"type": "python",
26+
"type": "debugpy",
2727
"request": "launch",
2828
"program": "${workspaceFolder}/main.py"
2929
}

.vscode/settings.json

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,22 @@
33
"mochaExplorer.ui": "tdd",
44
"mochaExplorer.require": [],
55
"typescript.tsserver.experimental.enableProjectDiagnostics": true,
6+
"typescript.reportStyleChecksAsErrors": true,
67
"eslint.lintTask.enable": true,
78
"eslint.run": "onType",
8-
"eslint.probe": ["typescript"],
9-
"eslint.validate": ["typescript"],
9+
"eslint.probe": [
10+
"typescript"
11+
],
12+
"eslint.validate": [
13+
"typescript"
14+
],
1015
"eslint.useFlatConfig": true,
11-
"eslint.workingDirectories": ["."],
16+
"eslint.workingDirectories": [
17+
"."
18+
],
1219
"eslint.debug": true,
1320
"editor.codeActionsOnSave": {
14-
"source.fixAll.eslint": "explicit"
21+
"source.fixAll.eslint": "explicit",
22+
"commandtree.enableAiSummaries": "explicit"
1523
}
16-
}
24+
}

.vscodeignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ src/**
55
test-fixtures/**
66
out/test/**
77
node_modules/**
8+
!node_modules/node-sqlite3-wasm/**
89
scripts/**
910
.too_many_cooks/**
1011
.claude/**

Agents.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
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)

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
11
# Changelog
22

3+
## 0.5.0
4+
5+
### Added
6+
7+
- **GitHub Copilot AI Summaries** — discovered commands are automatically summarised in plain language by GitHub Copilot, displayed in tooltips on hover
8+
- Security warnings: commands that perform dangerous operations (e.g. `rm -rf`, force-push) are flagged with a warning in the tree view
9+
- `commandtree.enableAiSummaries` setting to toggle AI summaries (enabled by default)
10+
- `commandtree.generateSummaries` command to manually trigger summary generation
11+
- Content-hash change detection — summaries only regenerate when scripts change
12+
13+
### Fixed
14+
15+
- Terminal execution no longer throws when xterm viewport is uninitialised in headless environments
16+
317
## 0.4.0
418

19+
### Added
20+
21+
- SQLite storage for summaries and embeddings via `node-sqlite3-wasm`
22+
- Automatic migration from legacy JSON store to SQLite on activation
23+
- File watcher re-summarises scripts when they change, with user notification
24+
525
### Fixed
626

727
- Corrected homepage link to commandtree.dev in package.json and README

Claude.md

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ You are working with many other agents. Make sure there is effective cooperation
1010
## Coding Rules
1111

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

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

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

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

9699
## Critical Docs
97100

101+
### Vscode SDK
98102
[VSCode Extension API](https://code.visualstudio.com/api/)
99-
[SCode Extension Testing API](https://code.visualstudio.com/api/extension-guides/testing)
103+
[VSCode Extension Testing API](https://code.visualstudio.com/api/extension-guides/testing)
104+
[VSCODE Language Model API](https://code.visualstudio.com/api/extension-guides/ai/language-model)
105+
[Language Model Tool API](https://code.visualstudio.com/api/extension-guides/ai/tools)
106+
[AI extensibility in VS Cod](https://code.visualstudio.com/api/extension-guides/ai/ai-extensibility-overview)
107+
[AI language models in VS Code](https://code.visualstudio.com/docs/copilot/customization/language-models)
108+
109+
### Website
110+
111+
https://developers.google.com/search/blog/2025/05/succeeding-in-ai-search
112+
https://developers.google.com/search/docs/fundamentals/seo-starter-guide
113+
114+
https://studiohawk.com.au/blog/how-to-optimise-ai-overviews/
115+
https://about.ads.microsoft.com/en/blog/post/october-2025/optimizing-your-content-for-inclusion-in-ai-search-answers
100116

101117
## Project Structure
102118

@@ -109,11 +125,25 @@ CommandTree/
109125
│ │ └── TagConfig.ts # Tag configuration from commandtree.json
110126
│ ├── discovery/
111127
│ │ ├── index.ts # Discovery orchestration
112-
│ │ ├── shell.ts # Shell script discovery
113-
│ │ ├── npm.ts # NPM script discovery
114-
│ │ ├── make.ts # Makefile target discovery
115-
│ │ ├── launch.ts # launch.json discovery
116-
│ │ └── tasks.ts # tasks.json discovery
128+
│ │ ├── shell.ts # Shell scripts (.sh, .bash, .zsh)
129+
│ │ ├── npm.ts # NPM scripts (package.json)
130+
│ │ ├── make.ts # Makefile targets
131+
│ │ ├── launch.ts # VS Code launch configs
132+
│ │ ├── tasks.ts # VS Code tasks
133+
│ │ ├── python.ts # Python scripts (.py)
134+
│ │ ├── powershell.ts # PowerShell scripts (.ps1)
135+
│ │ ├── gradle.ts # Gradle tasks
136+
│ │ ├── cargo.ts # Cargo (Rust) tasks
137+
│ │ ├── maven.ts # Maven goals (pom.xml)
138+
│ │ ├── ant.ts # Ant targets (build.xml)
139+
│ │ ├── just.ts # Just recipes (justfile)
140+
│ │ ├── taskfile.ts # Taskfile tasks (Taskfile.yml)
141+
│ │ ├── deno.ts # Deno tasks (deno.json)
142+
│ │ ├── rake.ts # Rake tasks (Rakefile)
143+
│ │ ├── composer.ts # Composer scripts (composer.json)
144+
│ │ ├── docker.ts # Docker Compose services
145+
│ │ ├── dotnet.ts # .NET projects (.csproj)
146+
│ │ └── markdown.ts # Markdown files (.md)
117147
│ ├── models/
118148
│ │ └── TaskItem.ts # Task data model and TreeItem
119149
│ ├── runners/
@@ -179,5 +209,4 @@ vscode.commands.executeCommand('setContext', 'commandtree.hasFilter', true);
179209

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

0 commit comments

Comments
 (0)