prjct-cli 1.6.11 → 1.6.13

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,12 +1,76 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.6.13] - 2026-02-07
4
+
5
+ ### Refactoring
6
+
7
+ - remove unused templates and dead code (PRJ-293) (#138)
8
+ - remove unused templates and dead code (PRJ-293)
9
+
10
+
11
+ ## [1.6.15] - 2026-02-07
12
+
13
+ ### Refactor
14
+ - **Remove unused templates and dead code (PRJ-293)**: Deleted 8 unused template files from `templates/analysis/` (5) and `templates/agentic/` (3) that were never referenced by any code or other templates. Also removed unused type imports flagged by biome's `noUnusedImports` rule from `diff-generator.ts`, `sync-service.ts`, and `citations.ts`. Total: -471 lines removed.
15
+
16
+ ### Implementation Details
17
+ Audited all 135 templates by cross-referencing with code that loads them. Carefully distinguished between templates loaded dynamically via `readdir` (checklists, skills — kept) and templates with zero references (analysis prompts, agentic scaffolding — deleted). Unused imports were types imported for re-export where the `export type` statement imports independently from the source module, making the `import type` line redundant.
18
+
19
+ ### Learnings
20
+ - Dynamic template loading via `readdir` (in `prompt-builder.ts` and `skill-service.ts`) means simple grep searches can't identify all references — must trace runtime loading patterns to distinguish truly unused templates from dynamically loaded ones
21
+ - TypeScript `export type { X } from 'module'` is a standalone declaration that imports independently — a separate `import type { X }` is only needed if `X` is used in the file body
22
+
23
+ ### Test Plan
24
+
25
+ #### For QA
26
+ 1. Run `bun run build` — verify build succeeds with no errors
27
+ 2. Run `bun run lint` — verify zero biome warnings (especially `noUnusedImports`)
28
+ 3. Run `prjct sync` — verify sync still works (deleted templates were unused by sync)
29
+ 4. Verify `templates/checklists/*.md` and `templates/skills/*.md` are untouched (dynamically loaded)
30
+
31
+ #### For Users
32
+ **What changed:** Removed 8 unused internal template files and cleaned up dead imports. No user-facing behavior changes.
33
+ **How to use:** No action needed — this is an internal cleanup.
34
+ **Breaking changes:** None.
35
+
36
+ ## [1.6.12] - 2026-02-07
37
+
38
+ ### Bug Fixes
39
+
40
+ - replace sync I/O in imports-tool hot path (PRJ-290) (#137)
41
+
42
+ ## [1.6.14] - 2026-02-07
43
+
44
+ ### Bug Fixes
45
+ - **Replace sync I/O in imports-tool hot path (PRJ-290)**: Converted `tryResolve`/`resolveImport`/`extractImports` from sync `require('node:fs')` with `existsSync`+`statSync` to async `fs.stat()` from `node:fs/promises`. Also replaced repeated `getPackageRoot()` calls with the pre-resolved `PACKAGE_ROOT` constant in prompt-builder, command-installer, and setup modules.
46
+
47
+ ### Implementation Details
48
+ The `imports-tool.ts` file had an inline `require('node:fs')` call inside `tryResolve()` that used `existsSync` and `statSync` in a loop — a true hot path during import analysis. Converted the entire chain (`tryResolve` → `resolveImport` → `extractImports`) to async, using the already-imported `fs` from `node:fs/promises`. `version.ts` was kept sync intentionally: esbuild CJS output (used for postinstall) doesn't support top-level await, and its I/O runs once at cold start with results cached.
49
+
50
+ ### Learnings
51
+ - esbuild CJS format does not support top-level `await` — async module exports require ESM format
52
+ - `version.ts` cold-start I/O is negligible (runs once, cached) vs `imports-tool.ts` which resolves extensions in a loop per import
53
+ - Using pre-resolved `PACKAGE_ROOT` constant avoids repeated sync function calls across modules
54
+
55
+ ### Test Plan
56
+
57
+ #### For QA
58
+ 1. Run `prjct context imports <file>` — verify import resolution works correctly (resolves `.ts`, `.tsx`, `.js` extensions and `/index.ts` barrel imports)
59
+ 2. Run `prjct sync` — verify command-installer and setup find templates via `PACKAGE_ROOT`
60
+ 3. Run `bun run build` — verify all 5 build targets compile without errors
61
+ 4. Verify no `fs.*Sync()` calls remain in `imports-tool.ts`
62
+
63
+ #### For Users
64
+ **What changed:** Import analysis is now fully async, eliminating sync file system calls in the hot path.
65
+ **How to use:** No changes needed — `prjct context imports` works the same way.
66
+ **Breaking changes:** None.
67
+
3
68
  ## [1.6.11] - 2026-02-07
4
69
 
5
70
  ### Performance
6
71
 
7
72
  - cache provider detection to eliminate redundant shell spawns (PRJ-289) (#136)
8
73
 
9
-
10
74
  ## [1.6.13] - 2026-02-07
11
75
 
12
76
  ### Improvements
@@ -27,7 +27,7 @@ import type {
27
27
  } from '../types'
28
28
  import { getErrorMessage, isNotFoundError } from '../types/fs'
29
29
  import { fileExists } from '../utils/fs-helpers'
30
- import { getPackageRoot } from '../utils/version'
30
+ import { PACKAGE_ROOT } from '../utils/version'
31
31
 
32
32
  // Re-export types for convenience
33
33
  export type {
@@ -132,7 +132,7 @@ class PromptBuilder {
132
132
  * These modules extend the base global CLAUDE.md for complex operations
133
133
  */
134
134
  async loadModule(moduleName: string): Promise<string | null> {
135
- const modulePath = path.join(getPackageRoot(), 'templates/global/modules', moduleName)
135
+ const modulePath = path.join(PACKAGE_ROOT, 'templates/global/modules', moduleName)
136
136
  return this.getTemplate(modulePath)
137
137
  }
138
138
 
@@ -178,7 +178,7 @@ export async function analyzeImports(
178
178
  const patterns = IMPORT_PATTERNS[language] || []
179
179
 
180
180
  // Extract imports
181
- const imports = extractImports(content, patterns, absolutePath, projectPath)
181
+ const imports = await extractImports(content, patterns, absolutePath, projectPath)
182
182
 
183
183
  // Get reverse imports if requested
184
184
  let importedBy: ImportedBy[] = []
@@ -217,12 +217,12 @@ export async function analyzeImports(
217
217
  /**
218
218
  * Extract imports from file content
219
219
  */
220
- function extractImports(
220
+ async function extractImports(
221
221
  content: string,
222
222
  patterns: ImportPattern[],
223
223
  absolutePath: string,
224
224
  projectPath: string
225
- ): ImportRelation[] {
225
+ ): Promise<ImportRelation[]> {
226
226
  const imports: ImportRelation[] = []
227
227
  const seen = new Set<string>()
228
228
 
@@ -254,7 +254,7 @@ function extractImports(
254
254
  // Resolve internal imports
255
255
  let resolved: string | null = null
256
256
  if (!isExternal) {
257
- resolved = resolveImport(source, absolutePath, projectPath)
257
+ resolved = await resolveImport(source, absolutePath, projectPath)
258
258
  }
259
259
 
260
260
  imports.push({
@@ -274,7 +274,11 @@ function extractImports(
274
274
  /**
275
275
  * Resolve a relative import to an absolute path
276
276
  */
277
- function resolveImport(source: string, fromFile: string, projectPath: string): string | null {
277
+ async function resolveImport(
278
+ source: string,
279
+ fromFile: string,
280
+ projectPath: string
281
+ ): Promise<string | null> {
278
282
  const fileDir = path.dirname(fromFile)
279
283
 
280
284
  // Handle path alias like @/
@@ -291,15 +295,14 @@ function resolveImport(source: string, fromFile: string, projectPath: string): s
291
295
  /**
292
296
  * Try to resolve a path, adding extensions if needed
293
297
  */
294
- function tryResolve(basePath: string, projectPath: string): string | null {
298
+ async function tryResolve(basePath: string, projectPath: string): Promise<string | null> {
295
299
  const extensions = ['', '.ts', '.tsx', '.js', '.jsx', '/index.ts', '/index.js']
296
300
 
297
301
  for (const ext of extensions) {
298
302
  const fullPath = basePath + ext
299
303
  try {
300
- // Check synchronously (we're in a hot path)
301
- const fs = require('node:fs')
302
- if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
304
+ const stat = await fs.stat(fullPath)
305
+ if (stat.isFile()) {
303
306
  return path.relative(projectPath, fullPath)
304
307
  }
305
308
  } catch {}
@@ -23,7 +23,7 @@ import type {
23
23
  UninstallResult,
24
24
  } from '../types'
25
25
  import { getErrorMessage, isNotFoundError } from '../types/fs'
26
- import { getPackageRoot } from '../utils/version'
26
+ import { PACKAGE_ROOT } from '../utils/version'
27
27
 
28
28
  // =============================================================================
29
29
  // Module Types
@@ -51,7 +51,7 @@ interface ModuleConfig {
51
51
  */
52
52
  async function loadModuleConfig(): Promise<ModuleConfig | null> {
53
53
  try {
54
- const configPath = path.join(getPackageRoot(), 'templates/global/modules/module-config.json')
54
+ const configPath = path.join(PACKAGE_ROOT, 'templates/global/modules/module-config.json')
55
55
  const content = await fs.readFile(configPath, 'utf-8')
56
56
  return JSON.parse(content) as ModuleConfig
57
57
  } catch {
@@ -66,11 +66,11 @@ async function loadModuleConfig(): Promise<ModuleConfig | null> {
66
66
  */
67
67
  export async function composeGlobalTemplate(profile?: string): Promise<string> {
68
68
  const config = await loadModuleConfig()
69
- const modulesDir = path.join(getPackageRoot(), 'templates/global/modules')
69
+ const modulesDir = path.join(PACKAGE_ROOT, 'templates/global/modules')
70
70
 
71
71
  // Fallback to legacy template if config not found
72
72
  if (!config) {
73
- const legacyPath = path.join(getPackageRoot(), 'templates/global/CLAUDE.md')
73
+ const legacyPath = path.join(PACKAGE_ROOT, 'templates/global/CLAUDE.md')
74
74
  return fs.readFile(legacyPath, 'utf-8')
75
75
  }
76
76
 
@@ -81,7 +81,7 @@ export async function composeGlobalTemplate(profile?: string): Promise<string> {
81
81
  // Fallback to default profile
82
82
  const defaultProfile = config.profiles[config.default]
83
83
  if (!defaultProfile) {
84
- const legacyPath = path.join(getPackageRoot(), 'templates/global/CLAUDE.md')
84
+ const legacyPath = path.join(PACKAGE_ROOT, 'templates/global/CLAUDE.md')
85
85
  return fs.readFile(legacyPath, 'utf-8')
86
86
  }
87
87
  }
@@ -130,7 +130,7 @@ export async function getProfileForCommand(command: string): Promise<string> {
130
130
  export async function installDocs(): Promise<{ success: boolean; error?: string }> {
131
131
  try {
132
132
  const docsDir = path.join(os.homedir(), '.prjct-cli', 'docs')
133
- const templateDocsDir = path.join(getPackageRoot(), 'templates/global/docs')
133
+ const templateDocsDir = path.join(PACKAGE_ROOT, 'templates/global/docs')
134
134
 
135
135
  // Ensure docs directory exists
136
136
  await fs.mkdir(docsDir, { recursive: true })
@@ -177,12 +177,7 @@ export async function installGlobalConfig(): Promise<GlobalConfigResult> {
177
177
  await fs.mkdir(activeProvider.configDir, { recursive: true })
178
178
 
179
179
  const globalConfigPath = path.join(activeProvider.configDir, activeProvider.contextFile)
180
- const templatePath = path.join(
181
- getPackageRoot(),
182
- 'templates',
183
- 'global',
184
- activeProvider.contextFile
185
- )
180
+ const templatePath = path.join(PACKAGE_ROOT, 'templates', 'global', activeProvider.contextFile)
186
181
 
187
182
  // Read template content - use modular composition (PRJ-94)
188
183
  let templateContent = ''
@@ -196,12 +191,12 @@ export async function installGlobalConfig(): Promise<GlobalConfigResult> {
196
191
  templateContent = await composeGlobalTemplate('standard')
197
192
  } catch {
198
193
  // Final fallback to legacy template
199
- const fallbackTemplatePath = path.join(getPackageRoot(), 'templates/global/CLAUDE.md')
194
+ const fallbackTemplatePath = path.join(PACKAGE_ROOT, 'templates/global/CLAUDE.md')
200
195
  templateContent = await fs.readFile(fallbackTemplatePath, 'utf-8')
201
196
  }
202
197
  } else {
203
198
  // Fallback for other providers
204
- const fallbackTemplatePath = path.join(getPackageRoot(), 'templates/global/CLAUDE.md')
199
+ const fallbackTemplatePath = path.join(PACKAGE_ROOT, 'templates/global/CLAUDE.md')
205
200
  templateContent = await fs.readFile(fallbackTemplatePath, 'utf-8')
206
201
  // If it is Gemini, we should rename Claude to Gemini in the fallback content
207
202
  if (providerName === 'gemini') {
@@ -296,7 +291,7 @@ export class CommandInstaller {
296
291
 
297
292
  constructor() {
298
293
  this.homeDir = os.homedir()
299
- this.templatesDir = path.join(getPackageRoot(), 'templates', 'commands')
294
+ this.templatesDir = path.join(PACKAGE_ROOT, 'templates', 'commands')
300
295
  }
301
296
 
302
297
  private async ensureInit(): Promise<void> {
@@ -28,7 +28,7 @@ import { getErrorMessage, isNotFoundError } from '../types/fs'
28
28
  import type { AIProviderConfig, AIProviderName } from '../types/provider'
29
29
  import { fileExists } from '../utils/fs-helpers'
30
30
  import log from '../utils/logger'
31
- import { getPackageRoot, VERSION } from '../utils/version'
31
+ import { PACKAGE_ROOT, VERSION } from '../utils/version'
32
32
  import {
33
33
  detectAllProviders,
34
34
  detectAntigravity,
@@ -255,7 +255,7 @@ export async function run(): Promise<SetupResults> {
255
255
  async function installGeminiRouter(): Promise<boolean> {
256
256
  try {
257
257
  const geminiCommandsDir = path.join(os.homedir(), '.gemini', 'commands')
258
- const routerSource = path.join(getPackageRoot(), 'templates', 'commands', 'p.toml')
258
+ const routerSource = path.join(PACKAGE_ROOT, 'templates', 'commands', 'p.toml')
259
259
  const routerDest = path.join(geminiCommandsDir, 'p.toml')
260
260
 
261
261
  // Ensure commands directory exists
@@ -280,7 +280,7 @@ async function installGeminiGlobalConfig(): Promise<{ success: boolean; action:
280
280
  try {
281
281
  const geminiDir = path.join(os.homedir(), '.gemini')
282
282
  const globalConfigPath = path.join(geminiDir, 'GEMINI.md')
283
- const templatePath = path.join(getPackageRoot(), 'templates', 'global', 'GEMINI.md')
283
+ const templatePath = path.join(PACKAGE_ROOT, 'templates', 'global', 'GEMINI.md')
284
284
 
285
285
  // Ensure ~/.gemini directory exists
286
286
  await fs.mkdir(geminiDir, { recursive: true })
@@ -361,7 +361,7 @@ export async function installAntigravitySkill(): Promise<{
361
361
  const antigravitySkillsDir = path.join(os.homedir(), '.gemini', 'antigravity', 'skills')
362
362
  const prjctSkillDir = path.join(antigravitySkillsDir, 'prjct')
363
363
  const skillMdPath = path.join(prjctSkillDir, 'SKILL.md')
364
- const templatePath = path.join(getPackageRoot(), 'templates', 'antigravity', 'SKILL.md')
364
+ const templatePath = path.join(PACKAGE_ROOT, 'templates', 'antigravity', 'SKILL.md')
365
365
 
366
366
  // Ensure skills directory exists
367
367
  await fs.mkdir(prjctSkillDir, { recursive: true })
@@ -431,8 +431,8 @@ export async function installCursorProject(projectRoot: string): Promise<{
431
431
 
432
432
  const routerMdcDest = path.join(rulesDir, 'prjct.mdc')
433
433
 
434
- const routerMdcSource = path.join(getPackageRoot(), 'templates', 'cursor', 'router.mdc')
435
- const cursorCommandsSource = path.join(getPackageRoot(), 'templates', 'cursor', 'commands')
434
+ const routerMdcSource = path.join(PACKAGE_ROOT, 'templates', 'cursor', 'router.mdc')
435
+ const cursorCommandsSource = path.join(PACKAGE_ROOT, 'templates', 'cursor', 'commands')
436
436
 
437
437
  // Ensure directories exist
438
438
  await fs.mkdir(rulesDir, { recursive: true })
@@ -574,13 +574,8 @@ export async function installWindsurfProject(projectRoot: string): Promise<{
574
574
 
575
575
  const routerDest = path.join(rulesDir, 'prjct.md')
576
576
 
577
- const routerSource = path.join(getPackageRoot(), 'templates', 'windsurf', 'router.md')
578
- const windsurfWorkflowsSource = path.join(
579
- getPackageRoot(),
580
- 'templates',
581
- 'windsurf',
582
- 'workflows'
583
- )
577
+ const routerSource = path.join(PACKAGE_ROOT, 'templates', 'windsurf', 'router.md')
578
+ const windsurfWorkflowsSource = path.join(PACKAGE_ROOT, 'templates', 'windsurf', 'workflows')
584
579
 
585
580
  // Ensure directories exist
586
581
  await fs.mkdir(rulesDir, { recursive: true })
@@ -785,7 +780,7 @@ async function installStatusLine(): Promise<void> {
785
780
  const prjctConfigPath = path.join(prjctStatusLineDir, 'config.json')
786
781
 
787
782
  // Source assets (from the package)
788
- const assetsDir = path.join(getPackageRoot(), 'assets', 'statusline')
783
+ const assetsDir = path.join(PACKAGE_ROOT, 'assets', 'statusline')
789
784
  const sourceScript = path.join(assetsDir, 'statusline.sh')
790
785
  const sourceThemeDir = path.join(assetsDir, 'themes')
791
786
  const sourceLibDir = path.join(assetsDir, 'lib')
@@ -9,13 +9,7 @@
9
9
  */
10
10
 
11
11
  import chalk from 'chalk'
12
- import type {
13
- DiffOptions,
14
- DiffSection,
15
- ParsedMarkdownSection,
16
- PreservedInfo,
17
- SyncDiff,
18
- } from '../types'
12
+ import type { DiffOptions, ParsedMarkdownSection, SyncDiff } from '../types'
19
13
 
20
14
  export type {
21
15
  DiffOptions,
@@ -33,7 +33,6 @@ import configManager from '../infrastructure/config-manager'
33
33
  import pathManager from '../infrastructure/path-manager'
34
34
  import { metricsStorage } from '../storage/metrics-storage'
35
35
  import type {
36
- AIToolResult,
37
36
  GitData,
38
37
  ProjectCommands,
39
38
  ProjectStats,
@@ -48,7 +47,6 @@ import { type ContextSources, defaultSources, type SourceInfo } from '../utils/c
48
47
  import * as dateHelper from '../utils/date-helper'
49
48
  import log from '../utils/logger'
50
49
  import { ContextFileGenerator } from './context-generator'
51
- import type { SyncDiff } from './diff-generator'
52
50
  import { localStateGenerator } from './local-state-generator'
53
51
  import { skillInstaller } from './skill-installer'
54
52
  import { StackDetector } from './stack-detector'
@@ -7,7 +7,7 @@
7
7
  * @see PRJ-113
8
8
  */
9
9
 
10
- import type { ContextSources, SourceInfo, SourceType } from '../types/citations'
10
+ import type { ContextSources, SourceInfo } from '../types/citations'
11
11
 
12
12
  export type { ContextSources, SourceInfo, SourceType } from '../types/citations'
13
13
 
@@ -7,6 +7,9 @@ import { getErrorMessage } from '../types/fs'
7
7
  *
8
8
  * Reads version from package.json dynamically to ensure consistency
9
9
  * across the entire application.
10
+ *
11
+ * Uses sync I/O intentionally: runs once at cold start, results cached.
12
+ * CJS build (postinstall) requires sync module-level exports.
10
13
  */
11
14
 
12
15
  interface PackageJson {
@@ -4309,7 +4309,7 @@ async function analyzeImports(filePath, projectPath = process.cwd(), options = {
4309
4309
  const ext = path14.extname(filePath).toLowerCase();
4310
4310
  const language = EXT_TO_LANG[ext] || "unknown";
4311
4311
  const patterns = IMPORT_PATTERNS[language] || [];
4312
- const imports = extractImports(content, patterns, absolutePath, projectPath);
4312
+ const imports = await extractImports(content, patterns, absolutePath, projectPath);
4313
4313
  let importedBy = [];
4314
4314
  if (options.reverse) {
4315
4315
  importedBy = await findImportedBy(filePath, projectPath);
@@ -4333,7 +4333,7 @@ async function analyzeImports(filePath, projectPath = process.cwd(), options = {
4333
4333
  }
4334
4334
  };
4335
4335
  }
4336
- function extractImports(content, patterns, absolutePath, projectPath) {
4336
+ async function extractImports(content, patterns, absolutePath, projectPath) {
4337
4337
  const imports = [];
4338
4338
  const seen = /* @__PURE__ */ new Set();
4339
4339
  for (const patternDef of patterns) {
@@ -4353,7 +4353,7 @@ function extractImports(content, patterns, absolutePath, projectPath) {
4353
4353
  const isExternal = !source.startsWith(".") && !source.startsWith("/") && !source.startsWith("@/");
4354
4354
  let resolved = null;
4355
4355
  if (!isExternal) {
4356
- resolved = resolveImport(source, absolutePath, projectPath);
4356
+ resolved = await resolveImport(source, absolutePath, projectPath);
4357
4357
  }
4358
4358
  imports.push({
4359
4359
  source,
@@ -4367,7 +4367,7 @@ function extractImports(content, patterns, absolutePath, projectPath) {
4367
4367
  }
4368
4368
  return imports;
4369
4369
  }
4370
- function resolveImport(source, fromFile, projectPath) {
4370
+ async function resolveImport(source, fromFile, projectPath) {
4371
4371
  const fileDir = path14.dirname(fromFile);
4372
4372
  if (source.startsWith("@/")) {
4373
4373
  const aliasPath = path14.join(projectPath, "src", source.slice(2));
@@ -4376,13 +4376,13 @@ function resolveImport(source, fromFile, projectPath) {
4376
4376
  const resolved = path14.resolve(fileDir, source);
4377
4377
  return tryResolve(resolved, projectPath);
4378
4378
  }
4379
- function tryResolve(basePath, projectPath) {
4379
+ async function tryResolve(basePath, projectPath) {
4380
4380
  const extensions = ["", ".ts", ".tsx", ".js", ".jsx", "/index.ts", "/index.js"];
4381
4381
  for (const ext of extensions) {
4382
4382
  const fullPath = basePath + ext;
4383
4383
  try {
4384
- const fs52 = __require("node:fs");
4385
- if (fs52.existsSync(fullPath) && fs52.statSync(fullPath).isFile()) {
4384
+ const stat = await fs14.stat(fullPath);
4385
+ if (stat.isFile()) {
4386
4386
  return path14.relative(projectPath, fullPath);
4387
4387
  }
4388
4388
  } catch {
@@ -6609,7 +6609,7 @@ import os6 from "node:os";
6609
6609
  import path19 from "node:path";
6610
6610
  async function loadModuleConfig() {
6611
6611
  try {
6612
- const configPath = path19.join(getPackageRoot(), "templates/global/modules/module-config.json");
6612
+ const configPath = path19.join(PACKAGE_ROOT, "templates/global/modules/module-config.json");
6613
6613
  const content = await fs19.readFile(configPath, "utf-8");
6614
6614
  return JSON.parse(content);
6615
6615
  } catch {
@@ -6618,9 +6618,9 @@ async function loadModuleConfig() {
6618
6618
  }
6619
6619
  async function composeGlobalTemplate(profile) {
6620
6620
  const config = await loadModuleConfig();
6621
- const modulesDir = path19.join(getPackageRoot(), "templates/global/modules");
6621
+ const modulesDir = path19.join(PACKAGE_ROOT, "templates/global/modules");
6622
6622
  if (!config) {
6623
- const legacyPath = path19.join(getPackageRoot(), "templates/global/CLAUDE.md");
6623
+ const legacyPath = path19.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
6624
6624
  return fs19.readFile(legacyPath, "utf-8");
6625
6625
  }
6626
6626
  const profileName = profile || config.default;
@@ -6628,7 +6628,7 @@ async function composeGlobalTemplate(profile) {
6628
6628
  if (!selectedProfile) {
6629
6629
  const defaultProfile = config.profiles[config.default];
6630
6630
  if (!defaultProfile) {
6631
- const legacyPath = path19.join(getPackageRoot(), "templates/global/CLAUDE.md");
6631
+ const legacyPath = path19.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
6632
6632
  return fs19.readFile(legacyPath, "utf-8");
6633
6633
  }
6634
6634
  }
@@ -6653,7 +6653,7 @@ async function composeGlobalTemplate(profile) {
6653
6653
  async function installDocs() {
6654
6654
  try {
6655
6655
  const docsDir = path19.join(os6.homedir(), ".prjct-cli", "docs");
6656
- const templateDocsDir = path19.join(getPackageRoot(), "templates/global/docs");
6656
+ const templateDocsDir = path19.join(PACKAGE_ROOT, "templates/global/docs");
6657
6657
  await fs19.mkdir(docsDir, { recursive: true });
6658
6658
  const docFiles = await fs19.readdir(templateDocsDir);
6659
6659
  for (const file of docFiles) {
@@ -6684,12 +6684,7 @@ async function installGlobalConfig2() {
6684
6684
  try {
6685
6685
  await fs19.mkdir(activeProvider.configDir, { recursive: true });
6686
6686
  const globalConfigPath = path19.join(activeProvider.configDir, activeProvider.contextFile);
6687
- const templatePath = path19.join(
6688
- getPackageRoot(),
6689
- "templates",
6690
- "global",
6691
- activeProvider.contextFile
6692
- );
6687
+ const templatePath = path19.join(PACKAGE_ROOT, "templates", "global", activeProvider.contextFile);
6693
6688
  let templateContent = "";
6694
6689
  try {
6695
6690
  templateContent = await fs19.readFile(templatePath, "utf-8");
@@ -6698,11 +6693,11 @@ async function installGlobalConfig2() {
6698
6693
  try {
6699
6694
  templateContent = await composeGlobalTemplate("standard");
6700
6695
  } catch {
6701
- const fallbackTemplatePath = path19.join(getPackageRoot(), "templates/global/CLAUDE.md");
6696
+ const fallbackTemplatePath = path19.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
6702
6697
  templateContent = await fs19.readFile(fallbackTemplatePath, "utf-8");
6703
6698
  }
6704
6699
  } else {
6705
- const fallbackTemplatePath = path19.join(getPackageRoot(), "templates/global/CLAUDE.md");
6700
+ const fallbackTemplatePath = path19.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
6706
6701
  templateContent = await fs19.readFile(fallbackTemplatePath, "utf-8");
6707
6702
  if (providerName === "gemini") {
6708
6703
  templateContent = templateContent.replace(/Claude/g, "Gemini");
@@ -6804,7 +6799,7 @@ var init_command_installer = __esm({
6804
6799
  _initialized = false;
6805
6800
  constructor() {
6806
6801
  this.homeDir = os6.homedir();
6807
- this.templatesDir = path19.join(getPackageRoot(), "templates", "commands");
6802
+ this.templatesDir = path19.join(PACKAGE_ROOT, "templates", "commands");
6808
6803
  }
6809
6804
  async ensureInit() {
6810
6805
  if (this._initialized) return;
@@ -13851,7 +13846,7 @@ var init_prompt_builder = __esm({
13851
13846
  * These modules extend the base global CLAUDE.md for complex operations
13852
13847
  */
13853
13848
  async loadModule(moduleName) {
13854
- const modulePath = path28.join(getPackageRoot(), "templates/global/modules", moduleName);
13849
+ const modulePath = path28.join(PACKAGE_ROOT, "templates/global/modules", moduleName);
13855
13850
  return this.getTemplate(modulePath);
13856
13851
  }
13857
13852
  /**
@@ -24764,7 +24759,7 @@ async function run() {
24764
24759
  async function installGeminiRouter() {
24765
24760
  try {
24766
24761
  const geminiCommandsDir = path53.join(os17.homedir(), ".gemini", "commands");
24767
- const routerSource = path53.join(getPackageRoot(), "templates", "commands", "p.toml");
24762
+ const routerSource = path53.join(PACKAGE_ROOT, "templates", "commands", "p.toml");
24768
24763
  const routerDest = path53.join(geminiCommandsDir, "p.toml");
24769
24764
  await fs48.mkdir(geminiCommandsDir, { recursive: true });
24770
24765
  if (await fileExists(routerSource)) {
@@ -24781,7 +24776,7 @@ async function installGeminiGlobalConfig() {
24781
24776
  try {
24782
24777
  const geminiDir = path53.join(os17.homedir(), ".gemini");
24783
24778
  const globalConfigPath = path53.join(geminiDir, "GEMINI.md");
24784
- const templatePath = path53.join(getPackageRoot(), "templates", "global", "GEMINI.md");
24779
+ const templatePath = path53.join(PACKAGE_ROOT, "templates", "global", "GEMINI.md");
24785
24780
  await fs48.mkdir(geminiDir, { recursive: true });
24786
24781
  const templateContent = await fs48.readFile(templatePath, "utf-8");
24787
24782
  let existingContent = "";
@@ -24831,7 +24826,7 @@ async function installAntigravitySkill() {
24831
24826
  const antigravitySkillsDir = path53.join(os17.homedir(), ".gemini", "antigravity", "skills");
24832
24827
  const prjctSkillDir = path53.join(antigravitySkillsDir, "prjct");
24833
24828
  const skillMdPath = path53.join(prjctSkillDir, "SKILL.md");
24834
- const templatePath = path53.join(getPackageRoot(), "templates", "antigravity", "SKILL.md");
24829
+ const templatePath = path53.join(PACKAGE_ROOT, "templates", "antigravity", "SKILL.md");
24835
24830
  await fs48.mkdir(prjctSkillDir, { recursive: true });
24836
24831
  const skillExists = await fileExists(skillMdPath);
24837
24832
  if (!await fileExists(templatePath)) {
@@ -24862,8 +24857,8 @@ async function installCursorProject(projectRoot) {
24862
24857
  const rulesDir = path53.join(cursorDir, "rules");
24863
24858
  const commandsDir = path53.join(cursorDir, "commands");
24864
24859
  const routerMdcDest = path53.join(rulesDir, "prjct.mdc");
24865
- const routerMdcSource = path53.join(getPackageRoot(), "templates", "cursor", "router.mdc");
24866
- const cursorCommandsSource = path53.join(getPackageRoot(), "templates", "cursor", "commands");
24860
+ const routerMdcSource = path53.join(PACKAGE_ROOT, "templates", "cursor", "router.mdc");
24861
+ const cursorCommandsSource = path53.join(PACKAGE_ROOT, "templates", "cursor", "commands");
24867
24862
  await fs48.mkdir(rulesDir, { recursive: true });
24868
24863
  await fs48.mkdir(commandsDir, { recursive: true });
24869
24864
  if (await fileExists(routerMdcSource)) {
@@ -24946,13 +24941,8 @@ async function installWindsurfProject(projectRoot) {
24946
24941
  const rulesDir = path53.join(windsurfDir, "rules");
24947
24942
  const workflowsDir = path53.join(windsurfDir, "workflows");
24948
24943
  const routerDest = path53.join(rulesDir, "prjct.md");
24949
- const routerSource = path53.join(getPackageRoot(), "templates", "windsurf", "router.md");
24950
- const windsurfWorkflowsSource = path53.join(
24951
- getPackageRoot(),
24952
- "templates",
24953
- "windsurf",
24954
- "workflows"
24955
- );
24944
+ const routerSource = path53.join(PACKAGE_ROOT, "templates", "windsurf", "router.md");
24945
+ const windsurfWorkflowsSource = path53.join(PACKAGE_ROOT, "templates", "windsurf", "workflows");
24956
24946
  await fs48.mkdir(rulesDir, { recursive: true });
24957
24947
  await fs48.mkdir(workflowsDir, { recursive: true });
24958
24948
  if (await fileExists(routerSource)) {
@@ -25086,7 +25076,7 @@ async function installStatusLine() {
25086
25076
  const prjctLibDir = path53.join(prjctStatusLineDir, "lib");
25087
25077
  const prjctComponentsDir = path53.join(prjctStatusLineDir, "components");
25088
25078
  const prjctConfigPath = path53.join(prjctStatusLineDir, "config.json");
25089
- const assetsDir = path53.join(getPackageRoot(), "assets", "statusline");
25079
+ const assetsDir = path53.join(PACKAGE_ROOT, "assets", "statusline");
25090
25080
  const sourceScript = path53.join(assetsDir, "statusline.sh");
25091
25081
  const sourceThemeDir = path53.join(assetsDir, "themes");
25092
25082
  const sourceLibDir = path53.join(assetsDir, "lib");
@@ -28716,7 +28706,7 @@ var require_package = __commonJS({
28716
28706
  "package.json"(exports, module) {
28717
28707
  module.exports = {
28718
28708
  name: "prjct-cli",
28719
- version: "1.6.11",
28709
+ version: "1.6.13",
28720
28710
  description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
28721
28711
  main: "core/index.ts",
28722
28712
  bin: {
@@ -517,7 +517,7 @@ var PACKAGE_ROOT = getPackageRoot();
517
517
  // core/infrastructure/command-installer.ts
518
518
  async function loadModuleConfig() {
519
519
  try {
520
- const configPath = import_node_path4.default.join(getPackageRoot(), "templates/global/modules/module-config.json");
520
+ const configPath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/modules/module-config.json");
521
521
  const content = await import_promises3.default.readFile(configPath, "utf-8");
522
522
  return JSON.parse(content);
523
523
  } catch {
@@ -527,9 +527,9 @@ async function loadModuleConfig() {
527
527
  __name(loadModuleConfig, "loadModuleConfig");
528
528
  async function composeGlobalTemplate(profile) {
529
529
  const config = await loadModuleConfig();
530
- const modulesDir = import_node_path4.default.join(getPackageRoot(), "templates/global/modules");
530
+ const modulesDir = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/modules");
531
531
  if (!config) {
532
- const legacyPath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
532
+ const legacyPath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
533
533
  return import_promises3.default.readFile(legacyPath, "utf-8");
534
534
  }
535
535
  const profileName = profile || config.default;
@@ -537,7 +537,7 @@ async function composeGlobalTemplate(profile) {
537
537
  if (!selectedProfile) {
538
538
  const defaultProfile = config.profiles[config.default];
539
539
  if (!defaultProfile) {
540
- const legacyPath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
540
+ const legacyPath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
541
541
  return import_promises3.default.readFile(legacyPath, "utf-8");
542
542
  }
543
543
  }
@@ -569,7 +569,7 @@ __name(getProfileForCommand, "getProfileForCommand");
569
569
  async function installDocs() {
570
570
  try {
571
571
  const docsDir = import_node_path4.default.join(import_node_os3.default.homedir(), ".prjct-cli", "docs");
572
- const templateDocsDir = import_node_path4.default.join(getPackageRoot(), "templates/global/docs");
572
+ const templateDocsDir = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/docs");
573
573
  await import_promises3.default.mkdir(docsDir, { recursive: true });
574
574
  const docFiles = await import_promises3.default.readdir(templateDocsDir);
575
575
  for (const file of docFiles) {
@@ -601,12 +601,7 @@ async function installGlobalConfig() {
601
601
  try {
602
602
  await import_promises3.default.mkdir(activeProvider.configDir, { recursive: true });
603
603
  const globalConfigPath = import_node_path4.default.join(activeProvider.configDir, activeProvider.contextFile);
604
- const templatePath = import_node_path4.default.join(
605
- getPackageRoot(),
606
- "templates",
607
- "global",
608
- activeProvider.contextFile
609
- );
604
+ const templatePath = import_node_path4.default.join(PACKAGE_ROOT, "templates", "global", activeProvider.contextFile);
610
605
  let templateContent = "";
611
606
  try {
612
607
  templateContent = await import_promises3.default.readFile(templatePath, "utf-8");
@@ -615,11 +610,11 @@ async function installGlobalConfig() {
615
610
  try {
616
611
  templateContent = await composeGlobalTemplate("standard");
617
612
  } catch {
618
- const fallbackTemplatePath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
613
+ const fallbackTemplatePath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
619
614
  templateContent = await import_promises3.default.readFile(fallbackTemplatePath, "utf-8");
620
615
  }
621
616
  } else {
622
- const fallbackTemplatePath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
617
+ const fallbackTemplatePath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
623
618
  templateContent = await import_promises3.default.readFile(fallbackTemplatePath, "utf-8");
624
619
  if (providerName === "gemini") {
625
620
  templateContent = templateContent.replace(/Claude/g, "Gemini");
@@ -697,7 +692,7 @@ var CommandInstaller = class {
697
692
  _initialized = false;
698
693
  constructor() {
699
694
  this.homeDir = import_node_os3.default.homedir();
700
- this.templatesDir = import_node_path4.default.join(getPackageRoot(), "templates", "commands");
695
+ this.templatesDir = import_node_path4.default.join(PACKAGE_ROOT, "templates", "commands");
701
696
  }
702
697
  async ensureInit() {
703
698
  if (this._initialized) return;
@@ -838,7 +838,7 @@ var import_node_os3 = __toESM(require("node:os"));
838
838
  var import_node_path4 = __toESM(require("node:path"));
839
839
  async function loadModuleConfig() {
840
840
  try {
841
- const configPath = import_node_path4.default.join(getPackageRoot(), "templates/global/modules/module-config.json");
841
+ const configPath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/modules/module-config.json");
842
842
  const content = await import_promises3.default.readFile(configPath, "utf-8");
843
843
  return JSON.parse(content);
844
844
  } catch {
@@ -848,9 +848,9 @@ async function loadModuleConfig() {
848
848
  __name(loadModuleConfig, "loadModuleConfig");
849
849
  async function composeGlobalTemplate(profile) {
850
850
  const config = await loadModuleConfig();
851
- const modulesDir = import_node_path4.default.join(getPackageRoot(), "templates/global/modules");
851
+ const modulesDir = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/modules");
852
852
  if (!config) {
853
- const legacyPath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
853
+ const legacyPath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
854
854
  return import_promises3.default.readFile(legacyPath, "utf-8");
855
855
  }
856
856
  const profileName = profile || config.default;
@@ -858,7 +858,7 @@ async function composeGlobalTemplate(profile) {
858
858
  if (!selectedProfile) {
859
859
  const defaultProfile = config.profiles[config.default];
860
860
  if (!defaultProfile) {
861
- const legacyPath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
861
+ const legacyPath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
862
862
  return import_promises3.default.readFile(legacyPath, "utf-8");
863
863
  }
864
864
  }
@@ -884,7 +884,7 @@ __name(composeGlobalTemplate, "composeGlobalTemplate");
884
884
  async function installDocs() {
885
885
  try {
886
886
  const docsDir = import_node_path4.default.join(import_node_os3.default.homedir(), ".prjct-cli", "docs");
887
- const templateDocsDir = import_node_path4.default.join(getPackageRoot(), "templates/global/docs");
887
+ const templateDocsDir = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/docs");
888
888
  await import_promises3.default.mkdir(docsDir, { recursive: true });
889
889
  const docFiles = await import_promises3.default.readdir(templateDocsDir);
890
890
  for (const file of docFiles) {
@@ -916,12 +916,7 @@ async function installGlobalConfig() {
916
916
  try {
917
917
  await import_promises3.default.mkdir(activeProvider.configDir, { recursive: true });
918
918
  const globalConfigPath = import_node_path4.default.join(activeProvider.configDir, activeProvider.contextFile);
919
- const templatePath = import_node_path4.default.join(
920
- getPackageRoot(),
921
- "templates",
922
- "global",
923
- activeProvider.contextFile
924
- );
919
+ const templatePath = import_node_path4.default.join(PACKAGE_ROOT, "templates", "global", activeProvider.contextFile);
925
920
  let templateContent = "";
926
921
  try {
927
922
  templateContent = await import_promises3.default.readFile(templatePath, "utf-8");
@@ -930,11 +925,11 @@ async function installGlobalConfig() {
930
925
  try {
931
926
  templateContent = await composeGlobalTemplate("standard");
932
927
  } catch {
933
- const fallbackTemplatePath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
928
+ const fallbackTemplatePath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
934
929
  templateContent = await import_promises3.default.readFile(fallbackTemplatePath, "utf-8");
935
930
  }
936
931
  } else {
937
- const fallbackTemplatePath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
932
+ const fallbackTemplatePath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
938
933
  templateContent = await import_promises3.default.readFile(fallbackTemplatePath, "utf-8");
939
934
  if (providerName === "gemini") {
940
935
  templateContent = templateContent.replace(/Claude/g, "Gemini");
@@ -1012,7 +1007,7 @@ var CommandInstaller = class {
1012
1007
  _initialized = false;
1013
1008
  constructor() {
1014
1009
  this.homeDir = import_node_os3.default.homedir();
1015
- this.templatesDir = import_node_path4.default.join(getPackageRoot(), "templates", "commands");
1010
+ this.templatesDir = import_node_path4.default.join(PACKAGE_ROOT, "templates", "commands");
1016
1011
  }
1017
1012
  async ensureInit() {
1018
1013
  if (this._initialized) return;
@@ -1626,7 +1621,7 @@ __name(run, "run");
1626
1621
  async function installGeminiRouter() {
1627
1622
  try {
1628
1623
  const geminiCommandsDir = import_node_path6.default.join(import_node_os5.default.homedir(), ".gemini", "commands");
1629
- const routerSource = import_node_path6.default.join(getPackageRoot(), "templates", "commands", "p.toml");
1624
+ const routerSource = import_node_path6.default.join(PACKAGE_ROOT, "templates", "commands", "p.toml");
1630
1625
  const routerDest = import_node_path6.default.join(geminiCommandsDir, "p.toml");
1631
1626
  await import_promises5.default.mkdir(geminiCommandsDir, { recursive: true });
1632
1627
  if (await fileExists(routerSource)) {
@@ -1644,7 +1639,7 @@ async function installGeminiGlobalConfig() {
1644
1639
  try {
1645
1640
  const geminiDir = import_node_path6.default.join(import_node_os5.default.homedir(), ".gemini");
1646
1641
  const globalConfigPath = import_node_path6.default.join(geminiDir, "GEMINI.md");
1647
- const templatePath = import_node_path6.default.join(getPackageRoot(), "templates", "global", "GEMINI.md");
1642
+ const templatePath = import_node_path6.default.join(PACKAGE_ROOT, "templates", "global", "GEMINI.md");
1648
1643
  await import_promises5.default.mkdir(geminiDir, { recursive: true });
1649
1644
  const templateContent = await import_promises5.default.readFile(templatePath, "utf-8");
1650
1645
  let existingContent = "";
@@ -1695,7 +1690,7 @@ async function installAntigravitySkill() {
1695
1690
  const antigravitySkillsDir = import_node_path6.default.join(import_node_os5.default.homedir(), ".gemini", "antigravity", "skills");
1696
1691
  const prjctSkillDir = import_node_path6.default.join(antigravitySkillsDir, "prjct");
1697
1692
  const skillMdPath = import_node_path6.default.join(prjctSkillDir, "SKILL.md");
1698
- const templatePath = import_node_path6.default.join(getPackageRoot(), "templates", "antigravity", "SKILL.md");
1693
+ const templatePath = import_node_path6.default.join(PACKAGE_ROOT, "templates", "antigravity", "SKILL.md");
1699
1694
  await import_promises5.default.mkdir(prjctSkillDir, { recursive: true });
1700
1695
  const skillExists = await fileExists(skillMdPath);
1701
1696
  if (!await fileExists(templatePath)) {
@@ -1728,8 +1723,8 @@ async function installCursorProject(projectRoot) {
1728
1723
  const rulesDir = import_node_path6.default.join(cursorDir, "rules");
1729
1724
  const commandsDir = import_node_path6.default.join(cursorDir, "commands");
1730
1725
  const routerMdcDest = import_node_path6.default.join(rulesDir, "prjct.mdc");
1731
- const routerMdcSource = import_node_path6.default.join(getPackageRoot(), "templates", "cursor", "router.mdc");
1732
- const cursorCommandsSource = import_node_path6.default.join(getPackageRoot(), "templates", "cursor", "commands");
1726
+ const routerMdcSource = import_node_path6.default.join(PACKAGE_ROOT, "templates", "cursor", "router.mdc");
1727
+ const cursorCommandsSource = import_node_path6.default.join(PACKAGE_ROOT, "templates", "cursor", "commands");
1733
1728
  await import_promises5.default.mkdir(rulesDir, { recursive: true });
1734
1729
  await import_promises5.default.mkdir(commandsDir, { recursive: true });
1735
1730
  if (await fileExists(routerMdcSource)) {
@@ -1816,13 +1811,8 @@ async function installWindsurfProject(projectRoot) {
1816
1811
  const rulesDir = import_node_path6.default.join(windsurfDir, "rules");
1817
1812
  const workflowsDir = import_node_path6.default.join(windsurfDir, "workflows");
1818
1813
  const routerDest = import_node_path6.default.join(rulesDir, "prjct.md");
1819
- const routerSource = import_node_path6.default.join(getPackageRoot(), "templates", "windsurf", "router.md");
1820
- const windsurfWorkflowsSource = import_node_path6.default.join(
1821
- getPackageRoot(),
1822
- "templates",
1823
- "windsurf",
1824
- "workflows"
1825
- );
1814
+ const routerSource = import_node_path6.default.join(PACKAGE_ROOT, "templates", "windsurf", "router.md");
1815
+ const windsurfWorkflowsSource = import_node_path6.default.join(PACKAGE_ROOT, "templates", "windsurf", "workflows");
1826
1816
  await import_promises5.default.mkdir(rulesDir, { recursive: true });
1827
1817
  await import_promises5.default.mkdir(workflowsDir, { recursive: true });
1828
1818
  if (await fileExists(routerSource)) {
@@ -1962,7 +1952,7 @@ async function installStatusLine() {
1962
1952
  const prjctLibDir = import_node_path6.default.join(prjctStatusLineDir, "lib");
1963
1953
  const prjctComponentsDir = import_node_path6.default.join(prjctStatusLineDir, "components");
1964
1954
  const prjctConfigPath = import_node_path6.default.join(prjctStatusLineDir, "config.json");
1965
- const assetsDir = import_node_path6.default.join(getPackageRoot(), "assets", "statusline");
1955
+ const assetsDir = import_node_path6.default.join(PACKAGE_ROOT, "assets", "statusline");
1966
1956
  const sourceScript = import_node_path6.default.join(assetsDir, "statusline.sh");
1967
1957
  const sourceThemeDir = import_node_path6.default.join(assetsDir, "themes");
1968
1958
  const sourceLibDir = import_node_path6.default.join(assetsDir, "lib");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "1.6.11",
3
+ "version": "1.6.13",
4
4
  "description": "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
5
5
  "main": "core/index.ts",
6
6
  "bin": {
@@ -1,35 +0,0 @@
1
- ---
2
- allowed-tools: [Glob, Read]
3
- ---
4
-
5
- # Context Filtering
6
-
7
- Determine relevant files for a task.
8
-
9
- ## Process
10
-
11
- 1. **Get real extensions**: Only include what EXISTS in project
12
- 2. **Identify directories**: Based on task, not assumptions
13
- 3. **Filter by task**: What files will be modified?
14
- 4. **Exclude non-relevant**: node_modules, .git, dist, build
15
-
16
- ## Output
17
-
18
- ```json
19
- {
20
- "include": {
21
- "extensions": [".ts", ".tsx"],
22
- "directories": ["src/", "lib/"]
23
- },
24
- "exclude": {
25
- "directories": ["node_modules/", ".git/", "dist/"]
26
- },
27
- "reasoning": "why these patterns"
28
- }
29
- ```
30
-
31
- ## Rules
32
-
33
- - Use REAL extensions (not assumed)
34
- - Task-specific filtering
35
- - Efficient - focus on what matters
@@ -1,59 +0,0 @@
1
- # Skill Integration
2
-
3
- Agents integrate with Claude Code skills from claude-plugins.dev.
4
-
5
- ## Agent → Skill Mapping
6
-
7
- | Agent | Skill |
8
- |-------|-------|
9
- | frontend.md | frontend-design |
10
- | uxui.md | frontend-design |
11
- | backend.md | javascript-typescript |
12
- | testing.md | developer-kit |
13
- | devops.md | developer-kit |
14
- | prjct-planner.md | feature-dev |
15
- | prjct-shipper.md | code-review |
16
-
17
- ## Installation (during `p. sync`)
18
-
19
- 1. Check existing: `ls ~/.claude/skills/*.md`
20
- 2. Search: `https://claude-plugins.dev/skills?q={term}`
21
- 3. Prefer: @anthropics, high downloads
22
- 4. Write to: `~/.claude/skills/{name}.md`
23
- 5. Save mapping: `{globalPath}/config/skills.json`
24
-
25
- ## Agent Frontmatter
26
-
27
- ```yaml
28
- ---
29
- name: frontend
30
- description: "Frontend specialist. Use PROACTIVELY."
31
- tools: Read, Write, Glob, Grep
32
- skills: [frontend-design]
33
- ---
34
- ```
35
-
36
- ## Usage
37
-
38
- **During `p. task`**:
39
- - Load agent → invoke linked skills
40
-
41
- **During `p. ship`**:
42
- - Invoke code-review skill
43
-
44
- ## Key Skills
45
-
46
- | Skill | Purpose |
47
- |-------|---------|
48
- | frontend-design | UI components, anti-AI-slop |
49
- | javascript-typescript | Node.js, React patterns |
50
- | python-development | Django, FastAPI patterns |
51
- | feature-dev | Architecture, planning |
52
- | code-review | PR review, security |
53
- | developer-kit | Testing, DevOps |
54
-
55
- ## Troubleshooting
56
-
57
- - Skill not invoking? Check agent `skills:` frontmatter
58
- - Wrong skill? Re-run `p. sync`
59
- - Manual invoke: `/frontend-design`
@@ -1,54 +0,0 @@
1
- # Sub-Agent Generation
2
-
3
- Generate project-specific agents based on detected stack.
4
-
5
- ## Output Location
6
-
7
- `{globalPath}/agents/` (NEVER local project)
8
-
9
- ## Agent Format
10
-
11
- ```markdown
12
- ---
13
- name: agent-name
14
- description: When to use. Include "Use PROACTIVELY" for auto-invoke.
15
- tools: Read, Write, Glob, Grep, Bash
16
- model: sonnet
17
- skills: [skill-name]
18
- ---
19
- Agent prompt...
20
- ```
21
-
22
- ## Required Workflow Agents
23
-
24
- | Agent | Purpose | Skill |
25
- |-------|---------|-------|
26
- | prjct-workflow.md | Task lifecycle | - |
27
- | prjct-planner.md | Feature planning | feature-dev |
28
- | prjct-shipper.md | Git, deploy | code-review |
29
-
30
- ## Domain Agents (based on stack)
31
-
32
- | If Detected | Generate | Skill |
33
- |-------------|----------|-------|
34
- | React, Vue, CSS | frontend.md | frontend-design |
35
- | Node, Express, API | backend.md | javascript-typescript |
36
- | PostgreSQL, MongoDB | database.md | - |
37
- | Docker, CI/CD | devops.md | developer-kit |
38
- | Jest, Pytest | testing.md | developer-kit |
39
- | Any UI | uxui.md | frontend-design |
40
-
41
- ## Execution
42
-
43
- 1. Read `{globalPath}/analysis/repo-summary.md`
44
- 2. Create `{globalPath}/agents/` directory
45
- 3. Generate workflow agents (always)
46
- 4. Generate domain agents (based on analysis)
47
- 5. Add skills to frontmatter
48
- 6. Report generated agents
49
-
50
- ## Rules
51
-
52
- - **ALWAYS** write to `{globalPath}/agents/`
53
- - **NEVER** write to `.claude/` or `.prjct/`
54
- - Adapt templates to project context
@@ -1,74 +0,0 @@
1
- ---
2
- name: bug-severity
3
- description: Assess bug severity from description
4
- allowed-tools: [Read]
5
- ---
6
-
7
- # Bug Severity Assessment
8
-
9
- Analyze the bug description to determine its severity and priority.
10
-
11
- ## Input
12
- - Bug: {{description}}
13
- - Context (if available)
14
-
15
- ## Severity Levels
16
-
17
- ### CRITICAL
18
- - System crash or data loss
19
- - Security vulnerability
20
- - Blocks all users
21
- - Production is down
22
-
23
- ### HIGH
24
- - Major feature broken
25
- - Significant user impact
26
- - Workaround difficult
27
- - Affects many users
28
-
29
- ### MEDIUM
30
- - Feature partially broken
31
- - Workaround exists
32
- - Limited user impact
33
- - Non-essential functionality
34
-
35
- ### LOW
36
- - Minor inconvenience
37
- - Cosmetic issue
38
- - Edge case only
39
- - Easy workaround
40
-
41
- ## Analysis Steps
42
-
43
- 1. **Assess Impact**
44
- - Who is affected?
45
- - How many users?
46
- - Is there data loss risk?
47
-
48
- 2. **Check Urgency**
49
- - Is production affected?
50
- - Is there a deadline?
51
- - Are users blocked?
52
-
53
- 3. **Evaluate Workaround**
54
- - Can users continue working?
55
- - How hard is the workaround?
56
-
57
- ## Output Format
58
-
59
- Return JSON:
60
- ```json
61
- {
62
- "severity": "critical|high|medium|low",
63
- "priority": 1-4,
64
- "reasoning": "<brief explanation>",
65
- "suggestedAction": "<what to do next>"
66
- }
67
- ```
68
-
69
- ## Guidelines
70
-
71
- - Err on the side of higher severity if unsure
72
- - Security issues are always CRITICAL
73
- - Data loss is always CRITICAL
74
- - User-reported = add weight
@@ -1,54 +0,0 @@
1
- ---
2
- name: complexity-analysis
3
- description: Analyze task complexity semantically
4
- allowed-tools: [Read]
5
- ---
6
-
7
- # Task Complexity Analysis
8
-
9
- Analyze the given task description and determine its complexity level.
10
-
11
- ## Input
12
- - Task: {{task}}
13
- - Project context (if available)
14
-
15
- ## Analysis Steps
16
-
17
- 1. **Understand the Task**
18
- - What is being asked?
19
- - What systems/files are affected?
20
- - Are there dependencies?
21
-
22
- 2. **Evaluate Scope**
23
- - Single file change → LOW
24
- - Multiple files, same module → MEDIUM
25
- - Cross-module or architectural → HIGH
26
-
27
- 3. **Assess Risk**
28
- - Read-only or additive → LOW risk
29
- - Modifying existing logic → MEDIUM risk
30
- - Refactoring or migration → HIGH risk
31
-
32
- 4. **Consider Dependencies**
33
- - No external deps → LOW
34
- - Some integration → MEDIUM
35
- - Multiple systems → HIGH
36
-
37
- ## Output Format
38
-
39
- Return JSON:
40
- ```json
41
- {
42
- "complexity": "low|medium|high",
43
- "type": "feature|bugfix|refactor|testing|docs|chore",
44
- "estimatedHours": <number>,
45
- "reasoning": "<brief explanation>"
46
- }
47
- ```
48
-
49
- ## Guidelines
50
-
51
- - Be realistic, not optimistic
52
- - Consider testing time in estimates
53
- - If unsure, lean toward higher complexity
54
- - Don't use keyword matching - analyze semantically
@@ -1,66 +0,0 @@
1
- ---
2
- name: health-score
3
- description: Calculate project health score
4
- allowed-tools: [Read]
5
- ---
6
-
7
- # Project Health Score
8
-
9
- Evaluate the project's health based on activity metrics.
10
-
11
- ## Input
12
- - Active task: {{hasActiveTask}}
13
- - Queue size: {{queueSize}}
14
- - Recent ships: {{recentShips}}
15
- - Ideas count: {{ideasCount}}
16
- - Days since last ship: {{daysSinceShip}}
17
-
18
- ## Health Factors
19
-
20
- ### Momentum (40%)
21
- - Active task = good
22
- - Regular shipping = good
23
- - Long gaps = concerning
24
-
25
- ### Focus (30%)
26
- - Queue < 10 = focused
27
- - Queue 10-20 = busy
28
- - Queue > 20 = overloaded
29
-
30
- ### Progress (20%)
31
- - Ships this week > 0 = active
32
- - Ships this month > 2 = productive
33
- - No ships in 7+ days = stalled
34
-
35
- ### Planning (10%)
36
- - Ideas captured = thinking ahead
37
- - Too many ideas = unfocused
38
-
39
- ## Score Calculation
40
-
41
- Evaluate each factor and combine:
42
-
43
- | Score | Label | Meaning |
44
- |-------|-------|---------|
45
- | 80-100 | Excellent | High momentum, focused, shipping |
46
- | 60-79 | Good | Active, some room to improve |
47
- | 40-59 | Fair | Slowing down, needs attention |
48
- | 0-39 | Low | Stalled, intervention needed |
49
-
50
- ## Output Format
51
-
52
- Return JSON:
53
- ```json
54
- {
55
- "score": <0-100>,
56
- "label": "Excellent|Good|Fair|Low",
57
- "momentum": "<assessment>",
58
- "suggestions": ["<action 1>", "<action 2>"]
59
- }
60
- ```
61
-
62
- ## Guidelines
63
-
64
- - Be encouraging but honest
65
- - Suggest specific actions
66
- - Focus on momentum, not perfection
@@ -1,66 +0,0 @@
1
- ---
2
- name: intent-detection
3
- description: Detect user intent from natural language
4
- allowed-tools: []
5
- ---
6
-
7
- # Intent Detection
8
-
9
- Analyze user input to determine their intent and map to appropriate action.
10
-
11
- ## Input
12
- - User message: {{message}}
13
-
14
- ## Intent Categories
15
-
16
- ### Work Intents
17
- - **start_task**: User wants to begin working on something
18
- - **complete_task**: User finished current work
19
- - **ship**: User wants to release/deploy
20
- - **pause**: User needs to pause current work
21
-
22
- ### Planning Intents
23
- - **add_feature**: User has a new feature idea
24
- - **add_idea**: Quick thought to capture
25
- - **add_bug**: Report a problem
26
- - **view_queue**: See what's next
27
-
28
- ### Status Intents
29
- - **check_progress**: View metrics/status
30
- - **get_recap**: Project overview
31
- - **get_help**: Need guidance
32
-
33
- ### System Intents
34
- - **sync**: Update project state
35
- - **analyze**: Analyze codebase
36
- - **cleanup**: Clean up files
37
-
38
- ## Analysis
39
-
40
- Look for semantic meaning, not keywords:
41
- - "I'm done" → complete_task
42
- - "Let's ship this" → ship
43
- - "Quick thought..." → add_idea
44
- - "What should I do?" → get_help OR view_queue
45
-
46
- ## Output Format
47
-
48
- Return JSON:
49
- ```json
50
- {
51
- "intent": "<intent_name>",
52
- "confidence": <0.0-1.0>,
53
- "parameters": {
54
- "task": "<extracted task if any>",
55
- "feature": "<extracted feature if any>"
56
- },
57
- "suggestedCommand": "/p:<command>"
58
- }
59
- ```
60
-
61
- ## Guidelines
62
-
63
- - Use semantic understanding, not regex
64
- - Extract relevant parameters
65
- - High confidence (>0.8) for clear intents
66
- - Ask for clarification if < 0.5
@@ -1,53 +0,0 @@
1
- ---
2
- name: task-breakdown
3
- description: Break down a feature into actionable tasks
4
- allowed-tools: [Read, Glob, Grep]
5
- ---
6
-
7
- # Feature Task Breakdown
8
-
9
- Analyze the feature description and break it into concrete, actionable tasks.
10
-
11
- ## Input
12
- - Feature: {{feature}}
13
- - Project path: {{projectPath}}
14
-
15
- ## Analysis Steps
16
-
17
- 1. **Understand the Feature**
18
- - Read related code if paths are obvious
19
- - Identify affected systems
20
- - Note existing patterns to follow
21
-
22
- 2. **Identify Components**
23
- - What new files/modules are needed?
24
- - What existing code needs modification?
25
- - What tests are required?
26
-
27
- 3. **Order by Dependencies**
28
- - Foundation tasks first (models, types, interfaces)
29
- - Core logic second
30
- - Integration third
31
- - Tests and polish last
32
-
33
- 4. **Size Each Task**
34
- - Each task should be 20-60 minutes
35
- - If larger, break down further
36
- - If smaller, combine with related task
37
-
38
- ## Output Format
39
-
40
- Return a numbered task list:
41
- ```
42
- 1. [20m] Task description - specific action
43
- 2. [30m] Another task - what exactly to do
44
- 3. [45m] Final task - clear deliverable
45
- ```
46
-
47
- ## Guidelines
48
-
49
- - Tasks must be specific and actionable
50
- - Include time estimates in brackets
51
- - Order matters - dependencies first
52
- - Don't assume - if unsure, read code first
53
- - Match project patterns (read existing code)