coder-config 0.40.1

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 (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +553 -0
  3. package/cli.js +431 -0
  4. package/config-loader.js +294 -0
  5. package/hooks/activity-track.sh +56 -0
  6. package/hooks/codex-workstream.sh +44 -0
  7. package/hooks/gemini-workstream.sh +44 -0
  8. package/hooks/workstream-inject.sh +20 -0
  9. package/lib/activity.js +283 -0
  10. package/lib/apply.js +344 -0
  11. package/lib/cli.js +267 -0
  12. package/lib/config.js +171 -0
  13. package/lib/constants.js +55 -0
  14. package/lib/env.js +114 -0
  15. package/lib/index.js +47 -0
  16. package/lib/init.js +122 -0
  17. package/lib/mcps.js +139 -0
  18. package/lib/memory.js +201 -0
  19. package/lib/projects.js +138 -0
  20. package/lib/registry.js +83 -0
  21. package/lib/utils.js +129 -0
  22. package/lib/workstreams.js +652 -0
  23. package/package.json +80 -0
  24. package/scripts/capture-screenshots.js +142 -0
  25. package/scripts/postinstall.js +122 -0
  26. package/scripts/release.sh +71 -0
  27. package/scripts/sync-version.js +77 -0
  28. package/scripts/tauri-prepare.js +328 -0
  29. package/shared/mcp-registry.json +76 -0
  30. package/ui/dist/assets/index-DbZ3_HBD.js +3204 -0
  31. package/ui/dist/assets/index-DjLdm3Mr.css +32 -0
  32. package/ui/dist/icons/icon-192.svg +16 -0
  33. package/ui/dist/icons/icon-512.svg +16 -0
  34. package/ui/dist/index.html +39 -0
  35. package/ui/dist/manifest.json +25 -0
  36. package/ui/dist/sw.js +24 -0
  37. package/ui/dist/tutorial/claude-settings.png +0 -0
  38. package/ui/dist/tutorial/header.png +0 -0
  39. package/ui/dist/tutorial/mcp-registry.png +0 -0
  40. package/ui/dist/tutorial/memory-view.png +0 -0
  41. package/ui/dist/tutorial/permissions.png +0 -0
  42. package/ui/dist/tutorial/plugins-view.png +0 -0
  43. package/ui/dist/tutorial/project-explorer.png +0 -0
  44. package/ui/dist/tutorial/projects-view.png +0 -0
  45. package/ui/dist/tutorial/sidebar.png +0 -0
  46. package/ui/dist/tutorial/tutorial-view.png +0 -0
  47. package/ui/dist/tutorial/workstreams-view.png +0 -0
  48. package/ui/routes/activity.js +58 -0
  49. package/ui/routes/commands.js +74 -0
  50. package/ui/routes/configs.js +329 -0
  51. package/ui/routes/env.js +40 -0
  52. package/ui/routes/file-explorer.js +668 -0
  53. package/ui/routes/index.js +41 -0
  54. package/ui/routes/mcp-discovery.js +235 -0
  55. package/ui/routes/memory.js +385 -0
  56. package/ui/routes/package.json +3 -0
  57. package/ui/routes/plugins.js +466 -0
  58. package/ui/routes/projects.js +198 -0
  59. package/ui/routes/registry.js +30 -0
  60. package/ui/routes/rules.js +74 -0
  61. package/ui/routes/search.js +125 -0
  62. package/ui/routes/settings.js +381 -0
  63. package/ui/routes/subprojects.js +208 -0
  64. package/ui/routes/tool-sync.js +127 -0
  65. package/ui/routes/updates.js +339 -0
  66. package/ui/routes/workstreams.js +224 -0
  67. package/ui/server.cjs +773 -0
  68. package/ui/terminal-server.cjs +160 -0
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Workstreams Routes
3
+ */
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const os = require('os');
8
+
9
+ /**
10
+ * Get all workstreams
11
+ */
12
+ function getWorkstreams(manager) {
13
+ if (!manager) return { error: 'Manager not available' };
14
+ const data = manager.loadWorkstreams();
15
+ return {
16
+ workstreams: data.workstreams,
17
+ activeId: data.activeId,
18
+ lastUsedByProject: data.lastUsedByProject || {}
19
+ };
20
+ }
21
+
22
+ /**
23
+ * Get active workstream
24
+ */
25
+ function getActiveWorkstream(manager) {
26
+ if (!manager) return { error: 'Manager not available' };
27
+ const active = manager.workstreamActive();
28
+ return { workstream: active };
29
+ }
30
+
31
+ /**
32
+ * Set active workstream
33
+ */
34
+ function setActiveWorkstream(manager, id) {
35
+ if (!manager) return { error: 'Manager not available' };
36
+ const ws = manager.workstreamUse(id);
37
+ if (!ws) {
38
+ return { error: 'Workstream not found' };
39
+ }
40
+ return { success: true, workstream: ws };
41
+ }
42
+
43
+ /**
44
+ * Create a new workstream
45
+ */
46
+ function createWorkstream(manager, body) {
47
+ if (!manager) return { error: 'Manager not available' };
48
+ const { name, projects = [], rules = '' } = body;
49
+
50
+ if (!name) {
51
+ return { error: 'Name is required' };
52
+ }
53
+
54
+ const ws = manager.workstreamCreate(name, projects, rules);
55
+ if (!ws) {
56
+ return { error: 'Failed to create workstream (name may already exist)' };
57
+ }
58
+
59
+ return { success: true, workstream: ws };
60
+ }
61
+
62
+ /**
63
+ * Update a workstream
64
+ */
65
+ function updateWorkstream(manager, id, updates) {
66
+ if (!manager) return { error: 'Manager not available' };
67
+ const ws = manager.workstreamUpdate(id, updates);
68
+ if (!ws) {
69
+ return { error: 'Workstream not found' };
70
+ }
71
+ return { success: true, workstream: ws };
72
+ }
73
+
74
+ /**
75
+ * Delete a workstream
76
+ */
77
+ function deleteWorkstream(manager, id) {
78
+ if (!manager) return { error: 'Manager not available' };
79
+ const success = manager.workstreamDelete(id);
80
+ if (!success) {
81
+ return { error: 'Workstream not found' };
82
+ }
83
+ return { success: true };
84
+ }
85
+
86
+ /**
87
+ * Add project to workstream
88
+ */
89
+ function addProjectToWorkstream(manager, workstreamId, projectPath) {
90
+ if (!manager) return { error: 'Manager not available' };
91
+ const ws = manager.workstreamAddProject(workstreamId, projectPath);
92
+ if (!ws) {
93
+ return { error: 'Workstream not found' };
94
+ }
95
+ return { success: true, workstream: ws };
96
+ }
97
+
98
+ /**
99
+ * Remove project from workstream
100
+ */
101
+ function removeProjectFromWorkstream(manager, workstreamId, projectPath) {
102
+ if (!manager) return { error: 'Manager not available' };
103
+ const ws = manager.workstreamRemoveProject(workstreamId, projectPath);
104
+ if (!ws) {
105
+ return { error: 'Workstream not found' };
106
+ }
107
+ return { success: true, workstream: ws };
108
+ }
109
+
110
+ /**
111
+ * Inject active workstream rules (for hooks)
112
+ */
113
+ function injectWorkstream(manager) {
114
+ if (!manager) return { error: 'Manager not available' };
115
+ const output = manager.workstreamInject(true);
116
+ return { rules: output };
117
+ }
118
+
119
+ /**
120
+ * Detect workstream from directory
121
+ */
122
+ function detectWorkstream(manager, dir, projectDir) {
123
+ if (!manager) return { error: 'Manager not available' };
124
+ const ws = manager.workstreamDetect(dir || projectDir);
125
+ return { workstream: ws };
126
+ }
127
+
128
+ /**
129
+ * Count how many workstreams include a given project path
130
+ */
131
+ function countWorkstreamsForProject(manager, projectPath) {
132
+ if (!manager) return { error: 'Manager not available' };
133
+ const count = manager.countWorkstreamsForProject(projectPath);
134
+ return { count };
135
+ }
136
+
137
+ /**
138
+ * Check if workstream hook is installed
139
+ */
140
+ function getWorkstreamHookStatus() {
141
+ const hookPath = path.join(os.homedir(), '.claude', 'hooks', 'pre-prompt.sh');
142
+ const hookDir = path.dirname(hookPath);
143
+
144
+ const status = {
145
+ hookPath,
146
+ dirExists: fs.existsSync(hookDir),
147
+ fileExists: fs.existsSync(hookPath),
148
+ isInstalled: false,
149
+ content: null
150
+ };
151
+
152
+ if (status.fileExists) {
153
+ try {
154
+ const content = fs.readFileSync(hookPath, 'utf8');
155
+ status.content = content;
156
+ status.isInstalled = content.includes('workstream inject');
157
+ } catch (e) {
158
+ status.error = e.message;
159
+ }
160
+ }
161
+
162
+ return status;
163
+ }
164
+
165
+ /**
166
+ * Install workstream hook
167
+ */
168
+ function installWorkstreamHook() {
169
+ const hookDir = path.join(os.homedir(), '.claude', 'hooks');
170
+ const hookPath = path.join(hookDir, 'pre-prompt.sh');
171
+
172
+ const hookCode = `
173
+ # Workstream rule injection (added by claude-config)
174
+ if command -v claude-config &> /dev/null; then
175
+ claude-config workstream inject --silent
176
+ fi
177
+ `;
178
+
179
+ try {
180
+ if (!fs.existsSync(hookDir)) {
181
+ fs.mkdirSync(hookDir, { recursive: true });
182
+ }
183
+
184
+ let content = '';
185
+ let alreadyInstalled = false;
186
+
187
+ if (fs.existsSync(hookPath)) {
188
+ content = fs.readFileSync(hookPath, 'utf8');
189
+ if (content.includes('workstream inject')) {
190
+ alreadyInstalled = true;
191
+ }
192
+ } else {
193
+ content = '#!/bin/bash\n';
194
+ }
195
+
196
+ if (alreadyInstalled) {
197
+ return { success: true, message: 'Hook already installed', path: hookPath };
198
+ }
199
+
200
+ content += hookCode;
201
+ fs.writeFileSync(hookPath, content);
202
+ fs.chmodSync(hookPath, '755');
203
+
204
+ return { success: true, message: 'Hook installed successfully', path: hookPath };
205
+ } catch (e) {
206
+ return { error: e.message };
207
+ }
208
+ }
209
+
210
+ module.exports = {
211
+ getWorkstreams,
212
+ getActiveWorkstream,
213
+ setActiveWorkstream,
214
+ createWorkstream,
215
+ updateWorkstream,
216
+ deleteWorkstream,
217
+ addProjectToWorkstream,
218
+ removeProjectFromWorkstream,
219
+ injectWorkstream,
220
+ detectWorkstream,
221
+ countWorkstreamsForProject,
222
+ getWorkstreamHookStatus,
223
+ installWorkstreamHook,
224
+ };