cmdr-mcp 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/.claude-plugin/marketplace.json +1 -1
- package/README.md +15 -2
- package/docs/README.zh-CN.md +18 -2
- package/docs/agent-integration.md +7 -3
- package/docs/implementation.md +8 -5
- package/docs/iteration-plan-zcode.md +152 -0
- package/docs/publishing.md +11 -9
- package/docs/troubleshooting.md +63 -0
- package/marketplace.json +1 -1
- package/package.json +7 -7
- package/plugins/cmdr/.claude-plugin/plugin.json +1 -1
- package/plugins/cmdr/.codex-plugin/plugin.json +1 -1
- package/plugins/cmdr/.zcode-plugin/plugin.json +1 -1
- package/plugins/cmdr/README.md +2 -0
- package/plugins/cmdr/bin/cmdr +9 -1
- package/plugins/cmdr/bin/cmdr-check.mjs +97 -0
- package/plugins/cmdr/bin/cmdr-daemon +9 -1
- package/plugins/cmdr/bin/cmdr-hook +9 -1
- package/plugins/cmdr/bin/cmdr-mcp +9 -1
- package/plugins/cmdr/bin/cmdr-node +24 -1
- package/plugins/cmdr/commands/cmdr.md +2 -0
- package/plugins/cmdr/dist/cli.mjs +4757 -223
- package/plugins/cmdr/dist/daemon.mjs +35 -9
- package/plugins/cmdr/dist/hook.mjs +64 -11
- package/plugins/cmdr/dist/integrity.json +25 -0
- package/plugins/cmdr/dist/mcp.mjs +101 -38
- package/plugins/cmdr/skills/using-cmdr/SKILL.md +2 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Kept outside dist so a damaged runtime can still be inspected with Node alone.
|
|
3
|
+
import { readFileSync, existsSync, lstatSync } from 'node:fs';
|
|
4
|
+
import { resolve, join } from 'node:path';
|
|
5
|
+
import { createHash } from 'node:crypto';
|
|
6
|
+
const root = resolve(process.argv[2]);
|
|
7
|
+
const errors = [];
|
|
8
|
+
const read = (path) => JSON.parse(readFileSync(join(root, path), 'utf8'));
|
|
9
|
+
let manifest;
|
|
10
|
+
try {
|
|
11
|
+
manifest = read('dist/integrity.json');
|
|
12
|
+
} catch {
|
|
13
|
+
errors.push(
|
|
14
|
+
'Missing or invalid dist/integrity.json; reinstall this plugin from the built npm package.',
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
const files = {};
|
|
18
|
+
const required = [
|
|
19
|
+
'dist/cli.mjs',
|
|
20
|
+
'dist/mcp.mjs',
|
|
21
|
+
'dist/hook.mjs',
|
|
22
|
+
'dist/daemon.mjs',
|
|
23
|
+
'bin/cmdr',
|
|
24
|
+
'bin/cmdr-node',
|
|
25
|
+
'bin/cmdr-mcp',
|
|
26
|
+
'bin/cmdr-hook',
|
|
27
|
+
'bin/cmdr-daemon',
|
|
28
|
+
'bin/cmdr-check.mjs',
|
|
29
|
+
'hooks/hooks.json',
|
|
30
|
+
'.mcp.json',
|
|
31
|
+
'.claude-plugin/plugin.json',
|
|
32
|
+
'.codex-plugin/plugin.json',
|
|
33
|
+
'.zcode-plugin/plugin.json',
|
|
34
|
+
];
|
|
35
|
+
for (const path of new Set([...required, ...Object.keys(manifest?.files || {})])) {
|
|
36
|
+
if (
|
|
37
|
+
!required.includes(path) &&
|
|
38
|
+
!path.startsWith('skills/') &&
|
|
39
|
+
!path.startsWith('commands/') &&
|
|
40
|
+
path !== 'THIRD_PARTY_NOTICES.txt'
|
|
41
|
+
) {
|
|
42
|
+
errors.push(`Unexpected manifest path: ${path}`);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (path.split('/').some((part) => part === '..' || part === '')) {
|
|
46
|
+
errors.push('Invalid manifest path');
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const full = join(root, path);
|
|
51
|
+
const linked = path
|
|
52
|
+
.split('/')
|
|
53
|
+
.some((_, i, parts) => lstatSync(join(root, ...parts.slice(0, i + 1))).isSymbolicLink());
|
|
54
|
+
const digest = createHash('sha256').update(readFileSync(full)).digest('hex');
|
|
55
|
+
files[path] = !linked && manifest?.files?.[path] === digest;
|
|
56
|
+
} catch {
|
|
57
|
+
files[path] = false;
|
|
58
|
+
}
|
|
59
|
+
if (!files[path]) errors.push(`Missing, modified or linked asset: ${path}`);
|
|
60
|
+
}
|
|
61
|
+
const versions = {};
|
|
62
|
+
for (const host of ['claude', 'codex', 'zcode']) {
|
|
63
|
+
try {
|
|
64
|
+
versions[host] = read(`.${host}-plugin/plugin.json`).version;
|
|
65
|
+
if (versions[host] !== manifest?.version) errors.push(`${host} version differs from build`);
|
|
66
|
+
} catch {
|
|
67
|
+
errors.push(`Invalid ${host} manifest`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
let hooks = {};
|
|
71
|
+
try {
|
|
72
|
+
hooks = read('hooks/hooks.json').hooks;
|
|
73
|
+
} catch {
|
|
74
|
+
errors.push('Invalid hooks configuration');
|
|
75
|
+
}
|
|
76
|
+
console.log(
|
|
77
|
+
JSON.stringify(
|
|
78
|
+
{
|
|
79
|
+
ok: errors.length === 0,
|
|
80
|
+
plugin_root: root,
|
|
81
|
+
version: manifest?.version,
|
|
82
|
+
node: process.version,
|
|
83
|
+
files,
|
|
84
|
+
versions,
|
|
85
|
+
hooks: {
|
|
86
|
+
configured: Object.keys(hooks || {}),
|
|
87
|
+
observed: 'unknown; configuration alone does not prove execution',
|
|
88
|
+
},
|
|
89
|
+
errors,
|
|
90
|
+
repair:
|
|
91
|
+
'npm install -g cmdr-mcp; register its package root, then refresh/reinstall the host plugin cache and start a new session. For a source checkout run npm ci && npm run build at repository root. Do not link dist from another installation.',
|
|
92
|
+
},
|
|
93
|
+
null,
|
|
94
|
+
2,
|
|
95
|
+
),
|
|
96
|
+
);
|
|
97
|
+
process.exitCode = errors.length ? 1 : 0;
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
|
-
|
|
2
|
+
CMDR_SCRIPT=$0
|
|
3
|
+
while [ -L "$CMDR_SCRIPT" ]; do
|
|
4
|
+
CMDR_LINK=$(readlink "$CMDR_SCRIPT") || exit 1
|
|
5
|
+
case "$CMDR_LINK" in
|
|
6
|
+
/*) CMDR_SCRIPT=$CMDR_LINK ;;
|
|
7
|
+
*) CMDR_SCRIPT=$(dirname -- "$CMDR_SCRIPT")/$CMDR_LINK ;;
|
|
8
|
+
esac
|
|
9
|
+
done
|
|
10
|
+
CMDR_BIN_DIR=$(CDPATH= cd -- "$(dirname -- "$CMDR_SCRIPT")" && pwd)
|
|
3
11
|
export CMDR_BIN_DIR
|
|
4
12
|
exec "$CMDR_BIN_DIR/cmdr-node" daemon "$@"
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
|
-
|
|
2
|
+
CMDR_SCRIPT=$0
|
|
3
|
+
while [ -L "$CMDR_SCRIPT" ]; do
|
|
4
|
+
CMDR_LINK=$(readlink "$CMDR_SCRIPT") || exit 1
|
|
5
|
+
case "$CMDR_LINK" in
|
|
6
|
+
/*) CMDR_SCRIPT=$CMDR_LINK ;;
|
|
7
|
+
*) CMDR_SCRIPT=$(dirname -- "$CMDR_SCRIPT")/$CMDR_LINK ;;
|
|
8
|
+
esac
|
|
9
|
+
done
|
|
10
|
+
CMDR_BIN_DIR=$(CDPATH= cd -- "$(dirname -- "$CMDR_SCRIPT")" && pwd)
|
|
3
11
|
export CMDR_BIN_DIR
|
|
4
12
|
exec "$CMDR_BIN_DIR/cmdr-node" hook "$@"
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
|
-
|
|
2
|
+
CMDR_SCRIPT=$0
|
|
3
|
+
while [ -L "$CMDR_SCRIPT" ]; do
|
|
4
|
+
CMDR_LINK=$(readlink "$CMDR_SCRIPT") || exit 1
|
|
5
|
+
case "$CMDR_LINK" in
|
|
6
|
+
/*) CMDR_SCRIPT=$CMDR_LINK ;;
|
|
7
|
+
*) CMDR_SCRIPT=$(dirname -- "$CMDR_SCRIPT")/$CMDR_LINK ;;
|
|
8
|
+
esac
|
|
9
|
+
done
|
|
10
|
+
CMDR_BIN_DIR=$(CDPATH= cd -- "$(dirname -- "$CMDR_SCRIPT")" && pwd)
|
|
3
11
|
export CMDR_BIN_DIR
|
|
4
12
|
exec "$CMDR_BIN_DIR/cmdr-node" mcp "$@"
|
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
CMDR_ENTRY=$1
|
|
4
4
|
shift
|
|
5
5
|
CMDR_RUNTIME_HOME=${CMDR_HOME:-"$HOME/.cmdr"}
|
|
6
|
+
cmdr_failure() {
|
|
7
|
+
# One fixed-size record per failure type, rate limited across hook processes.
|
|
8
|
+
(umask 077
|
|
9
|
+
CMDR_LOG_DIR="$CMDR_RUNTIME_HOME/logs/diagnostics"
|
|
10
|
+
mkdir -p "$CMDR_LOG_DIR" || exit 0
|
|
11
|
+
CMDR_LOG_FILE="$CMDR_LOG_DIR/bootstrap-$1.json"
|
|
12
|
+
CMDR_NOW=$(date +%s)
|
|
13
|
+
CMDR_LAST=$(cat "$CMDR_LOG_DIR/bootstrap-$1.time" 2>/dev/null || true)
|
|
14
|
+
case "$CMDR_LAST" in ''|*[!0-9]*) CMDR_LAST=0 ;; esac
|
|
15
|
+
[ $((CMDR_NOW - CMDR_LAST)) -lt 60 ] && exit 0
|
|
16
|
+
printf '%s\n' "$CMDR_NOW" > "$CMDR_LOG_DIR/bootstrap-$1.time"
|
|
17
|
+
printf '{"code":"bootstrap-%s","at":%s000}\n' "$1" "$CMDR_NOW" > "$CMDR_LOG_FILE"
|
|
18
|
+
) 2>/dev/null || true
|
|
19
|
+
}
|
|
6
20
|
CMDR_NODE=''
|
|
7
21
|
if [ -r "$CMDR_RUNTIME_HOME/node-path" ]; then
|
|
8
22
|
IFS= read -r CMDR_NODE < "$CMDR_RUNTIME_HOME/node-path"
|
|
@@ -22,13 +36,22 @@ if [ -z "$CMDR_NODE" ]; then
|
|
|
22
36
|
fi
|
|
23
37
|
fi
|
|
24
38
|
if [ -z "$CMDR_NODE" ]; then
|
|
39
|
+
cmdr_failure node
|
|
25
40
|
[ "$CMDR_ENTRY" = hook ] && exit 0
|
|
26
41
|
echo 'cmdr requires Node.js >=22.5 (24 recommended). Install Node and retry.' >&2
|
|
27
42
|
exit 1
|
|
28
43
|
fi
|
|
29
44
|
if [ ! -f "$CMDR_BIN_DIR/../dist/$CMDR_ENTRY.mjs" ]; then
|
|
45
|
+
cmdr_failure runtime
|
|
30
46
|
[ "$CMDR_ENTRY" = hook ] && exit 0
|
|
31
|
-
|
|
47
|
+
if [ "$CMDR_ENTRY" = cli ] && [ "$1" = doctor ] && [ -f "$CMDR_BIN_DIR/cmdr-check.mjs" ]; then
|
|
48
|
+
exec "$CMDR_NODE" "$CMDR_BIN_DIR/cmdr-check.mjs" "$CMDR_BIN_DIR/.."
|
|
49
|
+
fi
|
|
50
|
+
echo 'cmdr runtime is not built. Run npm ci && npm run build in the repository, or install cmdr-mcp from npm, refresh/reinstall the host plugin cache and start a new session. Do not symlink another installation. Inspect this plugin with a working cmdr doctor --plugin-root PATH.' >&2
|
|
32
51
|
exit 1
|
|
33
52
|
fi
|
|
53
|
+
if [ "$CMDR_ENTRY" = hook ]; then
|
|
54
|
+
"$CMDR_NODE" --experimental-sqlite --disable-warning=ExperimentalWarning "$CMDR_BIN_DIR/../dist/hook.mjs" "$@" 2>/dev/null || cmdr_failure runtime
|
|
55
|
+
exit 0
|
|
56
|
+
fi
|
|
34
57
|
exec "$CMDR_NODE" --experimental-sqlite --disable-warning=ExperimentalWarning "$CMDR_BIN_DIR/../dist/$CMDR_ENTRY.mjs" "$@"
|
|
@@ -5,3 +5,5 @@ argument-hint: <name>
|
|
|
5
5
|
Call the cmdr join tool with squad_name="$ARGUMENTS". This is an atomic find-or-create operation; do not list then create. If no name was provided, ask for one. Do not invent a name.
|
|
6
6
|
If the squad is orphaned, ask whether to take over as commander or join as executor and then use explicit role and squad ID.
|
|
7
7
|
Follow the returned protocol_hint. An executor reports ready with cwd, capabilities and context before replying. Translate user_reply into the user's language, keep the join line unchanged, and reply with only that text. Then use read(wait=me.recommended_wait) to participate.
|
|
8
|
+
|
|
9
|
+
If cmdr tools are unavailable, follow the using-cmdr installation diagnostics and member CLI fallback. Do not invent native session IDs or access raw sockets.
|