prjct-cli 0.18.2 → 0.19.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 +40 -0
- package/CLAUDE.md +74 -211
- package/core/agentic/prompt-builder.ts +3 -7
- package/core/command-registry/optional-commands.ts +0 -20
- package/core/infrastructure/command-installer/command-installer.ts +8 -1
- package/core/infrastructure/command-installer/global-config.ts +31 -1
- package/core/infrastructure/command-installer/index.ts +1 -1
- package/core/infrastructure/setup.ts +3 -0
- package/package.json +3 -17
- package/templates/commands/done.md +57 -258
- package/templates/commands/now.md +72 -277
- package/templates/commands/ship.md +55 -261
- package/templates/commands/test.md +328 -21
- package/templates/global/CLAUDE.md +40 -205
- package/templates/global/docs/agents.md +88 -0
- package/templates/global/docs/architecture.md +103 -0
- package/templates/global/docs/commands.md +98 -0
- package/templates/global/docs/validation.md +95 -0
- package/templates/mcp-config.json +36 -0
- package/bin/dev.js +0 -216
- package/bin/serve.js +0 -361
- package/packages/web/README.md +0 -36
- package/packages/web/app/api/claude/sessions/route.ts +0 -44
- package/packages/web/app/api/claude/status/route.ts +0 -34
- package/packages/web/app/api/projects/[id]/icon/route.ts +0 -33
- package/packages/web/app/api/projects/[id]/momentum/route.ts +0 -257
- package/packages/web/app/api/projects/[id]/route.ts +0 -29
- package/packages/web/app/api/projects/[id]/stats/route.ts +0 -41
- package/packages/web/app/api/projects/[id]/status/route.ts +0 -21
- package/packages/web/app/api/projects/route.ts +0 -16
- package/packages/web/app/api/sessions/current/route.ts +0 -132
- package/packages/web/app/api/sessions/history/route.ts +0 -204
- package/packages/web/app/error.tsx +0 -34
- package/packages/web/app/favicon.ico +0 -0
- package/packages/web/app/globals.css +0 -198
- package/packages/web/app/layout.tsx +0 -53
- package/packages/web/app/loading.tsx +0 -7
- package/packages/web/app/not-found.tsx +0 -25
- package/packages/web/app/page.tsx +0 -12
- package/packages/web/app/project/[id]/code/layout.tsx +0 -18
- package/packages/web/app/project/[id]/code/page.tsx +0 -408
- package/packages/web/app/project/[id]/error.tsx +0 -41
- package/packages/web/app/project/[id]/loading.tsx +0 -9
- package/packages/web/app/project/[id]/not-found.tsx +0 -27
- package/packages/web/app/project/[id]/page.tsx +0 -384
- package/packages/web/app/project/[id]/reports/page.tsx +0 -59
- package/packages/web/app/project/[id]/reports/print/page.tsx +0 -58
- package/packages/web/app/sessions/page.tsx +0 -165
- package/packages/web/app/settings/page.tsx +0 -151
- package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +0 -2
- package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +0 -49
- package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +0 -8
- package/packages/web/components/ActivityTimeline/hooks/index.ts +0 -2
- package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +0 -9
- package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +0 -23
- package/packages/web/components/ActivityTimeline/index.ts +0 -2
- package/packages/web/components/AgentsCard/AgentsCard.tsx +0 -93
- package/packages/web/components/AgentsCard/AgentsCard.types.ts +0 -14
- package/packages/web/components/AgentsCard/index.ts +0 -2
- package/packages/web/components/AppSidebar/AppSidebar.tsx +0 -316
- package/packages/web/components/AppSidebar/index.ts +0 -1
- package/packages/web/components/BackLink/BackLink.tsx +0 -18
- package/packages/web/components/BackLink/BackLink.types.ts +0 -5
- package/packages/web/components/BackLink/index.ts +0 -2
- package/packages/web/components/BentoCard/BentoCard.constants.ts +0 -16
- package/packages/web/components/BentoCard/BentoCard.tsx +0 -48
- package/packages/web/components/BentoCard/BentoCard.types.ts +0 -15
- package/packages/web/components/BentoCard/index.ts +0 -2
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +0 -9
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +0 -18
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +0 -5
- package/packages/web/components/BentoCardSkeleton/index.ts +0 -2
- package/packages/web/components/BentoGrid/BentoGrid.tsx +0 -18
- package/packages/web/components/BentoGrid/BentoGrid.types.ts +0 -4
- package/packages/web/components/BentoGrid/index.ts +0 -2
- package/packages/web/components/BlockersCard/BlockersCard.tsx +0 -75
- package/packages/web/components/BlockersCard/BlockersCard.types.ts +0 -12
- package/packages/web/components/BlockersCard/index.ts +0 -2
- package/packages/web/components/CommandBar/CommandBar.tsx +0 -67
- package/packages/web/components/CommandBar/index.ts +0 -1
- package/packages/web/components/CommandButton/CommandButton.tsx +0 -46
- package/packages/web/components/CommandButton/index.ts +0 -1
- package/packages/web/components/ConnectionStatus/ConnectionStatus.tsx +0 -29
- package/packages/web/components/ConnectionStatus/index.ts +0 -1
- package/packages/web/components/DashboardContent/DashboardContent.tsx +0 -284
- package/packages/web/components/DashboardContent/index.ts +0 -1
- package/packages/web/components/DateGroup/DateGroup.tsx +0 -18
- package/packages/web/components/DateGroup/DateGroup.types.ts +0 -6
- package/packages/web/components/DateGroup/DateGroup.utils.ts +0 -11
- package/packages/web/components/DateGroup/index.ts +0 -2
- package/packages/web/components/EmptyState/EmptyState.tsx +0 -76
- package/packages/web/components/EmptyState/EmptyState.types.ts +0 -11
- package/packages/web/components/EmptyState/index.ts +0 -2
- package/packages/web/components/EventRow/EventRow.constants.ts +0 -10
- package/packages/web/components/EventRow/EventRow.tsx +0 -49
- package/packages/web/components/EventRow/EventRow.types.ts +0 -7
- package/packages/web/components/EventRow/EventRow.utils.ts +0 -49
- package/packages/web/components/EventRow/index.ts +0 -2
- package/packages/web/components/ExpandButton/ExpandButton.tsx +0 -18
- package/packages/web/components/ExpandButton/ExpandButton.types.ts +0 -6
- package/packages/web/components/ExpandButton/index.ts +0 -2
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +0 -14
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +0 -5
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +0 -13
- package/packages/web/components/HealthGradientBackground/index.ts +0 -2
- package/packages/web/components/HeroSection/HeroSection.tsx +0 -92
- package/packages/web/components/HeroSection/HeroSection.types.ts +0 -14
- package/packages/web/components/HeroSection/HeroSection.utils.ts +0 -11
- package/packages/web/components/HeroSection/hooks/index.ts +0 -2
- package/packages/web/components/HeroSection/hooks/useCountUp.ts +0 -45
- package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +0 -18
- package/packages/web/components/HeroSection/index.ts +0 -2
- package/packages/web/components/IdeasCard/IdeasCard.tsx +0 -115
- package/packages/web/components/IdeasCard/IdeasCard.types.ts +0 -10
- package/packages/web/components/IdeasCard/index.ts +0 -2
- package/packages/web/components/InsightMessage/InsightMessage.tsx +0 -9
- package/packages/web/components/InsightMessage/InsightMessage.types.ts +0 -3
- package/packages/web/components/InsightMessage/index.ts +0 -2
- package/packages/web/components/Logo/Logo.tsx +0 -65
- package/packages/web/components/Logo/index.ts +0 -1
- package/packages/web/components/MarkdownContent/MarkdownContent.tsx +0 -123
- package/packages/web/components/MarkdownContent/index.ts +0 -1
- package/packages/web/components/MasonryGrid/MasonryGrid.tsx +0 -18
- package/packages/web/components/MasonryGrid/index.ts +0 -1
- package/packages/web/components/MomentumWidget/MomentumWidget.tsx +0 -119
- package/packages/web/components/MomentumWidget/MomentumWidget.types.ts +0 -16
- package/packages/web/components/MomentumWidget/index.ts +0 -2
- package/packages/web/components/NowCard/NowCard.tsx +0 -118
- package/packages/web/components/NowCard/NowCard.types.ts +0 -16
- package/packages/web/components/NowCard/index.ts +0 -2
- package/packages/web/components/PageHeader/PageHeader.tsx +0 -24
- package/packages/web/components/PageHeader/index.ts +0 -1
- package/packages/web/components/ProgressRing/ProgressRing.constants.ts +0 -20
- package/packages/web/components/ProgressRing/ProgressRing.tsx +0 -51
- package/packages/web/components/ProgressRing/ProgressRing.types.ts +0 -11
- package/packages/web/components/ProgressRing/index.ts +0 -2
- package/packages/web/components/ProjectAvatar/ProjectAvatar.tsx +0 -54
- package/packages/web/components/ProjectAvatar/index.ts +0 -1
- package/packages/web/components/ProjectColorDot/ProjectColorDot.tsx +0 -37
- package/packages/web/components/ProjectColorDot/index.ts +0 -1
- package/packages/web/components/ProjectSelectorModal/ProjectSelectorModal.tsx +0 -104
- package/packages/web/components/ProjectSelectorModal/index.ts +0 -1
- package/packages/web/components/Providers/Providers.tsx +0 -48
- package/packages/web/components/Providers/index.ts +0 -1
- package/packages/web/components/QueueCard/QueueCard.tsx +0 -125
- package/packages/web/components/QueueCard/QueueCard.types.ts +0 -12
- package/packages/web/components/QueueCard/QueueCard.utils.ts +0 -12
- package/packages/web/components/QueueCard/index.ts +0 -2
- package/packages/web/components/RecoverCard/RecoverCard.tsx +0 -72
- package/packages/web/components/RecoverCard/RecoverCard.types.ts +0 -16
- package/packages/web/components/RecoverCard/index.ts +0 -2
- package/packages/web/components/RoadmapCard/RoadmapCard.tsx +0 -145
- package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +0 -16
- package/packages/web/components/RoadmapCard/index.ts +0 -2
- package/packages/web/components/ShipsCard/ShipsCard.tsx +0 -95
- package/packages/web/components/ShipsCard/ShipsCard.types.ts +0 -14
- package/packages/web/components/ShipsCard/ShipsCard.utils.ts +0 -4
- package/packages/web/components/ShipsCard/index.ts +0 -2
- package/packages/web/components/SparklineChart/SparklineChart.tsx +0 -40
- package/packages/web/components/SparklineChart/SparklineChart.types.ts +0 -6
- package/packages/web/components/SparklineChart/index.ts +0 -2
- package/packages/web/components/StatsMasonry/StatsMasonry.tsx +0 -95
- package/packages/web/components/StatsMasonry/index.ts +0 -1
- package/packages/web/components/StreakCard/StreakCard.constants.ts +0 -2
- package/packages/web/components/StreakCard/StreakCard.tsx +0 -55
- package/packages/web/components/StreakCard/StreakCard.types.ts +0 -4
- package/packages/web/components/StreakCard/index.ts +0 -2
- package/packages/web/components/TasksCounter/TasksCounter.tsx +0 -14
- package/packages/web/components/TasksCounter/TasksCounter.types.ts +0 -3
- package/packages/web/components/TasksCounter/index.ts +0 -2
- package/packages/web/components/TechStackBadges/TechStackBadges.tsx +0 -28
- package/packages/web/components/TechStackBadges/index.ts +0 -1
- package/packages/web/components/TerminalDock/DockToggleTab.tsx +0 -29
- package/packages/web/components/TerminalDock/TerminalDock.tsx +0 -386
- package/packages/web/components/TerminalDock/TerminalDockTab.tsx +0 -130
- package/packages/web/components/TerminalDock/TerminalTabBar.tsx +0 -142
- package/packages/web/components/TerminalDock/index.ts +0 -2
- package/packages/web/components/TerminalTabs/TerminalTab.tsx +0 -95
- package/packages/web/components/TerminalTabs/TerminalTabs.tsx +0 -211
- package/packages/web/components/TerminalTabs/index.ts +0 -1
- package/packages/web/components/VelocityBadge/VelocityBadge.tsx +0 -32
- package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +0 -3
- package/packages/web/components/VelocityBadge/index.ts +0 -2
- package/packages/web/components/VelocityCard/VelocityCard.tsx +0 -73
- package/packages/web/components/VelocityCard/VelocityCard.types.ts +0 -7
- package/packages/web/components/VelocityCard/index.ts +0 -2
- package/packages/web/components/WeeklyReports/PrintableReport.tsx +0 -259
- package/packages/web/components/WeeklyReports/ReportPreviewCard.tsx +0 -187
- package/packages/web/components/WeeklyReports/WeekCalendar.tsx +0 -288
- package/packages/web/components/WeeklyReports/WeeklyReports.tsx +0 -149
- package/packages/web/components/WeeklyReports/index.ts +0 -4
- package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +0 -25
- package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +0 -4
- package/packages/web/components/WeeklySparkline/index.ts +0 -2
- package/packages/web/components/charts/SessionsChart.tsx +0 -175
- package/packages/web/components/ui/alert-dialog.tsx +0 -157
- package/packages/web/components/ui/badge.tsx +0 -46
- package/packages/web/components/ui/button.tsx +0 -60
- package/packages/web/components/ui/card.tsx +0 -92
- package/packages/web/components/ui/chart.tsx +0 -385
- package/packages/web/components/ui/dialog.tsx +0 -143
- package/packages/web/components/ui/drawer.tsx +0 -135
- package/packages/web/components/ui/dropdown-menu.tsx +0 -257
- package/packages/web/components/ui/input.tsx +0 -21
- package/packages/web/components/ui/scroll-area.tsx +0 -58
- package/packages/web/components/ui/select.tsx +0 -187
- package/packages/web/components/ui/sheet.tsx +0 -139
- package/packages/web/components/ui/tabs.tsx +0 -66
- package/packages/web/components/ui/tooltip.tsx +0 -61
- package/packages/web/components.json +0 -22
- package/packages/web/context/GlobalTerminalContext.tsx +0 -538
- package/packages/web/context/TerminalContext.tsx +0 -45
- package/packages/web/context/TerminalTabsContext.tsx +0 -181
- package/packages/web/eslint.config.mjs +0 -18
- package/packages/web/hooks/useClaudeTerminal.ts +0 -425
- package/packages/web/hooks/useProjectStats.ts +0 -93
- package/packages/web/hooks/useProjects.ts +0 -73
- package/packages/web/lib/actions/projects.ts +0 -15
- package/packages/web/lib/commands.ts +0 -81
- package/packages/web/lib/format.ts +0 -23
- package/packages/web/lib/generate-week-report.ts +0 -285
- package/packages/web/lib/parse-prjct-files.ts +0 -1123
- package/packages/web/lib/project-colors.ts +0 -58
- package/packages/web/lib/projects.ts +0 -506
- package/packages/web/lib/pty.ts +0 -101
- package/packages/web/lib/query-config.ts +0 -44
- package/packages/web/lib/services/index.ts +0 -9
- package/packages/web/lib/services/projects.server.ts +0 -66
- package/packages/web/lib/services/stats.server.ts +0 -562
- package/packages/web/lib/unified-loader.ts +0 -396
- package/packages/web/lib/utils.ts +0 -6
- package/packages/web/next-env.d.ts +0 -6
- package/packages/web/next.config.ts +0 -7
- package/packages/web/package.json +0 -57
- package/packages/web/postcss.config.mjs +0 -7
- package/packages/web/public/file.svg +0 -1
- package/packages/web/public/globe.svg +0 -1
- package/packages/web/public/next.svg +0 -1
- package/packages/web/public/vercel.svg +0 -1
- package/packages/web/public/window.svg +0 -1
- package/packages/web/server.ts +0 -312
- package/packages/web/tsconfig.json +0 -34
- package/templates/commands/serve.md +0 -121
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Using Agents
|
|
2
|
+
|
|
3
|
+
## What Are Agents?
|
|
4
|
+
|
|
5
|
+
Agents are specialized Claude configurations for different domains:
|
|
6
|
+
|
|
7
|
+
| Agent | Domain | When to Use |
|
|
8
|
+
|-------|--------|-------------|
|
|
9
|
+
| `fe.md` | Frontend | React, CSS, UI components |
|
|
10
|
+
| `be.md` | Backend | APIs, databases, servers |
|
|
11
|
+
| `ux.md` | UX Design | Layouts, user flows |
|
|
12
|
+
| `qa.md` | Testing | Tests, QA, bug fixes |
|
|
13
|
+
| `docs.md` | Documentation | README, docs, comments |
|
|
14
|
+
|
|
15
|
+
## Agent Location
|
|
16
|
+
|
|
17
|
+
Agents live in global storage:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
~/.prjct-cli/projects/{projectId}/agents/
|
|
21
|
+
├── fe.md # Frontend specialist
|
|
22
|
+
├── be.md # Backend specialist
|
|
23
|
+
├── ux.md # UX specialist
|
|
24
|
+
├── qa.md # Testing specialist
|
|
25
|
+
└── docs.md # Documentation specialist
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## When to Read Agent Files
|
|
29
|
+
|
|
30
|
+
Read the relevant agent file before working in that domain:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
Task: "implement React component"
|
|
34
|
+
→ Read agents/fe.md for React patterns
|
|
35
|
+
→ Follow detected conventions
|
|
36
|
+
|
|
37
|
+
Task: "add API endpoint"
|
|
38
|
+
→ Read agents/be.md for API patterns
|
|
39
|
+
→ Follow project architecture
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Agent File Structure
|
|
43
|
+
|
|
44
|
+
Each agent file contains:
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
---
|
|
48
|
+
name: fe
|
|
49
|
+
description: Frontend specialist for React/TypeScript
|
|
50
|
+
tools: Read, Write, Glob, Grep, Bash
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Expertise
|
|
54
|
+
- React components and hooks
|
|
55
|
+
- TypeScript patterns
|
|
56
|
+
- CSS/styling conventions
|
|
57
|
+
|
|
58
|
+
## Project Patterns
|
|
59
|
+
- Components in src/components/
|
|
60
|
+
- Use functional components
|
|
61
|
+
- CSS modules for styling
|
|
62
|
+
|
|
63
|
+
## Code Conventions
|
|
64
|
+
- Named exports
|
|
65
|
+
- Props interfaces defined inline
|
|
66
|
+
- Error boundaries for async components
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Auto-Detection
|
|
70
|
+
|
|
71
|
+
When starting a task with `/p:now`, agents are auto-detected by keywords:
|
|
72
|
+
|
|
73
|
+
| Keywords | Agent |
|
|
74
|
+
|----------|-------|
|
|
75
|
+
| UI, frontend, React, component, CSS | `fe` |
|
|
76
|
+
| API, backend, database, server | `be` |
|
|
77
|
+
| design, UX, layout, wireframe | `ux` |
|
|
78
|
+
| test, QA, bug, coverage | `qa` |
|
|
79
|
+
| docs, README, documentation | `docs` |
|
|
80
|
+
|
|
81
|
+
## Agent Generation
|
|
82
|
+
|
|
83
|
+
Agents are generated by `/p:sync` based on:
|
|
84
|
+
- Detected tech stack (package.json, etc.)
|
|
85
|
+
- Project structure
|
|
86
|
+
- Code patterns found in codebase
|
|
87
|
+
|
|
88
|
+
Re-run `/p:sync` to regenerate agents after major changes.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# prjct Architecture
|
|
2
|
+
|
|
3
|
+
## Write-Through Pattern
|
|
4
|
+
|
|
5
|
+
All data flows through three layers:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
User Action → Storage (JSON) → Context (MD) → Sync Events (JSONL)
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Layer Responsibilities
|
|
12
|
+
|
|
13
|
+
| Layer | Path | Purpose | Format |
|
|
14
|
+
|-------|------|---------|--------|
|
|
15
|
+
| **Storage** | `storage/*.json` | Source of truth | JSON |
|
|
16
|
+
| **Context** | `context/*.md` | Claude-readable summaries | Markdown |
|
|
17
|
+
| **Sync** | `sync/pending.json` | Backend event queue | JSON array |
|
|
18
|
+
| **Memory** | `memory/events.jsonl` | Audit trail | JSONL (append-only) |
|
|
19
|
+
|
|
20
|
+
### Data Flow Example
|
|
21
|
+
|
|
22
|
+
When user runs `/p:now "implement auth"`:
|
|
23
|
+
|
|
24
|
+
1. **Storage**: Write to `storage/state.json`
|
|
25
|
+
```json
|
|
26
|
+
{ "currentTask": { "description": "implement auth", ... } }
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
2. **Context**: Generate `context/now.md`
|
|
30
|
+
```markdown
|
|
31
|
+
# NOW
|
|
32
|
+
**implement auth**
|
|
33
|
+
Started: 2025-12-20T10:30:00.000Z
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
3. **Sync**: Append to `sync/pending.json`
|
|
37
|
+
```json
|
|
38
|
+
{ "type": "task.started", "data": {...} }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
4. **Memory**: Append to `memory/events.jsonl`
|
|
42
|
+
```json
|
|
43
|
+
{"timestamp":"...","action":"task_started","task":"implement auth"}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## File Structure
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
~/.prjct-cli/projects/{projectId}/
|
|
50
|
+
├── storage/ # SOURCE OF TRUTH
|
|
51
|
+
│ ├── state.json # Current task state
|
|
52
|
+
│ ├── shipped.json # Shipped features
|
|
53
|
+
│ ├── ideas.json # Ideas backlog
|
|
54
|
+
│ └── queue.json # Task queue
|
|
55
|
+
│
|
|
56
|
+
├── context/ # CLAUDE-READABLE (generated)
|
|
57
|
+
│ ├── now.md # Current task summary
|
|
58
|
+
│ ├── shipped.md # Recent ships
|
|
59
|
+
│ └── next.md # Priority queue
|
|
60
|
+
│
|
|
61
|
+
├── sync/ # BACKEND EVENTS
|
|
62
|
+
│ └── pending.json # Events waiting for sync
|
|
63
|
+
│
|
|
64
|
+
├── memory/ # AUDIT TRAIL
|
|
65
|
+
│ └── events.jsonl # Append-only log
|
|
66
|
+
│
|
|
67
|
+
├── agents/ # DOMAIN SPECIALISTS
|
|
68
|
+
│ ├── fe.md # Frontend agent
|
|
69
|
+
│ ├── be.md # Backend agent
|
|
70
|
+
│ └── ...
|
|
71
|
+
│
|
|
72
|
+
└── CLAUDE.md # Project context (read first)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Storage vs Context
|
|
76
|
+
|
|
77
|
+
| Aspect | Storage (JSON) | Context (MD) |
|
|
78
|
+
|--------|----------------|--------------|
|
|
79
|
+
| Format | Structured JSON | Human-readable Markdown |
|
|
80
|
+
| Purpose | Source of truth | Claude summaries |
|
|
81
|
+
| Updates | Direct writes | Generated from storage |
|
|
82
|
+
| Read by | Code, Claude | Primarily Claude |
|
|
83
|
+
|
|
84
|
+
## Timestamps
|
|
85
|
+
|
|
86
|
+
All timestamps use ISO 8601 format:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Prefer bun, fallback to node
|
|
90
|
+
bun -e "console.log(new Date().toISOString())" 2>/dev/null || node -e "console.log(new Date().toISOString())"
|
|
91
|
+
# Output: "2025-12-20T10:30:00.000Z"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**NEVER** hardcode timestamps. Always generate dynamically.
|
|
95
|
+
|
|
96
|
+
## IDs
|
|
97
|
+
|
|
98
|
+
Use UUID v4 for all IDs:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
bun -e "console.log(crypto.randomUUID())" 2>/dev/null || node -e "console.log(require('crypto').randomUUID())"
|
|
102
|
+
# Output: "550e8400-e29b-41d4-a716-446655440000"
|
|
103
|
+
```
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# prjct Commands Reference
|
|
2
|
+
|
|
3
|
+
## Command Table
|
|
4
|
+
|
|
5
|
+
| Command | Purpose | Arguments |
|
|
6
|
+
|---------|---------|-----------|
|
|
7
|
+
| `/p:sync` | Analyze project, generate agents | - |
|
|
8
|
+
| `/p:now [task] [estimate]` | Start/show current task | task: string, estimate: "2h", "30m" |
|
|
9
|
+
| `/p:done` | Complete current task | - |
|
|
10
|
+
| `/p:ship [feature]` | Ship with quality checks | feature: string |
|
|
11
|
+
| `/p:next` | Show priority queue | - |
|
|
12
|
+
| `/p:feature [desc]` | Add feature to roadmap | desc: string |
|
|
13
|
+
| `/p:idea [text]` | Quick idea capture | text: string |
|
|
14
|
+
| `/p:recap` | Project overview | - |
|
|
15
|
+
| `/p:progress [period]` | Show metrics | period: "week", "month" |
|
|
16
|
+
| `/p:pause [reason]` | Pause current task | reason: string |
|
|
17
|
+
| `/p:resume` | Resume paused task | - |
|
|
18
|
+
| `/p:bug [desc]` | Report bug | desc: string |
|
|
19
|
+
|
|
20
|
+
## Recommended Workflow
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
1. /p:sync → Analyze project, generate agents
|
|
24
|
+
2. /p:feature → Plan what to build
|
|
25
|
+
3. /p:now → Start working on task
|
|
26
|
+
4. [code...] → Do the actual work
|
|
27
|
+
5. /p:done → Mark task complete
|
|
28
|
+
6. /p:ship → Ship and celebrate
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Command Examples
|
|
32
|
+
|
|
33
|
+
### Starting Work
|
|
34
|
+
```
|
|
35
|
+
/p:now "implement user authentication" 2h
|
|
36
|
+
```
|
|
37
|
+
- Sets current task
|
|
38
|
+
- Optional estimate for tracking accuracy
|
|
39
|
+
|
|
40
|
+
### Completing Work
|
|
41
|
+
```
|
|
42
|
+
/p:done
|
|
43
|
+
```
|
|
44
|
+
- Calculates duration
|
|
45
|
+
- Logs metrics (files changed, commits)
|
|
46
|
+
- Clears current task
|
|
47
|
+
|
|
48
|
+
### Shipping
|
|
49
|
+
```
|
|
50
|
+
/p:ship "user authentication"
|
|
51
|
+
```
|
|
52
|
+
- Runs lint/tests (optional)
|
|
53
|
+
- Bumps version
|
|
54
|
+
- Creates git commit
|
|
55
|
+
- Updates CHANGELOG
|
|
56
|
+
|
|
57
|
+
### Quick Capture
|
|
58
|
+
```
|
|
59
|
+
/p:idea "add dark mode support"
|
|
60
|
+
```
|
|
61
|
+
- Saves to ideas backlog
|
|
62
|
+
- Doesn't interrupt current work
|
|
63
|
+
|
|
64
|
+
## Natural Language Trigger
|
|
65
|
+
|
|
66
|
+
Start message with `p.` for natural language:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
p. start working on login form
|
|
70
|
+
→ Executes /p:now "login form"
|
|
71
|
+
|
|
72
|
+
p. done with this
|
|
73
|
+
→ Executes /p:done
|
|
74
|
+
|
|
75
|
+
p. ship authentication feature
|
|
76
|
+
→ Executes /p:ship "authentication"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Command Output Format
|
|
80
|
+
|
|
81
|
+
All commands output concise responses:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
✅ [What was done]
|
|
85
|
+
|
|
86
|
+
[Key metrics if applicable]
|
|
87
|
+
|
|
88
|
+
Next: [suggested action]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Example:
|
|
92
|
+
```
|
|
93
|
+
✅ implement auth (2h 15m)
|
|
94
|
+
|
|
95
|
+
Files: 5 | +120/-30 | Commits: 3
|
|
96
|
+
|
|
97
|
+
Next: /p:ship or /p:now
|
|
98
|
+
```
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Validation Patterns
|
|
2
|
+
|
|
3
|
+
## Before Any Command
|
|
4
|
+
|
|
5
|
+
```javascript
|
|
6
|
+
// 1. Check project exists
|
|
7
|
+
const config = await Read('.prjct/prjct.config.json')
|
|
8
|
+
if (!config) {
|
|
9
|
+
return "No prjct project. Run /p:init first."
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// 2. Extract projectId
|
|
13
|
+
const { projectId } = JSON.parse(config)
|
|
14
|
+
|
|
15
|
+
// 3. Construct global path
|
|
16
|
+
const globalPath = `~/.prjct-cli/projects/${projectId}`
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Before /p:done
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
const state = await Read(`${globalPath}/storage/state.json`)
|
|
23
|
+
|
|
24
|
+
if (!state || !state.currentTask) {
|
|
25
|
+
return "Not working on anything. Use /p:now to start a task."
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (state.currentTask.status !== 'active') {
|
|
29
|
+
return "No active task. Use /p:now to start one."
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Before /p:ship
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
// Check git status
|
|
37
|
+
const gitStatus = await Bash('git status --porcelain')
|
|
38
|
+
|
|
39
|
+
if (!gitStatus.trim()) {
|
|
40
|
+
return "No changes to ship. Make some commits first."
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Verify git repo
|
|
44
|
+
const isGitRepo = await Bash('git rev-parse --is-inside-work-tree')
|
|
45
|
+
if (!isGitRepo) {
|
|
46
|
+
return "Not a git repository. Initialize git first."
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Before /p:pause
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
const state = await Read(`${globalPath}/storage/state.json`)
|
|
54
|
+
|
|
55
|
+
if (!state?.currentTask || state.currentTask.status !== 'active') {
|
|
56
|
+
return "No active task to pause."
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Before /p:resume
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
const state = await Read(`${globalPath}/storage/state.json`)
|
|
64
|
+
|
|
65
|
+
if (!state?.pausedTask) {
|
|
66
|
+
return "No paused task to resume. Use /p:now to start a new task."
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Error Handling
|
|
71
|
+
|
|
72
|
+
| Error | Response | Action |
|
|
73
|
+
|-------|----------|--------|
|
|
74
|
+
| Config not found | "No prjct project" | STOP |
|
|
75
|
+
| No current task | "Not working on anything" | STOP |
|
|
76
|
+
| No paused task | "No paused task" | STOP |
|
|
77
|
+
| Git fails | Use defaults for metrics | CONTINUE |
|
|
78
|
+
| Write fails | Log warning | CONTINUE |
|
|
79
|
+
| File not found | Return empty/default state | CONTINUE |
|
|
80
|
+
|
|
81
|
+
## Path Resolution
|
|
82
|
+
|
|
83
|
+
**CRITICAL**: All paths resolve to global storage.
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
// Template says:
|
|
87
|
+
"Read: storage/state.json"
|
|
88
|
+
|
|
89
|
+
// Actually reads:
|
|
90
|
+
`~/.prjct-cli/projects/${projectId}/storage/state.json`
|
|
91
|
+
|
|
92
|
+
// NEVER:
|
|
93
|
+
".prjct/storage/state.json" // Wrong - local
|
|
94
|
+
"./storage/state.json" // Wrong - current dir
|
|
95
|
+
```
|
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
"command": "npx",
|
|
5
5
|
"args": ["-y", "@upstash/context7-mcp@latest"],
|
|
6
6
|
"description": "Library documentation lookup - use for framework/library docs"
|
|
7
|
+
},
|
|
8
|
+
"testsprite": {
|
|
9
|
+
"command": "npx",
|
|
10
|
+
"args": ["-y", "@testsprite/testsprite-mcp@latest"],
|
|
11
|
+
"env": {
|
|
12
|
+
"API_KEY": "${TESTSPRITE_API_KEY}"
|
|
13
|
+
},
|
|
14
|
+
"description": "AI-powered test generation and execution"
|
|
7
15
|
}
|
|
8
16
|
},
|
|
9
17
|
"usage": {
|
|
@@ -22,6 +30,34 @@
|
|
|
22
30
|
"resolve-library-id('nextjs') → get-library-docs('/vercel/next.js', 'app router')",
|
|
23
31
|
"resolve-library-id('tailwindcss') → get-library-docs('/tailwindlabs/tailwindcss', 'configuration')"
|
|
24
32
|
]
|
|
33
|
+
},
|
|
34
|
+
"testsprite": {
|
|
35
|
+
"when": [
|
|
36
|
+
"User runs /p:test ai or /p:test --testsprite",
|
|
37
|
+
"Project needs AI-generated tests for frontend or backend",
|
|
38
|
+
"Auto-fixing flaky or broken tests",
|
|
39
|
+
"Generating comprehensive test coverage"
|
|
40
|
+
],
|
|
41
|
+
"tools": [
|
|
42
|
+
"testsprite_bootstrap_tests: Initialize testing environment",
|
|
43
|
+
"testsprite_generate_code_summary: Analyze project architecture",
|
|
44
|
+
"testsprite_generate_standardized_prd: Generate structured requirements",
|
|
45
|
+
"testsprite_generate_frontend_test_plan: Create frontend test plan",
|
|
46
|
+
"testsprite_generate_backend_test_plan: Create backend test plan",
|
|
47
|
+
"testsprite_generate_code_and_execute: Generate and run tests",
|
|
48
|
+
"testsprite_rerun_tests: Re-run tests with auto-healing"
|
|
49
|
+
],
|
|
50
|
+
"examples": [
|
|
51
|
+
"testsprite_bootstrap_tests(projectPath, 'frontend', 'diff')",
|
|
52
|
+
"testsprite_generate_code_and_execute(projectName, projectPath)"
|
|
53
|
+
],
|
|
54
|
+
"apiKeySetup": "Get free API key at https://testsprite.com/dashboard/api-keys",
|
|
55
|
+
"configFields": {
|
|
56
|
+
"testspriteApiKey": "API key (optional)",
|
|
57
|
+
"testspriteSkip": "'never' | 'later' | null",
|
|
58
|
+
"testspriteSkipUntil": "ISO timestamp for snooze"
|
|
59
|
+
},
|
|
60
|
+
"nonBlocking": true
|
|
25
61
|
}
|
|
26
62
|
}
|
|
27
63
|
}
|
package/bin/dev.js
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* prjct dev - Start prjct web development environment
|
|
5
|
-
*
|
|
6
|
-
* Launches Next.js fullstack app on port 9472
|
|
7
|
-
* - Frontend + API routes + WebSocket for PTY
|
|
8
|
-
*
|
|
9
|
-
* Usage: prjct dev [--no-open]
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const { spawn, exec } = require('child_process')
|
|
13
|
-
const path = require('path')
|
|
14
|
-
const os = require('os')
|
|
15
|
-
|
|
16
|
-
// Configuration
|
|
17
|
-
const PORT = process.env.PRJCT_PORT || 9472
|
|
18
|
-
const WEB_URL = `http://localhost:${PORT}`
|
|
19
|
-
|
|
20
|
-
// Colors for terminal output
|
|
21
|
-
const colors = {
|
|
22
|
-
reset: '\x1b[0m',
|
|
23
|
-
bright: '\x1b[1m',
|
|
24
|
-
dim: '\x1b[2m',
|
|
25
|
-
cyan: '\x1b[36m',
|
|
26
|
-
green: '\x1b[32m',
|
|
27
|
-
yellow: '\x1b[33m',
|
|
28
|
-
red: '\x1b[31m',
|
|
29
|
-
magenta: '\x1b[35m'
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Find prjct-cli root (where packages/ lives)
|
|
33
|
-
function findPrjctRoot() {
|
|
34
|
-
const locations = [
|
|
35
|
-
path.join(__dirname, '..'),
|
|
36
|
-
path.join(os.homedir(), 'Apps', 'prjct', 'prjct-cli'),
|
|
37
|
-
path.join(os.homedir(), '.prjct-cli', 'source'),
|
|
38
|
-
]
|
|
39
|
-
|
|
40
|
-
for (const loc of locations) {
|
|
41
|
-
const pkgPath = path.join(loc, 'packages')
|
|
42
|
-
try {
|
|
43
|
-
require('fs').accessSync(pkgPath)
|
|
44
|
-
return loc
|
|
45
|
-
} catch {}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return locations[0]
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const PRJCT_ROOT = findPrjctRoot()
|
|
52
|
-
const WEB_PATH = path.join(PRJCT_ROOT, 'packages', 'web')
|
|
53
|
-
|
|
54
|
-
// Print banner
|
|
55
|
-
function printBanner() {
|
|
56
|
-
console.log(`
|
|
57
|
-
${colors.cyan}${colors.bright}╔═══════════════════════════════════════════════╗
|
|
58
|
-
║ ║
|
|
59
|
-
║ ⚡ prjct dev ║
|
|
60
|
-
║ ║
|
|
61
|
-
║ App: ${colors.green}http://localhost:${PORT}${colors.cyan} ║
|
|
62
|
-
║ ║
|
|
63
|
-
║ ${colors.dim}Press Ctrl+C to stop${colors.cyan}${colors.bright} ║
|
|
64
|
-
║ ║
|
|
65
|
-
╚═══════════════════════════════════════════════╝${colors.reset}
|
|
66
|
-
`)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Open browser based on OS
|
|
70
|
-
function openBrowser(url) {
|
|
71
|
-
const platform = os.platform()
|
|
72
|
-
let command
|
|
73
|
-
|
|
74
|
-
switch (platform) {
|
|
75
|
-
case 'darwin':
|
|
76
|
-
command = `open "${url}"`
|
|
77
|
-
break
|
|
78
|
-
case 'win32':
|
|
79
|
-
command = `start "" "${url}"`
|
|
80
|
-
break
|
|
81
|
-
default:
|
|
82
|
-
command = `xdg-open "${url}"`
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
exec(command, (err) => {
|
|
86
|
-
if (err) {
|
|
87
|
-
console.log(`${colors.yellow}Could not open browser automatically. Visit: ${url}${colors.reset}`)
|
|
88
|
-
}
|
|
89
|
-
})
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Check if port is available
|
|
93
|
-
function checkPort(port) {
|
|
94
|
-
return new Promise((resolve) => {
|
|
95
|
-
const net = require('net')
|
|
96
|
-
const server = net.createServer()
|
|
97
|
-
|
|
98
|
-
server.once('error', () => resolve(false))
|
|
99
|
-
server.once('listening', () => {
|
|
100
|
-
server.close()
|
|
101
|
-
resolve(true)
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
server.listen(port)
|
|
105
|
-
})
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Wait for server to be ready
|
|
109
|
-
function waitForServer(port, maxAttempts = 60) {
|
|
110
|
-
return new Promise((resolve, reject) => {
|
|
111
|
-
let attempts = 0
|
|
112
|
-
|
|
113
|
-
const check = () => {
|
|
114
|
-
const http = require('http')
|
|
115
|
-
const req = http.get(`http://localhost:${port}`, (res) => {
|
|
116
|
-
resolve(true)
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
req.on('error', () => {
|
|
120
|
-
attempts++
|
|
121
|
-
if (attempts >= maxAttempts) {
|
|
122
|
-
reject(new Error(`Server on port ${port} did not start`))
|
|
123
|
-
} else {
|
|
124
|
-
setTimeout(check, 500)
|
|
125
|
-
}
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
req.end()
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
check()
|
|
132
|
-
})
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Main function
|
|
136
|
-
async function main() {
|
|
137
|
-
const args = process.argv.slice(2)
|
|
138
|
-
const noOpen = args.includes('--no-open')
|
|
139
|
-
|
|
140
|
-
// Check port
|
|
141
|
-
const portAvailable = await checkPort(PORT)
|
|
142
|
-
|
|
143
|
-
if (!portAvailable) {
|
|
144
|
-
console.log(`${colors.red}Port ${PORT} is already in use. Stop other services or set PRJCT_PORT.${colors.reset}`)
|
|
145
|
-
process.exit(1)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
printBanner()
|
|
149
|
-
|
|
150
|
-
// Start Next.js with custom server
|
|
151
|
-
console.log(`${colors.cyan}Starting prjct...${colors.reset}`)
|
|
152
|
-
const webProc = spawn('npm', ['run', 'dev'], {
|
|
153
|
-
cwd: WEB_PATH,
|
|
154
|
-
env: { ...process.env, PORT: PORT.toString() },
|
|
155
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
webProc.stdout.on('data', (data) => {
|
|
159
|
-
const lines = data.toString().split('\n').filter(Boolean)
|
|
160
|
-
lines.forEach(line => {
|
|
161
|
-
// Show relevant output
|
|
162
|
-
if (line.includes('ready') || line.includes('Ready') || line.includes('[WS]')) {
|
|
163
|
-
console.log(`${colors.green}${line}${colors.reset}`)
|
|
164
|
-
} else if (!line.includes('╔') && !line.includes('║') && !line.includes('╚')) {
|
|
165
|
-
console.log(`${colors.dim}${line}${colors.reset}`)
|
|
166
|
-
}
|
|
167
|
-
})
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
webProc.stderr.on('data', (data) => {
|
|
171
|
-
const msg = data.toString().trim()
|
|
172
|
-
// Filter out common non-error messages
|
|
173
|
-
if (!msg.includes('ExperimentalWarning') && !msg.includes('punycode')) {
|
|
174
|
-
console.log(`${colors.red}${msg}${colors.reset}`)
|
|
175
|
-
}
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
// Wait for server and open browser
|
|
179
|
-
try {
|
|
180
|
-
console.log(`${colors.dim}Waiting for server to start...${colors.reset}`)
|
|
181
|
-
await waitForServer(PORT)
|
|
182
|
-
|
|
183
|
-
console.log(`${colors.green}${colors.bright}Ready!${colors.reset}\n`)
|
|
184
|
-
|
|
185
|
-
if (!noOpen) {
|
|
186
|
-
setTimeout(() => openBrowser(WEB_URL), 500)
|
|
187
|
-
}
|
|
188
|
-
} catch (err) {
|
|
189
|
-
console.log(`${colors.red}${err.message}${colors.reset}`)
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Handle shutdown
|
|
193
|
-
const cleanup = () => {
|
|
194
|
-
console.log(`\n${colors.yellow}Shutting down...${colors.reset}`)
|
|
195
|
-
webProc.kill()
|
|
196
|
-
process.exit(0)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
process.on('SIGINT', cleanup)
|
|
200
|
-
process.on('SIGTERM', cleanup)
|
|
201
|
-
|
|
202
|
-
webProc.on('error', (err) => {
|
|
203
|
-
console.log(`${colors.red}Error: ${err.message}${colors.reset}`)
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
webProc.on('exit', (code) => {
|
|
207
|
-
if (code !== 0 && code !== null) {
|
|
208
|
-
console.log(`${colors.red}Exited with code ${code}${colors.reset}`)
|
|
209
|
-
}
|
|
210
|
-
})
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
main().catch((err) => {
|
|
214
|
-
console.error(`${colors.red}Error: ${err.message}${colors.reset}`)
|
|
215
|
-
process.exit(1)
|
|
216
|
-
})
|