prjct-cli 0.11.5 → 0.12.1
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 +58 -0
- package/README.md +81 -25
- package/bin/dev.js +1 -1
- package/bin/generate-views.js +209 -0
- package/bin/migrate-to-json.js +742 -0
- package/bin/prjct +5 -5
- package/bin/serve.js +226 -50
- package/core/__tests__/agentic/{memory-system.test.js → memory-system.test.ts} +12 -23
- package/core/__tests__/agentic/{plan-mode.test.js → plan-mode.test.ts} +26 -24
- package/core/__tests__/agentic/{prompt-builder.test.js → prompt-builder.test.ts} +3 -8
- package/core/__tests__/utils/{date-helper.test.js → date-helper.test.ts} +19 -30
- package/core/__tests__/utils/{output.test.js → output.test.ts} +12 -24
- package/core/agentic/agent-router.ts +137 -0
- package/core/agentic/chain-of-thought.ts +228 -0
- package/core/agentic/command-executor/command-executor.ts +384 -0
- package/core/agentic/command-executor/index.ts +16 -0
- package/core/agentic/command-executor/status-signal.ts +38 -0
- package/core/agentic/command-executor/types.ts +79 -0
- package/core/agentic/command-executor.ts +8 -0
- package/core/agentic/{context-builder.js → context-builder.ts} +92 -81
- package/core/agentic/context-filter.ts +365 -0
- package/core/agentic/ground-truth/index.ts +76 -0
- package/core/agentic/ground-truth/types.ts +33 -0
- package/core/agentic/ground-truth/utils.ts +48 -0
- package/core/agentic/ground-truth/verifiers/analyze.ts +54 -0
- package/core/agentic/ground-truth/verifiers/done.ts +75 -0
- package/core/agentic/ground-truth/verifiers/feature.ts +70 -0
- package/core/agentic/ground-truth/verifiers/index.ts +37 -0
- package/core/agentic/ground-truth/verifiers/init.ts +52 -0
- package/core/agentic/ground-truth/verifiers/now.ts +57 -0
- package/core/agentic/ground-truth/verifiers/ship.ts +85 -0
- package/core/agentic/ground-truth/verifiers/spec.ts +45 -0
- package/core/agentic/ground-truth/verifiers/sync.ts +47 -0
- package/core/agentic/ground-truth/verifiers.ts +6 -0
- package/core/agentic/ground-truth.ts +8 -0
- package/core/agentic/loop-detector/error-analysis.ts +97 -0
- package/core/agentic/loop-detector/hallucination.ts +71 -0
- package/core/agentic/loop-detector/index.ts +41 -0
- package/core/agentic/loop-detector/loop-detector.ts +222 -0
- package/core/agentic/loop-detector/types.ts +66 -0
- package/core/agentic/loop-detector.ts +8 -0
- package/core/agentic/memory-system/history.ts +53 -0
- package/core/agentic/memory-system/index.ts +192 -0
- package/core/agentic/memory-system/patterns.ts +156 -0
- package/core/agentic/memory-system/semantic-memories.ts +277 -0
- package/core/agentic/memory-system/session.ts +21 -0
- package/core/agentic/memory-system/types.ts +159 -0
- package/core/agentic/memory-system.ts +8 -0
- package/core/agentic/parallel-tools.ts +165 -0
- package/core/agentic/plan-mode/approval.ts +57 -0
- package/core/agentic/plan-mode/constants.ts +44 -0
- package/core/agentic/plan-mode/index.ts +28 -0
- package/core/agentic/plan-mode/plan-mode.ts +406 -0
- package/core/agentic/plan-mode/types.ts +193 -0
- package/core/agentic/plan-mode.ts +8 -0
- package/core/agentic/prompt-builder.ts +566 -0
- package/core/agentic/response-templates.ts +164 -0
- package/core/agentic/semantic-compression.ts +273 -0
- package/core/agentic/services.ts +206 -0
- package/core/agentic/smart-context.ts +476 -0
- package/core/agentic/{template-loader.js → template-loader.ts} +27 -16
- package/core/agentic/think-blocks.ts +202 -0
- package/core/agentic/tool-registry.ts +119 -0
- package/core/agentic/validation-rules.ts +313 -0
- package/core/agents/index.ts +28 -0
- package/core/agents/performance.ts +444 -0
- package/core/agents/types.ts +126 -0
- package/core/bus/{index.js → index.ts} +57 -61
- package/core/command-registry/categories.ts +23 -0
- package/core/command-registry/commands.ts +15 -0
- package/core/command-registry/core-commands.ts +319 -0
- package/core/command-registry/index.ts +158 -0
- package/core/command-registry/optional-commands.ts +119 -0
- package/core/command-registry/setup-commands.ts +53 -0
- package/core/command-registry/types.ts +59 -0
- package/core/command-registry.ts +9 -0
- package/core/commands/analysis.ts +298 -0
- package/core/commands/analytics.ts +288 -0
- package/core/commands/base.ts +273 -0
- package/core/commands/index.ts +211 -0
- package/core/commands/maintenance.ts +226 -0
- package/core/commands/planning.ts +311 -0
- package/core/commands/setup.ts +309 -0
- package/core/commands/shipping.ts +188 -0
- package/core/commands/types.ts +183 -0
- package/core/commands/workflow.ts +226 -0
- package/core/commands.ts +11 -0
- package/core/constants/formats.ts +187 -0
- package/core/constants/index.ts +7 -0
- package/core/{context-sync.js → context-sync.ts} +59 -26
- package/core/data/agents-manager.ts +76 -0
- package/core/data/analysis-manager.ts +83 -0
- package/core/data/base-manager.ts +156 -0
- package/core/data/ideas-manager.ts +81 -0
- package/core/data/index.ts +32 -0
- package/core/data/outcomes-manager.ts +96 -0
- package/core/data/project-manager.ts +75 -0
- package/core/data/roadmap-manager.ts +118 -0
- package/core/data/shipped-manager.ts +65 -0
- package/core/data/state-manager.ts +214 -0
- package/core/domain/{agent-generator.js → agent-generator.ts} +77 -57
- package/core/domain/{agent-loader.js → agent-loader.ts} +65 -56
- package/core/domain/{agent-matcher.js → agent-matcher.ts} +51 -24
- package/core/domain/{agent-validator.js → agent-validator.ts} +70 -37
- package/core/domain/{analyzer.js → analyzer.ts} +91 -85
- package/core/domain/{architect-session.js → architect-session.ts} +49 -34
- package/core/domain/{architecture-generator.js → architecture-generator.ts} +25 -13
- package/core/domain/{context-estimator.js → context-estimator.ts} +57 -36
- package/core/domain/{product-standards.js → product-standards.ts} +40 -26
- package/core/domain/{smart-cache.js → smart-cache.ts} +39 -30
- package/core/domain/{snapshot-manager.js → snapshot-manager.ts} +103 -100
- package/core/domain/{task-analyzer.js → task-analyzer.ts} +82 -43
- package/core/domain/task-stack/index.ts +19 -0
- package/core/domain/task-stack/parser.ts +86 -0
- package/core/domain/task-stack/storage.ts +123 -0
- package/core/domain/task-stack/task-stack.ts +340 -0
- package/core/domain/task-stack/types.ts +51 -0
- package/core/domain/task-stack.ts +8 -0
- package/core/{index.js → index.ts} +61 -18
- package/core/infrastructure/{agent-detector.js → agent-detector.ts} +55 -19
- package/core/infrastructure/agents/{claude-agent.js → claude-agent.ts} +61 -21
- package/core/infrastructure/{author-detector.js → author-detector.ts} +42 -49
- package/core/infrastructure/{capability-installer.js → capability-installer.ts} +51 -27
- package/core/infrastructure/{command-installer.js → command-installer/command-installer.ts} +43 -144
- package/core/infrastructure/command-installer/global-config.ts +106 -0
- package/core/infrastructure/command-installer/index.ts +25 -0
- package/core/infrastructure/command-installer/types.ts +41 -0
- package/core/infrastructure/command-installer.ts +8 -0
- package/core/infrastructure/{config-manager.js → config-manager.ts} +60 -80
- package/core/infrastructure/{editors-config.js → editors-config.ts} +33 -31
- package/core/infrastructure/legacy-installer-detector/cleanup.ts +216 -0
- package/core/infrastructure/legacy-installer-detector/detection.ts +95 -0
- package/core/infrastructure/legacy-installer-detector/index.ts +171 -0
- package/core/infrastructure/legacy-installer-detector/migration.ts +87 -0
- package/core/infrastructure/legacy-installer-detector/types.ts +42 -0
- package/core/infrastructure/legacy-installer-detector.ts +7 -0
- package/core/infrastructure/migrator/file-operations.ts +125 -0
- package/core/infrastructure/migrator/index.ts +288 -0
- package/core/infrastructure/migrator/project-scanner.ts +89 -0
- package/core/infrastructure/migrator/reports.ts +117 -0
- package/core/infrastructure/migrator/types.ts +124 -0
- package/core/infrastructure/migrator/validation.ts +94 -0
- package/core/infrastructure/migrator/version-migration.ts +117 -0
- package/core/infrastructure/migrator.ts +10 -0
- package/core/infrastructure/{path-manager.js → path-manager.ts} +51 -91
- package/core/infrastructure/session-manager/index.ts +23 -0
- package/core/infrastructure/session-manager/migration.ts +88 -0
- package/core/infrastructure/session-manager/session-manager.ts +307 -0
- package/core/infrastructure/session-manager/types.ts +45 -0
- package/core/infrastructure/session-manager.ts +8 -0
- package/core/infrastructure/{setup.js → setup.ts} +29 -21
- package/core/infrastructure/{update-checker.js → update-checker.ts} +40 -18
- package/core/outcomes/analyzer.ts +333 -0
- package/core/outcomes/index.ts +34 -0
- package/core/outcomes/recorder.ts +194 -0
- package/core/outcomes/types.ts +145 -0
- package/core/plugin/{hooks.js → hooks.ts} +56 -58
- package/core/plugin/{index.js → index.ts} +19 -8
- package/core/plugin/{loader.js → loader.ts} +87 -69
- package/core/plugin/{registry.js → registry.ts} +49 -45
- package/core/plugins/{webhook.js → webhook.ts} +43 -27
- package/core/schemas/agents.ts +27 -0
- package/core/schemas/analysis.ts +41 -0
- package/core/schemas/ideas.ts +83 -0
- package/core/schemas/index.ts +73 -0
- package/core/schemas/outcomes.ts +22 -0
- package/core/schemas/project.ts +26 -0
- package/core/schemas/roadmap.ts +90 -0
- package/core/schemas/shipped.ts +82 -0
- package/core/schemas/state.ts +107 -0
- package/core/session/index.ts +17 -0
- package/core/session/{metrics.js → metrics.ts} +64 -46
- package/core/session/{index.js → session-manager.ts} +51 -117
- package/core/session/types.ts +29 -0
- package/core/session/utils.ts +57 -0
- package/core/state/index.ts +25 -0
- package/core/state/manager.ts +376 -0
- package/core/state/types.ts +185 -0
- package/core/tsconfig.json +22 -0
- package/core/types/index.ts +506 -0
- package/core/utils/{animations.js → animations.ts} +74 -28
- package/core/utils/{branding.js → branding.ts} +29 -4
- package/core/utils/{date-helper.js → date-helper.ts} +31 -74
- package/core/utils/file-helper.ts +262 -0
- package/core/utils/{jsonl-helper.js → jsonl-helper.ts} +71 -107
- package/core/utils/{logger.js → logger.ts} +24 -12
- package/core/utils/{output.js → output.ts} +25 -13
- package/core/utils/{project-capabilities.js → project-capabilities.ts} +31 -18
- package/core/utils/{session-helper.js → session-helper.ts} +79 -66
- package/core/utils/{version.js → version.ts} +23 -31
- package/core/view-generator.ts +536 -0
- package/package.json +23 -17
- package/packages/shared/.turbo/turbo-build.log +14 -0
- package/packages/shared/dist/index.d.ts +8 -613
- package/packages/shared/dist/index.d.ts.map +1 -0
- package/packages/shared/dist/index.js +4110 -118
- package/packages/shared/dist/schemas.d.ts +408 -0
- package/packages/shared/dist/schemas.d.ts.map +1 -0
- package/packages/shared/dist/types.d.ts +144 -0
- package/packages/shared/dist/types.d.ts.map +1 -0
- package/packages/shared/dist/unified.d.ts +139 -0
- package/packages/shared/dist/unified.d.ts.map +1 -0
- package/packages/shared/dist/utils.d.ts +60 -0
- package/packages/shared/dist/utils.d.ts.map +1 -0
- package/packages/shared/package.json +4 -4
- package/packages/shared/src/index.ts +1 -0
- package/packages/shared/src/unified.ts +174 -0
- package/packages/web/app/api/claude/sessions/route.ts +1 -1
- package/packages/web/app/api/claude/status/route.ts +1 -1
- package/packages/web/app/api/migrate/route.ts +46 -0
- package/packages/web/app/api/projects/[id]/route.ts +1 -1
- package/packages/web/app/api/projects/[id]/stats/route.ts +30 -2
- package/packages/web/app/api/projects/[id]/status/route.ts +1 -1
- package/packages/web/app/api/projects/route.ts +1 -1
- package/packages/web/app/api/settings/route.ts +97 -0
- package/packages/web/app/api/v2/projects/[id]/unified/route.ts +57 -0
- package/packages/web/app/globals.css +38 -0
- package/packages/web/app/layout.tsx +10 -2
- package/packages/web/app/page.tsx +9 -224
- package/packages/web/app/project/[id]/page.tsx +191 -63
- package/packages/web/app/project/[id]/stats/loading.tsx +43 -0
- package/packages/web/app/project/[id]/stats/page.tsx +204 -163
- package/packages/web/app/settings/page.tsx +222 -2
- package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +2 -0
- package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +50 -0
- package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +8 -0
- package/packages/web/components/ActivityTimeline/hooks/index.ts +2 -0
- package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +9 -0
- package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +23 -0
- package/packages/web/components/ActivityTimeline/index.ts +2 -0
- package/packages/web/components/AgentsCard/AgentsCard.tsx +63 -0
- package/packages/web/components/AgentsCard/AgentsCard.types.ts +13 -0
- package/packages/web/components/AgentsCard/index.ts +2 -0
- package/packages/web/components/AppSidebar/AppSidebar.tsx +190 -0
- package/packages/web/components/AppSidebar/index.ts +1 -0
- package/packages/web/components/BackLink/BackLink.tsx +18 -0
- package/packages/web/components/BackLink/BackLink.types.ts +5 -0
- package/packages/web/components/BackLink/index.ts +2 -0
- package/packages/web/components/BentoCard/BentoCard.constants.ts +16 -0
- package/packages/web/components/BentoCard/BentoCard.tsx +47 -0
- package/packages/web/components/BentoCard/BentoCard.types.ts +15 -0
- package/packages/web/components/BentoCard/index.ts +2 -0
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +9 -0
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +18 -0
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +5 -0
- package/packages/web/components/BentoCardSkeleton/index.ts +2 -0
- package/packages/web/components/{stats → BentoGrid}/BentoGrid.tsx +4 -8
- package/packages/web/components/BentoGrid/BentoGrid.types.ts +4 -0
- package/packages/web/components/BentoGrid/index.ts +2 -0
- package/packages/web/components/CommandButton/index.ts +1 -0
- package/packages/web/components/ConnectionStatus/index.ts +1 -0
- package/packages/web/components/DashboardContent/DashboardContent.tsx +254 -0
- package/packages/web/components/DashboardContent/index.ts +1 -0
- package/packages/web/components/DateGroup/DateGroup.tsx +18 -0
- package/packages/web/components/DateGroup/DateGroup.types.ts +6 -0
- package/packages/web/components/DateGroup/DateGroup.utils.ts +11 -0
- package/packages/web/components/DateGroup/index.ts +2 -0
- package/packages/web/components/{stats → EmptyState}/EmptyState.tsx +1 -10
- package/packages/web/components/EmptyState/EmptyState.types.ts +10 -0
- package/packages/web/components/EmptyState/index.ts +2 -0
- package/packages/web/components/EventRow/EventRow.constants.ts +10 -0
- package/packages/web/components/EventRow/EventRow.tsx +49 -0
- package/packages/web/components/EventRow/EventRow.types.ts +7 -0
- package/packages/web/components/EventRow/EventRow.utils.ts +49 -0
- package/packages/web/components/EventRow/index.ts +2 -0
- package/packages/web/components/ExpandButton/ExpandButton.tsx +18 -0
- package/packages/web/components/ExpandButton/ExpandButton.types.ts +6 -0
- package/packages/web/components/ExpandButton/index.ts +2 -0
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +14 -0
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +5 -0
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +13 -0
- package/packages/web/components/HealthGradientBackground/index.ts +2 -0
- package/packages/web/components/HeroSection/HeroSection.tsx +55 -0
- package/packages/web/components/HeroSection/HeroSection.types.ts +14 -0
- package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -0
- package/packages/web/components/HeroSection/hooks/index.ts +2 -0
- package/packages/web/components/HeroSection/hooks/useCountUp.ts +45 -0
- package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +18 -0
- package/packages/web/components/HeroSection/index.ts +2 -0
- package/packages/web/components/{stats → IdeasCard}/IdeasCard.tsx +3 -14
- package/packages/web/components/IdeasCard/IdeasCard.types.ts +9 -0
- package/packages/web/components/IdeasCard/index.ts +2 -0
- package/packages/web/components/InsightMessage/InsightMessage.tsx +9 -0
- package/packages/web/components/InsightMessage/InsightMessage.types.ts +3 -0
- package/packages/web/components/InsightMessage/index.ts +2 -0
- package/packages/web/components/Logo/index.ts +1 -0
- package/packages/web/components/MarkdownContent/index.ts +1 -0
- package/packages/web/components/NowCard/NowCard.tsx +93 -0
- package/packages/web/components/NowCard/NowCard.types.ts +15 -0
- package/packages/web/components/NowCard/index.ts +2 -0
- package/packages/web/components/ProgressRing/ProgressRing.constants.ts +20 -0
- package/packages/web/components/{stats → ProgressRing}/ProgressRing.tsx +4 -27
- package/packages/web/components/ProgressRing/ProgressRing.types.ts +11 -0
- package/packages/web/components/ProgressRing/index.ts +2 -0
- package/packages/web/components/ProjectAvatar/index.ts +1 -0
- package/packages/web/components/Providers/index.ts +1 -0
- package/packages/web/components/QueueCard/QueueCard.tsx +72 -0
- package/packages/web/components/QueueCard/QueueCard.types.ts +11 -0
- package/packages/web/components/QueueCard/QueueCard.utils.ts +12 -0
- package/packages/web/components/QueueCard/index.ts +2 -0
- package/packages/web/components/{stats → RoadmapCard}/RoadmapCard.tsx +3 -23
- package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
- package/packages/web/components/RoadmapCard/index.ts +2 -0
- package/packages/web/components/{stats → ShipsCard}/ShipsCard.tsx +4 -22
- package/packages/web/components/ShipsCard/ShipsCard.types.ts +12 -0
- package/packages/web/components/ShipsCard/ShipsCard.utils.ts +4 -0
- package/packages/web/components/ShipsCard/index.ts +2 -0
- package/packages/web/components/{stats → SparklineChart}/SparklineChart.tsx +1 -7
- package/packages/web/components/SparklineChart/SparklineChart.types.ts +6 -0
- package/packages/web/components/SparklineChart/index.ts +2 -0
- package/packages/web/components/StreakCard/StreakCard.constants.ts +2 -0
- package/packages/web/components/{stats → StreakCard}/StreakCard.tsx +5 -11
- package/packages/web/components/StreakCard/StreakCard.types.ts +4 -0
- package/packages/web/components/StreakCard/index.ts +2 -0
- package/packages/web/components/TasksCounter/TasksCounter.tsx +14 -0
- package/packages/web/components/TasksCounter/TasksCounter.types.ts +3 -0
- package/packages/web/components/TasksCounter/index.ts +2 -0
- package/packages/web/components/TechStackBadges/index.ts +1 -0
- package/packages/web/components/{TerminalTab.tsx → TerminalTabs/TerminalTab.tsx} +11 -0
- package/packages/web/components/{TerminalTabs.tsx → TerminalTabs/TerminalTabs.tsx} +29 -28
- package/packages/web/components/TerminalTabs/index.ts +1 -0
- package/packages/web/components/VelocityBadge/VelocityBadge.tsx +27 -0
- package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +3 -0
- package/packages/web/components/VelocityBadge/index.ts +2 -0
- package/packages/web/components/VelocityCard/VelocityCard.tsx +71 -0
- package/packages/web/components/VelocityCard/VelocityCard.types.ts +7 -0
- package/packages/web/components/VelocityCard/index.ts +2 -0
- package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +13 -0
- package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +3 -0
- package/packages/web/components/WeeklySparkline/index.ts +2 -0
- package/packages/web/components/ui/input.tsx +21 -0
- package/packages/web/context/TerminalTabsContext.tsx +46 -1
- package/packages/web/hooks/useClaudeTerminal.ts +71 -21
- package/packages/web/hooks/useProjectStats.ts +55 -0
- package/packages/web/hooks/useProjects.ts +6 -6
- package/packages/web/lib/actions/projects.ts +15 -0
- package/packages/web/lib/json-loader.ts +630 -0
- package/packages/web/lib/services/index.ts +9 -0
- package/packages/web/lib/services/migration.server.ts +600 -0
- package/packages/web/lib/services/projects.server.ts +52 -0
- package/packages/web/lib/services/stats.server.ts +264 -0
- package/packages/web/lib/unified-loader.ts +396 -0
- package/packages/web/package.json +10 -7
- package/packages/web/server.ts +58 -8
- package/templates/commands/done.md +76 -32
- package/templates/commands/feature.md +121 -47
- package/templates/commands/idea.md +81 -8
- package/templates/commands/now.md +41 -17
- package/templates/commands/ship.md +64 -25
- package/templates/commands/sync.md +28 -3
- package/core/agentic/agent-router.js +0 -140
- package/core/agentic/chain-of-thought.js +0 -578
- package/core/agentic/command-executor.js +0 -417
- package/core/agentic/context-filter.js +0 -354
- package/core/agentic/ground-truth.js +0 -591
- package/core/agentic/loop-detector.js +0 -406
- package/core/agentic/memory-system.js +0 -845
- package/core/agentic/parallel-tools.js +0 -366
- package/core/agentic/plan-mode.js +0 -572
- package/core/agentic/prompt-builder.js +0 -352
- package/core/agentic/response-templates.js +0 -290
- package/core/agentic/semantic-compression.js +0 -517
- package/core/agentic/think-blocks.js +0 -657
- package/core/agentic/tool-registry.js +0 -184
- package/core/agentic/validation-rules.js +0 -380
- package/core/command-registry.js +0 -698
- package/core/commands.js +0 -2237
- package/core/domain/task-stack.js +0 -497
- package/core/infrastructure/legacy-installer-detector.js +0 -546
- package/core/infrastructure/migrator.js +0 -796
- package/core/infrastructure/session-manager.js +0 -390
- package/core/utils/file-helper.js +0 -329
- package/packages/web/app/api/projects/[id]/delete/route.ts +0 -21
- package/packages/web/app/api/stats/route.ts +0 -38
- package/packages/web/components/AppSidebar.tsx +0 -113
- package/packages/web/components/stats/ActivityTimeline.tsx +0 -201
- package/packages/web/components/stats/AgentsCard.tsx +0 -56
- package/packages/web/components/stats/BentoCard.tsx +0 -88
- package/packages/web/components/stats/HeroSection.tsx +0 -172
- package/packages/web/components/stats/NowCard.tsx +0 -71
- package/packages/web/components/stats/QueueCard.tsx +0 -58
- package/packages/web/components/stats/VelocityCard.tsx +0 -60
- package/packages/web/components/stats/index.ts +0 -17
- package/packages/web/hooks/useStats.ts +0 -28
- /package/packages/web/components/{CommandButton.tsx → CommandButton/CommandButton.tsx} +0 -0
- /package/packages/web/components/{ConnectionStatus.tsx → ConnectionStatus/ConnectionStatus.tsx} +0 -0
- /package/packages/web/components/{Logo.tsx → Logo/Logo.tsx} +0 -0
- /package/packages/web/components/{MarkdownContent.tsx → MarkdownContent/MarkdownContent.tsx} +0 -0
- /package/packages/web/components/{ProjectAvatar.tsx → ProjectAvatar/ProjectAvatar.tsx} +0 -0
- /package/packages/web/components/{providers.tsx → Providers/Providers.tsx} +0 -0
- /package/packages/web/components/{TechStackBadges.tsx → TechStackBadges/TechStackBadges.tsx} +0 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Planning Commands: init, feature, bug, architect
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import path from 'path'
|
|
6
|
+
|
|
7
|
+
import type { CommandResult, AnalyzeOptions, Context } from './types'
|
|
8
|
+
import {
|
|
9
|
+
PrjctCommandsBase,
|
|
10
|
+
contextBuilder,
|
|
11
|
+
toolRegistry,
|
|
12
|
+
pathManager,
|
|
13
|
+
configManager,
|
|
14
|
+
fileHelper,
|
|
15
|
+
dateHelper,
|
|
16
|
+
out
|
|
17
|
+
} from './base'
|
|
18
|
+
import authorDetector from '../infrastructure/author-detector'
|
|
19
|
+
|
|
20
|
+
export class PlanningCommands extends PrjctCommandsBase {
|
|
21
|
+
/**
|
|
22
|
+
* /p:init - Initialize prjct project
|
|
23
|
+
*/
|
|
24
|
+
async init(idea: string | null = null, projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
25
|
+
try {
|
|
26
|
+
await this.initializeAgent()
|
|
27
|
+
|
|
28
|
+
const isConfigured = await configManager.isConfigured(projectPath)
|
|
29
|
+
|
|
30
|
+
if (isConfigured) {
|
|
31
|
+
out.warn('already initialized')
|
|
32
|
+
return { success: false, message: 'Already initialized' }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
out.spin('initializing...')
|
|
36
|
+
|
|
37
|
+
const detectedAuthor = await authorDetector.detect()
|
|
38
|
+
// Convert null to undefined for createConfig
|
|
39
|
+
const author = {
|
|
40
|
+
name: detectedAuthor.name || undefined,
|
|
41
|
+
email: detectedAuthor.email || undefined,
|
|
42
|
+
github: detectedAuthor.github || undefined
|
|
43
|
+
}
|
|
44
|
+
const config = await configManager.createConfig(projectPath, author)
|
|
45
|
+
const projectId = config.projectId
|
|
46
|
+
|
|
47
|
+
out.spin('creating structure...')
|
|
48
|
+
|
|
49
|
+
await pathManager.ensureProjectStructure(projectId)
|
|
50
|
+
const globalPath = pathManager.getGlobalProjectPath(projectId)
|
|
51
|
+
|
|
52
|
+
const baseFiles: Record<string, string> = {
|
|
53
|
+
'core/now.md': '# NOW\n\nNo current task. Use `/p:now` to set focus.\n',
|
|
54
|
+
'core/next.md': '# NEXT\n\n## Priority Queue\n\n',
|
|
55
|
+
'core/context.md': '# CONTEXT\n\n',
|
|
56
|
+
'progress/shipped.md': '# SHIPPED 🚀\n\n',
|
|
57
|
+
'progress/metrics.md': '# METRICS\n\n',
|
|
58
|
+
'planning/ideas.md': '# IDEAS 💡\n\n## Brain Dump\n\n',
|
|
59
|
+
'planning/roadmap.md': '# ROADMAP\n\n',
|
|
60
|
+
'planning/specs/.gitkeep': '# Specs directory - created by /p:spec\n',
|
|
61
|
+
'memory/context.jsonl': '',
|
|
62
|
+
'memory/patterns.json': JSON.stringify({
|
|
63
|
+
version: 1,
|
|
64
|
+
decisions: {},
|
|
65
|
+
preferences: {},
|
|
66
|
+
workflows: {},
|
|
67
|
+
counters: {}
|
|
68
|
+
}, null, 2),
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
for (const [filePath, content] of Object.entries(baseFiles)) {
|
|
72
|
+
await toolRegistry.get('Write')!(path.join(globalPath, filePath), content)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const isEmpty = await this._detectEmptyDirectory(projectPath)
|
|
76
|
+
const hasCode = await this._detectExistingCode(projectPath)
|
|
77
|
+
|
|
78
|
+
if (hasCode || !isEmpty) {
|
|
79
|
+
out.spin('analyzing project...')
|
|
80
|
+
const analysisResult = await (this as unknown as { analyze: (options: AnalyzeOptions, projectPath: string) => Promise<CommandResult> }).analyze({}, projectPath)
|
|
81
|
+
|
|
82
|
+
if (analysisResult.success) {
|
|
83
|
+
out.spin('generating agents...')
|
|
84
|
+
await (this as unknown as { sync: (projectPath: string) => Promise<CommandResult> }).sync(projectPath)
|
|
85
|
+
out.done('initialized')
|
|
86
|
+
return { success: true, mode: 'existing', projectId }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (isEmpty && !hasCode) {
|
|
91
|
+
if (!idea) {
|
|
92
|
+
out.done('blank project - provide idea for architect mode')
|
|
93
|
+
return { success: true, mode: 'blank_no_idea', projectId }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
out.spin('architect mode...')
|
|
97
|
+
const sessionPath = path.join(globalPath, 'planning', 'architect-session.md')
|
|
98
|
+
const sessionContent = `# Architect Session\n\n## Idea\n${idea}\n\n## Status\nInitialized - awaiting stack recommendation\n\nGenerated: ${new Date().toLocaleString()}\n`
|
|
99
|
+
await toolRegistry.get('Write')!(sessionPath, sessionContent)
|
|
100
|
+
|
|
101
|
+
const commandInstaller = require('../infrastructure/command-installer')
|
|
102
|
+
await commandInstaller.installGlobalConfig()
|
|
103
|
+
|
|
104
|
+
out.done('architect mode ready')
|
|
105
|
+
return { success: true, mode: 'architect', projectId, idea }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const commandInstaller = require('../infrastructure/command-installer')
|
|
109
|
+
await commandInstaller.installGlobalConfig()
|
|
110
|
+
|
|
111
|
+
out.done('initialized')
|
|
112
|
+
return { success: true, projectId }
|
|
113
|
+
} catch (error) {
|
|
114
|
+
out.fail((error as Error).message)
|
|
115
|
+
return { success: false, error: (error as Error).message }
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* /p:feature - Add feature with value analysis, roadmap, and task breakdown
|
|
121
|
+
*/
|
|
122
|
+
async feature(description: string, projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
123
|
+
try {
|
|
124
|
+
const initResult = await this.ensureProjectInit(projectPath)
|
|
125
|
+
if (!initResult.success) return initResult
|
|
126
|
+
|
|
127
|
+
if (!description) {
|
|
128
|
+
out.fail('description required')
|
|
129
|
+
return { success: false, error: 'Description required' }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
out.spin(`planning ${description}...`)
|
|
133
|
+
|
|
134
|
+
const context = await contextBuilder.build(projectPath, { description }) as Context
|
|
135
|
+
const tasks = this._breakdownFeatureTasks(description)
|
|
136
|
+
|
|
137
|
+
const tasksWithAgents: { task: string; agent: string }[] = []
|
|
138
|
+
for (const taskDesc of tasks) {
|
|
139
|
+
const agentResult = await this._assignAgentForTask(taskDesc, projectPath, context)
|
|
140
|
+
const agent = agentResult.agent?.name || 'generalist'
|
|
141
|
+
tasksWithAgents.push({ task: taskDesc, agent })
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const nextContent =
|
|
145
|
+
(await toolRegistry.get('Read')!(context.paths.next) as string) || '# NEXT\n\n## Priority Queue\n\n'
|
|
146
|
+
const taskSection =
|
|
147
|
+
`\n## Feature: ${description}\n\n` +
|
|
148
|
+
tasksWithAgents.map((t, i) => `${i + 1}. [${t.agent}] [ ] ${t.task}`).join('\n') +
|
|
149
|
+
`\n\nEstimated: ${tasks.length * 2}h\n`
|
|
150
|
+
|
|
151
|
+
await toolRegistry.get('Write')!(context.paths.next, nextContent + taskSection)
|
|
152
|
+
|
|
153
|
+
await this.logToMemory(projectPath, 'feature_planned', {
|
|
154
|
+
feature: description,
|
|
155
|
+
tasks: tasksWithAgents.length,
|
|
156
|
+
assignments: tasksWithAgents.map(t => ({ task: t.task, agent: t.agent })),
|
|
157
|
+
timestamp: dateHelper.getTimestamp(),
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
const agentCounts = tasksWithAgents.reduce((acc: Record<string, number>, t) => {
|
|
161
|
+
acc[t.agent] = (acc[t.agent] || 0) + 1
|
|
162
|
+
return acc
|
|
163
|
+
}, {})
|
|
164
|
+
const agentSummary = Object.entries(agentCounts).map(([a, c]) => `${a}:${c}`).join(' ')
|
|
165
|
+
|
|
166
|
+
out.done(`${tasks.length} tasks [${agentSummary}]`)
|
|
167
|
+
|
|
168
|
+
return { success: true, feature: description, tasks: tasksWithAgents }
|
|
169
|
+
} catch (error) {
|
|
170
|
+
out.fail((error as Error).message)
|
|
171
|
+
return { success: false, error: (error as Error).message }
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* /p:bug - Report and track bugs with auto-prioritization
|
|
177
|
+
*/
|
|
178
|
+
async bug(description: string, projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
179
|
+
try {
|
|
180
|
+
const initResult = await this.ensureProjectInit(projectPath)
|
|
181
|
+
if (!initResult.success) return initResult
|
|
182
|
+
|
|
183
|
+
if (!description) {
|
|
184
|
+
out.fail('bug description required')
|
|
185
|
+
return { success: false, error: 'Description required' }
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
out.spin('tracking bug...')
|
|
189
|
+
|
|
190
|
+
const context = await contextBuilder.build(projectPath, { description }) as Context
|
|
191
|
+
const severity = this._detectBugSeverity(description)
|
|
192
|
+
|
|
193
|
+
const agentResult = await this._assignAgentForTask(`fix bug: ${description}`, projectPath, context)
|
|
194
|
+
const agent = agentResult.agent?.name || 'generalist'
|
|
195
|
+
|
|
196
|
+
const nextContent =
|
|
197
|
+
(await toolRegistry.get('Read')!(context.paths.next) as string) || '# NEXT\n\n## Priority Queue\n\n'
|
|
198
|
+
const bugEntry = `\n## 🐛 BUG [${severity.toUpperCase()}] [${agent}]: ${description}\n\nReported: ${new Date().toLocaleString()}\nPriority: ${severity === 'critical' ? '⚠️ URGENT' : severity === 'high' ? '🔴 High' : '🟡 Normal'}\nAssigned: ${agent}\n`
|
|
199
|
+
|
|
200
|
+
const updatedContent =
|
|
201
|
+
severity === 'critical' || severity === 'high'
|
|
202
|
+
? nextContent.replace('## Priority Queue\n\n', `## Priority Queue\n\n${bugEntry}\n`)
|
|
203
|
+
: nextContent + bugEntry
|
|
204
|
+
|
|
205
|
+
await toolRegistry.get('Write')!(context.paths.next, updatedContent)
|
|
206
|
+
|
|
207
|
+
await this.logToMemory(projectPath, 'bug_reported', {
|
|
208
|
+
bug: description,
|
|
209
|
+
severity,
|
|
210
|
+
agent,
|
|
211
|
+
timestamp: dateHelper.getTimestamp(),
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
out.done(`bug [${severity}] → ${agent}`)
|
|
215
|
+
|
|
216
|
+
return { success: true, bug: description, severity, agent }
|
|
217
|
+
} catch (error) {
|
|
218
|
+
out.fail((error as Error).message)
|
|
219
|
+
return { success: false, error: (error as Error).message }
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* /p:architect - Execute architect plan and generate code
|
|
225
|
+
*/
|
|
226
|
+
async architect(action: string = 'execute', projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
227
|
+
if (action !== 'execute') {
|
|
228
|
+
return {
|
|
229
|
+
success: false,
|
|
230
|
+
message: '❌ Invalid action. Use: /p:architect execute',
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
const initResult = await this.ensureProjectInit(projectPath)
|
|
236
|
+
if (!initResult.success) return initResult
|
|
237
|
+
|
|
238
|
+
console.log('🏗️ Architect Mode - Code Generation\n')
|
|
239
|
+
|
|
240
|
+
const globalPath = await this.getGlobalProjectPath(projectPath)
|
|
241
|
+
const planPath = path.join(globalPath, 'planning', 'architect-session.md')
|
|
242
|
+
|
|
243
|
+
let planContent: string
|
|
244
|
+
try {
|
|
245
|
+
planContent = await fileHelper.readFile(planPath)
|
|
246
|
+
} catch {
|
|
247
|
+
return {
|
|
248
|
+
success: false,
|
|
249
|
+
message:
|
|
250
|
+
'❌ No architect plan found.\n\n' +
|
|
251
|
+
'Create a plan first:\n' +
|
|
252
|
+
' 1. Run /p:init in an empty directory\n' +
|
|
253
|
+
' 2. Answer the discovery questions\n' +
|
|
254
|
+
' 3. Plan will be auto-generated\n' +
|
|
255
|
+
' 4. Then run /p:architect execute',
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (!planContent || planContent.trim() === '') {
|
|
260
|
+
return {
|
|
261
|
+
success: false,
|
|
262
|
+
message: '❌ Architect plan is empty',
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
console.log('📋 Reading architect plan...\n')
|
|
267
|
+
|
|
268
|
+
const ideaMatch = planContent.match(/## Project Idea\n(.+)/s)
|
|
269
|
+
const stackMatch = planContent.match(/\*\*Stack:\*\*\n([\s\S]+?)\n\n/)
|
|
270
|
+
const stepsMatch = planContent.match(/\*\*Implementation Steps:\*\*\n([\s\S]+?)\n\n/)
|
|
271
|
+
|
|
272
|
+
const idea = ideaMatch ? ideaMatch[1].split('\n')[0].trim() : 'Unknown project'
|
|
273
|
+
const stack = stackMatch ? stackMatch[1] : 'Not specified'
|
|
274
|
+
const steps = stepsMatch ? stepsMatch[1] : 'Not specified'
|
|
275
|
+
|
|
276
|
+
console.log(`📝 Project: ${idea}`)
|
|
277
|
+
console.log(`\n🔧 Stack:\n${stack}`)
|
|
278
|
+
console.log(`\n📋 Implementation Steps:\n${steps}`)
|
|
279
|
+
|
|
280
|
+
console.log('\n' + '='.repeat(60))
|
|
281
|
+
console.log('🤖 READY TO GENERATE CODE')
|
|
282
|
+
console.log('='.repeat(60))
|
|
283
|
+
|
|
284
|
+
console.log(
|
|
285
|
+
'\nThe architect plan is ready. Claude will now:\n' +
|
|
286
|
+
' 1. Read the architectural plan\n' +
|
|
287
|
+
' 2. Use Context7 for official documentation\n' +
|
|
288
|
+
' 3. Generate project structure\n' +
|
|
289
|
+
' 4. Create starter files with boilerplate\n'
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
console.log('\n💡 This command shows the plan.')
|
|
293
|
+
console.log(' For code generation, Claude Code will read this plan')
|
|
294
|
+
console.log(' and generate the structure automatically.\n')
|
|
295
|
+
|
|
296
|
+
await this.logToMemory(projectPath, 'architect_executed', {
|
|
297
|
+
timestamp: dateHelper.getTimestamp(),
|
|
298
|
+
idea,
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
return {
|
|
302
|
+
success: true,
|
|
303
|
+
plan: planContent,
|
|
304
|
+
idea,
|
|
305
|
+
}
|
|
306
|
+
} catch (error) {
|
|
307
|
+
console.error('❌ Error:', (error as Error).message)
|
|
308
|
+
return { success: false, error: (error as Error).message }
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Setup Commands: start, setup, migrateAll, installStatusLine, showAsciiArt
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import path from 'path'
|
|
6
|
+
import fs from 'fs'
|
|
7
|
+
import os from 'os'
|
|
8
|
+
|
|
9
|
+
import migrator from '../infrastructure/migrator'
|
|
10
|
+
import type { CommandResult, SetupOptions, MigrateOptions, GlobalConfig, MigrationResult } from './types'
|
|
11
|
+
import {
|
|
12
|
+
PrjctCommandsBase,
|
|
13
|
+
configManager,
|
|
14
|
+
dateHelper
|
|
15
|
+
} from './base'
|
|
16
|
+
import { VERSION } from '../utils/version'
|
|
17
|
+
|
|
18
|
+
export class SetupCommands extends PrjctCommandsBase {
|
|
19
|
+
/**
|
|
20
|
+
* First-time setup - Install commands to editors
|
|
21
|
+
*/
|
|
22
|
+
async start(): Promise<CommandResult> {
|
|
23
|
+
const commandInstaller = require('../infrastructure/command-installer')
|
|
24
|
+
|
|
25
|
+
console.log('🚀 Setting up prjct for Claude...\n')
|
|
26
|
+
|
|
27
|
+
const status = await commandInstaller.checkInstallation()
|
|
28
|
+
|
|
29
|
+
if (!status.claudeDetected) {
|
|
30
|
+
return {
|
|
31
|
+
success: false,
|
|
32
|
+
message:
|
|
33
|
+
'❌ Claude not detected.\n\nPlease install Claude Code or Claude Desktop first:\n' +
|
|
34
|
+
' - Claude Code: https://claude.com/code\n' +
|
|
35
|
+
' - Claude Desktop: https://claude.com/desktop',
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
console.log('📦 Installing /p:* commands...')
|
|
40
|
+
const result = await commandInstaller.installCommands()
|
|
41
|
+
|
|
42
|
+
if (!result.success) {
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
message: `❌ Installation failed: ${result.error}`,
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
console.log(`\n✅ Installed ${result.installed.length} commands to:\n ${result.path}`)
|
|
50
|
+
|
|
51
|
+
if (result.errors.length > 0) {
|
|
52
|
+
console.log(`\n⚠️ ${result.errors.length} errors:`)
|
|
53
|
+
result.errors.forEach((e: { file: string; error: string }) => console.log(` - ${e.file}: ${e.error}`))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
console.log('\n🎉 Setup complete!')
|
|
57
|
+
console.log('\nNext steps:')
|
|
58
|
+
console.log(' 1. Open Claude Code or Claude Desktop')
|
|
59
|
+
console.log(' 2. Navigate to your project')
|
|
60
|
+
console.log(' 3. Run: /p:init')
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
success: true,
|
|
64
|
+
message: '',
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Reconfigure editor installations
|
|
70
|
+
*/
|
|
71
|
+
async setup(options: SetupOptions = {}): Promise<CommandResult> {
|
|
72
|
+
const commandInstaller = require('../infrastructure/command-installer')
|
|
73
|
+
|
|
74
|
+
console.log('🔧 Reconfiguring prjct...\n')
|
|
75
|
+
|
|
76
|
+
if (options.force) {
|
|
77
|
+
console.log('🗑️ Removing existing installation...')
|
|
78
|
+
await commandInstaller.uninstallCommands()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
console.log('📦 Installing /p:* commands...')
|
|
82
|
+
const result = await commandInstaller.updateCommands()
|
|
83
|
+
|
|
84
|
+
if (!result.success) {
|
|
85
|
+
return {
|
|
86
|
+
success: false,
|
|
87
|
+
message: `❌ Setup failed: ${result.error}`,
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
console.log(`\n✅ Installed ${result.installed.length} commands`)
|
|
92
|
+
|
|
93
|
+
if (result.errors.length > 0) {
|
|
94
|
+
console.log(`\n⚠️ ${result.errors.length} errors:`)
|
|
95
|
+
result.errors.forEach((e: { file: string; error: string }) => console.log(` - ${e.file}: ${e.error}`))
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
console.log('\n📝 Installing global configuration...')
|
|
99
|
+
const configResult = await commandInstaller.installGlobalConfig()
|
|
100
|
+
|
|
101
|
+
if (configResult.success) {
|
|
102
|
+
if (configResult.action === 'created') {
|
|
103
|
+
console.log('✅ Created ~/.claude/CLAUDE.md')
|
|
104
|
+
} else if (configResult.action === 'updated') {
|
|
105
|
+
console.log('✅ Updated ~/.claude/CLAUDE.md')
|
|
106
|
+
} else if (configResult.action === 'appended') {
|
|
107
|
+
console.log('✅ Added prjct config to ~/.claude/CLAUDE.md')
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
console.log(`⚠️ ${configResult.error}`)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
console.log('\n⚡ Installing status line...')
|
|
114
|
+
const statusLineResult = await this.installStatusLine()
|
|
115
|
+
if (statusLineResult.success) {
|
|
116
|
+
console.log('✅ Status line configured')
|
|
117
|
+
} else {
|
|
118
|
+
console.log(`⚠️ ${statusLineResult.error}`)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
console.log('\n🎉 Setup complete!\n')
|
|
122
|
+
|
|
123
|
+
this.showAsciiArt()
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
success: true,
|
|
127
|
+
message: '',
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Install status line script and configure settings.json
|
|
133
|
+
*/
|
|
134
|
+
async installStatusLine(): Promise<{ success: boolean; error?: string }> {
|
|
135
|
+
try {
|
|
136
|
+
const claudeDir = path.join(os.homedir(), '.claude')
|
|
137
|
+
const settingsPath = path.join(claudeDir, 'settings.json')
|
|
138
|
+
const statusLinePath = path.join(claudeDir, 'prjct-statusline.sh')
|
|
139
|
+
|
|
140
|
+
const scriptContent = `#!/bin/bash
|
|
141
|
+
# prjct Status Line for Claude Code
|
|
142
|
+
# Shows ⚡ prjct with animated spinner when command is running
|
|
143
|
+
|
|
144
|
+
# Read JSON context from stdin (provided by Claude Code)
|
|
145
|
+
read -r json
|
|
146
|
+
|
|
147
|
+
# Spinner frames
|
|
148
|
+
frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
|
|
149
|
+
|
|
150
|
+
# Calculate frame based on time (changes every 80ms)
|
|
151
|
+
frame=$(($(date +%s%N 2>/dev/null || echo 0) / 80000000 % 10))
|
|
152
|
+
|
|
153
|
+
# Check if prjct command is running
|
|
154
|
+
running_file="$HOME/.prjct-cli/.running"
|
|
155
|
+
|
|
156
|
+
if [ -f "$running_file" ]; then
|
|
157
|
+
task=$(cat "$running_file" 2>/dev/null || echo "working")
|
|
158
|
+
echo "⚡ prjct \${frames[$frame]} $task"
|
|
159
|
+
else
|
|
160
|
+
echo "⚡ prjct"
|
|
161
|
+
fi
|
|
162
|
+
`
|
|
163
|
+
fs.writeFileSync(statusLinePath, scriptContent, { mode: 0o755 })
|
|
164
|
+
|
|
165
|
+
let settings: Record<string, unknown> = {}
|
|
166
|
+
if (fs.existsSync(settingsPath)) {
|
|
167
|
+
try {
|
|
168
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'))
|
|
169
|
+
} catch {
|
|
170
|
+
// Invalid JSON, start fresh
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
settings.statusLine = {
|
|
175
|
+
type: 'command',
|
|
176
|
+
command: statusLinePath
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2))
|
|
180
|
+
|
|
181
|
+
return { success: true }
|
|
182
|
+
} catch (error) {
|
|
183
|
+
return { success: false, error: (error as Error).message }
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Show beautiful ASCII art with quick start
|
|
189
|
+
*/
|
|
190
|
+
showAsciiArt(): void {
|
|
191
|
+
const chalk = require('chalk')
|
|
192
|
+
|
|
193
|
+
console.log(chalk.cyan('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
194
|
+
console.log('')
|
|
195
|
+
console.log(chalk.bold.cyan(' ██████╗ ██████╗ ██╗ ██████╗████████╗'))
|
|
196
|
+
console.log(chalk.bold.cyan(' ██╔══██╗██╔══██╗ ██║██╔════╝╚══██╔══╝'))
|
|
197
|
+
console.log(chalk.bold.cyan(' ██████╔╝██████╔╝ ██║██║ ██║'))
|
|
198
|
+
console.log(chalk.bold.cyan(' ██╔═══╝ ██╔══██╗██ ██║██║ ██║'))
|
|
199
|
+
console.log(chalk.bold.cyan(' ██║ ██║ ██║╚█████╔╝╚██████╗ ██║'))
|
|
200
|
+
console.log(chalk.bold.cyan(' ╚═╝ ╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚═╝'))
|
|
201
|
+
console.log('')
|
|
202
|
+
console.log(` ${chalk.bold.cyan('prjct')}${chalk.magenta('/')}${chalk.green('cli')} ${chalk.dim.white('v' + VERSION + ' installed')}`)
|
|
203
|
+
console.log('')
|
|
204
|
+
console.log(` ${chalk.yellow('⚡')} Ship faster with zero friction`)
|
|
205
|
+
console.log(` ${chalk.green('📝')} From idea to technical tasks in minutes`)
|
|
206
|
+
console.log(` ${chalk.cyan('🤖')} Perfect context for AI agents`)
|
|
207
|
+
console.log('')
|
|
208
|
+
console.log(chalk.cyan('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
209
|
+
console.log('')
|
|
210
|
+
console.log(chalk.bold.cyan('🚀 Quick Start'))
|
|
211
|
+
console.log(chalk.dim('─────────────────────────────────────────────────'))
|
|
212
|
+
console.log('')
|
|
213
|
+
console.log(` ${chalk.bold('1.')} Initialize your project:`)
|
|
214
|
+
console.log(` ${chalk.green('cd your-project && prjct init')}`)
|
|
215
|
+
console.log('')
|
|
216
|
+
console.log(` ${chalk.bold('2.')} Set your current focus:`)
|
|
217
|
+
console.log(` ${chalk.green('prjct now "build auth"')}`)
|
|
218
|
+
console.log('')
|
|
219
|
+
console.log(` ${chalk.bold('3.')} Ship & celebrate:`)
|
|
220
|
+
console.log(` ${chalk.green('prjct ship "user login"')}`)
|
|
221
|
+
console.log('')
|
|
222
|
+
console.log(chalk.dim('─────────────────────────────────────────────────'))
|
|
223
|
+
console.log('')
|
|
224
|
+
console.log(` ${chalk.dim('Documentation:')} ${chalk.cyan('https://prjct.app')}`)
|
|
225
|
+
console.log(` ${chalk.dim('Report issues:')} ${chalk.cyan('https://github.com/jlopezlira/prjct-cli/issues')}`)
|
|
226
|
+
console.log('')
|
|
227
|
+
console.log(chalk.bold.magenta('Happy shipping! 🚀'))
|
|
228
|
+
console.log('')
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Migrate all legacy projects
|
|
233
|
+
*/
|
|
234
|
+
async migrateAll(options: MigrateOptions = {}): Promise<CommandResult> {
|
|
235
|
+
const fsPromises = require('fs').promises
|
|
236
|
+
|
|
237
|
+
console.log('🔄 Scanning for legacy prjct projects...\n')
|
|
238
|
+
|
|
239
|
+
const homeDir = os.homedir()
|
|
240
|
+
const globalRoot = path.join(homeDir, '.prjct-cli', 'projects')
|
|
241
|
+
|
|
242
|
+
let projectIds: string[] = []
|
|
243
|
+
try {
|
|
244
|
+
const dirs = await fsPromises.readdir(globalRoot)
|
|
245
|
+
projectIds = dirs.filter((d: string) => !d.startsWith('.'))
|
|
246
|
+
} catch {
|
|
247
|
+
return {
|
|
248
|
+
success: false,
|
|
249
|
+
message: '❌ No prjct projects found',
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
console.log(`📁 Found ${projectIds.length} projects in global storage\n`)
|
|
254
|
+
|
|
255
|
+
const migrated: { projectId: string; path: string }[] = []
|
|
256
|
+
const failed: { projectId: string; path: string; error: string }[] = []
|
|
257
|
+
const skipped: { projectId: string; reason: string }[] = []
|
|
258
|
+
|
|
259
|
+
for (const projectId of projectIds) {
|
|
260
|
+
const globalConfig = await configManager.readGlobalConfig(projectId) as GlobalConfig | null
|
|
261
|
+
if (!globalConfig || !globalConfig.projectPath) {
|
|
262
|
+
skipped.push({ projectId, reason: 'No project path in config' })
|
|
263
|
+
continue
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const projectPath = globalConfig.projectPath!
|
|
267
|
+
|
|
268
|
+
if (!(await migrator.needsMigration(projectPath))) {
|
|
269
|
+
skipped.push({ projectId, reason: 'Already migrated' })
|
|
270
|
+
continue
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
console.log(`🔄 Migrating: ${projectPath}`)
|
|
274
|
+
|
|
275
|
+
try {
|
|
276
|
+
const result = await migrator.migrate(projectPath, options) as MigrationResult
|
|
277
|
+
|
|
278
|
+
if (result.success) {
|
|
279
|
+
migrated.push({ projectId, path: projectPath })
|
|
280
|
+
console.log(` ✅ Migrated successfully`)
|
|
281
|
+
} else {
|
|
282
|
+
const issues = result.issues?.join(', ') || 'Unknown error'
|
|
283
|
+
failed.push({ projectId, path: projectPath, error: issues })
|
|
284
|
+
console.log(` ❌ ${issues}`)
|
|
285
|
+
}
|
|
286
|
+
} catch (error) {
|
|
287
|
+
failed.push({ projectId, path: projectPath, error: (error as Error).message })
|
|
288
|
+
console.log(` ❌ ${(error as Error).message}`)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
console.log('')
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
console.log('\n📊 Migration Summary:')
|
|
295
|
+
console.log(` ✅ Migrated: ${migrated.length}`)
|
|
296
|
+
console.log(` ⏭️ Skipped: ${skipped.length}`)
|
|
297
|
+
console.log(` ❌ Failed: ${failed.length}`)
|
|
298
|
+
|
|
299
|
+
if (failed.length > 0) {
|
|
300
|
+
console.log('\n❌ Failed migrations:')
|
|
301
|
+
failed.forEach((f) => console.log(` - ${f.path}: ${f.error}`))
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return {
|
|
305
|
+
success: failed.length === 0,
|
|
306
|
+
message: '',
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|