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
@@ -1,16 +0,0 @@
1
- export type MomentumStatus = 'hot' | 'active' | 'cooling' | 'cold'
2
-
3
- export interface MomentumData {
4
- dailyTasks: number[]
5
- totalTasks: number
6
- totalShips: number
7
- lastActivityDate: string | null
8
- daysSinceActivity: number
9
- streak: number
10
- status: MomentumStatus
11
- message: string
12
- }
13
-
14
- export interface MomentumWidgetProps {
15
- projectId: string
16
- }
@@ -1,2 +0,0 @@
1
- export { MomentumWidget } from './MomentumWidget'
2
- export type { MomentumWidgetProps, MomentumData, MomentumStatus } from './MomentumWidget.types'
@@ -1,118 +0,0 @@
1
- 'use client'
2
-
3
- import Link from 'next/link'
4
- import { EmptyState } from '@/components/EmptyState'
5
- import { Target, Clock, Bot, Pause, Play, CheckCircle2 } from 'lucide-react'
6
- import { cn } from '@/lib/utils'
7
- import type { NowCardProps } from './NowCard.types'
8
-
9
- export function NowCard({ currentTask, codeHref, className }: NowCardProps) {
10
- return (
11
- <div className={cn(
12
- 'relative overflow-hidden rounded-xl border bg-card p-4',
13
- className
14
- )}>
15
- <div className="flex items-center justify-between mb-3">
16
- <div className="flex items-center gap-2">
17
- <Target className="h-4 w-4 text-muted-foreground" />
18
- <span className="text-xs font-bold uppercase tracking-[0.15em] text-muted-foreground">
19
- Now
20
- </span>
21
- </div>
22
- {currentTask && (
23
- <div className="flex items-center gap-2">
24
- {currentTask.pausedAt ? (
25
- <span className="inline-flex items-center gap-1 text-xs font-semibold text-muted-foreground bg-muted px-2 py-0.5 rounded-full">
26
- <Pause className="w-2.5 h-2.5" />
27
- Paused
28
- </span>
29
- ) : (
30
- <span className="inline-flex items-center gap-1 text-xs font-semibold text-foreground bg-muted px-2 py-0.5 rounded-full">
31
- <Play className="w-2.5 h-2.5 fill-current" />
32
- Working
33
- </span>
34
- )}
35
- </div>
36
- )}
37
- </div>
38
-
39
- {currentTask ? (
40
- <div className="space-y-3">
41
- <p className="text-sm font-medium leading-tight break-words">
42
- {currentTask.task}
43
- </p>
44
-
45
- <div className="flex flex-wrap items-center gap-3">
46
- {currentTask.agent && (
47
- <div className="inline-flex items-center gap-1.5 text-xs text-muted-foreground bg-muted/50 px-2 py-1 rounded">
48
- <Bot className="h-3 w-3" />
49
- <span className="font-mono">{currentTask.agent}</span>
50
- </div>
51
- )}
52
-
53
- {currentTask.startedAt && (
54
- <div className="inline-flex items-center gap-1.5 text-xs text-muted-foreground">
55
- <Clock className="h-3 w-3" />
56
- <span>Started {new Date(currentTask.startedAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</span>
57
- </div>
58
- )}
59
-
60
- {currentTask.estimatedDuration && (
61
- <span className="text-xs text-muted-foreground">
62
- Est. {currentTask.estimatedDuration}
63
- </span>
64
- )}
65
- </div>
66
-
67
- {/* Progress indicator */}
68
- <div className="pt-1">
69
- <div className="h-1.5 bg-muted rounded-full overflow-hidden">
70
- <div
71
- className="h-full rounded-full transition-all duration-300 bg-foreground"
72
- style={{ width: currentTask.pausedAt ? '30%' : '60%' }}
73
- />
74
- </div>
75
- </div>
76
-
77
- {/* Action buttons */}
78
- {codeHref && (
79
- <div className="flex gap-2 pt-2">
80
- <Link
81
- href={`${codeHref}?cmd=p.%20done`}
82
- className="flex-1 flex items-center justify-center gap-1.5 text-xs font-medium px-3 py-2 rounded-lg bg-muted text-foreground hover:bg-muted/80 transition-colors"
83
- >
84
- <CheckCircle2 className="h-3.5 w-3.5" />
85
- Done
86
- </Link>
87
- {currentTask.pausedAt ? (
88
- <Link
89
- href={`${codeHref}?cmd=p.%20resume`}
90
- className="flex-1 flex items-center justify-center gap-1.5 text-xs font-medium px-3 py-2 rounded-lg bg-muted text-foreground hover:bg-muted/80 transition-colors"
91
- >
92
- <Play className="h-3.5 w-3.5" />
93
- Resume
94
- </Link>
95
- ) : (
96
- <Link
97
- href={`${codeHref}?cmd=p.%20pause`}
98
- className="flex-1 flex items-center justify-center gap-1.5 text-xs font-medium px-3 py-2 rounded-lg bg-muted text-foreground hover:bg-muted/80 transition-colors"
99
- >
100
- <Pause className="h-3.5 w-3.5" />
101
- Pause
102
- </Link>
103
- )}
104
- </div>
105
- )}
106
- </div>
107
- ) : (
108
- <EmptyState
109
- icon={Target}
110
- title="No active task"
111
- description="Start working on something"
112
- command="/p:now"
113
- href={codeHref}
114
- />
115
- )}
116
- </div>
117
- )
118
- }
@@ -1,16 +0,0 @@
1
- export interface CurrentTask {
2
- task: string
3
- startedAt?: string
4
- agent?: string
5
- agentConfidence?: number
6
- estimatedDuration?: string
7
- pausedAt?: string
8
- pauseReason?: string
9
- duration?: string
10
- }
11
-
12
- export interface NowCardProps {
13
- currentTask: CurrentTask | null
14
- codeHref?: string
15
- className?: string
16
- }
@@ -1,2 +0,0 @@
1
- export { NowCard } from './NowCard'
2
- export type { NowCardProps } from './NowCard.types'
@@ -1,24 +0,0 @@
1
- import { getProjectBgClass } from '@/lib/project-colors'
2
-
3
- interface PageHeaderProps {
4
- projectId: string
5
- projectName: string
6
- section?: string
7
- }
8
-
9
- export function PageHeader({ projectId, projectName, section }: PageHeaderProps) {
10
- const colorBg = getProjectBgClass(projectId)
11
-
12
- return (
13
- <div className="flex items-center gap-3 mb-6">
14
- <div className={`w-3 h-3 rounded-full shrink-0 ${colorBg}`} />
15
- <h1 className="text-2xl font-semibold">{projectName}</h1>
16
- {section && (
17
- <>
18
- <span className="text-muted-foreground/50">/</span>
19
- <span className="text-xl text-muted-foreground">{section}</span>
20
- </>
21
- )}
22
- </div>
23
- )
24
- }
@@ -1 +0,0 @@
1
- export { PageHeader } from './PageHeader'
@@ -1,20 +0,0 @@
1
- import type { ProgressRingSize, AccentColor } from './ProgressRing.types'
2
-
3
- export const PROGRESS_RING_SIZES: Record<ProgressRingSize, {
4
- container: string
5
- text: string
6
- viewBox: number
7
- radius: number
8
- }> = {
9
- sm: { container: 'h-8 w-8', text: 'text-xs', viewBox: 36, radius: 14 },
10
- md: { container: 'h-12 w-12', text: 'text-xs', viewBox: 36, radius: 14 },
11
- lg: { container: 'h-16 w-16', text: 'text-sm', viewBox: 36, radius: 14 },
12
- xl: { container: 'h-20 w-20', text: 'text-base', viewBox: 36, radius: 14 },
13
- }
14
-
15
- export const PROGRESS_RING_COLOR_STYLES: Record<AccentColor, string> = {
16
- default: 'text-foreground',
17
- success: 'text-emerald-500',
18
- warning: 'text-amber-500',
19
- destructive: 'text-red-500',
20
- }
@@ -1,51 +0,0 @@
1
- 'use client'
2
-
3
- import { cn } from '@/lib/utils'
4
- import { PROGRESS_RING_SIZES, PROGRESS_RING_COLOR_STYLES } from './ProgressRing.constants'
5
- import type { ProgressRingProps } from './ProgressRing.types'
6
-
7
- export function ProgressRing({
8
- value,
9
- size = 'md',
10
- showValue = true,
11
- strokeWidth = 3,
12
- className,
13
- accentColor = 'default',
14
- }: ProgressRingProps) {
15
- const { container, text, viewBox, radius } = PROGRESS_RING_SIZES[size]
16
- const circumference = 2 * Math.PI * radius
17
- const strokeDashoffset = circumference - (value / 100) * circumference
18
-
19
- return (
20
- <div className={cn('relative', container, className)}>
21
- <svg className="h-full w-full -rotate-90" viewBox={`0 0 ${viewBox} ${viewBox}`}>
22
- <circle
23
- cx={viewBox / 2}
24
- cy={viewBox / 2}
25
- r={radius}
26
- fill="none"
27
- stroke="currentColor"
28
- strokeWidth={strokeWidth}
29
- className="text-foreground/10"
30
- />
31
- <circle
32
- cx={viewBox / 2}
33
- cy={viewBox / 2}
34
- r={radius}
35
- fill="none"
36
- stroke="currentColor"
37
- strokeWidth={strokeWidth}
38
- strokeDasharray={circumference}
39
- strokeDashoffset={strokeDashoffset}
40
- strokeLinecap="round"
41
- className={cn('transition-all duration-700 ease-out', PROGRESS_RING_COLOR_STYLES[accentColor])}
42
- />
43
- </svg>
44
- {showValue && (
45
- <span className={cn('absolute inset-0 flex items-center justify-center font-bold tabular-nums', text)}>
46
- {value}
47
- </span>
48
- )}
49
- </div>
50
- )
51
- }
@@ -1,11 +0,0 @@
1
- export type ProgressRingSize = 'sm' | 'md' | 'lg' | 'xl'
2
- export type AccentColor = 'default' | 'success' | 'warning' | 'destructive'
3
-
4
- export interface ProgressRingProps {
5
- value: number
6
- size?: ProgressRingSize
7
- showValue?: boolean
8
- strokeWidth?: number
9
- className?: string
10
- accentColor?: AccentColor
11
- }
@@ -1,2 +0,0 @@
1
- export { ProgressRing } from './ProgressRing'
2
- export type { ProgressRingProps } from './ProgressRing.types'
@@ -1,54 +0,0 @@
1
- 'use client'
2
-
3
- import { cn } from '@/lib/utils'
4
-
5
- interface ProjectAvatarProps {
6
- projectId: string
7
- name: string
8
- iconPath?: string | null
9
- size?: 'sm' | 'md' | 'lg'
10
- className?: string
11
- }
12
-
13
- const sizeClasses = {
14
- sm: 'w-8 h-8 text-xs',
15
- md: 'w-9 h-9 text-sm',
16
- lg: 'w-10 h-10 text-sm'
17
- }
18
-
19
- export function ProjectAvatar({
20
- projectId,
21
- name,
22
- iconPath,
23
- size = 'md',
24
- className
25
- }: ProjectAvatarProps) {
26
- const initials = name.slice(0, 2).toUpperCase()
27
-
28
- return (
29
- <div
30
- className={cn(
31
- 'rounded-lg flex items-center justify-center overflow-hidden shrink-0 bg-muted border border-border',
32
- sizeClasses[size],
33
- className
34
- )}
35
- >
36
- {iconPath ? (
37
- <img
38
- src={`/api/projects/${projectId}/icon`}
39
- alt=""
40
- className="w-full h-full object-cover"
41
- onError={(e) => {
42
- e.currentTarget.style.display = 'none'
43
- if (e.currentTarget.nextElementSibling) {
44
- (e.currentTarget.nextElementSibling as HTMLElement).classList.remove('hidden')
45
- }
46
- }}
47
- />
48
- ) : null}
49
- <span className={cn('font-medium text-muted-foreground', iconPath ? 'hidden' : '')}>
50
- {initials}
51
- </span>
52
- </div>
53
- )
54
- }
@@ -1 +0,0 @@
1
- export { ProjectAvatar } from './ProjectAvatar'
@@ -1,37 +0,0 @@
1
- 'use client'
2
-
3
- import { cn } from '@/lib/utils'
4
- import { getProjectColor } from '@/lib/project-colors'
5
-
6
- interface ProjectColorDotProps {
7
- projectId: string
8
- size?: 'sm' | 'md' | 'lg' | 'xl'
9
- className?: string
10
- }
11
-
12
- const sizeClasses = {
13
- sm: 'w-2 h-2',
14
- md: 'w-3 h-3',
15
- lg: 'w-4 h-4',
16
- xl: 'w-5 h-5',
17
- }
18
-
19
- export function ProjectColorDot({
20
- projectId,
21
- size = 'md',
22
- className
23
- }: ProjectColorDotProps) {
24
- const color = getProjectColor(projectId)
25
-
26
- return (
27
- <div
28
- className={cn(
29
- 'rounded-full shrink-0',
30
- sizeClasses[size],
31
- color.bg,
32
- className
33
- )}
34
- aria-hidden="true"
35
- />
36
- )
37
- }
@@ -1 +0,0 @@
1
- export { ProjectColorDot } from './ProjectColorDot'
@@ -1,104 +0,0 @@
1
- 'use client'
2
-
3
- import { useState } from 'react'
4
- import { useProjects } from '@/hooks/useProjects'
5
- import {
6
- Dialog,
7
- DialogContent,
8
- DialogHeader,
9
- DialogTitle,
10
- DialogDescription,
11
- } from '@/components/ui/dialog'
12
- import { Input } from '@/components/ui/input'
13
- import { ProjectAvatar } from '@/components/ProjectAvatar'
14
- import { Loader2, Search, FolderGit2 } from 'lucide-react'
15
- import { cn } from '@/lib/utils'
16
- import { formatPath } from '@/lib/format'
17
-
18
- interface ProjectSelectorModalProps {
19
- isOpen: boolean
20
- onClose: () => void
21
- onSelectProject: (projectId: string, projectName: string, projectPath: string) => void
22
- }
23
-
24
- export function ProjectSelectorModal({
25
- isOpen,
26
- onClose,
27
- onSelectProject,
28
- }: ProjectSelectorModalProps) {
29
- const [search, setSearch] = useState('')
30
- const { data: projects, isLoading } = useProjects()
31
-
32
- const filteredProjects = projects?.filter((project) =>
33
- project.name?.toLowerCase().includes(search.toLowerCase()) ||
34
- project.repoPath?.toLowerCase().includes(search.toLowerCase())
35
- ) || []
36
-
37
- return (
38
- <Dialog open={isOpen} onOpenChange={onClose}>
39
- <DialogContent className="sm:max-w-md">
40
- <DialogHeader>
41
- <DialogTitle>Select a Project</DialogTitle>
42
- <DialogDescription>
43
- Choose a project to open a terminal session
44
- </DialogDescription>
45
- </DialogHeader>
46
-
47
- <div className="relative">
48
- <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
49
- <Input
50
- placeholder="Search projects..."
51
- value={search}
52
- onChange={(e) => setSearch(e.target.value)}
53
- className="pl-9"
54
- />
55
- </div>
56
-
57
- <div className="max-h-[300px] overflow-y-auto space-y-1">
58
- {isLoading ? (
59
- <div className="flex items-center justify-center py-8">
60
- <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
61
- </div>
62
- ) : filteredProjects.length === 0 ? (
63
- <div className="text-center py-8 text-muted-foreground">
64
- {search ? 'No projects found' : 'No projects available'}
65
- </div>
66
- ) : (
67
- filteredProjects.map((project) => (
68
- <button
69
- key={project.id}
70
- onClick={() => {
71
- const projectPath = project.repoPath || project.path || '/tmp'
72
- const projectName = project.name || project.id
73
- onSelectProject(project.id, projectName, projectPath)
74
- }}
75
- className={cn(
76
- 'w-full flex items-center gap-3 p-3 rounded-lg transition-colors',
77
- 'hover:bg-accent text-left'
78
- )}
79
- >
80
- <ProjectAvatar
81
- projectId={project.id}
82
- name={project.name || project.id}
83
- iconPath={project.iconPath}
84
- size="sm"
85
- />
86
- <div className="flex-1 min-w-0">
87
- <div className="font-medium truncate">
88
- {project.name || project.id}
89
- </div>
90
- {project.repoPath && (
91
- <div className="text-xs text-muted-foreground flex items-center gap-1 truncate">
92
- <FolderGit2 className="h-3 w-3 shrink-0" />
93
- <span className="truncate">{formatPath(project.repoPath)}</span>
94
- </div>
95
- )}
96
- </div>
97
- </button>
98
- ))
99
- )}
100
- </div>
101
- </DialogContent>
102
- </Dialog>
103
- )
104
- }
@@ -1 +0,0 @@
1
- export { ProjectSelectorModal } from './ProjectSelectorModal'
@@ -1,48 +0,0 @@
1
- 'use client'
2
-
3
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
4
- import { useState, type ReactNode } from 'react'
5
- import { ThemeProvider, type ThemeProviderProps } from 'next-themes'
6
- import { TerminalProvider } from '@/context/TerminalContext'
7
- import { GlobalTerminalProvider } from '@/context/GlobalTerminalContext'
8
-
9
- function ThemeWrapper({ children, ...props }: ThemeProviderProps & { children: ReactNode }) {
10
- return <ThemeProvider {...props}>{children}</ThemeProvider>
11
- }
12
-
13
- export function Providers({ children }: { children: ReactNode }) {
14
- const [queryClient] = useState(() => new QueryClient({
15
- defaultOptions: {
16
- queries: {
17
- // Data considered fresh for 2.5 seconds
18
- staleTime: 2500,
19
- // Garbage collect after 5 minutes
20
- gcTime: 5 * 60 * 1000,
21
- // Refetch on window focus for real-time feel
22
- refetchOnWindowFocus: true,
23
- // Refetch when reconnecting
24
- refetchOnReconnect: true,
25
- // Retry failed requests once
26
- retry: 1,
27
- retryDelay: 1000,
28
- },
29
- },
30
- }))
31
-
32
- return (
33
- <QueryClientProvider client={queryClient}>
34
- <ThemeWrapper
35
- attribute="class"
36
- defaultTheme="dark"
37
- enableSystem
38
- disableTransitionOnChange
39
- >
40
- <TerminalProvider>
41
- <GlobalTerminalProvider>
42
- {children}
43
- </GlobalTerminalProvider>
44
- </TerminalProvider>
45
- </ThemeWrapper>
46
- </QueryClientProvider>
47
- )
48
- }
@@ -1 +0,0 @@
1
- export { Providers } from './Providers'
@@ -1,125 +0,0 @@
1
- 'use client'
2
-
3
- import { useState } from 'react'
4
- import Link from 'next/link'
5
- import { EmptyState } from '@/components/EmptyState'
6
- import { ExpandButton } from '@/components/ExpandButton'
7
- import { ListTodo, Bot, Play, X } from 'lucide-react'
8
- import { cn } from '@/lib/utils'
9
- import { getPriorityColor } from './QueueCard.utils'
10
- import type { QueueCardProps } from './QueueCard.types'
11
-
12
- const COLLAPSED_LIMIT = 10
13
- const EXPANDED_LIMIT = 50
14
-
15
- export function QueueCard({ queue, codeHref, className }: QueueCardProps) {
16
- const [expanded, setExpanded] = useState(false)
17
- const limit = expanded ? EXPANDED_LIMIT : COLLAPSED_LIMIT
18
- const displayItems = queue.slice(0, limit)
19
- const hasMore = queue.length > limit
20
-
21
- return (
22
- <div className={cn(
23
- 'relative overflow-hidden rounded-xl border bg-card p-4',
24
- className
25
- )}>
26
- <div className="flex items-center justify-between mb-3">
27
- <div className="flex items-center gap-2">
28
- <ListTodo className="h-4 w-4 text-muted-foreground" />
29
- <span className="text-xs font-bold uppercase tracking-[0.15em] text-muted-foreground">
30
- Queue
31
- </span>
32
- </div>
33
- <span className="text-xs font-medium text-muted-foreground tabular-nums">
34
- {queue.length} tasks
35
- </span>
36
- </div>
37
-
38
- {queue.length === 0 ? (
39
- <EmptyState
40
- icon={ListTodo}
41
- title="Queue empty"
42
- description="Plan your next tasks"
43
- command="/p:next"
44
- href={codeHref}
45
- compact
46
- />
47
- ) : (
48
- <div className="space-y-1.5">
49
- {displayItems.map((item, i) => {
50
- const priorityColor = getPriorityColor(item.priority)
51
- const startHref = codeHref
52
- ? `${codeHref}?cmd=${encodeURIComponent(`p. now "${item.task}"`)}`
53
- : undefined
54
- const deleteHref = codeHref
55
- ? `${codeHref}?cmd=${encodeURIComponent(`p. queue remove ${i + 1}`)}`
56
- : undefined
57
-
58
- return (
59
- <div
60
- key={i}
61
- className="flex items-start gap-2 group py-1.5 hover:bg-muted/50 rounded px-1 -mx-1"
62
- >
63
- <span className={cn(
64
- "text-xs font-bold w-5 shrink-0 pt-0.5 tabular-nums",
65
- priorityColor
66
- )}>
67
- {i + 1}.
68
- </span>
69
- <div className="flex-1 min-w-0">
70
- <p className="text-sm leading-tight">
71
- {item.task}
72
- </p>
73
- {(item.suggestedAgent || item.estimatedDuration) && (
74
- <div className="flex items-center gap-2 mt-0.5">
75
- {item.suggestedAgent && (
76
- <span className="inline-flex items-center gap-0.5 text-xs text-muted-foreground">
77
- <Bot className="h-3 w-3" />
78
- {item.suggestedAgent}
79
- </span>
80
- )}
81
- {item.estimatedDuration && (
82
- <span className="text-xs text-muted-foreground">
83
- ~{item.estimatedDuration}
84
- </span>
85
- )}
86
- </div>
87
- )}
88
- </div>
89
- {/* Always visible action buttons */}
90
- <div className="flex items-center gap-1 shrink-0">
91
- {startHref && (
92
- <Link
93
- href={startHref}
94
- className="p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors"
95
- title="Start now"
96
- >
97
- <Play className="h-3.5 w-3.5" />
98
- </Link>
99
- )}
100
- {deleteHref && (
101
- <Link
102
- href={deleteHref}
103
- className="p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors"
104
- title="Remove from queue"
105
- >
106
- <X className="h-3.5 w-3.5" />
107
- </Link>
108
- )}
109
- </div>
110
- </div>
111
- )
112
- })}
113
- {(hasMore || expanded) && queue.length > COLLAPSED_LIMIT && (
114
- <ExpandButton
115
- expanded={expanded}
116
- totalCount={queue.length}
117
- collapsedLimit={COLLAPSED_LIMIT}
118
- onToggle={() => setExpanded(!expanded)}
119
- />
120
- )}
121
- </div>
122
- )}
123
- </div>
124
- )
125
- }
@@ -1,12 +0,0 @@
1
- export interface QueueItem {
2
- task: string
3
- priority?: 'low' | 'medium' | 'high' | 'critical' | number
4
- suggestedAgent?: string
5
- estimatedDuration?: string
6
- }
7
-
8
- export interface QueueCardProps {
9
- queue: QueueItem[]
10
- codeHref?: string
11
- className?: string
12
- }