@evolve.labs/devflow 0.8.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 (106) hide show
  1. package/.claude/commands/agents/architect.md +1162 -0
  2. package/.claude/commands/agents/architect.meta.yaml +124 -0
  3. package/.claude/commands/agents/builder.md +1432 -0
  4. package/.claude/commands/agents/builder.meta.yaml +117 -0
  5. package/.claude/commands/agents/chronicler.md +633 -0
  6. package/.claude/commands/agents/chronicler.meta.yaml +217 -0
  7. package/.claude/commands/agents/guardian.md +456 -0
  8. package/.claude/commands/agents/guardian.meta.yaml +127 -0
  9. package/.claude/commands/agents/strategist.md +483 -0
  10. package/.claude/commands/agents/strategist.meta.yaml +158 -0
  11. package/.claude/commands/agents/system-designer.md +1137 -0
  12. package/.claude/commands/agents/system-designer.meta.yaml +156 -0
  13. package/.claude/commands/devflow-help.md +93 -0
  14. package/.claude/commands/devflow-status.md +60 -0
  15. package/.claude/commands/quick/create-adr.md +82 -0
  16. package/.claude/commands/quick/new-feature.md +57 -0
  17. package/.claude/commands/quick/security-check.md +54 -0
  18. package/.claude/commands/quick/system-design.md +58 -0
  19. package/.claude_project +52 -0
  20. package/.devflow/agents/architect.meta.yaml +122 -0
  21. package/.devflow/agents/builder.meta.yaml +116 -0
  22. package/.devflow/agents/chronicler.meta.yaml +222 -0
  23. package/.devflow/agents/guardian.meta.yaml +127 -0
  24. package/.devflow/agents/strategist.meta.yaml +158 -0
  25. package/.devflow/agents/system-designer.meta.yaml +265 -0
  26. package/.devflow/project.yaml +242 -0
  27. package/.gitignore-template +84 -0
  28. package/LICENSE +21 -0
  29. package/README.md +249 -0
  30. package/bin/devflow.js +54 -0
  31. package/lib/autopilot.js +235 -0
  32. package/lib/autopilotConstants.js +213 -0
  33. package/lib/constants.js +95 -0
  34. package/lib/init.js +200 -0
  35. package/lib/update.js +181 -0
  36. package/lib/utils.js +157 -0
  37. package/lib/web.js +119 -0
  38. package/package.json +57 -0
  39. package/web/CHANGELOG.md +192 -0
  40. package/web/README.md +156 -0
  41. package/web/app/api/autopilot/execute/route.ts +102 -0
  42. package/web/app/api/autopilot/terminal-execute/route.ts +124 -0
  43. package/web/app/api/files/route.ts +280 -0
  44. package/web/app/api/files/tree/route.ts +160 -0
  45. package/web/app/api/git/route.ts +201 -0
  46. package/web/app/api/health/route.ts +94 -0
  47. package/web/app/api/project/open/route.ts +134 -0
  48. package/web/app/api/search/route.ts +247 -0
  49. package/web/app/api/specs/route.ts +405 -0
  50. package/web/app/api/terminal/route.ts +222 -0
  51. package/web/app/globals.css +160 -0
  52. package/web/app/ide/layout.tsx +43 -0
  53. package/web/app/ide/page.tsx +216 -0
  54. package/web/app/layout.tsx +34 -0
  55. package/web/app/page.tsx +303 -0
  56. package/web/components/agents/AgentIcons.tsx +281 -0
  57. package/web/components/autopilot/AutopilotConfigModal.tsx +245 -0
  58. package/web/components/autopilot/AutopilotPanel.tsx +299 -0
  59. package/web/components/dashboard/DashboardPanel.tsx +393 -0
  60. package/web/components/editor/Breadcrumbs.tsx +134 -0
  61. package/web/components/editor/EditorPanel.tsx +120 -0
  62. package/web/components/editor/EditorTabs.tsx +229 -0
  63. package/web/components/editor/MarkdownPreview.tsx +154 -0
  64. package/web/components/editor/MermaidDiagram.tsx +113 -0
  65. package/web/components/editor/MonacoEditor.tsx +177 -0
  66. package/web/components/editor/TabContextMenu.tsx +207 -0
  67. package/web/components/git/GitPanel.tsx +534 -0
  68. package/web/components/layout/Shell.tsx +15 -0
  69. package/web/components/layout/StatusBar.tsx +100 -0
  70. package/web/components/modals/CommandPalette.tsx +393 -0
  71. package/web/components/modals/GlobalSearch.tsx +348 -0
  72. package/web/components/modals/QuickOpen.tsx +241 -0
  73. package/web/components/modals/RecentFiles.tsx +208 -0
  74. package/web/components/projects/ProjectSelector.tsx +147 -0
  75. package/web/components/settings/SettingItem.tsx +150 -0
  76. package/web/components/settings/SettingsPanel.tsx +323 -0
  77. package/web/components/specs/SpecsPanel.tsx +1091 -0
  78. package/web/components/terminal/TerminalPanel.tsx +683 -0
  79. package/web/components/ui/ContextMenu.tsx +182 -0
  80. package/web/components/ui/LoadingSpinner.tsx +66 -0
  81. package/web/components/ui/ResizeHandle.tsx +110 -0
  82. package/web/components/ui/Skeleton.tsx +108 -0
  83. package/web/components/ui/SkipLinks.tsx +37 -0
  84. package/web/components/ui/Toaster.tsx +57 -0
  85. package/web/hooks/useFocusTrap.ts +141 -0
  86. package/web/hooks/useKeyboardShortcuts.ts +169 -0
  87. package/web/hooks/useListNavigation.ts +237 -0
  88. package/web/lib/autopilotConstants.ts +213 -0
  89. package/web/lib/constants/agents.ts +67 -0
  90. package/web/lib/git.ts +339 -0
  91. package/web/lib/ptyManager.ts +191 -0
  92. package/web/lib/specsParser.ts +299 -0
  93. package/web/lib/stores/autopilotStore.ts +288 -0
  94. package/web/lib/stores/fileStore.ts +550 -0
  95. package/web/lib/stores/gitStore.ts +386 -0
  96. package/web/lib/stores/projectStore.ts +196 -0
  97. package/web/lib/stores/settingsStore.ts +126 -0
  98. package/web/lib/stores/specsStore.ts +297 -0
  99. package/web/lib/stores/uiStore.ts +175 -0
  100. package/web/lib/types/index.ts +177 -0
  101. package/web/lib/utils.ts +98 -0
  102. package/web/next.config.js +50 -0
  103. package/web/package.json +54 -0
  104. package/web/postcss.config.js +6 -0
  105. package/web/tailwind.config.ts +68 -0
  106. package/web/tsconfig.json +41 -0
@@ -0,0 +1,160 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ :root {
7
+ --background: 0 0% 100%;
8
+ --foreground: 222.2 84% 4.9%;
9
+ --card: 0 0% 100%;
10
+ --card-foreground: 222.2 84% 4.9%;
11
+ --popover: 0 0% 100%;
12
+ --popover-foreground: 222.2 84% 4.9%;
13
+ --primary: 221.2 83.2% 53.3%;
14
+ --primary-foreground: 210 40% 98%;
15
+ --secondary: 210 40% 96.1%;
16
+ --secondary-foreground: 222.2 47.4% 11.2%;
17
+ --muted: 210 40% 96.1%;
18
+ --muted-foreground: 215.4 16.3% 46.9%;
19
+ --accent: 210 40% 96.1%;
20
+ --accent-foreground: 222.2 47.4% 11.2%;
21
+ --destructive: 0 84.2% 60.2%;
22
+ --destructive-foreground: 210 40% 98%;
23
+ --border: 214.3 31.8% 91.4%;
24
+ --input: 214.3 31.8% 91.4%;
25
+ --ring: 221.2 83.2% 53.3%;
26
+ --radius: 0.5rem;
27
+ }
28
+
29
+ .dark {
30
+ --background: 222.2 84% 4.9%;
31
+ --foreground: 210 40% 98%;
32
+ --card: 222.2 84% 4.9%;
33
+ --card-foreground: 210 40% 98%;
34
+ --popover: 222.2 84% 4.9%;
35
+ --popover-foreground: 210 40% 98%;
36
+ --primary: 217.2 91.2% 59.8%;
37
+ --primary-foreground: 222.2 47.4% 11.2%;
38
+ --secondary: 217.2 32.6% 17.5%;
39
+ --secondary-foreground: 210 40% 98%;
40
+ --muted: 217.2 32.6% 17.5%;
41
+ --muted-foreground: 215 20.2% 65.1%;
42
+ --accent: 217.2 32.6% 17.5%;
43
+ --accent-foreground: 210 40% 98%;
44
+ --destructive: 0 62.8% 30.6%;
45
+ --destructive-foreground: 210 40% 98%;
46
+ --border: 217.2 32.6% 17.5%;
47
+ --input: 217.2 32.6% 17.5%;
48
+ --ring: 224.3 76.3% 48%;
49
+ }
50
+ }
51
+
52
+ @layer base {
53
+ * {
54
+ @apply border-border;
55
+ }
56
+ body {
57
+ @apply bg-background text-foreground;
58
+ font-feature-settings: "rlig" 1, "calt" 1;
59
+ }
60
+ }
61
+
62
+ /* Custom scrollbar */
63
+ ::-webkit-scrollbar {
64
+ width: 8px;
65
+ height: 8px;
66
+ }
67
+
68
+ ::-webkit-scrollbar-track {
69
+ @apply bg-transparent;
70
+ }
71
+
72
+ ::-webkit-scrollbar-thumb {
73
+ @apply bg-muted-foreground/20 rounded-full;
74
+ }
75
+
76
+ ::-webkit-scrollbar-thumb:hover {
77
+ @apply bg-muted-foreground/40;
78
+ }
79
+
80
+ /* Monaco editor adjustments */
81
+ .monaco-editor {
82
+ @apply rounded-md;
83
+ }
84
+
85
+ /* Monaco editor line highlight animation */
86
+ .highlight-line-animation {
87
+ background-color: rgba(168, 85, 247, 0.3) !important;
88
+ animation: highlight-fade 2s ease-out forwards;
89
+ }
90
+
91
+ .highlight-line-margin {
92
+ background-color: rgba(168, 85, 247, 0.8) !important;
93
+ width: 3px !important;
94
+ margin-left: 3px;
95
+ animation: highlight-fade 2s ease-out forwards;
96
+ }
97
+
98
+ @keyframes highlight-fade {
99
+ 0% {
100
+ background-color: rgba(168, 85, 247, 0.5);
101
+ }
102
+ 100% {
103
+ background-color: transparent;
104
+ }
105
+ }
106
+
107
+ /* File tree hover effects */
108
+ .file-node:hover {
109
+ @apply bg-accent;
110
+ }
111
+
112
+ .file-node.selected {
113
+ @apply bg-accent text-accent-foreground;
114
+ }
115
+
116
+ /* Chat message streaming cursor */
117
+ .streaming-cursor::after {
118
+ content: '▌';
119
+ @apply animate-pulse text-primary;
120
+ }
121
+
122
+ /* Terminal styles */
123
+ .xterm {
124
+ @apply p-2;
125
+ }
126
+
127
+ .xterm-screen canvas {
128
+ image-rendering: pixelated;
129
+ image-rendering: crisp-edges;
130
+ }
131
+
132
+ .xterm-viewport {
133
+ overflow-y: auto !important;
134
+ }
135
+
136
+ /* Resizable panels */
137
+ .resizable-handle {
138
+ @apply bg-transparent hover:bg-primary/20 transition-colors;
139
+ }
140
+
141
+ .resizable-handle:active {
142
+ @apply bg-primary/40;
143
+ }
144
+
145
+ /* Hide scrollbar utility */
146
+ .scrollbar-hide {
147
+ -ms-overflow-style: none;
148
+ scrollbar-width: none;
149
+ }
150
+
151
+ .scrollbar-hide::-webkit-scrollbar {
152
+ display: none;
153
+ }
154
+
155
+ /* Responsive text utilities */
156
+ @layer utilities {
157
+ .text-responsive {
158
+ font-size: clamp(0.75rem, 2vw, 0.875rem);
159
+ }
160
+ }
@@ -0,0 +1,43 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useState } from 'react';
4
+ import { useRouter } from 'next/navigation';
5
+ import { useProjectStore } from '@/lib/stores/projectStore';
6
+
7
+ export default function IDELayout({ children }: { children: React.ReactNode }) {
8
+ const router = useRouter();
9
+ const { projects, restoreProjects } = useProjectStore();
10
+ const [restoring, setRestoring] = useState(true);
11
+
12
+ useEffect(() => {
13
+ if (projects.length > 0) {
14
+ // Already have projects loaded
15
+ setRestoring(false);
16
+ return;
17
+ }
18
+
19
+ // Try to restore from persisted state
20
+ restoreProjects().then(() => {
21
+ const current = useProjectStore.getState();
22
+ if (current.projects.length === 0) {
23
+ // No projects could be restored, redirect to home
24
+ router.push('/');
25
+ } else {
26
+ setRestoring(false);
27
+ }
28
+ });
29
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
30
+
31
+ if (restoring && projects.length === 0) {
32
+ return (
33
+ <div className="min-h-screen flex items-center justify-center bg-[#0a0a0f]">
34
+ <div className="text-center space-y-4">
35
+ <div className="animate-spin w-8 h-8 border-2 border-purple-500 border-t-transparent rounded-full mx-auto" />
36
+ <p className="text-gray-400">Loading projects...</p>
37
+ </div>
38
+ </div>
39
+ );
40
+ }
41
+
42
+ return <>{children}</>;
43
+ }
@@ -0,0 +1,216 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useCallback } from 'react';
4
+ import { useProjectStore } from '@/lib/stores/projectStore';
5
+ import { useUIStore } from '@/lib/stores/uiStore';
6
+ import { useSettingsStore } from '@/lib/stores/settingsStore';
7
+ import { EditorPanel } from '@/components/editor/EditorPanel';
8
+ import { SpecsPanel } from '@/components/specs/SpecsPanel';
9
+ import { TerminalPanel } from '@/components/terminal/TerminalPanel';
10
+ import { GitPanel } from '@/components/git/GitPanel';
11
+ import { DashboardPanel } from '@/components/dashboard/DashboardPanel';
12
+ import { StatusBar } from '@/components/layout/StatusBar';
13
+ import { ResizeHandle } from '@/components/ui/ResizeHandle';
14
+ import { QuickOpen } from '@/components/modals/QuickOpen';
15
+ import { GlobalSearch } from '@/components/modals/GlobalSearch';
16
+ import { CommandPalette } from '@/components/modals/CommandPalette';
17
+ import { RecentFiles } from '@/components/modals/RecentFiles';
18
+ import { SettingsPanel } from '@/components/settings/SettingsPanel';
19
+ import { AutopilotPanel } from '@/components/autopilot/AutopilotPanel';
20
+ import { AutopilotConfigModal } from '@/components/autopilot/AutopilotConfigModal';
21
+ import { ProjectSelector } from '@/components/projects/ProjectSelector';
22
+ import { SkipLinks } from '@/components/ui/SkipLinks';
23
+ import { useKeyboardShortcuts } from '@/hooks/useKeyboardShortcuts';
24
+ import {
25
+ FileText,
26
+ Terminal,
27
+ LayoutDashboard,
28
+ Zap,
29
+ Settings,
30
+ GitBranch
31
+ } from 'lucide-react';
32
+ import { cn } from '@/lib/utils';
33
+
34
+ export default function IDEPage() {
35
+ const { currentProject, projects, activeProjectPath } = useProjectStore();
36
+ const { openSettings } = useSettingsStore();
37
+ const projectPaths = projects.map(p => p.path);
38
+
39
+ // Initialize keyboard shortcuts
40
+ useKeyboardShortcuts();
41
+
42
+ const {
43
+ sidebarVisible,
44
+ sidebarWidth,
45
+ activePanel,
46
+ setActivePanel,
47
+ terminalVisible,
48
+ terminalHeight,
49
+ terminalMaximized,
50
+ toggleSidebar,
51
+ toggleTerminal,
52
+ toggleTerminalMaximized,
53
+ setSidebarWidth,
54
+ setTerminalHeight,
55
+ } = useUIStore();
56
+
57
+ // Resize handlers
58
+ const handleSidebarResize = useCallback((delta: number) => {
59
+ setSidebarWidth(sidebarWidth + delta);
60
+ }, [sidebarWidth, setSidebarWidth]);
61
+
62
+ const sidebarItems = [
63
+ { id: 'specs', icon: FileText, label: 'Specs' },
64
+ { id: 'git', icon: GitBranch, label: 'Source Control' },
65
+ { id: 'dashboard', icon: LayoutDashboard, label: 'Dashboard' },
66
+ ] as const;
67
+
68
+ return (
69
+ <div className="h-screen flex flex-col bg-[#0a0a0f] text-white overflow-hidden">
70
+ {/* Skip Links for accessibility */}
71
+ <SkipLinks />
72
+
73
+ {/* Main Content */}
74
+ <div className="flex-1 flex overflow-hidden" role="main">
75
+ {/* Activity Bar */}
76
+ <div className="w-12 bg-[#08080c] border-r border-white/10 flex flex-col items-center py-2">
77
+ {/* Logo */}
78
+ <div className="w-8 h-8 bg-gradient-to-br from-purple-500 to-purple-700 rounded-lg flex items-center justify-center mb-4">
79
+ <Zap className="w-4 h-4 text-white" />
80
+ </div>
81
+
82
+ {/* Nav Items */}
83
+ <div className="flex-1 flex flex-col gap-1">
84
+ {sidebarItems.map((item) => (
85
+ <button
86
+ key={item.id}
87
+ onClick={() => {
88
+ if (activePanel === item.id && sidebarVisible) {
89
+ toggleSidebar();
90
+ } else {
91
+ setActivePanel(item.id);
92
+ if (!sidebarVisible) toggleSidebar();
93
+ }
94
+ }}
95
+ className={cn(
96
+ 'w-10 h-10 flex items-center justify-center rounded-lg transition-colors',
97
+ activePanel === item.id && sidebarVisible
98
+ ? 'bg-purple-500/20 text-purple-400'
99
+ : 'text-gray-500 hover:text-white hover:bg-white/5'
100
+ )}
101
+ title={item.label}
102
+ >
103
+ <item.icon className="w-5 h-5" />
104
+ </button>
105
+ ))}
106
+ </div>
107
+
108
+ {/* Bottom Actions */}
109
+ <div className="flex flex-col gap-1">
110
+ <button
111
+ onClick={toggleTerminal}
112
+ className={cn(
113
+ 'w-10 h-10 flex items-center justify-center rounded-lg transition-colors',
114
+ terminalVisible
115
+ ? 'bg-purple-500/20 text-purple-400'
116
+ : 'text-gray-500 hover:text-white hover:bg-white/5'
117
+ )}
118
+ title="Terminal"
119
+ >
120
+ <Terminal className="w-5 h-5" />
121
+ </button>
122
+ <button
123
+ onClick={openSettings}
124
+ className="w-10 h-10 flex items-center justify-center rounded-lg text-gray-500 hover:text-white hover:bg-white/5 transition-colors"
125
+ title="Settings (Cmd+,)"
126
+ >
127
+ <Settings className="w-5 h-5" />
128
+ </button>
129
+ </div>
130
+ </div>
131
+
132
+ {/* Sidebar Panel */}
133
+ {sidebarVisible && (
134
+ <>
135
+ <aside
136
+ id="main-sidebar"
137
+ className="h-full bg-[#0a0a0f] flex-shrink-0 overflow-hidden flex flex-col"
138
+ style={{ width: sidebarWidth }}
139
+ aria-label="Sidebar"
140
+ >
141
+ {/* Project Selector */}
142
+ <div className="px-2 pt-2 pb-1 flex-shrink-0">
143
+ <ProjectSelector />
144
+ </div>
145
+
146
+ {/* Panel Content */}
147
+ <div className="flex-1 min-h-0 overflow-hidden">
148
+ {activePanel === 'git' && currentProject && (
149
+ <GitPanel projectPath={currentProject.path} />
150
+ )}
151
+ {activePanel === 'specs' && projectPaths.length > 0 && (
152
+ <SpecsPanel projectPaths={projectPaths} activeProjectPath={activeProjectPath} />
153
+ )}
154
+ {activePanel === 'dashboard' && currentProject && (
155
+ <DashboardPanel projectPath={currentProject.path} />
156
+ )}
157
+ </div>
158
+ </aside>
159
+ {/* Sidebar Resize Handle */}
160
+ <ResizeHandle
161
+ direction="horizontal"
162
+ side="right"
163
+ onResize={handleSidebarResize}
164
+ className="bg-white/5 hover:bg-purple-500/30"
165
+ />
166
+ </>
167
+ )}
168
+
169
+ {/* Editor + Terminal Area */}
170
+ <div className="flex-1 min-w-0 flex flex-col">
171
+ {/* Editor */}
172
+ <div
173
+ id="main-editor"
174
+ className={cn(
175
+ 'flex-1 min-h-0',
176
+ terminalVisible && !terminalMaximized && 'pb-0'
177
+ )}
178
+ tabIndex={-1}
179
+ >
180
+ <EditorPanel />
181
+ </div>
182
+
183
+ {/* Terminal */}
184
+ {terminalVisible && currentProject && (
185
+ <TerminalPanel
186
+ projectPath={currentProject.path}
187
+ isMaximized={terminalMaximized}
188
+ onToggleMaximize={toggleTerminalMaximized}
189
+ onClose={toggleTerminal}
190
+ height={terminalHeight}
191
+ onHeightChange={setTerminalHeight}
192
+ />
193
+ )}
194
+ </div>
195
+ </div>
196
+
197
+ {/* Status Bar */}
198
+ <StatusBar />
199
+
200
+ {/* Modals */}
201
+ <QuickOpen />
202
+ <GlobalSearch />
203
+ <CommandPalette />
204
+ <RecentFiles />
205
+ <SettingsPanel />
206
+
207
+ {/* Autopilot */}
208
+ {currentProject && (
209
+ <>
210
+ <AutopilotConfigModal projectPath={currentProject.path} />
211
+ <AutopilotPanel />
212
+ </>
213
+ )}
214
+ </div>
215
+ );
216
+ }
@@ -0,0 +1,34 @@
1
+ import type { Metadata } from 'next';
2
+ import { Inter, JetBrains_Mono } from 'next/font/google';
3
+ import { Toaster } from '@/components/ui/Toaster';
4
+ import './globals.css';
5
+
6
+ const inter = Inter({
7
+ subsets: ['latin'],
8
+ variable: '--font-inter',
9
+ });
10
+
11
+ const jetbrainsMono = JetBrains_Mono({
12
+ subsets: ['latin'],
13
+ variable: '--font-mono',
14
+ });
15
+
16
+ export const metadata: Metadata = {
17
+ title: 'DevFlow IDE',
18
+ description: 'Spec-driven development IDE powered by AI agents',
19
+ };
20
+
21
+ export default function RootLayout({
22
+ children,
23
+ }: {
24
+ children: React.ReactNode;
25
+ }) {
26
+ return (
27
+ <html lang="en" className="dark">
28
+ <body className={`${inter.variable} ${jetbrainsMono.variable} font-sans antialiased`}>
29
+ {children}
30
+ <Toaster />
31
+ </body>
32
+ </html>
33
+ );
34
+ }