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
package/bin/serve.js
DELETED
|
@@ -1,361 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* prjct serve - Start the web server
|
|
5
|
-
*
|
|
6
|
-
* Launches the prjct web interface with Claude Code CLI integration.
|
|
7
|
-
* Uses your existing Claude subscription via PTY - no API costs!
|
|
8
|
-
*
|
|
9
|
-
* Smart dependency management:
|
|
10
|
-
* - Tracks installed version in .prjct-web-state.json
|
|
11
|
-
* - Only installs when version changes or node_modules missing
|
|
12
|
-
* - Reuses existing prjct-web server if already running on port
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const { spawn, spawnSync, execSync } = require('child_process')
|
|
16
|
-
const path = require('path')
|
|
17
|
-
const fs = require('fs')
|
|
18
|
-
|
|
19
|
-
const packagesDir = path.join(__dirname, '..', 'packages')
|
|
20
|
-
const sharedDir = path.join(packagesDir, 'shared')
|
|
21
|
-
const webDir = path.join(packagesDir, 'web')
|
|
22
|
-
const prjctDir = path.join(require('os').homedir(), '.prjct-cli')
|
|
23
|
-
const stateFile = path.join(prjctDir, '.prjct-web-state.json')
|
|
24
|
-
|
|
25
|
-
// Parse arguments
|
|
26
|
-
const args = process.argv.slice(2)
|
|
27
|
-
const portArg = args.find((a) => a.startsWith('--port='))
|
|
28
|
-
const port = portArg ? portArg.split('=')[1] : '9472'
|
|
29
|
-
|
|
30
|
-
// Check if web package exists
|
|
31
|
-
if (!fs.existsSync(webDir)) {
|
|
32
|
-
console.error('❌ Web package not found.')
|
|
33
|
-
console.error(' This might be a broken installation.')
|
|
34
|
-
console.error(' Try reinstalling: npm install -g prjct-cli')
|
|
35
|
-
process.exit(1)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Read the current state file
|
|
40
|
-
*/
|
|
41
|
-
function readState() {
|
|
42
|
-
try {
|
|
43
|
-
if (fs.existsSync(stateFile)) {
|
|
44
|
-
return JSON.parse(fs.readFileSync(stateFile, 'utf8'))
|
|
45
|
-
}
|
|
46
|
-
} catch {
|
|
47
|
-
// Ignore errors, return empty state
|
|
48
|
-
}
|
|
49
|
-
return {}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Write state file
|
|
54
|
-
*/
|
|
55
|
-
function writeState(state) {
|
|
56
|
-
try {
|
|
57
|
-
// Ensure ~/.prjct-cli directory exists
|
|
58
|
-
if (!fs.existsSync(prjctDir)) {
|
|
59
|
-
fs.mkdirSync(prjctDir, { recursive: true })
|
|
60
|
-
}
|
|
61
|
-
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2))
|
|
62
|
-
} catch {
|
|
63
|
-
// Ignore write errors
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Get package.json version
|
|
69
|
-
*/
|
|
70
|
-
function getPackageVersion(pkgPath) {
|
|
71
|
-
try {
|
|
72
|
-
const pkg = JSON.parse(fs.readFileSync(path.join(pkgPath, 'package.json'), 'utf8'))
|
|
73
|
-
return pkg.version || '0.0.0'
|
|
74
|
-
} catch {
|
|
75
|
-
return '0.0.0'
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Check if dependencies need to be installed
|
|
81
|
-
* Simple logic: install only if node_modules missing OR version changed
|
|
82
|
-
*/
|
|
83
|
-
function needsInstall(pkgDir, stateKey) {
|
|
84
|
-
const nodeModules = path.join(pkgDir, 'node_modules')
|
|
85
|
-
|
|
86
|
-
// If node_modules doesn't exist, need install
|
|
87
|
-
if (!fs.existsSync(nodeModules)) {
|
|
88
|
-
return { needed: true, reason: 'node_modules not found' }
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const state = readState()
|
|
92
|
-
const currentVersion = getPackageVersion(pkgDir)
|
|
93
|
-
const savedVersion = state[stateKey]?.version
|
|
94
|
-
|
|
95
|
-
// If version changed, need install
|
|
96
|
-
if (savedVersion && savedVersion !== currentVersion) {
|
|
97
|
-
return { needed: true, reason: `${savedVersion} → ${currentVersion}` }
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// node_modules exists and version unchanged = skip
|
|
101
|
-
return { needed: false }
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Update state after successful install
|
|
106
|
-
*/
|
|
107
|
-
function markInstalled(pkgDir, stateKey) {
|
|
108
|
-
const state = readState()
|
|
109
|
-
state[stateKey] = {
|
|
110
|
-
version: getPackageVersion(pkgDir),
|
|
111
|
-
installedAt: new Date().toISOString()
|
|
112
|
-
}
|
|
113
|
-
writeState(state)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Check if dependencies need installation
|
|
117
|
-
const sharedCheck = fs.existsSync(sharedDir) ? needsInstall(sharedDir, 'shared') : { needed: false }
|
|
118
|
-
const webCheck = needsInstall(webDir, 'web')
|
|
119
|
-
|
|
120
|
-
if (sharedCheck.needed || webCheck.needed) {
|
|
121
|
-
const reasons = []
|
|
122
|
-
if (sharedCheck.needed) reasons.push(`shared: ${sharedCheck.reason}`)
|
|
123
|
-
if (webCheck.needed) reasons.push(`web: ${webCheck.reason}`)
|
|
124
|
-
|
|
125
|
-
console.log(`
|
|
126
|
-
╔═══════════════════════════════════════════════════════════╗
|
|
127
|
-
║ ║
|
|
128
|
-
║ ⚡ prjct - Dependency Update ║
|
|
129
|
-
║ ║
|
|
130
|
-
║ ${reasons.join(', ').substring(0, 45).padEnd(45)} ║
|
|
131
|
-
║ ║
|
|
132
|
-
╚═══════════════════════════════════════════════════════════╝
|
|
133
|
-
`)
|
|
134
|
-
|
|
135
|
-
// Install shared dependencies first (if needed)
|
|
136
|
-
if (sharedCheck.needed) {
|
|
137
|
-
console.log('📦 Installing packages/shared dependencies...')
|
|
138
|
-
const sharedInstall = spawnSync('npm', ['install'], {
|
|
139
|
-
cwd: sharedDir,
|
|
140
|
-
stdio: 'inherit',
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
if (sharedInstall.status !== 0) {
|
|
144
|
-
console.error('❌ Failed to install shared dependencies')
|
|
145
|
-
process.exit(1)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Build shared package
|
|
149
|
-
console.log('🔨 Building shared package...')
|
|
150
|
-
const sharedBuild = spawnSync('npm', ['run', 'build'], {
|
|
151
|
-
cwd: sharedDir,
|
|
152
|
-
stdio: 'inherit',
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
if (sharedBuild.status !== 0) {
|
|
156
|
-
console.error('⚠️ Warning: Failed to build shared package')
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
markInstalled(sharedDir, 'shared')
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Install web dependencies (if needed)
|
|
163
|
-
if (webCheck.needed) {
|
|
164
|
-
console.log('📦 Installing packages/web dependencies...')
|
|
165
|
-
const webInstall = spawnSync('npm', ['install'], {
|
|
166
|
-
cwd: webDir,
|
|
167
|
-
stdio: 'inherit',
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
if (webInstall.status !== 0) {
|
|
171
|
-
console.error('❌ Failed to install web dependencies')
|
|
172
|
-
process.exit(1)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
markInstalled(webDir, 'web')
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
console.log('✅ Dependencies ready!\n')
|
|
179
|
-
} else {
|
|
180
|
-
console.log('✅ Dependencies up to date\n')
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Check if process on port is a prjct-web server
|
|
185
|
-
*/
|
|
186
|
-
function isPrjctWebProcess(pid) {
|
|
187
|
-
try {
|
|
188
|
-
if (process.platform === 'win32') {
|
|
189
|
-
// Windows: wmic needs shell for proper command parsing
|
|
190
|
-
const result = spawnSync('wmic', ['process', 'where', `processid=${pid}`, 'get', 'commandline'], {
|
|
191
|
-
shell: true,
|
|
192
|
-
encoding: 'utf8',
|
|
193
|
-
})
|
|
194
|
-
return result.stdout.includes('server.ts') || result.stdout.includes('prjct')
|
|
195
|
-
} else {
|
|
196
|
-
// macOS / Linux - check process command line
|
|
197
|
-
const result = spawnSync('ps', ['-p', pid, '-o', 'command='], {
|
|
198
|
-
encoding: 'utf8',
|
|
199
|
-
})
|
|
200
|
-
const cmd = result.stdout?.trim() || ''
|
|
201
|
-
return cmd.includes('server.ts') || cmd.includes('prjct') || cmd.includes('next')
|
|
202
|
-
}
|
|
203
|
-
} catch {
|
|
204
|
-
return false
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Get PIDs using a port
|
|
210
|
-
*/
|
|
211
|
-
function getPortPids(portToCheck) {
|
|
212
|
-
try {
|
|
213
|
-
if (process.platform === 'win32') {
|
|
214
|
-
// Windows: netstat works without shell
|
|
215
|
-
const result = spawnSync('netstat', ['-ano'], { encoding: 'utf8' })
|
|
216
|
-
const pids = []
|
|
217
|
-
const lines = (result.stdout || '').split('\n')
|
|
218
|
-
for (const line of lines) {
|
|
219
|
-
if (line.includes(`:${portToCheck}`) && line.includes('LISTENING')) {
|
|
220
|
-
const parts = line.trim().split(/\s+/)
|
|
221
|
-
const pid = parts[parts.length - 1]
|
|
222
|
-
if (pid && pid !== '0') pids.push(pid)
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
return pids
|
|
226
|
-
} else {
|
|
227
|
-
// macOS / Linux
|
|
228
|
-
const result = spawnSync('lsof', ['-ti', `:${portToCheck}`], {
|
|
229
|
-
encoding: 'utf8',
|
|
230
|
-
})
|
|
231
|
-
return (result.stdout || '').trim().split('\n').filter(Boolean)
|
|
232
|
-
}
|
|
233
|
-
} catch {
|
|
234
|
-
return []
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Kill specific PIDs
|
|
240
|
-
*/
|
|
241
|
-
function killPids(pids) {
|
|
242
|
-
for (const pid of pids) {
|
|
243
|
-
try {
|
|
244
|
-
if (process.platform === 'win32') {
|
|
245
|
-
// Windows: taskkill works without shell
|
|
246
|
-
spawnSync('taskkill', ['/F', '/PID', pid])
|
|
247
|
-
} else {
|
|
248
|
-
// Unix: kill works without shell
|
|
249
|
-
spawnSync('kill', ['-9', pid])
|
|
250
|
-
}
|
|
251
|
-
} catch {
|
|
252
|
-
// Ignore individual kill errors
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Open URL in browser
|
|
259
|
-
*/
|
|
260
|
-
function openBrowser(url) {
|
|
261
|
-
if (process.platform === 'darwin') {
|
|
262
|
-
spawn('open', [url], { detached: true, stdio: 'ignore' }).unref()
|
|
263
|
-
} else if (process.platform === 'win32') {
|
|
264
|
-
// Windows 'start' is a shell builtin, requires shell: true
|
|
265
|
-
spawn('cmd', ['/c', 'start', '', url], { detached: true, stdio: 'ignore' }).unref()
|
|
266
|
-
} else {
|
|
267
|
-
spawn('xdg-open', [url], { detached: true, stdio: 'ignore' }).unref()
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// Check if port is in use and handle accordingly
|
|
272
|
-
const portPids = getPortPids(port)
|
|
273
|
-
let serverAlreadyRunning = false
|
|
274
|
-
|
|
275
|
-
if (portPids.length > 0) {
|
|
276
|
-
// Check if it's a prjct-web server
|
|
277
|
-
const isPrjctWeb = portPids.some(pid => isPrjctWebProcess(pid))
|
|
278
|
-
|
|
279
|
-
if (isPrjctWeb) {
|
|
280
|
-
console.log(`
|
|
281
|
-
╔═══════════════════════════════════════════════════════════╗
|
|
282
|
-
║ ║
|
|
283
|
-
║ ⚡ prjct - Server Already Running ║
|
|
284
|
-
║ ║
|
|
285
|
-
║ Found existing prjct-web on port ${port} ║
|
|
286
|
-
║ Opening browser... ║
|
|
287
|
-
║ ║
|
|
288
|
-
╚═══════════════════════════════════════════════════════════╝
|
|
289
|
-
`)
|
|
290
|
-
openBrowser(`http://localhost:${port}`)
|
|
291
|
-
serverAlreadyRunning = true
|
|
292
|
-
} else {
|
|
293
|
-
// Not a prjct-web process, ask before killing
|
|
294
|
-
console.log(`⚠️ Port ${port} is in use by another process.`)
|
|
295
|
-
console.log(` PIDs: ${portPids.join(', ')}`)
|
|
296
|
-
console.log(` Stopping to avoid killing unrelated processes.`)
|
|
297
|
-
console.log(` Use --port=XXXX to specify a different port.`)
|
|
298
|
-
process.exit(1)
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// If server is already running, we're done - just opened browser above
|
|
303
|
-
if (serverAlreadyRunning) {
|
|
304
|
-
process.exit(0)
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
console.log(`
|
|
308
|
-
╔═══════════════════════════════════════════════════════════╗
|
|
309
|
-
║ ║
|
|
310
|
-
║ ⚡ prjct - Developer Momentum ║
|
|
311
|
-
║ ║
|
|
312
|
-
║ Starting production server... ║
|
|
313
|
-
║ ║
|
|
314
|
-
║ Web: http://localhost:${port} ║
|
|
315
|
-
║ ║
|
|
316
|
-
║ Using your Claude subscription - $0 API costs ║
|
|
317
|
-
║ ║
|
|
318
|
-
╚═══════════════════════════════════════════════════════════╝
|
|
319
|
-
`)
|
|
320
|
-
|
|
321
|
-
// Build for production if needed (first run or .next missing)
|
|
322
|
-
const nextDir = path.join(webDir, '.next')
|
|
323
|
-
if (!fs.existsSync(nextDir)) {
|
|
324
|
-
console.log('🔨 Building for production (first run)...\n')
|
|
325
|
-
const buildResult = spawnSync('npm', ['run', 'build'], {
|
|
326
|
-
cwd: webDir,
|
|
327
|
-
stdio: 'inherit',
|
|
328
|
-
})
|
|
329
|
-
if (buildResult.status !== 0) {
|
|
330
|
-
console.error('❌ Build failed')
|
|
331
|
-
process.exit(1)
|
|
332
|
-
}
|
|
333
|
-
console.log('✅ Build complete!\n')
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
// Start web server in production mode
|
|
337
|
-
const web = spawn('npm', ['run', 'start'], {
|
|
338
|
-
cwd: webDir,
|
|
339
|
-
stdio: 'inherit',
|
|
340
|
-
env: { ...process.env, PORT: port, NODE_ENV: 'production' },
|
|
341
|
-
})
|
|
342
|
-
|
|
343
|
-
// Open browser after a short delay
|
|
344
|
-
setTimeout(() => {
|
|
345
|
-
openBrowser(`http://localhost:${port}`)
|
|
346
|
-
}, 3000)
|
|
347
|
-
|
|
348
|
-
// Handle shutdown
|
|
349
|
-
const cleanup = () => {
|
|
350
|
-
console.log('\n👋 Shutting down prjct server...')
|
|
351
|
-
web.kill()
|
|
352
|
-
process.exit(0)
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
process.on('SIGINT', cleanup)
|
|
356
|
-
process.on('SIGTERM', cleanup)
|
|
357
|
-
|
|
358
|
-
// Handle errors
|
|
359
|
-
web.on('error', (err) => {
|
|
360
|
-
console.error('Web error:', err.message)
|
|
361
|
-
})
|
package/packages/web/README.md
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
|
2
|
-
|
|
3
|
-
## Getting Started
|
|
4
|
-
|
|
5
|
-
First, run the development server:
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm run dev
|
|
9
|
-
# or
|
|
10
|
-
yarn dev
|
|
11
|
-
# or
|
|
12
|
-
pnpm dev
|
|
13
|
-
# or
|
|
14
|
-
bun dev
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
|
18
|
-
|
|
19
|
-
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
|
20
|
-
|
|
21
|
-
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
|
22
|
-
|
|
23
|
-
## Learn More
|
|
24
|
-
|
|
25
|
-
To learn more about Next.js, take a look at the following resources:
|
|
26
|
-
|
|
27
|
-
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
|
28
|
-
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
|
29
|
-
|
|
30
|
-
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
|
31
|
-
|
|
32
|
-
## Deploy on Vercel
|
|
33
|
-
|
|
34
|
-
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
|
35
|
-
|
|
36
|
-
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from 'next/server'
|
|
2
|
-
import { createClaudeSession, listSessions } from '@/lib/pty'
|
|
3
|
-
|
|
4
|
-
export const dynamic = 'force-dynamic'
|
|
5
|
-
|
|
6
|
-
export async function GET() {
|
|
7
|
-
try {
|
|
8
|
-
const sessions = listSessions()
|
|
9
|
-
return NextResponse.json({ success: true, data: sessions })
|
|
10
|
-
} catch {
|
|
11
|
-
return NextResponse.json(
|
|
12
|
-
{ success: false, error: 'Failed to list sessions' },
|
|
13
|
-
{ status: 500 }
|
|
14
|
-
)
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export async function POST(request: Request) {
|
|
19
|
-
try {
|
|
20
|
-
const body = await request.json()
|
|
21
|
-
const { sessionId, projectDir } = body
|
|
22
|
-
|
|
23
|
-
if (!sessionId || !projectDir) {
|
|
24
|
-
return NextResponse.json(
|
|
25
|
-
{ success: false, error: 'sessionId and projectDir are required' },
|
|
26
|
-
{ status: 400 }
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Create PTY session
|
|
31
|
-
createClaudeSession(sessionId, projectDir)
|
|
32
|
-
|
|
33
|
-
return NextResponse.json({
|
|
34
|
-
success: true,
|
|
35
|
-
data: { sessionId, projectDir }
|
|
36
|
-
})
|
|
37
|
-
} catch (error) {
|
|
38
|
-
console.error('Failed to create session:', error)
|
|
39
|
-
return NextResponse.json(
|
|
40
|
-
{ success: false, error: 'Failed to create session' },
|
|
41
|
-
{ status: 500 }
|
|
42
|
-
)
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from 'next/server'
|
|
2
|
-
import { exec } from 'child_process'
|
|
3
|
-
import { promisify } from 'util'
|
|
4
|
-
|
|
5
|
-
const execAsync = promisify(exec)
|
|
6
|
-
|
|
7
|
-
export const dynamic = 'force-dynamic'
|
|
8
|
-
|
|
9
|
-
export async function GET() {
|
|
10
|
-
try {
|
|
11
|
-
// Check if claude is available
|
|
12
|
-
const { stdout } = await execAsync('which claude && claude --version 2>/dev/null || echo "not found"')
|
|
13
|
-
const lines = stdout.trim().split('\n')
|
|
14
|
-
|
|
15
|
-
const available = !stdout.includes('not found') && lines.length > 0
|
|
16
|
-
const version = available ? lines[lines.length - 1] : null
|
|
17
|
-
|
|
18
|
-
return NextResponse.json({
|
|
19
|
-
success: true,
|
|
20
|
-
data: {
|
|
21
|
-
available,
|
|
22
|
-
version
|
|
23
|
-
}
|
|
24
|
-
})
|
|
25
|
-
} catch {
|
|
26
|
-
return NextResponse.json({
|
|
27
|
-
success: true,
|
|
28
|
-
data: {
|
|
29
|
-
available: false,
|
|
30
|
-
version: null
|
|
31
|
-
}
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from 'next/server'
|
|
2
|
-
import { promises as fs } from 'fs'
|
|
3
|
-
import { getProjects } from '@/lib/projects'
|
|
4
|
-
import { lookup } from 'mime-types'
|
|
5
|
-
|
|
6
|
-
export const dynamic = 'force-dynamic'
|
|
7
|
-
|
|
8
|
-
export async function GET(
|
|
9
|
-
request: Request,
|
|
10
|
-
{ params }: { params: Promise<{ id: string }> }
|
|
11
|
-
) {
|
|
12
|
-
try {
|
|
13
|
-
const { id } = await params
|
|
14
|
-
const projects = await getProjects()
|
|
15
|
-
const project = projects.find(p => p.id === id)
|
|
16
|
-
|
|
17
|
-
if (!project?.iconPath) {
|
|
18
|
-
return new NextResponse(null, { status: 404 })
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const file = await fs.readFile(project.iconPath)
|
|
22
|
-
const mimeType = lookup(project.iconPath) || 'application/octet-stream'
|
|
23
|
-
|
|
24
|
-
return new NextResponse(file, {
|
|
25
|
-
headers: {
|
|
26
|
-
'Content-Type': mimeType,
|
|
27
|
-
'Cache-Control': 'public, max-age=86400'
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
} catch {
|
|
31
|
-
return new NextResponse(null, { status: 404 })
|
|
32
|
-
}
|
|
33
|
-
}
|