@shenlee/devcrew 0.1.0 → 0.1.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/README.md +2 -3
- package/README.zh-CN.md +2 -3
- package/dist/packages/core/src/version.js +1 -1
- package/dist/packages/plugins/src/index.js +32 -10
- package/docs/claude-code.md +1 -1
- package/docs/codex.md +1 -1
- package/docs/quickstart.md +1 -1
- package/package.json +1 -1
- package/packages/core/src/version.ts +1 -1
- package/packages/plugins/src/index.ts +34 -10
- package/plugins/devcrew-codex/.mcp.json +10 -3
- package/scripts/smoke-codex-plugin.mjs +1 -1
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ Restart Codex, open the plugin directory, choose the DevCrew marketplace, and in
|
|
|
34
34
|
The plugin starts the DevCrew MCP server with:
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
|
|
37
|
+
npm exec --silent --yes --package=@shenlee/devcrew@0.1.1 -- node -e "<DevCrew CLI wrapper>" -- serve --stdio
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
The plugin locks the MCP server to the published npm package version, so users do not need to clone the source or build TypeScript at install time. You only need Node.js and network access the first time Codex starts the MCP server.
|
|
@@ -43,7 +43,6 @@ The plugin locks the MCP server to the published npm package version, so users d
|
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
45
|
npm install -g @shenlee/devcrew
|
|
46
|
-
devcrew --version
|
|
47
46
|
devcrew doctor /path/to/repo
|
|
48
47
|
```
|
|
49
48
|
|
|
@@ -116,7 +115,7 @@ npm pack --dry-run
|
|
|
116
115
|
|
|
117
116
|
The SDK adapters use deterministic local fallback output when Codex or Claude SDK packages are not installed. This keeps local tests reliable while preserving the adapter boundary for real host integration. In `apply` mode, DevCrew still inherits the host sandbox and approval boundaries.
|
|
118
117
|
|
|
119
|
-
For published installs, the host SDK packages are pinned optional dependencies so
|
|
118
|
+
For published installs, the host SDK packages are pinned optional dependencies so the version-locked `npm exec --package=@shenlee/devcrew@<version>` wrapper can resolve them from the DevCrew package itself. Plan mode can still fall back to deterministic artifacts, but apply mode fails with a clear SDK resolution error if the selected host SDK is unavailable.
|
|
120
119
|
|
|
121
120
|
Public npm publishing is handled by the `npm publish` GitHub Actions workflow. It runs validation, checks the package with `npm pack --dry-run`, and publishes with npm provenance when a GitHub Release is published or the workflow is manually dispatched with `NPM_TOKEN` configured.
|
|
122
121
|
|
package/README.zh-CN.md
CHANGED
|
@@ -34,7 +34,7 @@ codex plugin marketplace add lishen802/devcrew
|
|
|
34
34
|
插件会用下面的命令启动 DevCrew MCP 服务:
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
|
|
37
|
+
npm exec --silent --yes --package=@shenlee/devcrew@0.1.1 -- node -e "<DevCrew CLI wrapper>" -- serve --stdio
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
插件会锁定到已发布的 npm 包版本,因此用户不需要克隆源码,也不需要在安装时编译 TypeScript;只需要本机有 Node.js,并且 Codex 第一次启动 MCP 服务时可以访问网络。
|
|
@@ -43,7 +43,6 @@ npx -y @shenlee/devcrew@0.1.0 serve --stdio
|
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
45
|
npm install -g @shenlee/devcrew
|
|
46
|
-
devcrew --version
|
|
47
46
|
devcrew doctor /path/to/repo
|
|
48
47
|
```
|
|
49
48
|
|
|
@@ -130,7 +129,7 @@ npm pack --dry-run
|
|
|
130
129
|
|
|
131
130
|
当前适配器在未安装 Codex SDK 或 Claude SDK 时会使用确定性的本地 fallback 输出。这样可以保证测试和演示稳定,同时保留接入真实宿主 SDK 的边界。即使在 `apply` 模式下,DevCrew 仍然继承宿主的 sandbox、审批和工具权限。
|
|
132
131
|
|
|
133
|
-
对于发布安装,宿主 SDK 包会作为精确锁定的 optional dependencies 随 DevCrew
|
|
132
|
+
对于发布安装,宿主 SDK 包会作为精确锁定的 optional dependencies 随 DevCrew 一起安装,因此锁定版本的 `npm exec --package=@shenlee/devcrew@<version>` wrapper 可以从 DevCrew 包自身解析这些 SDK。plan 模式仍允许 deterministic fallback;但 apply 模式在选定宿主 SDK 不可用时会直接失败,并给出明确的 SDK 解析错误。
|
|
134
133
|
|
|
135
134
|
公开 npm 发布由 `npm publish` GitHub Actions 工作流处理。发布 GitHub Release 或手动触发 workflow 时,它会先运行验证,再执行 `npm pack --dry-run` 检查包内容,最后在配置 `NPM_TOKEN` 后使用 npm provenance 发布公开包。
|
|
136
135
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const DEVCREW_VERSION = "0.1.
|
|
1
|
+
export const DEVCREW_VERSION = "0.1.1";
|
|
2
2
|
export const DEVCREW_NPM_PACKAGE = "@shenlee/devcrew";
|
|
@@ -63,6 +63,36 @@ function entrySkill() {
|
|
|
63
63
|
function npmPackageSpecifier() {
|
|
64
64
|
return `${DEVCREW_NPM_PACKAGE}@${DEVCREW_VERSION}`;
|
|
65
65
|
}
|
|
66
|
+
function npmExecCliWrapper() {
|
|
67
|
+
const [scope, name] = DEVCREW_NPM_PACKAGE.split("/");
|
|
68
|
+
return [
|
|
69
|
+
"const path = require('node:path');",
|
|
70
|
+
"const { pathToFileURL } = require('node:url');",
|
|
71
|
+
"const binDir = process.env.PATH.split(path.delimiter)[0];",
|
|
72
|
+
`const packageRoot = path.join(binDir.replace(/[\\\\/]\\.bin$/u, ''), ${JSON.stringify(scope)}, ${JSON.stringify(name)});`,
|
|
73
|
+
"process.argv = ['node', 'devcrew', ...process.argv.slice(1)];",
|
|
74
|
+
"import(pathToFileURL(path.join(packageRoot, 'dist/packages/cli/src/index.js')).href);",
|
|
75
|
+
].join(" ");
|
|
76
|
+
}
|
|
77
|
+
function mcpServerConfig(host) {
|
|
78
|
+
return {
|
|
79
|
+
command: "npm",
|
|
80
|
+
args: [
|
|
81
|
+
"exec",
|
|
82
|
+
"--silent",
|
|
83
|
+
"--yes",
|
|
84
|
+
`--package=${npmPackageSpecifier()}`,
|
|
85
|
+
"--",
|
|
86
|
+
"node",
|
|
87
|
+
"-e",
|
|
88
|
+
npmExecCliWrapper(),
|
|
89
|
+
"--",
|
|
90
|
+
"serve",
|
|
91
|
+
"--stdio",
|
|
92
|
+
],
|
|
93
|
+
env: { DEVCREW_HOST: host },
|
|
94
|
+
};
|
|
95
|
+
}
|
|
66
96
|
export async function generateCodexPlugin(root) {
|
|
67
97
|
const pluginRoot = join(root, "plugins", "devcrew-codex");
|
|
68
98
|
await mkdir(join(pluginRoot, ".codex-plugin"), { recursive: true });
|
|
@@ -103,11 +133,7 @@ export async function generateCodexPlugin(root) {
|
|
|
103
133
|
await writeFile(join(pluginRoot, "skills", "devcrew", "SKILL.md"), entrySkill(), "utf8");
|
|
104
134
|
await writeJson(join(pluginRoot, ".mcp.json"), {
|
|
105
135
|
mcpServers: {
|
|
106
|
-
devcrew:
|
|
107
|
-
command: "npx",
|
|
108
|
-
args: ["-y", npmPackageSpecifier(), "serve", "--stdio"],
|
|
109
|
-
env: { DEVCREW_HOST: "codex" },
|
|
110
|
-
},
|
|
136
|
+
devcrew: mcpServerConfig("codex"),
|
|
111
137
|
},
|
|
112
138
|
});
|
|
113
139
|
await writeRoleAgents(pluginRoot, "codex");
|
|
@@ -151,11 +177,7 @@ export async function generateClaudePlugin(root) {
|
|
|
151
177
|
await writeFile(join(pluginRoot, "skills", "devcrew", "SKILL.md"), entrySkill(), "utf8");
|
|
152
178
|
await writeJson(join(pluginRoot, ".mcp.json"), {
|
|
153
179
|
mcpServers: {
|
|
154
|
-
devcrew:
|
|
155
|
-
command: "npx",
|
|
156
|
-
args: ["-y", npmPackageSpecifier(), "serve", "--stdio"],
|
|
157
|
-
env: { DEVCREW_HOST: "claude" },
|
|
158
|
-
},
|
|
180
|
+
devcrew: mcpServerConfig("claude"),
|
|
159
181
|
},
|
|
160
182
|
});
|
|
161
183
|
await writeRoleAgents(pluginRoot, "claude");
|
package/docs/claude-code.md
CHANGED
|
@@ -26,7 +26,7 @@ For local plugin testing:
|
|
|
26
26
|
claude --plugin-dir plugins/devcrew-claude
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
Then ask Claude Code to use DevCrew for a feature or product workflow. The generated `.mcp.json` starts the version-locked npm package with `
|
|
29
|
+
Then ask Claude Code to use DevCrew for a feature or product workflow. The generated `.mcp.json` starts the version-locked npm package with an `npm exec --package=@shenlee/devcrew@0.1.1` wrapper.
|
|
30
30
|
|
|
31
31
|
Claude Code permissions, hooks, and approval settings remain authoritative. DevCrew inherits the host boundary.
|
|
32
32
|
|
package/docs/codex.md
CHANGED
|
@@ -13,7 +13,7 @@ Restart Codex, open the plugin directory, select the DevCrew marketplace, and in
|
|
|
13
13
|
The plugin launches the MCP server with:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
|
|
16
|
+
npm exec --silent --yes --package=@shenlee/devcrew@0.1.1 -- node -e "<DevCrew CLI wrapper>" -- serve --stdio
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Use this path when you want to use DevCrew without cloning the repository first. The version is locked to the published npm package that matches the plugin manifest.
|
package/docs/quickstart.md
CHANGED
|
@@ -37,7 +37,7 @@ devcrew serve --stdio
|
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
Normally the generated plugin starts this command for the host agent.
|
|
40
|
-
Codex and Claude plugin bundles use
|
|
40
|
+
Codex and Claude plugin bundles use a version-locked `npm exec --package=@shenlee/devcrew@0.1.1` wrapper so the MCP service is locked to the published package version.
|
|
41
41
|
|
|
42
42
|
## 4. Run A Workflow
|
|
43
43
|
|
package/package.json
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const DEVCREW_VERSION = "0.1.
|
|
1
|
+
export const DEVCREW_VERSION = "0.1.1";
|
|
2
2
|
export const DEVCREW_NPM_PACKAGE = "@shenlee/devcrew";
|
|
@@ -93,6 +93,38 @@ function npmPackageSpecifier(): string {
|
|
|
93
93
|
return `${DEVCREW_NPM_PACKAGE}@${DEVCREW_VERSION}`;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
function npmExecCliWrapper(): string {
|
|
97
|
+
const [scope, name] = DEVCREW_NPM_PACKAGE.split("/");
|
|
98
|
+
return [
|
|
99
|
+
"const path = require('node:path');",
|
|
100
|
+
"const { pathToFileURL } = require('node:url');",
|
|
101
|
+
"const binDir = process.env.PATH.split(path.delimiter)[0];",
|
|
102
|
+
`const packageRoot = path.join(binDir.replace(/[\\\\/]\\.bin$/u, ''), ${JSON.stringify(scope)}, ${JSON.stringify(name)});`,
|
|
103
|
+
"process.argv = ['node', 'devcrew', ...process.argv.slice(1)];",
|
|
104
|
+
"import(pathToFileURL(path.join(packageRoot, 'dist/packages/cli/src/index.js')).href);",
|
|
105
|
+
].join(" ");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function mcpServerConfig(host: "codex" | "claude"): unknown {
|
|
109
|
+
return {
|
|
110
|
+
command: "npm",
|
|
111
|
+
args: [
|
|
112
|
+
"exec",
|
|
113
|
+
"--silent",
|
|
114
|
+
"--yes",
|
|
115
|
+
`--package=${npmPackageSpecifier()}`,
|
|
116
|
+
"--",
|
|
117
|
+
"node",
|
|
118
|
+
"-e",
|
|
119
|
+
npmExecCliWrapper(),
|
|
120
|
+
"--",
|
|
121
|
+
"serve",
|
|
122
|
+
"--stdio",
|
|
123
|
+
],
|
|
124
|
+
env: { DEVCREW_HOST: host },
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
96
128
|
export async function generateCodexPlugin(root: string): Promise<GeneratedPlugin> {
|
|
97
129
|
const pluginRoot = join(root, "plugins", "devcrew-codex");
|
|
98
130
|
await mkdir(join(pluginRoot, ".codex-plugin"), { recursive: true });
|
|
@@ -134,11 +166,7 @@ export async function generateCodexPlugin(root: string): Promise<GeneratedPlugin
|
|
|
134
166
|
await writeFile(join(pluginRoot, "skills", "devcrew", "SKILL.md"), entrySkill(), "utf8");
|
|
135
167
|
await writeJson(join(pluginRoot, ".mcp.json"), {
|
|
136
168
|
mcpServers: {
|
|
137
|
-
devcrew:
|
|
138
|
-
command: "npx",
|
|
139
|
-
args: ["-y", npmPackageSpecifier(), "serve", "--stdio"],
|
|
140
|
-
env: { DEVCREW_HOST: "codex" },
|
|
141
|
-
},
|
|
169
|
+
devcrew: mcpServerConfig("codex"),
|
|
142
170
|
},
|
|
143
171
|
});
|
|
144
172
|
await writeRoleAgents(pluginRoot, "codex");
|
|
@@ -184,11 +212,7 @@ export async function generateClaudePlugin(root: string): Promise<GeneratedPlugi
|
|
|
184
212
|
await writeFile(join(pluginRoot, "skills", "devcrew", "SKILL.md"), entrySkill(), "utf8");
|
|
185
213
|
await writeJson(join(pluginRoot, ".mcp.json"), {
|
|
186
214
|
mcpServers: {
|
|
187
|
-
devcrew:
|
|
188
|
-
command: "npx",
|
|
189
|
-
args: ["-y", npmPackageSpecifier(), "serve", "--stdio"],
|
|
190
|
-
env: { DEVCREW_HOST: "claude" },
|
|
191
|
-
},
|
|
215
|
+
devcrew: mcpServerConfig("claude"),
|
|
192
216
|
},
|
|
193
217
|
});
|
|
194
218
|
await writeRoleAgents(pluginRoot, "claude");
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mcpServers": {
|
|
3
3
|
"devcrew": {
|
|
4
|
-
"command": "
|
|
4
|
+
"command": "npm",
|
|
5
5
|
"args": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
6
|
+
"exec",
|
|
7
|
+
"--silent",
|
|
8
|
+
"--yes",
|
|
9
|
+
"--package=@shenlee/devcrew@0.1.1",
|
|
10
|
+
"--",
|
|
11
|
+
"node",
|
|
12
|
+
"-e",
|
|
13
|
+
"const path = require('node:path'); const { pathToFileURL } = require('node:url'); const binDir = process.env.PATH.split(path.delimiter)[0]; const packageRoot = path.join(binDir.replace(/[\\\\/]\\.bin$/u, ''), \"@shenlee\", \"devcrew\"); process.argv = ['node', 'devcrew', ...process.argv.slice(1)]; import(pathToFileURL(path.join(packageRoot, 'dist/packages/cli/src/index.js')).href);",
|
|
14
|
+
"--",
|
|
8
15
|
"serve",
|
|
9
16
|
"--stdio"
|
|
10
17
|
],
|
|
@@ -298,7 +298,7 @@ async function main() {
|
|
|
298
298
|
await client.request("initialize", {
|
|
299
299
|
protocolVersion: "2025-03-26",
|
|
300
300
|
capabilities: {},
|
|
301
|
-
clientInfo: { name: "devcrew-codex-plugin-smoke", version: "0.1.
|
|
301
|
+
clientInfo: { name: "devcrew-codex-plugin-smoke", version: "0.1.1" },
|
|
302
302
|
});
|
|
303
303
|
client.notify("notifications/initialized", {});
|
|
304
304
|
const tools = await client.request("tools/list", {});
|