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.
- package/LICENSE +21 -0
- package/README.md +553 -0
- package/cli.js +431 -0
- package/config-loader.js +294 -0
- package/hooks/activity-track.sh +56 -0
- package/hooks/codex-workstream.sh +44 -0
- package/hooks/gemini-workstream.sh +44 -0
- package/hooks/workstream-inject.sh +20 -0
- package/lib/activity.js +283 -0
- package/lib/apply.js +344 -0
- package/lib/cli.js +267 -0
- package/lib/config.js +171 -0
- package/lib/constants.js +55 -0
- package/lib/env.js +114 -0
- package/lib/index.js +47 -0
- package/lib/init.js +122 -0
- package/lib/mcps.js +139 -0
- package/lib/memory.js +201 -0
- package/lib/projects.js +138 -0
- package/lib/registry.js +83 -0
- package/lib/utils.js +129 -0
- package/lib/workstreams.js +652 -0
- package/package.json +80 -0
- package/scripts/capture-screenshots.js +142 -0
- package/scripts/postinstall.js +122 -0
- package/scripts/release.sh +71 -0
- package/scripts/sync-version.js +77 -0
- package/scripts/tauri-prepare.js +328 -0
- package/shared/mcp-registry.json +76 -0
- package/ui/dist/assets/index-DbZ3_HBD.js +3204 -0
- package/ui/dist/assets/index-DjLdm3Mr.css +32 -0
- package/ui/dist/icons/icon-192.svg +16 -0
- package/ui/dist/icons/icon-512.svg +16 -0
- package/ui/dist/index.html +39 -0
- package/ui/dist/manifest.json +25 -0
- package/ui/dist/sw.js +24 -0
- package/ui/dist/tutorial/claude-settings.png +0 -0
- package/ui/dist/tutorial/header.png +0 -0
- package/ui/dist/tutorial/mcp-registry.png +0 -0
- package/ui/dist/tutorial/memory-view.png +0 -0
- package/ui/dist/tutorial/permissions.png +0 -0
- package/ui/dist/tutorial/plugins-view.png +0 -0
- package/ui/dist/tutorial/project-explorer.png +0 -0
- package/ui/dist/tutorial/projects-view.png +0 -0
- package/ui/dist/tutorial/sidebar.png +0 -0
- package/ui/dist/tutorial/tutorial-view.png +0 -0
- package/ui/dist/tutorial/workstreams-view.png +0 -0
- package/ui/routes/activity.js +58 -0
- package/ui/routes/commands.js +74 -0
- package/ui/routes/configs.js +329 -0
- package/ui/routes/env.js +40 -0
- package/ui/routes/file-explorer.js +668 -0
- package/ui/routes/index.js +41 -0
- package/ui/routes/mcp-discovery.js +235 -0
- package/ui/routes/memory.js +385 -0
- package/ui/routes/package.json +3 -0
- package/ui/routes/plugins.js +466 -0
- package/ui/routes/projects.js +198 -0
- package/ui/routes/registry.js +30 -0
- package/ui/routes/rules.js +74 -0
- package/ui/routes/search.js +125 -0
- package/ui/routes/settings.js +381 -0
- package/ui/routes/subprojects.js +208 -0
- package/ui/routes/tool-sync.js +127 -0
- package/ui/routes/updates.js +339 -0
- package/ui/routes/workstreams.js +224 -0
- package/ui/server.cjs +773 -0
- 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
|
+
};
|