prjct-cli 0.18.1 → 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.
Files changed (245) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/CLAUDE.md +74 -211
  3. package/core/agentic/prompt-builder.ts +3 -7
  4. package/core/command-registry/optional-commands.ts +0 -20
  5. package/core/infrastructure/command-installer/command-installer.ts +8 -1
  6. package/core/infrastructure/command-installer/global-config.ts +31 -1
  7. package/core/infrastructure/command-installer/index.ts +1 -1
  8. package/core/infrastructure/setup.ts +3 -0
  9. package/package.json +3 -17
  10. package/templates/agentic/subagent-generation.md +8 -6
  11. package/templates/commands/done.md +57 -258
  12. package/templates/commands/now.md +72 -277
  13. package/templates/commands/ship.md +55 -261
  14. package/templates/commands/sync.md +7 -7
  15. package/templates/commands/test.md +328 -21
  16. package/templates/global/CLAUDE.md +40 -205
  17. package/templates/global/docs/agents.md +88 -0
  18. package/templates/global/docs/architecture.md +103 -0
  19. package/templates/global/docs/commands.md +98 -0
  20. package/templates/global/docs/validation.md +95 -0
  21. package/templates/mcp-config.json +36 -0
  22. package/bin/dev.js +0 -216
  23. package/bin/serve.js +0 -361
  24. package/packages/web/README.md +0 -36
  25. package/packages/web/app/api/claude/sessions/route.ts +0 -44
  26. package/packages/web/app/api/claude/status/route.ts +0 -34
  27. package/packages/web/app/api/projects/[id]/icon/route.ts +0 -33
  28. package/packages/web/app/api/projects/[id]/momentum/route.ts +0 -257
  29. package/packages/web/app/api/projects/[id]/route.ts +0 -29
  30. package/packages/web/app/api/projects/[id]/stats/route.ts +0 -41
  31. package/packages/web/app/api/projects/[id]/status/route.ts +0 -21
  32. package/packages/web/app/api/projects/route.ts +0 -16
  33. package/packages/web/app/api/sessions/current/route.ts +0 -132
  34. package/packages/web/app/api/sessions/history/route.ts +0 -204
  35. package/packages/web/app/error.tsx +0 -34
  36. package/packages/web/app/favicon.ico +0 -0
  37. package/packages/web/app/globals.css +0 -198
  38. package/packages/web/app/layout.tsx +0 -53
  39. package/packages/web/app/loading.tsx +0 -7
  40. package/packages/web/app/not-found.tsx +0 -25
  41. package/packages/web/app/page.tsx +0 -12
  42. package/packages/web/app/project/[id]/code/layout.tsx +0 -18
  43. package/packages/web/app/project/[id]/code/page.tsx +0 -408
  44. package/packages/web/app/project/[id]/error.tsx +0 -41
  45. package/packages/web/app/project/[id]/loading.tsx +0 -9
  46. package/packages/web/app/project/[id]/not-found.tsx +0 -27
  47. package/packages/web/app/project/[id]/page.tsx +0 -384
  48. package/packages/web/app/project/[id]/reports/page.tsx +0 -59
  49. package/packages/web/app/project/[id]/reports/print/page.tsx +0 -58
  50. package/packages/web/app/sessions/page.tsx +0 -165
  51. package/packages/web/app/settings/page.tsx +0 -151
  52. package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +0 -2
  53. package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +0 -49
  54. package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +0 -8
  55. package/packages/web/components/ActivityTimeline/hooks/index.ts +0 -2
  56. package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +0 -9
  57. package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +0 -23
  58. package/packages/web/components/ActivityTimeline/index.ts +0 -2
  59. package/packages/web/components/AgentsCard/AgentsCard.tsx +0 -93
  60. package/packages/web/components/AgentsCard/AgentsCard.types.ts +0 -14
  61. package/packages/web/components/AgentsCard/index.ts +0 -2
  62. package/packages/web/components/AppSidebar/AppSidebar.tsx +0 -316
  63. package/packages/web/components/AppSidebar/index.ts +0 -1
  64. package/packages/web/components/BackLink/BackLink.tsx +0 -18
  65. package/packages/web/components/BackLink/BackLink.types.ts +0 -5
  66. package/packages/web/components/BackLink/index.ts +0 -2
  67. package/packages/web/components/BentoCard/BentoCard.constants.ts +0 -16
  68. package/packages/web/components/BentoCard/BentoCard.tsx +0 -48
  69. package/packages/web/components/BentoCard/BentoCard.types.ts +0 -15
  70. package/packages/web/components/BentoCard/index.ts +0 -2
  71. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +0 -9
  72. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +0 -18
  73. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +0 -5
  74. package/packages/web/components/BentoCardSkeleton/index.ts +0 -2
  75. package/packages/web/components/BentoGrid/BentoGrid.tsx +0 -18
  76. package/packages/web/components/BentoGrid/BentoGrid.types.ts +0 -4
  77. package/packages/web/components/BentoGrid/index.ts +0 -2
  78. package/packages/web/components/BlockersCard/BlockersCard.tsx +0 -75
  79. package/packages/web/components/BlockersCard/BlockersCard.types.ts +0 -12
  80. package/packages/web/components/BlockersCard/index.ts +0 -2
  81. package/packages/web/components/CommandBar/CommandBar.tsx +0 -67
  82. package/packages/web/components/CommandBar/index.ts +0 -1
  83. package/packages/web/components/CommandButton/CommandButton.tsx +0 -46
  84. package/packages/web/components/CommandButton/index.ts +0 -1
  85. package/packages/web/components/ConnectionStatus/ConnectionStatus.tsx +0 -29
  86. package/packages/web/components/ConnectionStatus/index.ts +0 -1
  87. package/packages/web/components/DashboardContent/DashboardContent.tsx +0 -284
  88. package/packages/web/components/DashboardContent/index.ts +0 -1
  89. package/packages/web/components/DateGroup/DateGroup.tsx +0 -18
  90. package/packages/web/components/DateGroup/DateGroup.types.ts +0 -6
  91. package/packages/web/components/DateGroup/DateGroup.utils.ts +0 -11
  92. package/packages/web/components/DateGroup/index.ts +0 -2
  93. package/packages/web/components/EmptyState/EmptyState.tsx +0 -76
  94. package/packages/web/components/EmptyState/EmptyState.types.ts +0 -11
  95. package/packages/web/components/EmptyState/index.ts +0 -2
  96. package/packages/web/components/EventRow/EventRow.constants.ts +0 -10
  97. package/packages/web/components/EventRow/EventRow.tsx +0 -49
  98. package/packages/web/components/EventRow/EventRow.types.ts +0 -7
  99. package/packages/web/components/EventRow/EventRow.utils.ts +0 -49
  100. package/packages/web/components/EventRow/index.ts +0 -2
  101. package/packages/web/components/ExpandButton/ExpandButton.tsx +0 -18
  102. package/packages/web/components/ExpandButton/ExpandButton.types.ts +0 -6
  103. package/packages/web/components/ExpandButton/index.ts +0 -2
  104. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +0 -14
  105. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +0 -5
  106. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +0 -13
  107. package/packages/web/components/HealthGradientBackground/index.ts +0 -2
  108. package/packages/web/components/HeroSection/HeroSection.tsx +0 -92
  109. package/packages/web/components/HeroSection/HeroSection.types.ts +0 -14
  110. package/packages/web/components/HeroSection/HeroSection.utils.ts +0 -11
  111. package/packages/web/components/HeroSection/hooks/index.ts +0 -2
  112. package/packages/web/components/HeroSection/hooks/useCountUp.ts +0 -45
  113. package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +0 -18
  114. package/packages/web/components/HeroSection/index.ts +0 -2
  115. package/packages/web/components/IdeasCard/IdeasCard.tsx +0 -115
  116. package/packages/web/components/IdeasCard/IdeasCard.types.ts +0 -10
  117. package/packages/web/components/IdeasCard/index.ts +0 -2
  118. package/packages/web/components/InsightMessage/InsightMessage.tsx +0 -9
  119. package/packages/web/components/InsightMessage/InsightMessage.types.ts +0 -3
  120. package/packages/web/components/InsightMessage/index.ts +0 -2
  121. package/packages/web/components/Logo/Logo.tsx +0 -65
  122. package/packages/web/components/Logo/index.ts +0 -1
  123. package/packages/web/components/MarkdownContent/MarkdownContent.tsx +0 -123
  124. package/packages/web/components/MarkdownContent/index.ts +0 -1
  125. package/packages/web/components/MasonryGrid/MasonryGrid.tsx +0 -18
  126. package/packages/web/components/MasonryGrid/index.ts +0 -1
  127. package/packages/web/components/MomentumWidget/MomentumWidget.tsx +0 -119
  128. package/packages/web/components/MomentumWidget/MomentumWidget.types.ts +0 -16
  129. package/packages/web/components/MomentumWidget/index.ts +0 -2
  130. package/packages/web/components/NowCard/NowCard.tsx +0 -118
  131. package/packages/web/components/NowCard/NowCard.types.ts +0 -16
  132. package/packages/web/components/NowCard/index.ts +0 -2
  133. package/packages/web/components/PageHeader/PageHeader.tsx +0 -24
  134. package/packages/web/components/PageHeader/index.ts +0 -1
  135. package/packages/web/components/ProgressRing/ProgressRing.constants.ts +0 -20
  136. package/packages/web/components/ProgressRing/ProgressRing.tsx +0 -51
  137. package/packages/web/components/ProgressRing/ProgressRing.types.ts +0 -11
  138. package/packages/web/components/ProgressRing/index.ts +0 -2
  139. package/packages/web/components/ProjectAvatar/ProjectAvatar.tsx +0 -54
  140. package/packages/web/components/ProjectAvatar/index.ts +0 -1
  141. package/packages/web/components/ProjectColorDot/ProjectColorDot.tsx +0 -37
  142. package/packages/web/components/ProjectColorDot/index.ts +0 -1
  143. package/packages/web/components/ProjectSelectorModal/ProjectSelectorModal.tsx +0 -104
  144. package/packages/web/components/ProjectSelectorModal/index.ts +0 -1
  145. package/packages/web/components/Providers/Providers.tsx +0 -48
  146. package/packages/web/components/Providers/index.ts +0 -1
  147. package/packages/web/components/QueueCard/QueueCard.tsx +0 -125
  148. package/packages/web/components/QueueCard/QueueCard.types.ts +0 -12
  149. package/packages/web/components/QueueCard/QueueCard.utils.ts +0 -12
  150. package/packages/web/components/QueueCard/index.ts +0 -2
  151. package/packages/web/components/RecoverCard/RecoverCard.tsx +0 -72
  152. package/packages/web/components/RecoverCard/RecoverCard.types.ts +0 -16
  153. package/packages/web/components/RecoverCard/index.ts +0 -2
  154. package/packages/web/components/RoadmapCard/RoadmapCard.tsx +0 -145
  155. package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +0 -16
  156. package/packages/web/components/RoadmapCard/index.ts +0 -2
  157. package/packages/web/components/ShipsCard/ShipsCard.tsx +0 -95
  158. package/packages/web/components/ShipsCard/ShipsCard.types.ts +0 -14
  159. package/packages/web/components/ShipsCard/ShipsCard.utils.ts +0 -4
  160. package/packages/web/components/ShipsCard/index.ts +0 -2
  161. package/packages/web/components/SparklineChart/SparklineChart.tsx +0 -40
  162. package/packages/web/components/SparklineChart/SparklineChart.types.ts +0 -6
  163. package/packages/web/components/SparklineChart/index.ts +0 -2
  164. package/packages/web/components/StatsMasonry/StatsMasonry.tsx +0 -95
  165. package/packages/web/components/StatsMasonry/index.ts +0 -1
  166. package/packages/web/components/StreakCard/StreakCard.constants.ts +0 -2
  167. package/packages/web/components/StreakCard/StreakCard.tsx +0 -55
  168. package/packages/web/components/StreakCard/StreakCard.types.ts +0 -4
  169. package/packages/web/components/StreakCard/index.ts +0 -2
  170. package/packages/web/components/TasksCounter/TasksCounter.tsx +0 -14
  171. package/packages/web/components/TasksCounter/TasksCounter.types.ts +0 -3
  172. package/packages/web/components/TasksCounter/index.ts +0 -2
  173. package/packages/web/components/TechStackBadges/TechStackBadges.tsx +0 -28
  174. package/packages/web/components/TechStackBadges/index.ts +0 -1
  175. package/packages/web/components/TerminalDock/DockToggleTab.tsx +0 -29
  176. package/packages/web/components/TerminalDock/TerminalDock.tsx +0 -386
  177. package/packages/web/components/TerminalDock/TerminalDockTab.tsx +0 -130
  178. package/packages/web/components/TerminalDock/TerminalTabBar.tsx +0 -142
  179. package/packages/web/components/TerminalDock/index.ts +0 -2
  180. package/packages/web/components/TerminalTabs/TerminalTab.tsx +0 -95
  181. package/packages/web/components/TerminalTabs/TerminalTabs.tsx +0 -211
  182. package/packages/web/components/TerminalTabs/index.ts +0 -1
  183. package/packages/web/components/VelocityBadge/VelocityBadge.tsx +0 -32
  184. package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +0 -3
  185. package/packages/web/components/VelocityBadge/index.ts +0 -2
  186. package/packages/web/components/VelocityCard/VelocityCard.tsx +0 -73
  187. package/packages/web/components/VelocityCard/VelocityCard.types.ts +0 -7
  188. package/packages/web/components/VelocityCard/index.ts +0 -2
  189. package/packages/web/components/WeeklyReports/PrintableReport.tsx +0 -259
  190. package/packages/web/components/WeeklyReports/ReportPreviewCard.tsx +0 -187
  191. package/packages/web/components/WeeklyReports/WeekCalendar.tsx +0 -288
  192. package/packages/web/components/WeeklyReports/WeeklyReports.tsx +0 -149
  193. package/packages/web/components/WeeklyReports/index.ts +0 -4
  194. package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +0 -25
  195. package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +0 -4
  196. package/packages/web/components/WeeklySparkline/index.ts +0 -2
  197. package/packages/web/components/charts/SessionsChart.tsx +0 -175
  198. package/packages/web/components/ui/alert-dialog.tsx +0 -157
  199. package/packages/web/components/ui/badge.tsx +0 -46
  200. package/packages/web/components/ui/button.tsx +0 -60
  201. package/packages/web/components/ui/card.tsx +0 -92
  202. package/packages/web/components/ui/chart.tsx +0 -385
  203. package/packages/web/components/ui/dialog.tsx +0 -143
  204. package/packages/web/components/ui/drawer.tsx +0 -135
  205. package/packages/web/components/ui/dropdown-menu.tsx +0 -257
  206. package/packages/web/components/ui/input.tsx +0 -21
  207. package/packages/web/components/ui/scroll-area.tsx +0 -58
  208. package/packages/web/components/ui/select.tsx +0 -187
  209. package/packages/web/components/ui/sheet.tsx +0 -139
  210. package/packages/web/components/ui/tabs.tsx +0 -66
  211. package/packages/web/components/ui/tooltip.tsx +0 -61
  212. package/packages/web/components.json +0 -22
  213. package/packages/web/context/GlobalTerminalContext.tsx +0 -538
  214. package/packages/web/context/TerminalContext.tsx +0 -45
  215. package/packages/web/context/TerminalTabsContext.tsx +0 -181
  216. package/packages/web/eslint.config.mjs +0 -18
  217. package/packages/web/hooks/useClaudeTerminal.ts +0 -425
  218. package/packages/web/hooks/useProjectStats.ts +0 -93
  219. package/packages/web/hooks/useProjects.ts +0 -73
  220. package/packages/web/lib/actions/projects.ts +0 -15
  221. package/packages/web/lib/commands.ts +0 -81
  222. package/packages/web/lib/format.ts +0 -23
  223. package/packages/web/lib/generate-week-report.ts +0 -285
  224. package/packages/web/lib/parse-prjct-files.ts +0 -1123
  225. package/packages/web/lib/project-colors.ts +0 -58
  226. package/packages/web/lib/projects.ts +0 -506
  227. package/packages/web/lib/pty.ts +0 -101
  228. package/packages/web/lib/query-config.ts +0 -44
  229. package/packages/web/lib/services/index.ts +0 -9
  230. package/packages/web/lib/services/projects.server.ts +0 -66
  231. package/packages/web/lib/services/stats.server.ts +0 -562
  232. package/packages/web/lib/unified-loader.ts +0 -396
  233. package/packages/web/lib/utils.ts +0 -6
  234. package/packages/web/next-env.d.ts +0 -6
  235. package/packages/web/next.config.ts +0 -7
  236. package/packages/web/package.json +0 -57
  237. package/packages/web/postcss.config.mjs +0 -7
  238. package/packages/web/public/file.svg +0 -1
  239. package/packages/web/public/globe.svg +0 -1
  240. package/packages/web/public/next.svg +0 -1
  241. package/packages/web/public/vercel.svg +0 -1
  242. package/packages/web/public/window.svg +0 -1
  243. package/packages/web/server.ts +0 -312
  244. package/packages/web/tsconfig.json +0 -34
  245. 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
- })
@@ -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
- }