specweave 1.0.186 → 1.0.187
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +24 -24
- package/bin/specweave.js +45 -0
- package/dist/src/cli/commands/lsp.d.ts +50 -0
- package/dist/src/cli/commands/lsp.d.ts.map +1 -0
- package/dist/src/cli/commands/lsp.js +410 -0
- package/dist/src/cli/commands/lsp.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/skills/lsp/SKILL.md +123 -153
package/CLAUDE.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- SW:META template="claude" version="1.0.
|
|
1
|
+
<!-- SW:META template="claude" version="1.0.186" sections="header,start,autodetect,metarule,rules,workflow,reflect,context,structure,taskformat,secrets,syncing,testing,tdd,api,limits,troubleshooting,lazyloading,principles,linking,mcp,auto,docs" -->
|
|
2
2
|
|
|
3
3
|
<!-- SW:SECTION:hook-priority version="1.0.171" -->
|
|
4
4
|
## ⛔ ABSOLUTE PRIORITY: Hook Instructions Are Mandatory
|
|
@@ -53,7 +53,7 @@ Hooks exist to enforce workflow discipline. If you ignore them:
|
|
|
53
53
|
**This is non-negotiable. No exceptions. No "just this once".**
|
|
54
54
|
<!-- SW:END:hook-priority -->
|
|
55
55
|
|
|
56
|
-
<!-- SW:SECTION:header version="1.0.
|
|
56
|
+
<!-- SW:SECTION:header version="1.0.186" -->
|
|
57
57
|
**Framework**: SpecWeave | **Truth**: `spec.md` + `tasks.md`
|
|
58
58
|
<!-- SW:END:header -->
|
|
59
59
|
|
|
@@ -244,7 +244,7 @@ The official `typescript-lsp@claude-plugins-official` and similar plugins:
|
|
|
244
244
|
|
|
245
245
|
Use `boostvolt/claude-code-lsps` until official plugins are fixed.
|
|
246
246
|
|
|
247
|
-
<!-- SW:SECTION:start version="1.0.
|
|
247
|
+
<!-- SW:SECTION:start version="1.0.186" -->
|
|
248
248
|
## Getting Started
|
|
249
249
|
|
|
250
250
|
**Initial increment**: `0001-project-setup` (auto-created by `specweave init`)
|
|
@@ -254,7 +254,7 @@ Use `boostvolt/claude-code-lsps` until official plugins are fixed.
|
|
|
254
254
|
2. **Customize**: Edit spec.md and use for setup tasks
|
|
255
255
|
<!-- SW:END:start -->
|
|
256
256
|
|
|
257
|
-
<!-- SW:SECTION:autodetect version="1.0.
|
|
257
|
+
<!-- SW:SECTION:autodetect version="1.0.186" -->
|
|
258
258
|
## Auto-Detection
|
|
259
259
|
|
|
260
260
|
SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
|
|
@@ -264,7 +264,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
|
|
|
264
264
|
**Opt-out phrases**: "Just brainstorm first" | "Don't plan yet" | "Quick discussion" | "Let's explore ideas"
|
|
265
265
|
<!-- SW:END:autodetect -->
|
|
266
266
|
|
|
267
|
-
<!-- SW:SECTION:metarule version="1.0.
|
|
267
|
+
<!-- SW:SECTION:metarule version="1.0.186" -->
|
|
268
268
|
## Meta-Rule: Think-Before-Act
|
|
269
269
|
|
|
270
270
|
**Satisfy dependencies BEFORE dependent operations.**
|
|
@@ -275,7 +275,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
|
|
|
275
275
|
```
|
|
276
276
|
<!-- SW:END:metarule -->
|
|
277
277
|
|
|
278
|
-
<!-- SW:SECTION:rules version="1.0.
|
|
278
|
+
<!-- SW:SECTION:rules version="1.0.186" -->
|
|
279
279
|
## Rules
|
|
280
280
|
|
|
281
281
|
1. **Files** → `.specweave/increments/####-name/` (see Structure section for details)
|
|
@@ -286,7 +286,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
|
|
|
286
286
|
6. **⛔ Marketplace refresh**: Use `specweave refresh-marketplace` CLI (not `scripts/refresh-marketplace.sh`)
|
|
287
287
|
<!-- SW:END:rules -->
|
|
288
288
|
|
|
289
|
-
<!-- SW:SECTION:workflow version="1.0.
|
|
289
|
+
<!-- SW:SECTION:workflow version="1.0.186" -->
|
|
290
290
|
## Workflow
|
|
291
291
|
|
|
292
292
|
`/sw:increment "X"` → `/sw:do` → `/sw:progress` → `/sw:done 0001`
|
|
@@ -306,7 +306,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
|
|
|
306
306
|
**Natural language**: "Let's build X" → `/sw:increment` | "What's status?" → `/sw:progress` | "We're done" → `/sw:done` | "Ship while sleeping" → `/sw:auto`
|
|
307
307
|
<!-- SW:END:workflow -->
|
|
308
308
|
|
|
309
|
-
<!-- SW:SECTION:reflect version="1.0.
|
|
309
|
+
<!-- SW:SECTION:reflect version="1.0.186" -->
|
|
310
310
|
## Skill Memories
|
|
311
311
|
|
|
312
312
|
SpecWeave learns from corrections. Learnings saved here automatically. Edit or delete as needed.
|
|
@@ -329,7 +329,7 @@ SpecWeave learns from corrections. Learnings saved here automatically. Edit or d
|
|
|
329
329
|
- **2026-01-29**: in this codebase. Then use goToDefinition to show me where it's defined.
|
|
330
330
|
- **2026-01-29**: ✗→✓ Find All References of handleAutoCommand using LSP The user wants me to find all references to handl
|
|
331
331
|
|
|
332
|
-
<!-- SW:SECTION:context version="1.0.
|
|
332
|
+
<!-- SW:SECTION:context version="1.0.186" -->
|
|
333
333
|
## Context
|
|
334
334
|
|
|
335
335
|
**Before implementing**: Check ADRs at `.specweave/docs/internal/architecture/adr/`
|
|
@@ -337,7 +337,7 @@ SpecWeave learns from corrections. Learnings saved here automatically. Edit or d
|
|
|
337
337
|
**Load context**: `/sw:context <topic>` loads relevant living docs into conversation
|
|
338
338
|
<!-- SW:END:context -->
|
|
339
339
|
|
|
340
|
-
<!-- SW:SECTION:structure version="1.0.
|
|
340
|
+
<!-- SW:SECTION:structure version="1.0.186" -->
|
|
341
341
|
## Structure
|
|
342
342
|
|
|
343
343
|
```
|
|
@@ -352,7 +352,7 @@ SpecWeave learns from corrections. Learnings saved here automatically. Edit or d
|
|
|
352
352
|
**Everything else → subfolders**: `reports/` | `logs/` | `scripts/` | `backups/`
|
|
353
353
|
<!-- SW:END:structure -->
|
|
354
354
|
|
|
355
|
-
<!-- SW:SECTION:taskformat version="1.0.
|
|
355
|
+
<!-- SW:SECTION:taskformat version="1.0.186" -->
|
|
356
356
|
## Task Format
|
|
357
357
|
|
|
358
358
|
```markdown
|
|
@@ -362,7 +362,7 @@ SpecWeave learns from corrections. Learnings saved here automatically. Edit or d
|
|
|
362
362
|
```
|
|
363
363
|
<!-- SW:END:taskformat -->
|
|
364
364
|
|
|
365
|
-
<!-- SW:SECTION:secrets version="1.0.
|
|
365
|
+
<!-- SW:SECTION:secrets version="1.0.186" -->
|
|
366
366
|
## Secrets Check
|
|
367
367
|
|
|
368
368
|
**BEFORE CLI tools**: Check existing config first!
|
|
@@ -376,7 +376,7 @@ gh auth status
|
|
|
376
376
|
**SECURITY**: NEVER use `grep TOKEN .env` without `-q` flag - it exposes credentials in terminal!
|
|
377
377
|
<!-- SW:END:secrets -->
|
|
378
378
|
|
|
379
|
-
<!-- SW:SECTION:syncing version="1.0.
|
|
379
|
+
<!-- SW:SECTION:syncing version="1.0.186" -->
|
|
380
380
|
## External Sync (GitHub/JIRA/ADO)
|
|
381
381
|
|
|
382
382
|
**Commands**: `/sw-github:sync {id}` (issues) | `/sw:sync-specs` (living docs only)
|
|
@@ -386,7 +386,7 @@ gh auth status
|
|
|
386
386
|
**Config**: Set `sync.github.enabled: true` + `canUpdateExternalItems: true` in config.json
|
|
387
387
|
<!-- SW:END:syncing -->
|
|
388
388
|
|
|
389
|
-
<!-- SW:SECTION:testing version="1.0.
|
|
389
|
+
<!-- SW:SECTION:testing version="1.0.186" -->
|
|
390
390
|
## Testing
|
|
391
391
|
|
|
392
392
|
BDD in tasks.md | Unit >80% | `.test.ts` (Vitest)
|
|
@@ -398,7 +398,7 @@ vi.mock('./module', () => ({ func: mockFn }));
|
|
|
398
398
|
```
|
|
399
399
|
<!-- SW:END:testing -->
|
|
400
400
|
|
|
401
|
-
<!-- SW:SECTION:tdd version="1.0.
|
|
401
|
+
<!-- SW:SECTION:tdd version="1.0.186" -->
|
|
402
402
|
## TDD Mode (Test-Driven Development)
|
|
403
403
|
|
|
404
404
|
**When `testing.defaultTestMode: "TDD"` is configured**, follow RED-GREEN-REFACTOR discipline:
|
|
@@ -459,7 +459,7 @@ When TDD is enabled, tasks include phase markers:
|
|
|
459
459
|
**Rule**: Complete dependencies BEFORE dependent tasks (RED before GREEN).
|
|
460
460
|
<!-- SW:END:tdd -->
|
|
461
461
|
|
|
462
|
-
<!-- SW:SECTION:api version="1.0.
|
|
462
|
+
<!-- SW:SECTION:api version="1.0.186" -->
|
|
463
463
|
## API Development (OpenAPI-First)
|
|
464
464
|
|
|
465
465
|
**For API projects only.** Commands: `/sw:api-docs --all` | `--openapi` | `--postman` | `--validate`
|
|
@@ -467,13 +467,13 @@ When TDD is enabled, tasks include phase markers:
|
|
|
467
467
|
Enable in config: `{"apiDocs":{"enabled":true,"openApiPath":"openapi.yaml"}}`
|
|
468
468
|
<!-- SW:END:api -->
|
|
469
469
|
|
|
470
|
-
<!-- SW:SECTION:limits version="1.0.
|
|
470
|
+
<!-- SW:SECTION:limits version="1.0.186" -->
|
|
471
471
|
## Limits
|
|
472
472
|
|
|
473
473
|
**Max 1500 lines/file** — extract before adding
|
|
474
474
|
<!-- SW:END:limits -->
|
|
475
475
|
|
|
476
|
-
<!-- SW:SECTION:troubleshooting version="1.0.
|
|
476
|
+
<!-- SW:SECTION:troubleshooting version="1.0.186" -->
|
|
477
477
|
## Troubleshooting
|
|
478
478
|
|
|
479
479
|
| Issue | Fix |
|
|
@@ -489,7 +489,7 @@ Enable in config: `{"apiDocs":{"enabled":true,"openApiPath":"openapi.yaml"}}`
|
|
|
489
489
|
| Marketplace shows 0 | Normal with auto-load; `/plugin list` shows actual |
|
|
490
490
|
<!-- SW:END:troubleshooting -->
|
|
491
491
|
|
|
492
|
-
<!-- SW:SECTION:lazyloading version="1.0.
|
|
492
|
+
<!-- SW:SECTION:lazyloading version="1.0.186" -->
|
|
493
493
|
## Plugin Auto-Loading
|
|
494
494
|
|
|
495
495
|
Plugins load automatically based on project type and keywords. Manual install if needed:
|
|
@@ -503,7 +503,7 @@ export SPECWEAVE_DISABLE_AUTO_LOAD=1 # Disable auto-load
|
|
|
503
503
|
**Token savings**: Core ~3-5K tokens vs all plugins ~60K+
|
|
504
504
|
<!-- SW:END:lazyloading -->
|
|
505
505
|
|
|
506
|
-
<!-- SW:SECTION:principles version="1.0.
|
|
506
|
+
<!-- SW:SECTION:principles version="1.0.186" -->
|
|
507
507
|
## Principles
|
|
508
508
|
|
|
509
509
|
1. **Spec-first**: `/sw:increment` before coding
|
|
@@ -512,7 +512,7 @@ export SPECWEAVE_DISABLE_AUTO_LOAD=1 # Disable auto-load
|
|
|
512
512
|
4. **Traceable**: All work → specs → ACs
|
|
513
513
|
<!-- SW:END:principles -->
|
|
514
514
|
|
|
515
|
-
<!-- SW:SECTION:linking version="1.0.
|
|
515
|
+
<!-- SW:SECTION:linking version="1.0.186" -->
|
|
516
516
|
## Bidirectional Linking
|
|
517
517
|
|
|
518
518
|
Tasks ↔ User Stories auto-linked via AC-IDs: `AC-US1-01` → `US-001`
|
|
@@ -520,7 +520,7 @@ Tasks ↔ User Stories auto-linked via AC-IDs: `AC-US1-01` → `US-001`
|
|
|
520
520
|
Task format: `**AC**: AC-US1-01, AC-US1-02` (CRITICAL for linking)
|
|
521
521
|
<!-- SW:END:linking -->
|
|
522
522
|
|
|
523
|
-
<!-- SW:SECTION:mcp version="1.0.
|
|
523
|
+
<!-- SW:SECTION:mcp version="1.0.186" -->
|
|
524
524
|
## External Services
|
|
525
525
|
|
|
526
526
|
**Priority**: CLI tools first (simpler) → MCP for complex integrations
|
|
@@ -542,7 +542,7 @@ claude mcp add --transport stdio postgres -- npx -y @modelcontextprotocol/server
|
|
|
542
542
|
MCP supports lazy-loading (auto mode) - tools load on-demand when >10% context.
|
|
543
543
|
<!-- SW:END:mcp -->
|
|
544
544
|
|
|
545
|
-
<!-- SW:SECTION:auto version="1.0.
|
|
545
|
+
<!-- SW:SECTION:auto version="1.0.186" -->
|
|
546
546
|
## Auto Mode
|
|
547
547
|
|
|
548
548
|
**Commands**: `/sw:auto` (start) | `/sw:auto-status` (check) | `/sw:cancel-auto` (emergency only)
|
|
@@ -559,7 +559,7 @@ MCP supports lazy-loading (auto mode) - tools load on-demand when >10% context.
|
|
|
559
559
|
**STOP & ASK** if: Spec conflicts | Task unnecessary | Requirement ambiguous
|
|
560
560
|
<!-- SW:END:auto -->
|
|
561
561
|
|
|
562
|
-
<!-- SW:SECTION:docs version="1.0.
|
|
562
|
+
<!-- SW:SECTION:docs version="1.0.186" -->
|
|
563
563
|
## Docs
|
|
564
564
|
|
|
565
565
|
[spec-weave.com](https://spec-weave.com)
|
package/bin/specweave.js
CHANGED
|
@@ -649,6 +649,51 @@ program
|
|
|
649
649
|
await cacheCommand(options);
|
|
650
650
|
});
|
|
651
651
|
|
|
652
|
+
// LSP command - Code intelligence operations
|
|
653
|
+
const lspCmd = program
|
|
654
|
+
.command('lsp')
|
|
655
|
+
.description('LSP code intelligence (refs, def, hover, symbols, search)');
|
|
656
|
+
|
|
657
|
+
lspCmd
|
|
658
|
+
.command('refs <file> <symbol>')
|
|
659
|
+
.description('Find all references to a symbol')
|
|
660
|
+
.action(async (file, symbol) => {
|
|
661
|
+
const { handleLspRefs } = await import('../dist/src/cli/commands/lsp.js');
|
|
662
|
+
await handleLspRefs(process.cwd(), file, symbol);
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
lspCmd
|
|
666
|
+
.command('def <file> <symbol>')
|
|
667
|
+
.description('Go to definition of a symbol')
|
|
668
|
+
.action(async (file, symbol) => {
|
|
669
|
+
const { handleLspDef } = await import('../dist/src/cli/commands/lsp.js');
|
|
670
|
+
await handleLspDef(process.cwd(), file, symbol);
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
lspCmd
|
|
674
|
+
.command('hover <file> <symbol>')
|
|
675
|
+
.description('Get type information for a symbol')
|
|
676
|
+
.action(async (file, symbol) => {
|
|
677
|
+
const { handleLspHover } = await import('../dist/src/cli/commands/lsp.js');
|
|
678
|
+
await handleLspHover(process.cwd(), file, symbol);
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
lspCmd
|
|
682
|
+
.command('symbols <file>')
|
|
683
|
+
.description('List all symbols in a file')
|
|
684
|
+
.action(async (file) => {
|
|
685
|
+
const { handleLspSymbols } = await import('../dist/src/cli/commands/lsp.js');
|
|
686
|
+
await handleLspSymbols(process.cwd(), file);
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
lspCmd
|
|
690
|
+
.command('search <query>')
|
|
691
|
+
.description('Search for symbols in workspace')
|
|
692
|
+
.action(async (query) => {
|
|
693
|
+
const { handleLspSearch } = await import('../dist/src/cli/commands/lsp.js');
|
|
694
|
+
await handleLspSearch(process.cwd(), query);
|
|
695
|
+
});
|
|
696
|
+
|
|
652
697
|
// Commits command - Display last 2 git commits
|
|
653
698
|
program
|
|
654
699
|
.command('commits')
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSP CLI Commands
|
|
3
|
+
*
|
|
4
|
+
* Provides CLI interface to LSP operations: refs, def, hover, symbols, search.
|
|
5
|
+
* Accepts symbol NAME (not line:char) for ease of use.
|
|
6
|
+
*
|
|
7
|
+
* @module cli/commands/lsp
|
|
8
|
+
*/
|
|
9
|
+
import { Command } from 'commander';
|
|
10
|
+
/**
|
|
11
|
+
* Position in a file (0-indexed)
|
|
12
|
+
*/
|
|
13
|
+
export interface SymbolPosition {
|
|
14
|
+
line: number;
|
|
15
|
+
character: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Find the position of a symbol in a file by name.
|
|
19
|
+
* Uses regex with word boundaries to find the symbol declaration.
|
|
20
|
+
*
|
|
21
|
+
* @param filePath - Path to the file
|
|
22
|
+
* @param symbolName - Name of the symbol to find
|
|
23
|
+
* @returns Position (0-indexed) or null if not found
|
|
24
|
+
*/
|
|
25
|
+
export declare function findSymbolPosition(filePath: string, symbolName: string): SymbolPosition | null;
|
|
26
|
+
/**
|
|
27
|
+
* Find all references to a symbol
|
|
28
|
+
*/
|
|
29
|
+
export declare function handleLspRefs(projectRoot: string, filePath: string, symbolName: string): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Go to definition of a symbol
|
|
32
|
+
*/
|
|
33
|
+
export declare function handleLspDef(projectRoot: string, filePath: string, symbolName: string): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Get hover/type information for a symbol
|
|
36
|
+
*/
|
|
37
|
+
export declare function handleLspHover(projectRoot: string, filePath: string, symbolName: string): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* List all symbols in a file
|
|
40
|
+
*/
|
|
41
|
+
export declare function handleLspSymbols(projectRoot: string, filePath: string): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Search for symbols in workspace
|
|
44
|
+
*/
|
|
45
|
+
export declare function handleLspSearch(projectRoot: string, query: string): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Create the LSP command for Commander.js
|
|
48
|
+
*/
|
|
49
|
+
export declare function createLspCommand(): Command;
|
|
50
|
+
//# sourceMappingURL=lsp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lsp.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/lsp.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAiD9F;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAiCf;AA+BD;;GAEG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAkCf;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CA2Bf;AA+BD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8B3F;AAsCD;;GAEG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BvF;AAyED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAiD1C"}
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSP CLI Commands
|
|
3
|
+
*
|
|
4
|
+
* Provides CLI interface to LSP operations: refs, def, hover, symbols, search.
|
|
5
|
+
* Accepts symbol NAME (not line:char) for ease of use.
|
|
6
|
+
*
|
|
7
|
+
* @module cli/commands/lsp
|
|
8
|
+
*/
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import { Command } from 'commander';
|
|
12
|
+
import { getGlobalLSPManager, shutdownGlobalLSPManager } from '../../core/lsp/lsp-manager.js';
|
|
13
|
+
/**
|
|
14
|
+
* Find the position of a symbol in a file by name.
|
|
15
|
+
* Uses regex with word boundaries to find the symbol declaration.
|
|
16
|
+
*
|
|
17
|
+
* @param filePath - Path to the file
|
|
18
|
+
* @param symbolName - Name of the symbol to find
|
|
19
|
+
* @returns Position (0-indexed) or null if not found
|
|
20
|
+
*/
|
|
21
|
+
export function findSymbolPosition(filePath, symbolName) {
|
|
22
|
+
const resolvedPath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
|
|
23
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const content = fs.readFileSync(resolvedPath, 'utf-8');
|
|
27
|
+
const lines = content.split('\n');
|
|
28
|
+
// Patterns to match symbol declarations (in order of specificity)
|
|
29
|
+
const patterns = [
|
|
30
|
+
// Function/method declaration: function name(, async function name(, name(
|
|
31
|
+
new RegExp(`\\b(?:export\\s+)?(?:async\\s+)?function\\s+(${symbolName})\\s*\\(`),
|
|
32
|
+
// Class declaration
|
|
33
|
+
new RegExp(`\\b(?:export\\s+)?class\\s+(${symbolName})\\b`),
|
|
34
|
+
// Interface declaration
|
|
35
|
+
new RegExp(`\\b(?:export\\s+)?interface\\s+(${symbolName})\\b`),
|
|
36
|
+
// Type declaration
|
|
37
|
+
new RegExp(`\\b(?:export\\s+)?type\\s+(${symbolName})\\b`),
|
|
38
|
+
// Const/let/var declaration
|
|
39
|
+
new RegExp(`\\b(?:export\\s+)?(?:const|let|var)\\s+(${symbolName})\\b`),
|
|
40
|
+
// Method in class (indented)
|
|
41
|
+
new RegExp(`^\\s+(?:async\\s+)?(${symbolName})\\s*\\(`),
|
|
42
|
+
// Property assignment in object/class
|
|
43
|
+
new RegExp(`\\b(${symbolName})\\s*[:=]`),
|
|
44
|
+
// Generic word boundary match (fallback)
|
|
45
|
+
new RegExp(`\\b(${symbolName})\\b`),
|
|
46
|
+
];
|
|
47
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
|
48
|
+
const line = lines[lineIndex];
|
|
49
|
+
for (const pattern of patterns) {
|
|
50
|
+
const match = pattern.exec(line);
|
|
51
|
+
if (match) {
|
|
52
|
+
// Find the position of the captured group (the symbol name)
|
|
53
|
+
const symbolStartIndex = line.indexOf(match[1], match.index);
|
|
54
|
+
if (symbolStartIndex !== -1) {
|
|
55
|
+
return {
|
|
56
|
+
line: lineIndex,
|
|
57
|
+
character: symbolStartIndex,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Find all references to a symbol
|
|
67
|
+
*/
|
|
68
|
+
export async function handleLspRefs(projectRoot, filePath, symbolName) {
|
|
69
|
+
const resolvedPath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
|
|
70
|
+
// Find symbol position
|
|
71
|
+
const position = findSymbolPosition(resolvedPath, symbolName);
|
|
72
|
+
if (!position) {
|
|
73
|
+
console.error(`Symbol '${symbolName}' not found in ${filePath}`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const lspManager = getGlobalLSPManager(projectRoot);
|
|
78
|
+
await lspManager.initialize();
|
|
79
|
+
const result = await lspManager.findReferences(resolvedPath, position.line, position.character);
|
|
80
|
+
if (result && result.success && result.locations.length > 0) {
|
|
81
|
+
console.log(`References to '${symbolName}':\n`);
|
|
82
|
+
for (const loc of result.locations) {
|
|
83
|
+
const relPath = path.relative(projectRoot, loc.uri.replace('file://', ''));
|
|
84
|
+
console.log(` ${relPath}:${loc.range.start.line + 1}:${loc.range.start.character + 1}`);
|
|
85
|
+
}
|
|
86
|
+
console.log(`\nTotal: ${result.locations.length} references`);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
// Fall back to grep-based search
|
|
90
|
+
await grepFallbackRefs(projectRoot, symbolName);
|
|
91
|
+
}
|
|
92
|
+
await shutdownGlobalLSPManager();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// LSP failed, fall back to grep
|
|
96
|
+
await grepFallbackRefs(projectRoot, symbolName);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Grep fallback for finding references
|
|
101
|
+
*/
|
|
102
|
+
async function grepFallbackRefs(projectRoot, symbolName) {
|
|
103
|
+
console.log(`References to '${symbolName}' (grep fallback):\n`);
|
|
104
|
+
const { execSync } = await import('child_process');
|
|
105
|
+
try {
|
|
106
|
+
const result = execSync(`grep -rn --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" "\\b${symbolName}\\b" .`, { cwd: projectRoot, encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 });
|
|
107
|
+
const lines = result.trim().split('\n').filter(Boolean);
|
|
108
|
+
for (const line of lines) {
|
|
109
|
+
console.log(` ${line}`);
|
|
110
|
+
}
|
|
111
|
+
console.log(`\nTotal: ${lines.length} matches (grep)`);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
const exitCode = error.status;
|
|
115
|
+
if (exitCode === 1) {
|
|
116
|
+
console.log(' No references found');
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
console.error('Grep search failed');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Go to definition of a symbol
|
|
125
|
+
*/
|
|
126
|
+
export async function handleLspDef(projectRoot, filePath, symbolName) {
|
|
127
|
+
const resolvedPath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
|
|
128
|
+
const position = findSymbolPosition(resolvedPath, symbolName);
|
|
129
|
+
if (!position) {
|
|
130
|
+
console.error(`Symbol '${symbolName}' not found in ${filePath}`);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
const lspManager = getGlobalLSPManager(projectRoot);
|
|
135
|
+
await lspManager.initialize();
|
|
136
|
+
const result = await lspManager.goToDefinition(resolvedPath, position.line, position.character);
|
|
137
|
+
if (result && result.success && result.location) {
|
|
138
|
+
const loc = result.location;
|
|
139
|
+
const relPath = path.relative(projectRoot, loc.uri.replace('file://', ''));
|
|
140
|
+
console.log(`Definition of '${symbolName}':\n`);
|
|
141
|
+
console.log(` ${relPath}:${loc.range.start.line + 1}:${loc.range.start.character + 1}`);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
// Symbol is likely defined at the position we found
|
|
145
|
+
const relPath = path.relative(projectRoot, resolvedPath);
|
|
146
|
+
console.log(`Definition of '${symbolName}':\n`);
|
|
147
|
+
console.log(` ${relPath}:${position.line + 1}:${position.character + 1}`);
|
|
148
|
+
}
|
|
149
|
+
await shutdownGlobalLSPManager();
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Fall back to showing found position
|
|
153
|
+
const relPath = path.relative(projectRoot, resolvedPath);
|
|
154
|
+
console.log(`Definition of '${symbolName}' (fallback):\n`);
|
|
155
|
+
console.log(` ${relPath}:${position.line + 1}:${position.character + 1}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get hover/type information for a symbol
|
|
160
|
+
*/
|
|
161
|
+
export async function handleLspHover(projectRoot, filePath, symbolName) {
|
|
162
|
+
const resolvedPath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
|
|
163
|
+
const position = findSymbolPosition(resolvedPath, symbolName);
|
|
164
|
+
if (!position) {
|
|
165
|
+
console.error(`Symbol '${symbolName}' not found in ${filePath}`);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
const lspManager = getGlobalLSPManager(projectRoot);
|
|
170
|
+
await lspManager.initialize();
|
|
171
|
+
const result = await lspManager.hover(resolvedPath, position.line, position.character);
|
|
172
|
+
if (result && result.success && result.contents) {
|
|
173
|
+
console.log(`Type info for '${symbolName}':\n`);
|
|
174
|
+
console.log(result.contents);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
// Fall back to showing the line content
|
|
178
|
+
await hoverFallback(resolvedPath, symbolName, position);
|
|
179
|
+
}
|
|
180
|
+
await shutdownGlobalLSPManager();
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
await hoverFallback(resolvedPath, symbolName, position);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Fallback hover showing line content
|
|
188
|
+
*/
|
|
189
|
+
async function hoverFallback(filePath, symbolName, position) {
|
|
190
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
191
|
+
const lines = content.split('\n');
|
|
192
|
+
const line = lines[position.line];
|
|
193
|
+
console.log(`Type info for '${symbolName}' (from source):\n`);
|
|
194
|
+
console.log(` ${line.trim()}`);
|
|
195
|
+
// Try to infer type from declaration
|
|
196
|
+
if (line.includes('function')) {
|
|
197
|
+
console.log(`\n Kind: function`);
|
|
198
|
+
}
|
|
199
|
+
else if (line.includes('class')) {
|
|
200
|
+
console.log(`\n Kind: class`);
|
|
201
|
+
}
|
|
202
|
+
else if (line.includes('interface')) {
|
|
203
|
+
console.log(`\n Kind: interface`);
|
|
204
|
+
}
|
|
205
|
+
else if (line.includes('type')) {
|
|
206
|
+
console.log(`\n Kind: type alias`);
|
|
207
|
+
}
|
|
208
|
+
else if (line.includes('const') || line.includes('let') || line.includes('var')) {
|
|
209
|
+
console.log(`\n Kind: variable`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* List all symbols in a file
|
|
214
|
+
*/
|
|
215
|
+
export async function handleLspSymbols(projectRoot, filePath) {
|
|
216
|
+
const resolvedPath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
|
|
217
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
218
|
+
console.error(`File not found: ${filePath}`);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
const lspManager = getGlobalLSPManager(projectRoot);
|
|
223
|
+
await lspManager.initialize();
|
|
224
|
+
const result = await lspManager.documentSymbols(resolvedPath);
|
|
225
|
+
if (result && result.success && result.symbols.length > 0) {
|
|
226
|
+
console.log(`Symbols in ${path.basename(filePath)}:\n`);
|
|
227
|
+
for (const sym of result.symbols) {
|
|
228
|
+
const kind = getSymbolKindName(sym.kind);
|
|
229
|
+
const line = sym.location?.range?.start?.line ?? 0;
|
|
230
|
+
console.log(` ${kind.padEnd(12)} ${sym.name} (line ${line + 1})`);
|
|
231
|
+
}
|
|
232
|
+
console.log(`\nTotal: ${result.symbols.length} symbols`);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
await symbolsFallback(resolvedPath);
|
|
236
|
+
}
|
|
237
|
+
await shutdownGlobalLSPManager();
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
await symbolsFallback(resolvedPath);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Fallback symbol extraction using regex
|
|
245
|
+
*/
|
|
246
|
+
async function symbolsFallback(filePath) {
|
|
247
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
248
|
+
const lines = content.split('\n');
|
|
249
|
+
console.log(`Symbols in ${path.basename(filePath)} (regex fallback):\n`);
|
|
250
|
+
const symbols = [];
|
|
251
|
+
const patterns = [
|
|
252
|
+
{ kind: 'function', regex: /(?:export\s+)?(?:async\s+)?function\s+(\w+)/ },
|
|
253
|
+
{ kind: 'class', regex: /(?:export\s+)?class\s+(\w+)/ },
|
|
254
|
+
{ kind: 'interface', regex: /(?:export\s+)?interface\s+(\w+)/ },
|
|
255
|
+
{ kind: 'type', regex: /(?:export\s+)?type\s+(\w+)/ },
|
|
256
|
+
{ kind: 'const', regex: /(?:export\s+)?const\s+(\w+)\s*[:=]/ },
|
|
257
|
+
];
|
|
258
|
+
for (let i = 0; i < lines.length; i++) {
|
|
259
|
+
const line = lines[i];
|
|
260
|
+
for (const { kind, regex } of patterns) {
|
|
261
|
+
const match = regex.exec(line);
|
|
262
|
+
if (match) {
|
|
263
|
+
symbols.push({ kind, name: match[1], line: i + 1 });
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
for (const sym of symbols) {
|
|
268
|
+
console.log(` ${sym.kind.padEnd(12)} ${sym.name} (line ${sym.line})`);
|
|
269
|
+
}
|
|
270
|
+
console.log(`\nTotal: ${symbols.length} symbols`);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Search for symbols in workspace
|
|
274
|
+
*/
|
|
275
|
+
export async function handleLspSearch(projectRoot, query) {
|
|
276
|
+
try {
|
|
277
|
+
const lspManager = getGlobalLSPManager(projectRoot);
|
|
278
|
+
await lspManager.initialize();
|
|
279
|
+
const result = await lspManager.workspaceSymbols(query);
|
|
280
|
+
if (result && result.success && result.symbols.length > 0) {
|
|
281
|
+
console.log(`Workspace symbols matching '${query}':\n`);
|
|
282
|
+
for (const sym of result.symbols) {
|
|
283
|
+
const kind = getSymbolKindName(sym.kind);
|
|
284
|
+
const relPath = sym.location?.uri
|
|
285
|
+
? path.relative(projectRoot, sym.location.uri.replace('file://', ''))
|
|
286
|
+
: 'unknown';
|
|
287
|
+
const line = sym.location?.range?.start?.line ?? 0;
|
|
288
|
+
console.log(` ${kind.padEnd(12)} ${sym.name} (${relPath}:${line + 1})`);
|
|
289
|
+
}
|
|
290
|
+
console.log(`\nTotal: ${result.symbols.length} symbols`);
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
await searchFallback(projectRoot, query);
|
|
294
|
+
}
|
|
295
|
+
await shutdownGlobalLSPManager();
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
await searchFallback(projectRoot, query);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Fallback workspace search using grep
|
|
303
|
+
*/
|
|
304
|
+
async function searchFallback(projectRoot, query) {
|
|
305
|
+
console.log(`Workspace symbols matching '${query}' (grep fallback):\n`);
|
|
306
|
+
const { execSync } = await import('child_process');
|
|
307
|
+
try {
|
|
308
|
+
// Search for declarations matching the query
|
|
309
|
+
const patterns = [
|
|
310
|
+
`function\\s+\\w*${query}\\w*`,
|
|
311
|
+
`class\\s+\\w*${query}\\w*`,
|
|
312
|
+
`interface\\s+\\w*${query}\\w*`,
|
|
313
|
+
`type\\s+\\w*${query}\\w*`,
|
|
314
|
+
];
|
|
315
|
+
const combinedPattern = patterns.join('|');
|
|
316
|
+
const result = execSync(`grep -rn --include="*.ts" --include="*.tsx" -E "${combinedPattern}" .`, { cwd: projectRoot, encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 });
|
|
317
|
+
const lines = result.trim().split('\n').filter(Boolean);
|
|
318
|
+
for (const line of lines.slice(0, 20)) {
|
|
319
|
+
// Limit to 20 results
|
|
320
|
+
console.log(` ${line}`);
|
|
321
|
+
}
|
|
322
|
+
if (lines.length > 20) {
|
|
323
|
+
console.log(` ... and ${lines.length - 20} more`);
|
|
324
|
+
}
|
|
325
|
+
console.log(`\nTotal: ${lines.length} matches`);
|
|
326
|
+
}
|
|
327
|
+
catch (error) {
|
|
328
|
+
const exitCode = error.status;
|
|
329
|
+
if (exitCode === 1) {
|
|
330
|
+
console.log(' No symbols found matching query');
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
console.error('Search failed');
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Convert LSP symbol kind number to name
|
|
339
|
+
*/
|
|
340
|
+
function getSymbolKindName(kind) {
|
|
341
|
+
const kinds = {
|
|
342
|
+
1: 'File',
|
|
343
|
+
2: 'Module',
|
|
344
|
+
3: 'Namespace',
|
|
345
|
+
4: 'Package',
|
|
346
|
+
5: 'Class',
|
|
347
|
+
6: 'Method',
|
|
348
|
+
7: 'Property',
|
|
349
|
+
8: 'Field',
|
|
350
|
+
9: 'Constructor',
|
|
351
|
+
10: 'Enum',
|
|
352
|
+
11: 'Interface',
|
|
353
|
+
12: 'Function',
|
|
354
|
+
13: 'Variable',
|
|
355
|
+
14: 'Constant',
|
|
356
|
+
15: 'String',
|
|
357
|
+
16: 'Number',
|
|
358
|
+
17: 'Boolean',
|
|
359
|
+
18: 'Array',
|
|
360
|
+
};
|
|
361
|
+
return kinds[kind] || 'Unknown';
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Create the LSP command for Commander.js
|
|
365
|
+
*/
|
|
366
|
+
export function createLspCommand() {
|
|
367
|
+
const lsp = new Command('lsp').description('LSP code intelligence operations');
|
|
368
|
+
// specweave lsp refs <file> <symbol>
|
|
369
|
+
lsp
|
|
370
|
+
.command('refs <file> <symbol>')
|
|
371
|
+
.description('Find all references to a symbol')
|
|
372
|
+
.action(async (file, symbol) => {
|
|
373
|
+
const projectRoot = process.cwd();
|
|
374
|
+
await handleLspRefs(projectRoot, file, symbol);
|
|
375
|
+
});
|
|
376
|
+
// specweave lsp def <file> <symbol>
|
|
377
|
+
lsp
|
|
378
|
+
.command('def <file> <symbol>')
|
|
379
|
+
.description('Go to definition of a symbol')
|
|
380
|
+
.action(async (file, symbol) => {
|
|
381
|
+
const projectRoot = process.cwd();
|
|
382
|
+
await handleLspDef(projectRoot, file, symbol);
|
|
383
|
+
});
|
|
384
|
+
// specweave lsp hover <file> <symbol>
|
|
385
|
+
lsp
|
|
386
|
+
.command('hover <file> <symbol>')
|
|
387
|
+
.description('Get type information for a symbol')
|
|
388
|
+
.action(async (file, symbol) => {
|
|
389
|
+
const projectRoot = process.cwd();
|
|
390
|
+
await handleLspHover(projectRoot, file, symbol);
|
|
391
|
+
});
|
|
392
|
+
// specweave lsp symbols <file>
|
|
393
|
+
lsp
|
|
394
|
+
.command('symbols <file>')
|
|
395
|
+
.description('List all symbols in a file')
|
|
396
|
+
.action(async (file) => {
|
|
397
|
+
const projectRoot = process.cwd();
|
|
398
|
+
await handleLspSymbols(projectRoot, file);
|
|
399
|
+
});
|
|
400
|
+
// specweave lsp search <query>
|
|
401
|
+
lsp
|
|
402
|
+
.command('search <query>')
|
|
403
|
+
.description('Search for symbols in workspace')
|
|
404
|
+
.action(async (query) => {
|
|
405
|
+
const projectRoot = process.cwd();
|
|
406
|
+
await handleLspSearch(projectRoot, query);
|
|
407
|
+
});
|
|
408
|
+
return lsp;
|
|
409
|
+
}
|
|
410
|
+
//# sourceMappingURL=lsp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lsp.js","sourceRoot":"","sources":["../../../../src/cli/commands/lsp.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specweave",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.187",
|
|
4
4
|
"description": "Spec-driven development framework for Claude Code. AI-native workflow with living documentation, intelligent agents, and multilingual support (9 languages). Enterprise-grade traceability with permanent specs and temporary increments.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -1,180 +1,141 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: lsp
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Code intelligence via LSP - find references, go to definition, hover type info, list symbols.
|
|
5
|
+
Activates on: "find all references", "go to definition", "where is X defined",
|
|
6
|
+
"show type of", "list symbols", "search symbols", "what uses", "who calls".
|
|
7
|
+
Works with TypeScript, Python, C#, Go, Rust. Falls back to grep if LSP unavailable.
|
|
4
8
|
---
|
|
5
9
|
|
|
6
|
-
#
|
|
10
|
+
# LSP Code Intelligence
|
|
7
11
|
|
|
8
|
-
|
|
12
|
+
Use SpecWeave's LSP CLI for semantic code navigation and analysis.
|
|
9
13
|
|
|
10
|
-
##
|
|
14
|
+
## How to Use (IMPORTANT)
|
|
11
15
|
|
|
12
|
-
Use
|
|
13
|
-
- "Find all references to X"
|
|
14
|
-
- "Go to definition of X"
|
|
15
|
-
- "Where is X defined?"
|
|
16
|
-
- "Show me the type of X"
|
|
17
|
-
- "List symbols in file X"
|
|
18
|
-
- "Search for symbol X in workspace"
|
|
16
|
+
**Use Bash tool with `specweave lsp` commands:**
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
```bash
|
|
19
|
+
# Find all references to a symbol
|
|
20
|
+
specweave lsp refs <file> <symbol>
|
|
21
|
+
|
|
22
|
+
# Go to definition
|
|
23
|
+
specweave lsp def <file> <symbol>
|
|
24
|
+
|
|
25
|
+
# Get type information (hover)
|
|
26
|
+
specweave lsp hover <file> <symbol>
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
# List all symbols in a file
|
|
29
|
+
specweave lsp symbols <file>
|
|
30
|
+
|
|
31
|
+
# Search workspace for symbols
|
|
32
|
+
specweave lsp search <query>
|
|
33
|
+
```
|
|
25
34
|
|
|
26
|
-
|
|
35
|
+
## Command Reference
|
|
27
36
|
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
| Command | Purpose | Example |
|
|
38
|
+
|---------|---------|---------|
|
|
39
|
+
| `lsp refs` | Find all usages of a symbol | `specweave lsp refs src/api.ts handleRequest` |
|
|
40
|
+
| `lsp def` | Navigate to symbol definition | `specweave lsp def src/utils.ts formatDate` |
|
|
41
|
+
| `lsp hover` | Get type signature and docs | `specweave lsp hover src/models.ts User` |
|
|
42
|
+
| `lsp symbols` | List all symbols in file | `specweave lsp symbols src/index.ts` |
|
|
43
|
+
| `lsp search` | Find symbols across workspace | `specweave lsp search Controller` |
|
|
30
44
|
|
|
31
|
-
|
|
32
|
-
const lspManager = getGlobalLSPManager(projectRoot);
|
|
45
|
+
## When to Use LSP vs Grep
|
|
33
46
|
|
|
34
|
-
|
|
35
|
-
|
|
47
|
+
| Task | Use LSP | Use Grep |
|
|
48
|
+
|------|---------|----------|
|
|
49
|
+
| Find function usages | ✅ `lsp refs` | ❌ |
|
|
50
|
+
| Navigate to definition | ✅ `lsp def` | ❌ |
|
|
51
|
+
| Get type information | ✅ `lsp hover` | ❌ |
|
|
52
|
+
| Search text patterns | ❌ | ✅ `Grep tool` |
|
|
53
|
+
| Find in comments | ❌ | ✅ `Grep tool` |
|
|
54
|
+
| Case-insensitive search | ❌ | ✅ `Grep -i` |
|
|
36
55
|
|
|
37
|
-
|
|
38
|
-
const def = await lspManager.goToDefinition('src/file.ts', line, character);
|
|
56
|
+
**Rule of thumb**: Use LSP for symbols, Grep for text patterns.
|
|
39
57
|
|
|
40
|
-
|
|
41
|
-
const hover = await lspManager.hover('src/file.ts', line, character);
|
|
58
|
+
## Examples
|
|
42
59
|
|
|
43
|
-
|
|
44
|
-
const symbols = await lspManager.documentSymbols('src/file.ts');
|
|
60
|
+
### Example 1: Find All References Before Refactoring
|
|
45
61
|
|
|
46
|
-
|
|
47
|
-
const wsSymbols = await lspManager.workspaceSymbols('MyClass');
|
|
62
|
+
User: "Find all references to handleAutoCommand"
|
|
48
63
|
|
|
49
|
-
|
|
50
|
-
|
|
64
|
+
```bash
|
|
65
|
+
specweave lsp refs src/cli/commands/auto.ts handleAutoCommand
|
|
51
66
|
```
|
|
52
67
|
|
|
53
|
-
|
|
68
|
+
Output:
|
|
69
|
+
```
|
|
70
|
+
References to 'handleAutoCommand':
|
|
54
71
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
| C#/.NET | `csharp-ls` | `*.csproj`, `*.sln` |
|
|
60
|
-
| Go | `gopls` | `go.mod` |
|
|
61
|
-
| Rust | `rust-analyzer` | `Cargo.toml` |
|
|
72
|
+
bin/specweave.js:473:1
|
|
73
|
+
bin/specweave.js:474:1
|
|
74
|
+
src/cli/commands/auto.ts:82:5
|
|
75
|
+
src/cli/commands/auto.ts:96:24
|
|
62
76
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
LSP positions are 0-indexed:
|
|
66
|
-
- `line`: 0-based line number (first line = 0)
|
|
67
|
-
- `character`: 0-based character offset
|
|
68
|
-
|
|
69
|
-
To find a symbol position:
|
|
70
|
-
1. Read the file
|
|
71
|
-
2. Count lines (0-indexed)
|
|
72
|
-
3. Find character offset within the line (0-indexed)
|
|
73
|
-
|
|
74
|
-
## Response Formats
|
|
75
|
-
|
|
76
|
-
### findReferences
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
{
|
|
80
|
-
locations: [
|
|
81
|
-
{
|
|
82
|
-
uri: 'file:///path/to/file.ts',
|
|
83
|
-
range: {
|
|
84
|
-
start: { line: 10, character: 5 },
|
|
85
|
-
end: { line: 10, character: 15 }
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
],
|
|
89
|
-
success: true
|
|
90
|
-
}
|
|
77
|
+
Total: 4 references
|
|
91
78
|
```
|
|
92
79
|
|
|
93
|
-
###
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
range: {
|
|
100
|
-
start: { line: 5, character: 0 },
|
|
101
|
-
end: { line: 5, character: 20 }
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
success: true
|
|
105
|
-
}
|
|
80
|
+
### Example 2: Go to Definition
|
|
81
|
+
|
|
82
|
+
User: "Where is processArgs defined?"
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
specweave lsp def src/cli/commands/auto.ts processArgs
|
|
106
86
|
```
|
|
107
87
|
|
|
108
|
-
###
|
|
88
|
+
### Example 3: Get Type Information
|
|
89
|
+
|
|
90
|
+
User: "What's the type signature of handleAutoCommand?"
|
|
109
91
|
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
contents: '(method) MyClass.myMethod(): void',
|
|
113
|
-
range: { start: {...}, end: {...} },
|
|
114
|
-
success: true
|
|
115
|
-
}
|
|
92
|
+
```bash
|
|
93
|
+
specweave lsp hover src/cli/commands/auto.ts handleAutoCommand
|
|
116
94
|
```
|
|
117
95
|
|
|
118
|
-
###
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
name: 'MyClass',
|
|
125
|
-
kind: 5, // Class
|
|
126
|
-
location: {...},
|
|
127
|
-
containerName: undefined
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
name: 'myMethod',
|
|
131
|
-
kind: 6, // Method
|
|
132
|
-
location: {...},
|
|
133
|
-
containerName: 'MyClass'
|
|
134
|
-
}
|
|
135
|
-
],
|
|
136
|
-
success: true
|
|
137
|
-
}
|
|
96
|
+
### Example 4: List All Exports
|
|
97
|
+
|
|
98
|
+
User: "What functions are exported from lsp.ts?"
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
specweave lsp symbols src/cli/commands/lsp.ts
|
|
138
102
|
```
|
|
139
103
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
|
151
|
-
|
|
152
|
-
|
|
|
153
|
-
|
|
|
154
|
-
|
|
|
155
|
-
|
|
|
156
|
-
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
104
|
+
### Example 5: Search Workspace
|
|
105
|
+
|
|
106
|
+
User: "Find all Command classes"
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
specweave lsp search Command
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Supported Languages
|
|
113
|
+
|
|
114
|
+
| Language | Server Required | Auto-detected by |
|
|
115
|
+
|----------|-----------------|------------------|
|
|
116
|
+
| TypeScript/JS | `typescript-language-server` | `tsconfig.json`, `package.json` |
|
|
117
|
+
| Python | `pyright` or `pylsp` | `requirements.txt`, `pyproject.toml` |
|
|
118
|
+
| C#/.NET | `csharp-ls` | `*.csproj`, `*.sln` |
|
|
119
|
+
| Go | `gopls` | `go.mod` |
|
|
120
|
+
| Rust | `rust-analyzer` | `Cargo.toml` |
|
|
121
|
+
|
|
122
|
+
## Fallback Behavior
|
|
123
|
+
|
|
124
|
+
If LSP is unavailable (server not installed, timeout, etc.):
|
|
125
|
+
1. Commands automatically fall back to grep-based search
|
|
126
|
+
2. Results show "(grep fallback)" in output
|
|
127
|
+
3. Still functional, but less precise for symbol resolution
|
|
162
128
|
|
|
163
129
|
## Requirements
|
|
164
130
|
|
|
165
131
|
Language servers must be installed globally:
|
|
166
132
|
|
|
167
133
|
```bash
|
|
168
|
-
# TypeScript
|
|
134
|
+
# TypeScript (most common)
|
|
169
135
|
npm install -g typescript-language-server typescript
|
|
170
136
|
|
|
171
137
|
# Python
|
|
172
138
|
pip install pyright
|
|
173
|
-
# or
|
|
174
|
-
pip install python-lsp-server
|
|
175
|
-
|
|
176
|
-
# C#
|
|
177
|
-
dotnet tool install -g csharp-ls
|
|
178
139
|
|
|
179
140
|
# Go
|
|
180
141
|
go install golang.org/x/tools/gopls@latest
|
|
@@ -183,23 +144,32 @@ go install golang.org/x/tools/gopls@latest
|
|
|
183
144
|
rustup component add rust-analyzer
|
|
184
145
|
```
|
|
185
146
|
|
|
186
|
-
##
|
|
187
|
-
|
|
188
|
-
If LSP is not available for a file type:
|
|
189
|
-
1. The manager returns `null`
|
|
190
|
-
2. Fall back to grep-based search
|
|
191
|
-
3. Results are less precise but still useful
|
|
147
|
+
## Decision Tree for Claude
|
|
192
148
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
149
|
+
```
|
|
150
|
+
User asks about code navigation?
|
|
151
|
+
│
|
|
152
|
+
├─ "Find references to X" or "What uses X" or "Who calls X"
|
|
153
|
+
│ └─ Use: specweave lsp refs <file> <symbol>
|
|
154
|
+
│
|
|
155
|
+
├─ "Go to definition" or "Where is X defined"
|
|
156
|
+
│ └─ Use: specweave lsp def <file> <symbol>
|
|
157
|
+
│
|
|
158
|
+
├─ "What type is X" or "Show signature of X"
|
|
159
|
+
│ └─ Use: specweave lsp hover <file> <symbol>
|
|
160
|
+
│
|
|
161
|
+
├─ "List symbols in file" or "What's exported"
|
|
162
|
+
│ └─ Use: specweave lsp symbols <file>
|
|
163
|
+
│
|
|
164
|
+
├─ "Find symbol X in workspace" or "Search for X"
|
|
165
|
+
│ └─ Use: specweave lsp search <query>
|
|
166
|
+
│
|
|
167
|
+
└─ Text search, patterns, comments
|
|
168
|
+
└─ Use: Grep tool (not LSP)
|
|
169
|
+
```
|
|
202
170
|
|
|
203
|
-
## Why This
|
|
171
|
+
## Why This Exists
|
|
204
172
|
|
|
205
|
-
Claude Code's built-in LSP has known bugs (GitHub Issues #15148, #16291, #20050).
|
|
173
|
+
Claude Code's built-in LSP has known bugs (GitHub Issues #15148, #16291, #20050).
|
|
174
|
+
This skill provides direct access to language servers via SpecWeave's CLI,
|
|
175
|
+
bypassing the broken infrastructure.
|