prjct-cli 1.22.0 → 1.24.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 +230 -0
- package/bin/prjct +30 -13
- package/dist/bin/prjct-core.mjs +1748 -0
- package/dist/bin/prjct.mjs +17 -36672
- package/dist/cli/linear.mjs +14 -0
- package/dist/daemon/entry.mjs +1429 -0
- package/dist/templates.json +1 -0
- package/package.json +4 -5
- package/bin/prjct.ts +0 -342
- package/core/__tests__/agentic/analysis-injection.test.ts +0 -377
- package/core/__tests__/agentic/cache-eviction.test.ts +0 -294
- package/core/__tests__/agentic/command-context.test.ts +0 -281
- package/core/__tests__/agentic/command-executor.test.ts +0 -659
- package/core/__tests__/agentic/domain-classifier.test.ts +0 -330
- package/core/__tests__/agentic/injection-validator.test.ts +0 -255
- package/core/__tests__/agentic/memory-system.test.ts +0 -281
- package/core/__tests__/agentic/plan-mode.test.ts +0 -386
- package/core/__tests__/agentic/prompt-assembly.test.ts +0 -298
- package/core/__tests__/agentic/prompt-builder.test.ts +0 -243
- package/core/__tests__/agentic/response-validator.test.ts +0 -263
- package/core/__tests__/agentic/semantic-matching.test.ts +0 -131
- package/core/__tests__/agentic/smart-context.test.ts +0 -372
- package/core/__tests__/agentic/tech-normalizer.test.ts +0 -136
- package/core/__tests__/agentic/token-budget.test.ts +0 -294
- package/core/__tests__/ai-tools/formatters.test.ts +0 -476
- package/core/__tests__/domain/bm25.test.ts +0 -225
- package/core/__tests__/domain/change-propagator.test.ts +0 -100
- package/core/__tests__/domain/fibonacci.test.ts +0 -113
- package/core/__tests__/domain/file-hasher.test.ts +0 -146
- package/core/__tests__/domain/file-ranker.test.ts +0 -169
- package/core/__tests__/domain/git-cochange.test.ts +0 -121
- package/core/__tests__/domain/import-graph.test.ts +0 -156
- package/core/__tests__/domain/velocity.test.ts +0 -623
- package/core/__tests__/infrastructure/performance-tracker.test.ts +0 -328
- package/core/__tests__/schemas/model.test.ts +0 -272
- package/core/__tests__/services/dependency-validator.test.ts +0 -175
- package/core/__tests__/services/hierarchical-agent-resolver.test.ts +0 -359
- package/core/__tests__/services/nested-context-resolver.test.ts +0 -443
- package/core/__tests__/services/project-index.test.ts +0 -355
- package/core/__tests__/services/staleness-checker.test.ts +0 -204
- package/core/__tests__/storage/analysis-storage.test.ts +0 -641
- package/core/__tests__/storage/archive-storage.test.ts +0 -455
- package/core/__tests__/storage/safe-reader.test.ts +0 -262
- package/core/__tests__/storage/sqlite-migration.test.ts +0 -1016
- package/core/__tests__/storage/state-storage-feedback.test.ts +0 -463
- package/core/__tests__/storage/state-storage-history.test.ts +0 -469
- package/core/__tests__/storage/storage-manager.test.ts +0 -383
- package/core/__tests__/storage/subtask-handoff.test.ts +0 -237
- package/core/__tests__/types/fs.test.ts +0 -125
- package/core/__tests__/utils/date-helper.test.ts +0 -449
- package/core/__tests__/utils/output.test.ts +0 -278
- package/core/__tests__/utils/preserve-sections.test.ts +0 -216
- package/core/__tests__/utils/project-commands.test.ts +0 -71
- package/core/__tests__/utils/retry.test.ts +0 -381
- package/core/__tests__/workflow/state-machine.test.ts +0 -216
- package/core/agentic/agent-router.ts +0 -150
- package/core/agentic/anti-hallucination.ts +0 -141
- package/core/agentic/chain-of-thought.ts +0 -234
- package/core/agentic/command-classifier.ts +0 -141
- package/core/agentic/command-context.ts +0 -168
- package/core/agentic/command-executor.ts +0 -471
- package/core/agentic/context-builder.ts +0 -285
- package/core/agentic/domain-classifier.ts +0 -525
- package/core/agentic/environment-block.ts +0 -102
- package/core/agentic/ground-truth.ts +0 -706
- package/core/agentic/index.ts +0 -193
- package/core/agentic/injection-validator.ts +0 -208
- package/core/agentic/loop-detector.ts +0 -451
- package/core/agentic/memory-system.ts +0 -1547
- package/core/agentic/orchestrator-executor.ts +0 -579
- package/core/agentic/plan-mode.ts +0 -525
- package/core/agentic/prompt-builder.ts +0 -1069
- package/core/agentic/response-validator.ts +0 -98
- package/core/agentic/services.ts +0 -167
- package/core/agentic/skill-loader.ts +0 -106
- package/core/agentic/smart-context.ts +0 -393
- package/core/agentic/tech-normalizer.ts +0 -167
- package/core/agentic/template-executor.ts +0 -272
- package/core/agentic/template-loader.ts +0 -109
- package/core/agentic/token-budget.ts +0 -226
- package/core/agentic/tool-registry.ts +0 -146
- package/core/agents/index.ts +0 -28
- package/core/agents/performance.ts +0 -429
- package/core/ai-tools/formatters.ts +0 -341
- package/core/ai-tools/generator.ts +0 -144
- package/core/ai-tools/index.ts +0 -15
- package/core/ai-tools/registry.ts +0 -201
- package/core/bus/bus.ts +0 -314
- package/core/bus/index.ts +0 -8
- package/core/cli/linear.ts +0 -500
- package/core/cli/lint-meta-commentary.ts +0 -177
- package/core/cli/start.ts +0 -386
- package/core/commands/analysis.ts +0 -1274
- package/core/commands/analytics.ts +0 -342
- package/core/commands/base.ts +0 -118
- package/core/commands/cleanup.ts +0 -157
- package/core/commands/command-data.ts +0 -463
- package/core/commands/commands.ts +0 -306
- package/core/commands/context.ts +0 -238
- package/core/commands/design.ts +0 -77
- package/core/commands/index.ts +0 -19
- package/core/commands/maintenance.ts +0 -77
- package/core/commands/performance.ts +0 -114
- package/core/commands/planning.ts +0 -662
- package/core/commands/register.ts +0 -127
- package/core/commands/registry.ts +0 -444
- package/core/commands/setup.ts +0 -280
- package/core/commands/shipping.ts +0 -267
- package/core/commands/snapshots.ts +0 -297
- package/core/commands/uninstall.ts +0 -542
- package/core/commands/velocity.ts +0 -149
- package/core/commands/workflow.ts +0 -505
- package/core/config/command-context.config.json +0 -66
- package/core/constants/index.ts +0 -379
- package/core/context/generator.ts +0 -368
- package/core/context-tools/files-tool.ts +0 -577
- package/core/context-tools/imports-tool.ts +0 -400
- package/core/context-tools/index.ts +0 -434
- package/core/context-tools/recent-tool.ts +0 -301
- package/core/context-tools/signatures-tool.ts +0 -495
- package/core/context-tools/summary-tool.ts +0 -301
- package/core/context-tools/token-counter.ts +0 -273
- package/core/context-tools/types.ts +0 -253
- package/core/domain/agent-generator.ts +0 -186
- package/core/domain/agent-loader.ts +0 -419
- package/core/domain/analyzer.ts +0 -387
- package/core/domain/architecture-generator.ts +0 -108
- package/core/domain/bm25.ts +0 -525
- package/core/domain/change-propagator.ts +0 -162
- package/core/domain/context-estimator.ts +0 -175
- package/core/domain/fibonacci.ts +0 -128
- package/core/domain/file-hasher.ts +0 -296
- package/core/domain/file-ranker.ts +0 -151
- package/core/domain/git-cochange.ts +0 -250
- package/core/domain/import-graph.ts +0 -315
- package/core/domain/snapshot-manager.ts +0 -415
- package/core/domain/task-stack.ts +0 -578
- package/core/domain/velocity.ts +0 -470
- package/core/errors.ts +0 -335
- package/core/events/events.ts +0 -85
- package/core/events/index.ts +0 -8
- package/core/index.ts +0 -481
- package/core/infrastructure/agent-detector.ts +0 -135
- package/core/infrastructure/ai-provider.ts +0 -578
- package/core/infrastructure/author-detector.ts +0 -133
- package/core/infrastructure/capability-installer.ts +0 -76
- package/core/infrastructure/claude-agent.ts +0 -297
- package/core/infrastructure/command-installer.ts +0 -752
- package/core/infrastructure/config-manager.ts +0 -364
- package/core/infrastructure/editors-config.ts +0 -172
- package/core/infrastructure/path-manager.ts +0 -571
- package/core/infrastructure/performance-tracker.ts +0 -326
- package/core/infrastructure/permission-manager.ts +0 -289
- package/core/infrastructure/setup.ts +0 -1061
- package/core/infrastructure/update-checker.ts +0 -246
- package/core/integrations/issue-tracker/enricher.ts +0 -271
- package/core/integrations/issue-tracker/index.ts +0 -8
- package/core/integrations/issue-tracker/manager.ts +0 -286
- package/core/integrations/issue-tracker/types.ts +0 -310
- package/core/integrations/jira/cache.ts +0 -57
- package/core/integrations/jira/client.ts +0 -688
- package/core/integrations/jira/index.ts +0 -23
- package/core/integrations/jira/service.ts +0 -244
- package/core/integrations/linear/cache.ts +0 -68
- package/core/integrations/linear/client.ts +0 -436
- package/core/integrations/linear/index.ts +0 -20
- package/core/integrations/linear/service.ts +0 -260
- package/core/integrations/linear/sync.ts +0 -314
- package/core/outcomes/analyzer.ts +0 -286
- package/core/outcomes/index.ts +0 -34
- package/core/outcomes/recorder.ts +0 -195
- package/core/plugin/builtin/webhook.ts +0 -148
- package/core/plugin/hooks.ts +0 -315
- package/core/plugin/index.ts +0 -50
- package/core/plugin/loader.ts +0 -354
- package/core/plugin/registry.ts +0 -326
- package/core/schemas/agents.ts +0 -27
- package/core/schemas/analysis.ts +0 -530
- package/core/schemas/classification.ts +0 -91
- package/core/schemas/command-context.ts +0 -29
- package/core/schemas/enriched-task.ts +0 -291
- package/core/schemas/ideas.ts +0 -114
- package/core/schemas/index.ts +0 -53
- package/core/schemas/issues.ts +0 -159
- package/core/schemas/llm-output.ts +0 -170
- package/core/schemas/metrics.ts +0 -143
- package/core/schemas/model.ts +0 -153
- package/core/schemas/outcomes.ts +0 -487
- package/core/schemas/performance.ts +0 -128
- package/core/schemas/permissions.ts +0 -180
- package/core/schemas/prd.ts +0 -450
- package/core/schemas/project.ts +0 -57
- package/core/schemas/roadmap.ts +0 -322
- package/core/schemas/schemas.ts +0 -38
- package/core/schemas/shipped.ts +0 -109
- package/core/schemas/state.ts +0 -284
- package/core/schemas/velocity.ts +0 -103
- package/core/server/index.ts +0 -21
- package/core/server/routes-extended.ts +0 -566
- package/core/server/routes.ts +0 -176
- package/core/server/server.ts +0 -149
- package/core/server/sse.ts +0 -192
- package/core/services/agent-generator.ts +0 -385
- package/core/services/agent-service.ts +0 -168
- package/core/services/breakdown-service.ts +0 -124
- package/core/services/context-generator.ts +0 -445
- package/core/services/context-selector.ts +0 -429
- package/core/services/dependency-validator.ts +0 -318
- package/core/services/diff-generator.ts +0 -313
- package/core/services/doctor-service.ts +0 -423
- package/core/services/file-categorizer.ts +0 -448
- package/core/services/file-scorer.ts +0 -270
- package/core/services/git-analyzer.ts +0 -293
- package/core/services/hierarchical-agent-resolver.ts +0 -236
- package/core/services/hooks-service.ts +0 -685
- package/core/services/index.ts +0 -46
- package/core/services/local-state-generator.ts +0 -158
- package/core/services/memory-service.ts +0 -181
- package/core/services/nested-context-resolver.ts +0 -842
- package/core/services/project-index.ts +0 -911
- package/core/services/project-service.ts +0 -155
- package/core/services/session-tracker.ts +0 -287
- package/core/services/skill-installer.ts +0 -447
- package/core/services/skill-lock.ts +0 -132
- package/core/services/skill-service.ts +0 -306
- package/core/services/stack-detector.ts +0 -229
- package/core/services/staleness-checker.ts +0 -327
- package/core/services/sync-service.ts +0 -1515
- package/core/services/sync-verifier.ts +0 -253
- package/core/services/watch-service.ts +0 -312
- package/core/session/compaction.ts +0 -248
- package/core/session/index.ts +0 -35
- package/core/session/log-migration.ts +0 -88
- package/core/session/metrics.ts +0 -323
- package/core/session/session-log-manager.ts +0 -307
- package/core/session/task-session-manager.ts +0 -404
- package/core/session/utils.ts +0 -51
- package/core/storage/analysis-storage.ts +0 -373
- package/core/storage/archive-storage.ts +0 -205
- package/core/storage/database.ts +0 -575
- package/core/storage/ideas-storage.ts +0 -298
- package/core/storage/index-storage.ts +0 -523
- package/core/storage/index.ts +0 -79
- package/core/storage/metrics-storage.ts +0 -321
- package/core/storage/migrate-json.ts +0 -720
- package/core/storage/queue-storage.ts +0 -336
- package/core/storage/safe-reader.ts +0 -105
- package/core/storage/shipped-storage.ts +0 -253
- package/core/storage/state-storage.ts +0 -1035
- package/core/storage/storage-manager.ts +0 -205
- package/core/storage/storage.ts +0 -177
- package/core/storage/velocity-storage.ts +0 -149
- package/core/sync/auth-config.ts +0 -138
- package/core/sync/index.ts +0 -31
- package/core/sync/oauth-handler.ts +0 -143
- package/core/sync/sync-client.ts +0 -251
- package/core/sync/sync-manager.ts +0 -327
- package/core/tsconfig.json +0 -22
- package/core/types/agentic.ts +0 -760
- package/core/types/agents.ts +0 -150
- package/core/types/bus.ts +0 -193
- package/core/types/citations.ts +0 -22
- package/core/types/commands.ts +0 -399
- package/core/types/config.ts +0 -92
- package/core/types/core.ts +0 -96
- package/core/types/diff.ts +0 -41
- package/core/types/domain.ts +0 -71
- package/core/types/errors.ts +0 -111
- package/core/types/events.ts +0 -42
- package/core/types/fs.ts +0 -72
- package/core/types/index.ts +0 -510
- package/core/types/infrastructure.ts +0 -210
- package/core/types/integrations.ts +0 -31
- package/core/types/jira.ts +0 -51
- package/core/types/logger.ts +0 -17
- package/core/types/memory.ts +0 -313
- package/core/types/outcomes.ts +0 -190
- package/core/types/output.ts +0 -47
- package/core/types/plugin.ts +0 -25
- package/core/types/project-sync.ts +0 -129
- package/core/types/provider.ts +0 -163
- package/core/types/server.ts +0 -71
- package/core/types/services.ts +0 -84
- package/core/types/session.ts +0 -135
- package/core/types/stack.ts +0 -19
- package/core/types/storage.ts +0 -318
- package/core/types/sync-verifier.ts +0 -33
- package/core/types/sync.ts +0 -121
- package/core/types/task.ts +0 -72
- package/core/types/template.ts +0 -24
- package/core/types/utils.ts +0 -92
- package/core/types/workflow.ts +0 -23
- package/core/utils/agent-stream.ts +0 -140
- package/core/utils/animations.ts +0 -251
- package/core/utils/branding.ts +0 -88
- package/core/utils/cache.ts +0 -187
- package/core/utils/citations.ts +0 -39
- package/core/utils/collection-filters.ts +0 -209
- package/core/utils/date-helper.ts +0 -176
- package/core/utils/error-messages.ts +0 -38
- package/core/utils/file-helper.ts +0 -277
- package/core/utils/fs-helpers.ts +0 -14
- package/core/utils/help.ts +0 -314
- package/core/utils/jsonl-helper.ts +0 -290
- package/core/utils/keychain.ts +0 -127
- package/core/utils/logger.ts +0 -77
- package/core/utils/markdown-builder.ts +0 -280
- package/core/utils/next-steps.ts +0 -95
- package/core/utils/output.ts +0 -403
- package/core/utils/preserve-sections.ts +0 -218
- package/core/utils/project-commands.ts +0 -126
- package/core/utils/project-credentials.ts +0 -143
- package/core/utils/provider-cache.ts +0 -49
- package/core/utils/retry.ts +0 -318
- package/core/utils/runtime.ts +0 -108
- package/core/utils/session-helper.ts +0 -278
- package/core/utils/subtask-table.ts +0 -227
- package/core/utils/version.ts +0 -128
- package/core/wizard/index.ts +0 -13
- package/core/wizard/onboarding.ts +0 -633
- package/core/workflow/index.ts +0 -7
- package/core/workflow/state-machine.ts +0 -198
- package/core/workflow/workflow-preferences.ts +0 -294
- package/dist/core/infrastructure/command-installer.js +0 -1141
- package/dist/core/infrastructure/editors-config.js +0 -177
- package/dist/core/infrastructure/setup.js +0 -2244
- package/dist/core/utils/version.js +0 -141
- package/templates/agentic/agent-routing.md +0 -45
- package/templates/agentic/agents/uxui.md +0 -63
- package/templates/agentic/checklist-routing.md +0 -98
- package/templates/agentic/orchestrator.md +0 -68
- package/templates/agentic/task-fragmentation.md +0 -89
- package/templates/agents/AGENTS.md +0 -68
- package/templates/analysis/analyze.md +0 -84
- package/templates/analysis/patterns.md +0 -60
- package/templates/antigravity/SKILL.md +0 -39
- package/templates/architect/discovery.md +0 -67
- package/templates/architect/phases.md +0 -59
- package/templates/checklists/architecture.md +0 -28
- package/templates/checklists/code-quality.md +0 -28
- package/templates/checklists/data.md +0 -33
- package/templates/checklists/documentation.md +0 -33
- package/templates/checklists/infrastructure.md +0 -33
- package/templates/checklists/performance.md +0 -33
- package/templates/checklists/security.md +0 -33
- package/templates/checklists/testing.md +0 -33
- package/templates/checklists/ux-ui.md +0 -37
- package/templates/commands/analyze.md +0 -56
- package/templates/commands/auth.md +0 -234
- package/templates/commands/bug.md +0 -163
- package/templates/commands/cleanup.md +0 -19
- package/templates/commands/dash.md +0 -99
- package/templates/commands/design.md +0 -15
- package/templates/commands/done.md +0 -291
- package/templates/commands/enrich.md +0 -174
- package/templates/commands/git.md +0 -295
- package/templates/commands/history.md +0 -389
- package/templates/commands/idea.md +0 -88
- package/templates/commands/impact.md +0 -864
- package/templates/commands/init.md +0 -54
- package/templates/commands/jira.md +0 -278
- package/templates/commands/linear.md +0 -288
- package/templates/commands/merge.md +0 -206
- package/templates/commands/next.md +0 -80
- package/templates/commands/p.md +0 -67
- package/templates/commands/p.toml +0 -37
- package/templates/commands/pause.md +0 -136
- package/templates/commands/plan.md +0 -696
- package/templates/commands/prd.md +0 -356
- package/templates/commands/resume.md +0 -171
- package/templates/commands/review.md +0 -276
- package/templates/commands/serve.md +0 -118
- package/templates/commands/setup.md +0 -91
- package/templates/commands/ship.md +0 -475
- package/templates/commands/skill.md +0 -259
- package/templates/commands/spec.md +0 -218
- package/templates/commands/status.md +0 -207
- package/templates/commands/sync.md +0 -104
- package/templates/commands/task.md +0 -312
- package/templates/commands/test.md +0 -93
- package/templates/commands/update.md +0 -63
- package/templates/commands/verify.md +0 -204
- package/templates/commands/workflow.md +0 -150
- package/templates/config/skill-mappings.json +0 -82
- package/templates/context/dashboard.md +0 -256
- package/templates/context/roadmap.md +0 -221
- package/templates/cursor/commands/bug.md +0 -8
- package/templates/cursor/commands/done.md +0 -4
- package/templates/cursor/commands/pause.md +0 -6
- package/templates/cursor/commands/resume.md +0 -4
- package/templates/cursor/commands/ship.md +0 -8
- package/templates/cursor/commands/sync.md +0 -4
- package/templates/cursor/commands/task.md +0 -8
- package/templates/cursor/p.md +0 -29
- package/templates/cursor/router.mdc +0 -28
- package/templates/design/api.md +0 -95
- package/templates/design/architecture.md +0 -77
- package/templates/design/component.md +0 -89
- package/templates/design/database.md +0 -78
- package/templates/design/flow.md +0 -94
- package/templates/global/ANTIGRAVITY.md +0 -254
- package/templates/global/CLAUDE.md +0 -497
- package/templates/global/CURSOR.mdc +0 -266
- package/templates/global/GEMINI.md +0 -293
- package/templates/global/STORAGE-SPEC.md +0 -391
- package/templates/global/WINDSURF.md +0 -266
- package/templates/global/modules/CLAUDE-commands.md +0 -70
- package/templates/global/modules/CLAUDE-core.md +0 -105
- package/templates/global/modules/CLAUDE-git.md +0 -50
- package/templates/global/modules/CLAUDE-intelligence.md +0 -92
- package/templates/global/modules/CLAUDE-storage.md +0 -50
- package/templates/global/modules/module-config.json +0 -36
- package/templates/mcp-config.json +0 -19
- package/templates/permissions/default.jsonc +0 -60
- package/templates/permissions/permissive.jsonc +0 -49
- package/templates/permissions/strict.jsonc +0 -58
- package/templates/planning-methodology.md +0 -195
- package/templates/skills/code-review.md +0 -47
- package/templates/skills/debug.md +0 -61
- package/templates/skills/refactor.md +0 -47
- package/templates/subagents/agent-base.md +0 -20
- package/templates/subagents/domain/backend.md +0 -109
- package/templates/subagents/domain/database.md +0 -121
- package/templates/subagents/domain/devops.md +0 -152
- package/templates/subagents/domain/frontend.md +0 -103
- package/templates/subagents/domain/testing.md +0 -169
- package/templates/subagents/pm-expert.md +0 -366
- package/templates/subagents/workflow/chief-architect.md +0 -657
- package/templates/subagents/workflow/prjct-planner.md +0 -159
- package/templates/subagents/workflow/prjct-shipper.md +0 -188
- package/templates/subagents/workflow/prjct-workflow.md +0 -98
- package/templates/tools/bash.txt +0 -22
- package/templates/tools/edit.txt +0 -18
- package/templates/tools/glob.txt +0 -19
- package/templates/tools/grep.txt +0 -21
- package/templates/tools/read.txt +0 -14
- package/templates/tools/task.txt +0 -20
- package/templates/tools/webfetch.txt +0 -16
- package/templates/tools/websearch.txt +0 -18
- package/templates/tools/write.txt +0 -17
- package/templates/windsurf/router.md +0 -28
- package/templates/windsurf/workflows/bug.md +0 -8
- package/templates/windsurf/workflows/done.md +0 -4
- package/templates/windsurf/workflows/pause.md +0 -4
- package/templates/windsurf/workflows/resume.md +0 -4
- package/templates/windsurf/workflows/ship.md +0 -8
- package/templates/windsurf/workflows/sync.md +0 -4
- package/templates/windsurf/workflows/task.md +0 -8
package/core/index.ts
DELETED
|
@@ -1,481 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* prjct CLI - Main Entry Point
|
|
3
|
-
*
|
|
4
|
-
* This file is required by bin/prjct after setup verification
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { PrjctCommands } from './commands/index'
|
|
8
|
-
import { commandRegistry } from './commands/registry'
|
|
9
|
-
import './commands/register' // Ensure commands are registered
|
|
10
|
-
import os from 'node:os'
|
|
11
|
-
import path from 'node:path'
|
|
12
|
-
import chalk from 'chalk'
|
|
13
|
-
import type { CommandMeta } from './commands/registry'
|
|
14
|
-
import { detectAllProviders, detectAntigravity } from './infrastructure/ai-provider'
|
|
15
|
-
import configManager from './infrastructure/config-manager'
|
|
16
|
-
import performanceTracker from './infrastructure/performance-tracker'
|
|
17
|
-
import { sessionTracker } from './services/session-tracker'
|
|
18
|
-
import { getErrorMessage, getErrorStack } from './types/fs'
|
|
19
|
-
import { getError } from './utils/error-messages'
|
|
20
|
-
import { fileExists } from './utils/fs-helpers'
|
|
21
|
-
import out from './utils/output'
|
|
22
|
-
|
|
23
|
-
interface ParsedCommandArgs {
|
|
24
|
-
parsedArgs: string[]
|
|
25
|
-
options: Record<string, string | boolean>
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
interface CommandResult {
|
|
29
|
-
success?: boolean
|
|
30
|
-
message?: string
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function main(): Promise<void> {
|
|
34
|
-
const [commandName, ...rawArgs] = process.argv.slice(2)
|
|
35
|
-
|
|
36
|
-
// === SPECIAL COMMANDS (version, help) ===
|
|
37
|
-
|
|
38
|
-
if (['-v', '--version', 'version'].includes(commandName)) {
|
|
39
|
-
const packageJson = await import('../package.json')
|
|
40
|
-
await displayVersion(packageJson.version)
|
|
41
|
-
process.exit(0)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (['-h', '--help', undefined].includes(commandName)) {
|
|
45
|
-
displayHelp()
|
|
46
|
-
process.exit(0)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// === DYNAMIC COMMAND EXECUTION ===
|
|
50
|
-
|
|
51
|
-
// Show branding header
|
|
52
|
-
out.start()
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
// 1. Find command in registry
|
|
56
|
-
const cmd = commandRegistry.getByName(commandName)
|
|
57
|
-
|
|
58
|
-
if (!cmd) {
|
|
59
|
-
const suggestion = findClosestCommand(commandName)
|
|
60
|
-
const hint = suggestion
|
|
61
|
-
? `Did you mean 'prjct ${suggestion}'? Run 'prjct --help' for all commands`
|
|
62
|
-
: "Run 'prjct --help' to see available commands"
|
|
63
|
-
out.failWithHint(
|
|
64
|
-
getError('UNKNOWN_COMMAND', { message: `Unknown command: ${commandName}`, hint })
|
|
65
|
-
)
|
|
66
|
-
out.end()
|
|
67
|
-
process.exit(1)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// 2. Check if deprecated
|
|
71
|
-
if (cmd.deprecated) {
|
|
72
|
-
const hint = cmd.replacedBy
|
|
73
|
-
? `Use 'prjct ${cmd.replacedBy}' instead`
|
|
74
|
-
: "Run 'prjct --help' to see available commands"
|
|
75
|
-
out.failWithHint({ message: `Command '${commandName}' is deprecated`, hint })
|
|
76
|
-
out.end()
|
|
77
|
-
process.exit(1)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// 3. Check if implemented
|
|
81
|
-
if (!cmd.implemented) {
|
|
82
|
-
out.failWithHint({
|
|
83
|
-
message: `Command '${commandName}' is not yet implemented`,
|
|
84
|
-
hint: "Run 'prjct --help' to see available commands",
|
|
85
|
-
docs: 'https://github.com/jlopezlira/prjct-cli',
|
|
86
|
-
})
|
|
87
|
-
out.end()
|
|
88
|
-
process.exit(1)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// 4. Parse arguments
|
|
92
|
-
const { parsedArgs, options } = parseCommandArgs(cmd, rawArgs)
|
|
93
|
-
|
|
94
|
-
// 4.5. Validate required params
|
|
95
|
-
const paramError = validateCommandParams(cmd, parsedArgs)
|
|
96
|
-
if (paramError) {
|
|
97
|
-
out.failWithHint(paramError)
|
|
98
|
-
out.end()
|
|
99
|
-
process.exit(1)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// 4.6. Session tracking — touch/create session before command execution
|
|
103
|
-
let projectId: string | null = null
|
|
104
|
-
const commandStartTime = Date.now()
|
|
105
|
-
try {
|
|
106
|
-
projectId = await configManager.getProjectId(process.cwd())
|
|
107
|
-
if (projectId) {
|
|
108
|
-
await sessionTracker.expireIfStale(projectId)
|
|
109
|
-
await sessionTracker.touch(projectId)
|
|
110
|
-
}
|
|
111
|
-
} catch {
|
|
112
|
-
// Session tracking is non-critical — silent fail
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// 5. Instantiate commands handler
|
|
116
|
-
const commands = new PrjctCommands()
|
|
117
|
-
|
|
118
|
-
// 6. Execute command
|
|
119
|
-
let result: CommandResult | undefined
|
|
120
|
-
|
|
121
|
-
// Commands with special option handling
|
|
122
|
-
if (commandName === 'design') {
|
|
123
|
-
const target = parsedArgs.join(' ')
|
|
124
|
-
result = await commands.design(target, options)
|
|
125
|
-
} else if (commandName === 'analyze') {
|
|
126
|
-
result = await commands.analyze(options)
|
|
127
|
-
} else if (commandName === 'cleanup') {
|
|
128
|
-
result = await commands.cleanup(options)
|
|
129
|
-
} else if (commandName === 'setup') {
|
|
130
|
-
result = await commands.setup(options)
|
|
131
|
-
} else {
|
|
132
|
-
// Standard commands - type-safe invocation
|
|
133
|
-
const param = parsedArgs.join(' ') || null
|
|
134
|
-
const standardCommands: Record<string, (p: string | null) => Promise<CommandResult>> = {
|
|
135
|
-
// Core workflow
|
|
136
|
-
done: () => commands.done(),
|
|
137
|
-
next: () => commands.next(),
|
|
138
|
-
pause: (p) => commands.pause(p || ''),
|
|
139
|
-
resume: (p) => commands.resume(p),
|
|
140
|
-
// Planning
|
|
141
|
-
init: (p) => commands.init(p),
|
|
142
|
-
bug: (p) => commands.bug(p || ''),
|
|
143
|
-
idea: (p) => commands.idea(p || ''),
|
|
144
|
-
spec: (p) => commands.spec(p),
|
|
145
|
-
ship: (p) => commands.ship(p),
|
|
146
|
-
// Analytics
|
|
147
|
-
dash: (p) => commands.dash(p || 'default'),
|
|
148
|
-
stats: () =>
|
|
149
|
-
commands.stats(process.cwd(), {
|
|
150
|
-
json: options.json === true,
|
|
151
|
-
export: options.export === true,
|
|
152
|
-
}),
|
|
153
|
-
status: () =>
|
|
154
|
-
commands.status(process.cwd(), {
|
|
155
|
-
json: options.json === true,
|
|
156
|
-
}),
|
|
157
|
-
help: (p) => commands.help(p || ''),
|
|
158
|
-
perf: (p) => commands.perf(p || '7'),
|
|
159
|
-
velocity: (p) => commands.velocity(p || '0'),
|
|
160
|
-
// Maintenance
|
|
161
|
-
recover: () => commands.recover(),
|
|
162
|
-
undo: () => commands.undo(),
|
|
163
|
-
redo: () => commands.redo(),
|
|
164
|
-
history: () => commands.history(),
|
|
165
|
-
// Setup
|
|
166
|
-
sync: () =>
|
|
167
|
-
commands.sync(process.cwd(), {
|
|
168
|
-
aiTools: options.agents ? String(options.agents).split(',') : undefined,
|
|
169
|
-
preview: options.preview === true || options['dry-run'] === true,
|
|
170
|
-
yes: options.yes === true,
|
|
171
|
-
json: options.json === true,
|
|
172
|
-
package: options.package ? String(options.package) : undefined,
|
|
173
|
-
full: options.full === true,
|
|
174
|
-
}),
|
|
175
|
-
seal: () => commands.seal(process.cwd(), { json: options.json === true }),
|
|
176
|
-
verify: () =>
|
|
177
|
-
commands.verify(process.cwd(), {
|
|
178
|
-
json: options.json === true,
|
|
179
|
-
semantic: options.semantic === true,
|
|
180
|
-
}),
|
|
181
|
-
start: () => commands.start(),
|
|
182
|
-
// Context (for Claude templates)
|
|
183
|
-
context: (p) => commands.context(p),
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const handler = standardCommands[commandName]
|
|
187
|
-
if (handler) {
|
|
188
|
-
result = await handler(param)
|
|
189
|
-
} else {
|
|
190
|
-
throw new Error(`Command '${commandName}' has no handler`)
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// 7. Track command in session + performance metrics
|
|
195
|
-
if (projectId) {
|
|
196
|
-
const durationMs = Date.now() - commandStartTime
|
|
197
|
-
try {
|
|
198
|
-
await sessionTracker.trackCommand(projectId, commandName, durationMs)
|
|
199
|
-
} catch {
|
|
200
|
-
// Non-critical
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Performance tracking (non-critical)
|
|
204
|
-
try {
|
|
205
|
-
// Record command duration
|
|
206
|
-
await performanceTracker.recordTiming(projectId, 'command_duration', durationMs, {
|
|
207
|
-
command: commandName,
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
// Record startup time (from bin/prjct.ts marker if available)
|
|
211
|
-
const perfStartNs = (globalThis as Record<string, unknown>).__perfStartNs as
|
|
212
|
-
| bigint
|
|
213
|
-
| undefined
|
|
214
|
-
if (perfStartNs) {
|
|
215
|
-
const startupMs = Number(process.hrtime.bigint() - perfStartNs) / 1_000_000
|
|
216
|
-
await performanceTracker.recordTiming(projectId, 'startup_time', startupMs)
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Record memory snapshot
|
|
220
|
-
await performanceTracker.recordMemory(projectId, { command: commandName })
|
|
221
|
-
} catch {
|
|
222
|
-
// Performance tracking is non-critical
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// 8. Display result
|
|
227
|
-
if (result?.message) {
|
|
228
|
-
console.log(result.message)
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Show branding footer
|
|
232
|
-
out.end()
|
|
233
|
-
process.exit(result?.success ? 0 : 1)
|
|
234
|
-
} catch (error) {
|
|
235
|
-
console.error('Error:', getErrorMessage(error))
|
|
236
|
-
if (process.env.DEBUG) {
|
|
237
|
-
console.error(getErrorStack(error))
|
|
238
|
-
}
|
|
239
|
-
// Show branding footer even on error
|
|
240
|
-
out.end()
|
|
241
|
-
process.exit(1)
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Validate that required params are provided
|
|
247
|
-
* Parses CommandMeta.params: <required> vs [optional]
|
|
248
|
-
*/
|
|
249
|
-
function validateCommandParams(
|
|
250
|
-
cmd: CommandMeta,
|
|
251
|
-
parsedArgs: string[]
|
|
252
|
-
): import('./utils/error-messages').ErrorWithHint | null {
|
|
253
|
-
if (!cmd.params) return null
|
|
254
|
-
|
|
255
|
-
// Extract required params: tokens wrapped in <angle brackets>
|
|
256
|
-
const requiredParams = cmd.params.match(/<[^>]+>/g)
|
|
257
|
-
if (!requiredParams || requiredParams.length === 0) return null
|
|
258
|
-
|
|
259
|
-
// Check if enough positional args provided
|
|
260
|
-
if (parsedArgs.length < requiredParams.length) {
|
|
261
|
-
const paramNames = requiredParams.map((p) => p.slice(1, -1)).join(', ')
|
|
262
|
-
const usage = cmd.usage.terminal || `prjct ${cmd.name} ${cmd.params}`
|
|
263
|
-
return getError('MISSING_PARAM', {
|
|
264
|
-
message: `Missing required parameter: ${paramNames}`,
|
|
265
|
-
hint: `Usage: ${usage}`,
|
|
266
|
-
})
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
return null
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* Find closest matching command name for did-you-mean suggestions
|
|
274
|
-
* Uses Levenshtein edit distance — suggests if distance <= 2
|
|
275
|
-
*/
|
|
276
|
-
function findClosestCommand(input: string): string | null {
|
|
277
|
-
const allNames = commandRegistry.getAll().map((c) => c.name)
|
|
278
|
-
let best: string | null = null
|
|
279
|
-
let bestDist = Infinity
|
|
280
|
-
|
|
281
|
-
for (const name of allNames) {
|
|
282
|
-
const dist = editDistance(input.toLowerCase(), name.toLowerCase())
|
|
283
|
-
if (dist < bestDist) {
|
|
284
|
-
bestDist = dist
|
|
285
|
-
best = name
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Only suggest if edit distance is at most 2
|
|
290
|
-
return bestDist <= 2 ? best : null
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
function editDistance(a: string, b: string): number {
|
|
294
|
-
const m = a.length
|
|
295
|
-
const n = b.length
|
|
296
|
-
const dp: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0))
|
|
297
|
-
for (let i = 0; i <= m; i++) dp[i][0] = i
|
|
298
|
-
for (let j = 0; j <= n; j++) dp[0][j] = j
|
|
299
|
-
for (let i = 1; i <= m; i++) {
|
|
300
|
-
for (let j = 1; j <= n; j++) {
|
|
301
|
-
dp[i][j] =
|
|
302
|
-
a[i - 1] === b[j - 1]
|
|
303
|
-
? dp[i - 1][j - 1]
|
|
304
|
-
: 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1])
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
return dp[m][n]
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* Parse command arguments dynamically
|
|
312
|
-
*/
|
|
313
|
-
function parseCommandArgs(_cmd: CommandMeta, rawArgs: string[]): ParsedCommandArgs {
|
|
314
|
-
const parsedArgs: string[] = []
|
|
315
|
-
const options: Record<string, string | boolean> = {}
|
|
316
|
-
|
|
317
|
-
for (let i = 0; i < rawArgs.length; i++) {
|
|
318
|
-
const arg = rawArgs[i]
|
|
319
|
-
|
|
320
|
-
if (arg.startsWith('--')) {
|
|
321
|
-
// Handle flags
|
|
322
|
-
const flagName = arg.slice(2)
|
|
323
|
-
|
|
324
|
-
// Check if next arg is a value
|
|
325
|
-
if (i + 1 < rawArgs.length && !rawArgs[i + 1].startsWith('--')) {
|
|
326
|
-
options[flagName] = rawArgs[++i]
|
|
327
|
-
} else {
|
|
328
|
-
options[flagName] = true
|
|
329
|
-
}
|
|
330
|
-
} else {
|
|
331
|
-
parsedArgs.push(arg)
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
return { parsedArgs, options }
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// Colors via chalk (respects NO_COLOR env)
|
|
339
|
-
|
|
340
|
-
/**
|
|
341
|
-
* Display version with provider status
|
|
342
|
-
*/
|
|
343
|
-
async function displayVersion(version: string): Promise<void> {
|
|
344
|
-
const detection = await detectAllProviders()
|
|
345
|
-
|
|
346
|
-
// Check if prjct commands are installed for each provider
|
|
347
|
-
const claudeCommandPath = path.join(os.homedir(), '.claude', 'commands', 'p.md')
|
|
348
|
-
const geminiCommandPath = path.join(os.homedir(), '.gemini', 'commands', 'p.toml')
|
|
349
|
-
const [claudeConfigured, geminiConfigured, cursorConfigured, cursorExists] = await Promise.all([
|
|
350
|
-
fileExists(claudeCommandPath),
|
|
351
|
-
fileExists(geminiCommandPath),
|
|
352
|
-
fileExists(path.join(process.cwd(), '.cursor', 'commands', 'sync.md')),
|
|
353
|
-
fileExists(path.join(process.cwd(), '.cursor')),
|
|
354
|
-
])
|
|
355
|
-
|
|
356
|
-
// Antigravity status (global, skills-based)
|
|
357
|
-
const antigravityDetection = await detectAntigravity()
|
|
358
|
-
|
|
359
|
-
console.log(`
|
|
360
|
-
${chalk.cyan('p/')} prjct v${version}
|
|
361
|
-
${chalk.dim('Context layer for AI coding agents')}
|
|
362
|
-
|
|
363
|
-
${chalk.dim('Providers:')}`)
|
|
364
|
-
|
|
365
|
-
// Claude status
|
|
366
|
-
if (detection.claude.installed) {
|
|
367
|
-
const status = claudeConfigured ? chalk.green('✓ ready') : chalk.yellow('● installed')
|
|
368
|
-
const ver = detection.claude.version ? ` (v${detection.claude.version})` : ''
|
|
369
|
-
console.log(` Claude Code ${status}${chalk.dim(ver)}`)
|
|
370
|
-
} else {
|
|
371
|
-
console.log(` Claude Code ${chalk.dim('○ not installed')}`)
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// Gemini status
|
|
375
|
-
if (detection.gemini.installed) {
|
|
376
|
-
const status = geminiConfigured ? chalk.green('✓ ready') : chalk.yellow('● installed')
|
|
377
|
-
const ver = detection.gemini.version ? ` (v${detection.gemini.version})` : ''
|
|
378
|
-
console.log(` Gemini CLI ${status}${chalk.dim(ver)}`)
|
|
379
|
-
} else {
|
|
380
|
-
console.log(` Gemini CLI ${chalk.dim('○ not installed')}`)
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
if (antigravityDetection.installed) {
|
|
384
|
-
const status = antigravityDetection.skillInstalled
|
|
385
|
-
? chalk.green('✓ ready')
|
|
386
|
-
: chalk.yellow('● detected')
|
|
387
|
-
const hint = antigravityDetection.skillInstalled ? '' : ` ${chalk.dim('(run prjct start)')}`
|
|
388
|
-
console.log(` Antigravity ${status}${hint}`)
|
|
389
|
-
} else {
|
|
390
|
-
console.log(` Antigravity ${chalk.dim('○ not installed')}`)
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// Cursor status (project-level, but shown in same format)
|
|
394
|
-
if (cursorConfigured) {
|
|
395
|
-
console.log(` Cursor IDE ${chalk.green('✓ ready')} ${chalk.dim('(use /sync, /task)')}`)
|
|
396
|
-
} else if (cursorExists) {
|
|
397
|
-
console.log(` Cursor IDE ${chalk.yellow('● detected')} ${chalk.dim('(run prjct init)')}`)
|
|
398
|
-
} else {
|
|
399
|
-
console.log(` Cursor IDE ${chalk.dim('○ no .cursor/ folder')}`)
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
console.log(`
|
|
403
|
-
${chalk.dim("Run 'prjct start' for Claude/Gemini, 'prjct init' for Cursor")}
|
|
404
|
-
${chalk.cyan('https://prjct.app')}
|
|
405
|
-
`)
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* Display help using registry
|
|
410
|
-
*/
|
|
411
|
-
function displayHelp(): void {
|
|
412
|
-
console.log(`
|
|
413
|
-
prjct - Context layer for AI coding agents
|
|
414
|
-
Works with Claude Code, Gemini CLI, Antigravity, Cursor IDE, and more.
|
|
415
|
-
|
|
416
|
-
QUICK START
|
|
417
|
-
-----------
|
|
418
|
-
Claude/Gemini:
|
|
419
|
-
1. prjct start Configure your AI provider
|
|
420
|
-
2. cd my-project && prjct init
|
|
421
|
-
3. Open in Claude Code or Gemini CLI
|
|
422
|
-
4. Type: p. sync Analyze project
|
|
423
|
-
|
|
424
|
-
Cursor IDE:
|
|
425
|
-
1. cd my-project && prjct init
|
|
426
|
-
2. Open in Cursor
|
|
427
|
-
3. Type: /sync Analyze project
|
|
428
|
-
|
|
429
|
-
COMMANDS (inside your AI agent)
|
|
430
|
-
-------------------------------
|
|
431
|
-
Claude/Gemini Cursor Description
|
|
432
|
-
─────────────────────────────────────────────────────
|
|
433
|
-
p. sync /sync Analyze project
|
|
434
|
-
p. task "desc" /task "desc" Start a task
|
|
435
|
-
p. done /done Complete subtask
|
|
436
|
-
p. ship "name" /ship "name" Ship with PR
|
|
437
|
-
|
|
438
|
-
TERMINAL COMMANDS (this CLI)
|
|
439
|
-
----------------------------
|
|
440
|
-
prjct start First-time setup (Claude/Gemini global config)
|
|
441
|
-
prjct init Initialize project (required for Cursor)
|
|
442
|
-
prjct setup Reconfigure installations
|
|
443
|
-
prjct sync Sync project state
|
|
444
|
-
prjct watch Auto-sync on file changes (Ctrl+C to stop)
|
|
445
|
-
prjct hooks Manage git hooks for auto-sync
|
|
446
|
-
prjct doctor Check system health and dependencies
|
|
447
|
-
|
|
448
|
-
EXAMPLES
|
|
449
|
-
--------
|
|
450
|
-
# Claude Code / Gemini CLI (global setup, then per-project)
|
|
451
|
-
$ prjct start
|
|
452
|
-
$ cd my-project && prjct init
|
|
453
|
-
> p. sync
|
|
454
|
-
> p. task "add user authentication"
|
|
455
|
-
|
|
456
|
-
# Cursor IDE (per-project only)
|
|
457
|
-
$ cd my-project && prjct init
|
|
458
|
-
> /sync
|
|
459
|
-
> /task "add user authentication"
|
|
460
|
-
|
|
461
|
-
FLAGS
|
|
462
|
-
-----
|
|
463
|
-
--quiet, -q Suppress all output (only errors to stderr)
|
|
464
|
-
--version, -v Show version
|
|
465
|
-
--help, -h Show this help
|
|
466
|
-
|
|
467
|
-
MORE INFO
|
|
468
|
-
---------
|
|
469
|
-
Documentation: https://prjct.app
|
|
470
|
-
GitHub: https://github.com/jlopezlira/prjct-cli
|
|
471
|
-
`)
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
// Run CLI
|
|
475
|
-
main().catch((error) => {
|
|
476
|
-
console.error('Fatal error:', getErrorMessage(error))
|
|
477
|
-
if (process.env.DEBUG) {
|
|
478
|
-
console.error(getErrorStack(error))
|
|
479
|
-
}
|
|
480
|
-
process.exit(1)
|
|
481
|
-
})
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Detector
|
|
3
|
-
* Detects Claude Code and Claude Desktop environments.
|
|
4
|
-
*
|
|
5
|
-
* @module infrastructure/agent-detector
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import path from 'node:path'
|
|
9
|
-
import type { DetectedAgent } from '../types'
|
|
10
|
-
import { fileExists } from '../utils/fs-helpers'
|
|
11
|
-
|
|
12
|
-
declare const global: typeof globalThis & {
|
|
13
|
-
mcp?: { filesystem?: unknown }
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// ============ Module State (for caching) ============
|
|
17
|
-
|
|
18
|
-
let cachedAgent: DetectedAgent | null = null
|
|
19
|
-
|
|
20
|
-
// ============ Agent Definitions ============
|
|
21
|
-
|
|
22
|
-
const CLAUDE_AGENT: DetectedAgent = {
|
|
23
|
-
type: 'claude',
|
|
24
|
-
name: 'Claude (Code + Desktop)',
|
|
25
|
-
isSupported: true,
|
|
26
|
-
capabilities: {
|
|
27
|
-
mcp: true,
|
|
28
|
-
filesystem: 'mcp',
|
|
29
|
-
markdown: true,
|
|
30
|
-
emojis: true,
|
|
31
|
-
colors: true,
|
|
32
|
-
interactive: true,
|
|
33
|
-
agents: true,
|
|
34
|
-
},
|
|
35
|
-
config: {
|
|
36
|
-
configFile: 'CLAUDE.md',
|
|
37
|
-
commandPrefix: '/p:',
|
|
38
|
-
responseStyle: 'rich',
|
|
39
|
-
dataDir: '.prjct',
|
|
40
|
-
agentsDir: '~/.claude/agents',
|
|
41
|
-
commandsDir: '~/.claude/commands/p',
|
|
42
|
-
},
|
|
43
|
-
environment: {
|
|
44
|
-
hasMCP: true,
|
|
45
|
-
sandboxed: false,
|
|
46
|
-
persistent: true,
|
|
47
|
-
agentSystem: true,
|
|
48
|
-
},
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const TERMINAL_AGENT: DetectedAgent = {
|
|
52
|
-
type: 'terminal',
|
|
53
|
-
name: 'Terminal/CLI',
|
|
54
|
-
isSupported: true,
|
|
55
|
-
capabilities: {
|
|
56
|
-
mcp: false,
|
|
57
|
-
filesystem: 'native',
|
|
58
|
-
markdown: false,
|
|
59
|
-
emojis: true,
|
|
60
|
-
colors: true,
|
|
61
|
-
interactive: true,
|
|
62
|
-
agents: false,
|
|
63
|
-
},
|
|
64
|
-
config: {
|
|
65
|
-
configFile: null,
|
|
66
|
-
commandPrefix: 'prjct',
|
|
67
|
-
responseStyle: 'cli',
|
|
68
|
-
dataDir: '.prjct',
|
|
69
|
-
agentsDir: null,
|
|
70
|
-
commandsDir: null,
|
|
71
|
-
},
|
|
72
|
-
environment: {
|
|
73
|
-
hasMCP: false,
|
|
74
|
-
sandboxed: false,
|
|
75
|
-
persistent: true,
|
|
76
|
-
agentSystem: false,
|
|
77
|
-
},
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// ============ Detection Functions ============
|
|
81
|
-
|
|
82
|
-
export async function isClaudeEnvironment(): Promise<boolean> {
|
|
83
|
-
// CLAUDE_AGENT / ANTHROPIC_CLAUDE: Set by Claude runtime to indicate agent environment
|
|
84
|
-
if (process.env.CLAUDE_AGENT || process.env.ANTHROPIC_CLAUDE) return true
|
|
85
|
-
|
|
86
|
-
// MCP_AVAILABLE: Set when Model Context Protocol is available
|
|
87
|
-
if (global.mcp || process.env.MCP_AVAILABLE) return true
|
|
88
|
-
|
|
89
|
-
// Configuration files
|
|
90
|
-
const projectRoot = process.cwd()
|
|
91
|
-
if (await fileExists(path.join(projectRoot, 'CLAUDE.md'))) return true
|
|
92
|
-
|
|
93
|
-
// Claude directory in home
|
|
94
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE || ''
|
|
95
|
-
if (await fileExists(path.join(homeDir, '.claude'))) return true
|
|
96
|
-
|
|
97
|
-
// Filesystem paths
|
|
98
|
-
const cwd = process.cwd()
|
|
99
|
-
if (cwd.includes('/.claude/') || cwd.includes('/claude-workspace/')) return true
|
|
100
|
-
|
|
101
|
-
return false
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export function getClaudeAgent(): DetectedAgent {
|
|
105
|
-
return { ...CLAUDE_AGENT }
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export function getTerminalAgent(): DetectedAgent {
|
|
109
|
-
return { ...TERMINAL_AGENT }
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export async function detect(): Promise<DetectedAgent> {
|
|
113
|
-
if (cachedAgent) return cachedAgent
|
|
114
|
-
|
|
115
|
-
cachedAgent = (await isClaudeEnvironment()) ? getClaudeAgent() : getTerminalAgent()
|
|
116
|
-
return cachedAgent
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function setAgent(type: string): DetectedAgent {
|
|
120
|
-
cachedAgent = type === 'claude' ? getClaudeAgent() : getTerminalAgent()
|
|
121
|
-
return cachedAgent
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export function reset(): void {
|
|
125
|
-
cachedAgent = null
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export async function isClaude(): Promise<boolean> {
|
|
129
|
-
if (cachedAgent) return cachedAgent.type === 'claude'
|
|
130
|
-
return isClaudeEnvironment()
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export async function isTerminal(): Promise<boolean> {
|
|
134
|
-
return !(await isClaude())
|
|
135
|
-
}
|