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