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