prjct-cli 0.37.1 → 0.40.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,128 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.40.0] - 2026-01-28
4
+
5
+ ### Feature: Enhanced Skill System
6
+
7
+ Inspired by vercel-labs/skills, prjct-cli now supports remote skill installation, version tracking via lock file, and full ecosystem-standard SKILL.md subdirectory format across all skill directories.
8
+
9
+ **New: Remote Skill Installation (`p. skill add`)**
10
+ - Install skills from GitHub repos: `p. skill add owner/repo`
11
+ - Install specific skill: `p. skill add owner/repo@skill-name`
12
+ - Install from local directory: `p. skill add ./path`
13
+ - Automatic source metadata injection (`_prjct` frontmatter block)
14
+
15
+ **New: Skill Lock File**
16
+ - Tracks installed skills at `~/.prjct-cli/skills/.skill-lock.json`
17
+ - Records source URL, commit SHA, install timestamp
18
+ - Enables update detection via `p. skill check`
19
+
20
+ **New: Additional Subcommands**
21
+ - `p. skill add <source>` — Install from GitHub or local path
22
+ - `p. skill remove <name>` — Uninstall a skill
23
+ - `p. skill init <name>` — Scaffold a new skill template
24
+ - `p. skill check` — Detect available updates
25
+
26
+ **Improved: Full SKILL.md Subdirectory Support**
27
+ - All skill directories now support both `{name}.md` (flat) and `{name}/SKILL.md` (subdirectory) formats
28
+ - Previously only provider dirs (`~/.claude/skills/`) checked subdirectories
29
+ - Orchestrator executor now checks both patterns when loading agent skills
30
+
31
+ **New Files:**
32
+ - `core/services/skill-installer.ts` — Remote installation service
33
+ - `core/services/skill-lock.ts` — Lock file management
34
+
35
+ **Modified:**
36
+ - `core/types/services.ts` — Extended `SkillMetadata` with `sourceUrl`, `sourceType`, `installedAt`, `sha`; added `'remote'` source type
37
+ - `core/services/skill-service.ts` — Unified SKILL.md discovery in all dirs
38
+ - `core/agentic/orchestrator-executor.ts` — Both path patterns for skill loading
39
+ - `templates/commands/skill.md` — New subcommands documentation
40
+
41
+ ## [0.39.0] - 2026-01-24
42
+
43
+ ### Feature: Windsurf IDE Support (PRJ-66)
44
+
45
+ prjct now works with **Windsurf IDE** as a project-level integration.
46
+
47
+ **Architecture:**
48
+ - Windsurf uses `.md` files (not `.mdc` like Cursor) with YAML frontmatter
49
+ - Uses `trigger: always_on` instead of `alwaysApply: true`
50
+ - Uses "workflows" directory instead of "commands"
51
+ - Character limits: 6000 per file, 12000 total
52
+
53
+ **New Files:**
54
+ - `templates/windsurf/router.md` - Minimal router with YAML frontmatter
55
+ - `templates/global/WINDSURF.md` - Full prjct instructions for Windsurf
56
+ - `templates/windsurf/workflows/*.md` - Individual workflow files (sync, task, done, ship, bug, pause, resume)
57
+
58
+ **Modified:**
59
+ - `core/types/provider.ts` - Added `'windsurf'` to AIProviderName, added `WindsurfProjectDetection`
60
+ - `core/infrastructure/ai-provider.ts` - Added WindsurfProvider, detectWindsurfProject(), branding
61
+ - `core/infrastructure/setup.ts` - Added installWindsurfProject(), hasWindsurfProject()
62
+ - `bin/prjct.ts` - Added Windsurf to --version display
63
+
64
+ **Project Structure:**
65
+ ```
66
+ .windsurf/
67
+ ├── rules/
68
+ │ └── prjct.md # Router (auto-generated)
69
+ └── workflows/
70
+ ├── sync.md
71
+ ├── task.md
72
+ ├── done.md
73
+ ├── ship.md
74
+ ├── bug.md
75
+ ├── pause.md
76
+ └── resume.md
77
+ ```
78
+
79
+ ---
80
+
81
+ ## [0.38.1] - 2026-01-24
82
+
83
+ ### Docs: Complete Antigravity documentation
84
+
85
+ - Added Antigravity badge to README
86
+ - Added Antigravity Quick Start section
87
+ - Updated "How It Works" table with Antigravity column
88
+ - Updated Requirements to include Antigravity
89
+ - Fixed version display to show all providers consistently
90
+
91
+ ---
92
+
93
+ ## [0.38.0] - 2026-01-24
94
+
95
+ ### Feature: Google Antigravity Support (PRJ-64)
96
+
97
+ prjct now works with **Google Antigravity** as a skill (not MCP server).
98
+
99
+ **Why Skills over MCP:**
100
+ - Zero overhead (just SKILL.md files)
101
+ - Cross-compatible with Claude Code skills
102
+ - No daemon process needed
103
+ - Aligned with prjct as "context layer"
104
+
105
+ **New Files:**
106
+ - `templates/global/ANTIGRAVITY.md` - Full prjct instructions
107
+ - `templates/antigravity/SKILL.md` - Skill router for Antigravity
108
+
109
+ **Modified:**
110
+ - `core/infrastructure/ai-provider.ts` - Added AntigravityProvider, detectAntigravity()
111
+ - `core/infrastructure/setup.ts` - Added installAntigravitySkill()
112
+ - `core/index.ts` - Show Antigravity in --version
113
+
114
+ **Skills Location:**
115
+ ```
116
+ ~/.gemini/antigravity/skills/prjct/SKILL.md
117
+ ```
118
+
119
+ **Critical Rule Added:**
120
+ All agent templates (CLAUDE.md, GEMINI.md, CURSOR.mdc, ANTIGRAVITY.md) now include:
121
+ - Rule #0: Plan Before Action (NON-NEGOTIABLE)
122
+ - Agent must create plan and get user approval before ANY execution
123
+
124
+ ---
125
+
3
126
  ## [0.37.1] - 2026-01-24
4
127
 
5
128
  ### Fix: Cursor Command Syntax (PRJ-65)
package/README.md CHANGED
@@ -2,10 +2,11 @@
2
2
 
3
3
  **Context layer for AI coding agents.**
4
4
 
5
- Works with Claude Code, Gemini CLI, Cursor IDE, and more.
5
+ Works with Claude Code, Gemini CLI, Antigravity, Cursor IDE, and more.
6
6
 
7
7
  [![Claude Code](https://img.shields.io/badge/Claude%20Code-Ready-6366f1)](CLAUDE.md)
8
8
  [![Gemini CLI](https://img.shields.io/badge/Gemini%20CLI-Ready-4285F4)]()
9
+ [![Antigravity](https://img.shields.io/badge/Antigravity-Ready-EA4335)]()
9
10
  [![Cursor IDE](https://img.shields.io/badge/Cursor%20IDE-Ready-00D4AA)]()
10
11
  [![npm](https://img.shields.io/npm/v/prjct-cli)](https://www.npmjs.com/package/prjct-cli)
11
12
 
@@ -14,18 +15,19 @@ Works with Claude Code, Gemini CLI, Cursor IDE, and more.
14
15
  prjct gives AI coding agents the context they need about your project. It maintains state between sessions, tracks progress, and ensures agents understand your codebase.
15
16
 
16
17
  ```
17
- Your AI Agent (Claude/Gemini/Cursor) prjct
18
-
19
- "What am I working on?"
20
- ───────────────────────────────►
21
- Reads project context
22
- Task: "Add user auth" │
23
- Branch: feature/auth │
24
- Subtask 2/5: API routes
25
- ◄───────────────────────────────
26
-
27
-
28
- Writes code with full context
18
+ Your AI Agent prjct
19
+ (Claude/Gemini/Antigravity/Cursor)
20
+
21
+ "What am I working on?"
22
+ ────────────────────────────────►
23
+ Reads project context
24
+ Task: "Add user auth"
25
+ Branch: feature/auth
26
+ Subtask 2/5: API routes
27
+ ◄────────────────────────────────
28
+
29
+
30
+ Writes code with full context │
29
31
  ```
30
32
 
31
33
  ## Install
@@ -53,6 +55,25 @@ p. done # Complete subtask
53
55
  p. ship # Ship with PR
54
56
  ```
55
57
 
58
+ ### Google Antigravity
59
+
60
+ ```bash
61
+ # 1. One-time global setup (installs prjct as a skill)
62
+ prjct start
63
+
64
+ # 2. Initialize your project
65
+ cd my-project
66
+ prjct init
67
+
68
+ # 3. Open in Antigravity and use:
69
+ p. sync # Analyze project
70
+ p. task "add user auth" # Start a task
71
+ p. done # Complete subtask
72
+ p. ship # Ship with PR
73
+ ```
74
+
75
+ > **Note:** prjct integrates as a Skill (not MCP server) for zero-overhead operation.
76
+
56
77
  ### Cursor IDE
57
78
 
58
79
  ```bash
@@ -72,19 +93,19 @@ prjct init
72
93
  ### Core Workflow
73
94
 
74
95
  ```
75
- Claude/Gemini: p. sync → p. task "..." → [code] → p. done → p. ship
76
- Cursor: /sync → /task "..." → [code] → /done → /ship
96
+ Claude/Gemini/Antigravity: p. sync → p. task "..." → [code] → p. done → p. ship
97
+ Cursor: /sync → /task "..." → [code] → /done → /ship
77
98
  ```
78
99
 
79
100
  ## How It Works
80
101
 
81
- | Component | Claude Code | Gemini CLI | Cursor IDE |
82
- |-----------|-------------|------------|------------|
83
- | Router | `~/.claude/commands/p.md` | `~/.gemini/commands/p.toml` | `.cursor/commands/*.md` |
84
- | Config | `~/.claude/CLAUDE.md` | `~/.gemini/GEMINI.md` | `.cursor/rules/prjct.mdc` |
85
- | Storage | `~/.prjct-cli/projects/` | `~/.prjct-cli/projects/` | `~/.prjct-cli/projects/` |
86
- | Scope | Global | Global | Per-project |
87
- | Syntax | `p. command` | `p. command` | `/command` |
102
+ | Component | Claude Code | Gemini CLI | Antigravity | Cursor IDE |
103
+ |-----------|-------------|------------|-------------|------------|
104
+ | Router | `~/.claude/commands/p.md` | `~/.gemini/commands/p.toml` | Skill | `.cursor/commands/*.md` |
105
+ | Config | `~/.claude/CLAUDE.md` | `~/.gemini/GEMINI.md` | `~/.gemini/antigravity/skills/prjct/` | `.cursor/rules/prjct.mdc` |
106
+ | Storage | `~/.prjct-cli/projects/` | `~/.prjct-cli/projects/` | `~/.prjct-cli/projects/` | `~/.prjct-cli/projects/` |
107
+ | Scope | Global | Global | Global | Per-project |
108
+ | Syntax | `p. command` | `p. command` | `p. command` | `/command` |
88
109
 
89
110
  All agents share the same project storage, so you can switch between them freely.
90
111
 
@@ -114,7 +135,7 @@ prjct --help # Show help
114
135
  ## Requirements
115
136
 
116
137
  - Node.js 18+ or Bun 1.0+
117
- - One of: Claude Code, Gemini CLI, or Cursor IDE
138
+ - One of: Claude Code, Gemini CLI, Antigravity, or Cursor IDE
118
139
 
119
140
  ## Links
120
141
 
package/bin/prjct.ts CHANGED
@@ -94,6 +94,8 @@ if (args[0] === 'start' || args[0] === 'setup') {
94
94
  const geminiConfigured = fs.existsSync(path.join(home, '.gemini', 'commands', 'p.toml'))
95
95
  const cursorDetected = fs.existsSync(path.join(cwd, '.cursor'))
96
96
  const cursorConfigured = fs.existsSync(path.join(cwd, '.cursor', 'rules', 'prjct.mdc'))
97
+ const windsurfDetected = fs.existsSync(path.join(cwd, '.windsurf'))
98
+ const windsurfConfigured = fs.existsSync(path.join(cwd, '.windsurf', 'rules', 'prjct.md'))
97
99
 
98
100
  const GREEN = '\x1b[32m'
99
101
 
@@ -129,9 +131,17 @@ ${DIM}Providers:${RESET}`)
129
131
  console.log(` Cursor IDE ${DIM}○ not detected${RESET}`)
130
132
  }
131
133
 
134
+ // Windsurf status (project-level)
135
+ if (windsurfDetected) {
136
+ const status = windsurfConfigured ? `${GREEN}✓ ready${RESET}` : `${YELLOW}● detected${RESET}`
137
+ console.log(` Windsurf IDE ${status}${DIM} (project)${RESET}`)
138
+ } else {
139
+ console.log(` Windsurf IDE ${DIM}○ not detected${RESET}`)
140
+ }
141
+
132
142
  console.log(`
133
143
  ${DIM}Run 'prjct start' to configure (CLI providers)${RESET}
134
- ${DIM}Run 'prjct init' to configure (Cursor IDE)${RESET}
144
+ ${DIM}Run 'prjct init' to configure (Cursor/Windsurf IDE)${RESET}
135
145
  ${CYAN}https://prjct.app${RESET}
136
146
  `)
137
147
  } else {
@@ -344,18 +344,35 @@ export class OrchestratorExecutor {
344
344
  // Skip if already loaded
345
345
  if (loadedSkillNames.has(skillName)) continue
346
346
 
347
- const skillPath = path.join(skillsDir, `${skillName}.md`)
347
+ // Check both patterns: flat file and subdirectory (ecosystem standard)
348
+ const flatPath = path.join(skillsDir, `${skillName}.md`)
349
+ const subdirPath = path.join(skillsDir, skillName, 'SKILL.md')
350
+
351
+ let content: string | null = null
352
+ let resolvedPath = flatPath
353
+
354
+ // Prefer subdirectory format (ecosystem standard)
348
355
  try {
349
- const content = await fs.readFile(skillPath, 'utf-8')
356
+ content = await fs.readFile(subdirPath, 'utf-8')
357
+ resolvedPath = subdirPath
358
+ } catch {
359
+ // Fall back to flat file
360
+ try {
361
+ content = await fs.readFile(flatPath, 'utf-8')
362
+ resolvedPath = flatPath
363
+ } catch {
364
+ // Skill not found - not an error, just skip
365
+ console.warn(`Skill not found: ${skillName}`)
366
+ }
367
+ }
368
+
369
+ if (content) {
350
370
  skills.push({
351
371
  name: skillName,
352
372
  content,
353
- filePath: skillPath,
373
+ filePath: resolvedPath,
354
374
  })
355
375
  loadedSkillNames.add(skillName)
356
- } catch {
357
- // Skill not found - not an error, just skip
358
- console.warn(`Skill not found: ${skillName}`)
359
376
  }
360
377
  }
361
378
  }
package/core/index.ts CHANGED
@@ -9,7 +9,7 @@ import { commandRegistry } from './commands/registry'
9
9
  import './commands/register' // Ensure commands are registered
10
10
  import out from './utils/output'
11
11
  import type { CommandMeta } from './commands/registry'
12
- import { detectAllProviders, Providers } from './infrastructure/ai-provider'
12
+ import { detectAllProviders, detectAntigravity, Providers } from './infrastructure/ai-provider'
13
13
  import fs from 'fs'
14
14
  import path from 'path'
15
15
  import os from 'os'
@@ -206,7 +206,7 @@ function displayVersion(version: string): void {
206
206
  ${CYAN}p/${RESET} prjct v${version}
207
207
  ${DIM}Context layer for AI coding agents${RESET}
208
208
 
209
- ${DIM}Global Providers:${RESET}`)
209
+ ${DIM}Providers:${RESET}`)
210
210
 
211
211
  // Claude status
212
212
  if (detection.claude.installed) {
@@ -226,9 +226,17 @@ ${DIM}Global Providers:${RESET}`)
226
226
  console.log(` Gemini CLI ${DIM}○ not installed${RESET}`)
227
227
  }
228
228
 
229
- // Cursor status (per-project)
230
- console.log(`
231
- ${DIM}Project Providers:${RESET}`)
229
+ // Antigravity status (global, skills-based)
230
+ const antigravityDetection = detectAntigravity()
231
+ if (antigravityDetection.installed) {
232
+ const status = antigravityDetection.skillInstalled ? `${GREEN}✓ ready${RESET}` : `${YELLOW}● detected${RESET}`
233
+ const hint = antigravityDetection.skillInstalled ? '' : ` ${DIM}(run prjct start)${RESET}`
234
+ console.log(` Antigravity ${status}${hint}`)
235
+ } else {
236
+ console.log(` Antigravity ${DIM}○ not installed${RESET}`)
237
+ }
238
+
239
+ // Cursor status (project-level, but shown in same format)
232
240
  if (cursorConfigured) {
233
241
  console.log(` Cursor IDE ${GREEN}✓ ready${RESET} ${DIM}(use /sync, /task)${RESET}`)
234
242
  } else if (cursorExists) {
@@ -249,7 +257,7 @@ ${CYAN}https://prjct.app${RESET}
249
257
  function displayHelp(): void {
250
258
  console.log(`
251
259
  prjct - Context layer for AI coding agents
252
- Works with Claude Code, Gemini CLI, Cursor IDE, and more.
260
+ Works with Claude Code, Gemini CLI, Antigravity, Cursor IDE, and more.
253
261
 
254
262
  QUICK START
255
263
  -----------
@@ -5,14 +5,16 @@
5
5
  * - Claude Code (CLI): ~/.claude/, CLAUDE.md, .md commands
6
6
  * - Gemini CLI (CLI): ~/.gemini/, GEMINI.md, .toml commands
7
7
  * - Cursor IDE (GUI): .cursor/ (project-level), .mdc rules
8
+ * - Windsurf IDE (GUI): .windsurf/ (project-level), .md rules with YAML frontmatter
8
9
  *
9
10
  * Key differences:
10
11
  * - CLI providers (Claude/Gemini) have global config directories
11
- * - Cursor has project-level config only (no ~/.cursor/)
12
+ * - Cursor/Windsurf have project-level config only (no ~/.cursor/ or ~/.windsurf/)
12
13
  *
13
14
  * @see https://geminicli.com/docs/cli/gemini-md/
14
15
  * @see https://geminicli.com/docs/cli/skills/
15
16
  * @see https://cursor.com/docs/context/rules
17
+ * @see https://docs.windsurf.com/windsurf/cascade/memories
16
18
  */
17
19
 
18
20
  import { execSync } from 'child_process'
@@ -26,6 +28,7 @@ import type {
26
28
  ProviderSelectionResult,
27
29
  ProviderBranding,
28
30
  CursorProjectDetection,
31
+ WindsurfProjectDetection,
29
32
  } from '../types/provider'
30
33
 
31
34
  // =============================================================================
@@ -70,6 +73,29 @@ export const GeminiProvider: AIProviderConfig = {
70
73
  docsUrl: 'https://geminicli.com/docs',
71
74
  }
72
75
 
76
+ /**
77
+ * Google Antigravity provider configuration
78
+ *
79
+ * An "agent-first" platform that manages multiple agents.
80
+ * Config is located in ~/.gemini/antigravity/
81
+ * Uses SKILL.md for skills and mcp_config.json for tools.
82
+ */
83
+ export const AntigravityProvider: AIProviderConfig = {
84
+ name: 'antigravity',
85
+ displayName: 'Google Antigravity',
86
+ cliCommand: null, // Not a CLI command, but a platform/app
87
+ configDir: path.join(os.homedir(), '.gemini', 'antigravity'),
88
+ contextFile: 'ANTIGRAVITY.md',
89
+ skillsDir: path.join(os.homedir(), '.gemini', 'antigravity', 'global_skills'),
90
+ commandsDir: '.agent/skills', // Antigravity uses .agent/skills in projects
91
+ commandFormat: 'md', // Uses SKILL.md
92
+ settingsFile: 'mcp_config.json', // Uses MCP config
93
+ projectSettingsFile: null,
94
+ ignoreFile: '.agentignore', // Assumed
95
+ websiteUrl: 'https://gemini.google.com/app/antigravity',
96
+ docsUrl: 'https://gemini.google.com/app/antigravity',
97
+ }
98
+
73
99
  /**
74
100
  * Cursor IDE provider configuration
75
101
  *
@@ -99,6 +125,36 @@ export const CursorProvider: AIProviderConfig = {
99
125
  docsUrl: 'https://cursor.com/docs',
100
126
  }
101
127
 
128
+ /**
129
+ * Windsurf IDE provider configuration
130
+ *
131
+ * Key differences from Cursor:
132
+ * - Uses .md files (not .mdc) with YAML frontmatter
133
+ * - Uses "workflows" instead of "commands"
134
+ * - Frontmatter uses `trigger: always_on` instead of `alwaysApply: true`
135
+ * - Character limits: 6000 per file, 12000 total
136
+ *
137
+ * @see https://docs.windsurf.com/windsurf/cascade/memories
138
+ * @see https://docs.windsurf.com/windsurf/cascade/workflows
139
+ */
140
+ export const WindsurfProvider: AIProviderConfig = {
141
+ name: 'windsurf',
142
+ displayName: 'Windsurf IDE',
143
+ cliCommand: null, // Not a CLI - GUI app
144
+ configDir: null, // No global config directory
145
+ contextFile: 'prjct.md', // Uses .md format (not .mdc)
146
+ skillsDir: null, // No skills directory
147
+ commandsDir: '.windsurf/workflows', // Windsurf uses "workflows" not "commands"
148
+ rulesDir: '.windsurf/rules',
149
+ commandFormat: 'md',
150
+ settingsFile: null,
151
+ projectSettingsFile: null,
152
+ ignoreFile: '.windsurfignore',
153
+ isProjectLevel: true, // Config is project-level only
154
+ websiteUrl: 'https://windsurf.com',
155
+ docsUrl: 'https://docs.windsurf.com',
156
+ }
157
+
102
158
  /**
103
159
  * All available providers
104
160
  */
@@ -106,6 +162,8 @@ export const Providers: Record<AIProviderName, AIProviderConfig> = {
106
162
  claude: ClaudeProvider,
107
163
  gemini: GeminiProvider,
108
164
  cursor: CursorProvider,
165
+ antigravity: AntigravityProvider,
166
+ windsurf: WindsurfProvider,
109
167
  }
110
168
 
111
169
  // =============================================================================
@@ -243,6 +301,22 @@ Built with [Cursor](${config.websiteUrl})`,
243
301
  }
244
302
  }
245
303
 
304
+ if (provider === 'antigravity') {
305
+ return {
306
+ commitFooter: `🤖 Generated with [p/](https://www.prjct.app/)
307
+ Powered by [Antigravity](${config.websiteUrl})`,
308
+ signature: '⚡ prjct + Antigravity',
309
+ }
310
+ }
311
+
312
+ if (provider === 'windsurf') {
313
+ return {
314
+ commitFooter: `🤖 Generated with [p/](https://www.prjct.app/)
315
+ Built with [Windsurf](${config.websiteUrl})`,
316
+ signature: '⚡ prjct + Windsurf',
317
+ }
318
+ }
319
+
246
320
  // Default: Claude
247
321
  return {
248
322
  commitFooter: `🤖 Generated with [p/](https://www.prjct.app/)
@@ -287,6 +361,83 @@ export function needsCursorRouterRegeneration(projectRoot: string): boolean {
287
361
  return detection.detected && !detection.routerInstalled
288
362
  }
289
363
 
364
+ // =============================================================================
365
+ // Windsurf Project Detection
366
+ // =============================================================================
367
+
368
+ /**
369
+ * Detect if a project is configured for Windsurf IDE
370
+ *
371
+ * Windsurf has NO global config (~/.windsurf/ doesn't exist).
372
+ * Detection is based on project-level .windsurf/ directory.
373
+ */
374
+ export function detectWindsurfProject(projectRoot: string): WindsurfProjectDetection {
375
+ const windsurfDir = path.join(projectRoot, '.windsurf')
376
+ const rulesDir = path.join(windsurfDir, 'rules')
377
+ const routerPath = path.join(rulesDir, 'prjct.md')
378
+
379
+ const detected = fs.existsSync(windsurfDir)
380
+ const routerInstalled = fs.existsSync(routerPath)
381
+
382
+ return {
383
+ detected,
384
+ routerInstalled,
385
+ projectRoot: detected ? projectRoot : undefined,
386
+ }
387
+ }
388
+
389
+ /**
390
+ * Check if Windsurf routers need to be regenerated
391
+ */
392
+ export function needsWindsurfRouterRegeneration(projectRoot: string): boolean {
393
+ const detection = detectWindsurfProject(projectRoot)
394
+
395
+ // Only check if .windsurf/ exists (project uses Windsurf)
396
+ // and prjct router is missing
397
+ return detection.detected && !detection.routerInstalled
398
+ }
399
+
400
+ // =============================================================================
401
+ // Antigravity Detection
402
+ // =============================================================================
403
+
404
+ /**
405
+ * Result of Antigravity detection
406
+ */
407
+ export interface AntigravityDetection {
408
+ /** Whether ~/.gemini/antigravity/ exists */
409
+ installed: boolean
410
+
411
+ /** Whether prjct skill is installed */
412
+ skillInstalled: boolean
413
+
414
+ /** Path to config directory */
415
+ configPath?: string
416
+ }
417
+
418
+ /**
419
+ * Detect if Google Antigravity is installed
420
+ *
421
+ * Antigravity is NOT a CLI command - it's a GUI platform.
422
+ * Detection is based on ~/.gemini/antigravity/ directory.
423
+ */
424
+ export function detectAntigravity(): AntigravityDetection {
425
+ const configPath = AntigravityProvider.configDir
426
+ if (!configPath) {
427
+ return { installed: false, skillInstalled: false }
428
+ }
429
+
430
+ const installed = fs.existsSync(configPath)
431
+ const skillPath = path.join(configPath, 'skills', 'prjct', 'SKILL.md')
432
+ const skillInstalled = fs.existsSync(skillPath)
433
+
434
+ return {
435
+ installed,
436
+ skillInstalled,
437
+ configPath: installed ? configPath : undefined,
438
+ }
439
+ }
440
+
290
441
  // =============================================================================
291
442
  // Provider Paths
292
443
  // =============================================================================
@@ -398,8 +549,11 @@ export default {
398
549
  ClaudeProvider,
399
550
  GeminiProvider,
400
551
  CursorProvider,
552
+ AntigravityProvider,
553
+ WindsurfProvider,
401
554
  detectProvider,
402
555
  detectAllProviders,
556
+ detectAntigravity,
403
557
  getActiveProvider,
404
558
  hasProviderConfig,
405
559
  getProviderBranding,
@@ -411,4 +565,6 @@ export default {
411
565
  selectProvider,
412
566
  detectCursorProject,
413
567
  needsCursorRouterRegeneration,
568
+ detectWindsurfProject,
569
+ needsWindsurfRouterRegeneration,
414
570
  }