claws-code 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.
- package/.claude/commands/claws-auto.md +90 -0
- package/.claude/commands/claws-bin.md +28 -0
- package/.claude/commands/claws-cleanup.md +28 -0
- package/.claude/commands/claws-do.md +82 -0
- package/.claude/commands/claws-fix.md +40 -0
- package/.claude/commands/claws-goal.md +111 -0
- package/.claude/commands/claws-help.md +54 -0
- package/.claude/commands/claws-plan.md +103 -0
- package/.claude/commands/claws-report.md +29 -0
- package/.claude/commands/claws-status.md +37 -0
- package/.claude/commands/claws-update.md +32 -0
- package/.claude/commands/claws.md +64 -0
- package/.claude/rules/claws-default-behavior.md +76 -0
- package/.claude/settings.json +112 -0
- package/.claude/settings.local.json +19 -0
- package/.claude/skills/claws-auto-engine/SKILL.md +97 -0
- package/.claude/skills/claws-goal-tracker/SKILL.md +106 -0
- package/.claude/skills/claws-prompt-templates/SKILL.md +203 -0
- package/.claude/skills/claws-wave-lead/SKILL.md +126 -0
- package/.claude/skills/claws-wave-subworker/SKILL.md +60 -0
- package/CHANGELOG.md +1949 -0
- package/LICENSE +21 -0
- package/README.md +420 -0
- package/bin/cli.js +84 -0
- package/cli.js +223 -0
- package/docs/ARCHITECTURE.md +511 -0
- package/docs/event-protocol.md +588 -0
- package/docs/features.md +562 -0
- package/docs/guide.md +891 -0
- package/docs/index.html +716 -0
- package/docs/protocol.md +323 -0
- package/extension/.vscodeignore +15 -0
- package/extension/CHANGELOG.md +1906 -0
- package/extension/LICENSE +21 -0
- package/extension/README.md +137 -0
- package/extension/docs/features.md +424 -0
- package/extension/docs/protocol.md +197 -0
- package/extension/esbuild.mjs +25 -0
- package/extension/icon.png +0 -0
- package/extension/native/.metadata.json +10 -0
- package/extension/native/node-pty/LICENSE +69 -0
- package/extension/native/node-pty/README.md +165 -0
- package/extension/native/node-pty/lib/conpty_console_list_agent.js +16 -0
- package/extension/native/node-pty/lib/conpty_console_list_agent.js.map +1 -0
- package/extension/native/node-pty/lib/eventEmitter2.js +47 -0
- package/extension/native/node-pty/lib/eventEmitter2.js.map +1 -0
- package/extension/native/node-pty/lib/index.js +52 -0
- package/extension/native/node-pty/lib/index.js.map +1 -0
- package/extension/native/node-pty/lib/interfaces.js +7 -0
- package/extension/native/node-pty/lib/interfaces.js.map +1 -0
- package/extension/native/node-pty/lib/shared/conout.js +11 -0
- package/extension/native/node-pty/lib/shared/conout.js.map +1 -0
- package/extension/native/node-pty/lib/terminal.js +190 -0
- package/extension/native/node-pty/lib/terminal.js.map +1 -0
- package/extension/native/node-pty/lib/types.js +7 -0
- package/extension/native/node-pty/lib/types.js.map +1 -0
- package/extension/native/node-pty/lib/unixTerminal.js +346 -0
- package/extension/native/node-pty/lib/unixTerminal.js.map +1 -0
- package/extension/native/node-pty/lib/utils.js +39 -0
- package/extension/native/node-pty/lib/utils.js.map +1 -0
- package/extension/native/node-pty/lib/windowsConoutConnection.js +125 -0
- package/extension/native/node-pty/lib/windowsConoutConnection.js.map +1 -0
- package/extension/native/node-pty/lib/windowsPtyAgent.js +320 -0
- package/extension/native/node-pty/lib/windowsPtyAgent.js.map +1 -0
- package/extension/native/node-pty/lib/windowsTerminal.js +199 -0
- package/extension/native/node-pty/lib/windowsTerminal.js.map +1 -0
- package/extension/native/node-pty/lib/worker/conoutSocketWorker.js +22 -0
- package/extension/native/node-pty/lib/worker/conoutSocketWorker.js.map +1 -0
- package/extension/native/node-pty/package.json +64 -0
- package/extension/native/node-pty/prebuilds/darwin-arm64/pty.node +0 -0
- package/extension/native/node-pty/prebuilds/darwin-arm64/spawn-helper +0 -0
- package/extension/native/node-pty/prebuilds/darwin-x64/pty.node +0 -0
- package/extension/native/node-pty/prebuilds/darwin-x64/spawn-helper +0 -0
- package/extension/native/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe +0 -0
- package/extension/native/node-pty/prebuilds/win32-arm64/conpty/conpty.dll +0 -0
- package/extension/native/node-pty/prebuilds/win32-arm64/conpty.node +0 -0
- package/extension/native/node-pty/prebuilds/win32-arm64/conpty_console_list.node +0 -0
- package/extension/native/node-pty/prebuilds/win32-arm64/pty.node +0 -0
- package/extension/native/node-pty/prebuilds/win32-arm64/winpty-agent.exe +0 -0
- package/extension/native/node-pty/prebuilds/win32-arm64/winpty.dll +0 -0
- package/extension/native/node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
- package/extension/native/node-pty/prebuilds/win32-x64/conpty/conpty.dll +0 -0
- package/extension/native/node-pty/prebuilds/win32-x64/conpty.node +0 -0
- package/extension/native/node-pty/prebuilds/win32-x64/conpty_console_list.node +0 -0
- package/extension/native/node-pty/prebuilds/win32-x64/pty.node +0 -0
- package/extension/native/node-pty/prebuilds/win32-x64/winpty-agent.exe +0 -0
- package/extension/native/node-pty/prebuilds/win32-x64/winpty.dll +0 -0
- package/extension/package-lock.json +605 -0
- package/extension/package.json +343 -0
- package/extension/scripts/bundle-native.mjs +104 -0
- package/extension/scripts/deploy-dev.mjs +60 -0
- package/extension/src/ansi-strip.ts +52 -0
- package/extension/src/backends/vscode/claws-pty.ts +483 -0
- package/extension/src/backends/vscode/status-bar.ts +99 -0
- package/extension/src/backends/vscode/vscode-backend.ts +282 -0
- package/extension/src/capture-store.ts +125 -0
- package/extension/src/event-log.ts +629 -0
- package/extension/src/event-schemas.ts +478 -0
- package/extension/src/extension.js +492 -0
- package/extension/src/extension.ts +873 -0
- package/extension/src/lifecycle-engine.ts +60 -0
- package/extension/src/lifecycle-rules.ts +171 -0
- package/extension/src/lifecycle-store.ts +506 -0
- package/extension/src/peer-registry.ts +176 -0
- package/extension/src/pipeline-registry.ts +82 -0
- package/extension/src/platform.ts +64 -0
- package/extension/src/protocol.ts +532 -0
- package/extension/src/server-config.ts +98 -0
- package/extension/src/server.ts +2210 -0
- package/extension/src/task-registry.ts +51 -0
- package/extension/src/terminal-backend.ts +211 -0
- package/extension/src/terminal-manager.ts +395 -0
- package/extension/src/topic-registry.ts +70 -0
- package/extension/src/topic-utils.ts +46 -0
- package/extension/src/transport.ts +45 -0
- package/extension/src/uninstall-cleanup.ts +232 -0
- package/extension/src/wave-registry.ts +314 -0
- package/extension/src/websocket-transport.ts +153 -0
- package/extension/tsconfig.json +23 -0
- package/lib/capabilities.js +145 -0
- package/lib/dry-run.js +43 -0
- package/lib/install.js +1018 -0
- package/lib/mcp-setup.js +92 -0
- package/lib/platform.js +240 -0
- package/lib/preflight.js +152 -0
- package/lib/shell-hook.js +343 -0
- package/lib/uninstall.js +162 -0
- package/lib/verify.js +166 -0
- package/mcp_server.js +3529 -0
- package/package.json +48 -0
- package/rules/claws-default-behavior.md +72 -0
- package/scripts/_helpers/atomic-file.mjs +137 -0
- package/scripts/_helpers/fix-repair.js +64 -0
- package/scripts/_helpers/json-safe.mjs +218 -0
- package/scripts/bump-version.sh +84 -0
- package/scripts/codegen/gen-docs.mjs +61 -0
- package/scripts/codegen/gen-json-schema.mjs +62 -0
- package/scripts/codegen/gen-mcp-tools.mjs +358 -0
- package/scripts/codegen/gen-types.mjs +172 -0
- package/scripts/codegen/index.mjs +42 -0
- package/scripts/dev-hooks/check-extension-dirs.js +77 -0
- package/scripts/dev-hooks/check-open-claws-terminals.js +70 -0
- package/scripts/dev-hooks/check-stale-main.js +55 -0
- package/scripts/dev-hooks/check-tag-pushed.js +51 -0
- package/scripts/dev-hooks/check-tag-vs-main.js +56 -0
- package/scripts/dev-vsix-install.sh +60 -0
- package/scripts/fix.sh +702 -0
- package/scripts/gen-client-types.mjs +81 -0
- package/scripts/git-hooks/pre-commit +31 -0
- package/scripts/hooks/lifecycle-state.js +61 -0
- package/scripts/hooks/package.json +4 -0
- package/scripts/hooks/post-tool-use-claws.js +292 -0
- package/scripts/hooks/pre-bash-no-verify-block.js +72 -0
- package/scripts/hooks/pre-tool-use-claws.js +206 -0
- package/scripts/hooks/session-start-claws.js +97 -0
- package/scripts/hooks/stop-claws.js +88 -0
- package/scripts/inject-claude-md.js +205 -0
- package/scripts/inject-dev-hooks.js +96 -0
- package/scripts/inject-global-claude-md.js +140 -0
- package/scripts/inject-settings-hooks.js +370 -0
- package/scripts/install.ps1 +146 -0
- package/scripts/install.sh +1729 -0
- package/scripts/monitor-arm-watch.js +155 -0
- package/scripts/rebuild-node-pty.sh +245 -0
- package/scripts/report.sh +232 -0
- package/scripts/shell-hook.fish +164 -0
- package/scripts/shell-hook.ps1 +33 -0
- package/scripts/shell-hook.sh +232 -0
- package/scripts/stream-events.js +399 -0
- package/scripts/terminal-wrapper.sh +36 -0
- package/scripts/test-enforcement.sh +132 -0
- package/scripts/test-install.sh +174 -0
- package/scripts/test-installer-parity.sh +135 -0
- package/scripts/test-template-enforcement.sh +76 -0
- package/scripts/uninstall.sh +143 -0
- package/scripts/update.sh +337 -0
- package/scripts/verify-release.sh +323 -0
- package/scripts/verify-wrapped.sh +194 -0
- package/templates/CLAUDE.global.md +135 -0
- package/templates/CLAUDE.project.md +37 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SessionStart hook: warn if multiple neunaha.claws-* extension dirs exist OR
|
|
3
|
+
// if the active extension's package.json has invalid semver.
|
|
4
|
+
// Always exits 0 — warnings only. Timeout < 5s. Logs misfires to /tmp/claws-dev-hooks.log.
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
const LOG = '/tmp/claws-dev-hooks.log';
|
|
11
|
+
const SEMVER_RE = /^\d+\.\d+\.\d+$/;
|
|
12
|
+
|
|
13
|
+
function log(msg) {
|
|
14
|
+
const ts = new Date().toISOString();
|
|
15
|
+
try { fs.appendFileSync(LOG, `${ts} [check-extension-dirs] ${msg}\n`); } catch (_) {}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function main() {
|
|
19
|
+
const extRoot = path.join(process.env.HOME || process.env.USERPROFILE || '', '.vscode', 'extensions');
|
|
20
|
+
let entries = [];
|
|
21
|
+
try { entries = fs.readdirSync(extRoot); } catch (_) { return; } // no vscode dir
|
|
22
|
+
|
|
23
|
+
const clawsDirs = entries.filter((e) => e.startsWith('neunaha.claws-'));
|
|
24
|
+
|
|
25
|
+
if (clawsDirs.length > 1) {
|
|
26
|
+
console.warn(
|
|
27
|
+
`\n⚠️ [claws-dev-hook] Multiple Claws extension dirs detected:\n` +
|
|
28
|
+
clawsDirs.map((d) => ` ${path.join(extRoot, d)}`).join('\n') + '\n' +
|
|
29
|
+
` Remove old versions: rm -rf ~/.vscode/extensions/neunaha.claws-<old>\n` +
|
|
30
|
+
` Reload VS Code after removal (Cmd+Shift+P → Developer: Reload Window)\n`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Validate semver on the newest dir
|
|
35
|
+
const sorted = clawsDirs
|
|
36
|
+
.map((d) => ({ dir: d, ver: d.replace('neunaha.claws-', '') }))
|
|
37
|
+
.filter((x) => SEMVER_RE.test(x.ver))
|
|
38
|
+
.sort((a, b) => {
|
|
39
|
+
const [am, an, ap] = a.ver.split('.').map(Number);
|
|
40
|
+
const [bm, bn, bp] = b.ver.split('.').map(Number);
|
|
41
|
+
return bm - am || bn - an || bp - ap;
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (sorted.length === 0 && clawsDirs.length > 0) {
|
|
45
|
+
const badDirs = clawsDirs.filter((d) => !SEMVER_RE.test(d.replace('neunaha.claws-', '')));
|
|
46
|
+
if (badDirs.length > 0) {
|
|
47
|
+
console.warn(
|
|
48
|
+
`\n⚠️ [claws-dev-hook] Extension dir(s) with invalid semver: ${badDirs.join(', ')}\n` +
|
|
49
|
+
` Expected format: neunaha.claws-MAJOR.MINOR.PATCH\n`
|
|
50
|
+
);
|
|
51
|
+
log(`invalid semver dirs: ${badDirs.join(', ')}`);
|
|
52
|
+
}
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (sorted.length > 0) {
|
|
57
|
+
const newest = path.join(extRoot, sorted[0].dir);
|
|
58
|
+
let pkgVer = '';
|
|
59
|
+
try {
|
|
60
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(newest, 'package.json'), 'utf8'));
|
|
61
|
+
pkgVer = pkg.version || '';
|
|
62
|
+
} catch (e) {
|
|
63
|
+
log(`package.json read failed for ${newest}: ${e.message}`);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (!SEMVER_RE.test(pkgVer)) {
|
|
67
|
+
console.warn(
|
|
68
|
+
`\n⚠️ [claws-dev-hook] Extension manifest version "${pkgVer}" is not valid semver.\n` +
|
|
69
|
+
` Expected: MAJOR.MINOR.PATCH (e.g. 0.7.7)\n`
|
|
70
|
+
);
|
|
71
|
+
log(`invalid manifest version: ${pkgVer} in ${newest}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try { main(); } catch (e) { log(`uncaught: ${e.message}`); }
|
|
77
|
+
process.exit(0);
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Stop hook: list open wrapped terminals via raw socket; warn if >0 remain open.
|
|
3
|
+
// Always exits 0 — warnings only. Timeout < 5s. Logs misfires to /tmp/claws-dev-hooks.log.
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const net = require('net');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
const LOG = '/tmp/claws-dev-hooks.log';
|
|
11
|
+
|
|
12
|
+
function log(msg) {
|
|
13
|
+
const ts = new Date().toISOString();
|
|
14
|
+
try { fs.appendFileSync(LOG, `${ts} [check-open-claws-terminals] ${msg}\n`); } catch (_) {}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function findSock() {
|
|
18
|
+
if (process.env.CLAWS_SOCKET) return process.env.CLAWS_SOCKET;
|
|
19
|
+
let d = process.env.PROJECT_ROOT || process.cwd();
|
|
20
|
+
for (let i = 0; i < 20 && d && d !== '/'; i++) {
|
|
21
|
+
const candidate = path.join(d, '.claws', 'claws.sock');
|
|
22
|
+
try { if (fs.statSync(candidate).isSocket()) return candidate; } catch (_) {}
|
|
23
|
+
d = path.dirname(d);
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function listTerminals(sockPath) {
|
|
29
|
+
return new Promise((resolve) => {
|
|
30
|
+
const s = net.createConnection(sockPath);
|
|
31
|
+
const timer = setTimeout(() => { s.destroy(); resolve([]); }, 4000);
|
|
32
|
+
s.on('connect', () => s.write(JSON.stringify({ id: 1, cmd: 'list' }) + '\n'));
|
|
33
|
+
let buf = '';
|
|
34
|
+
s.on('data', (d) => {
|
|
35
|
+
buf += d;
|
|
36
|
+
const nl = buf.indexOf('\n');
|
|
37
|
+
if (nl !== -1) {
|
|
38
|
+
clearTimeout(timer);
|
|
39
|
+
try {
|
|
40
|
+
const parsed = JSON.parse(buf.slice(0, nl));
|
|
41
|
+
resolve(parsed.terminals || []);
|
|
42
|
+
} catch (_) { resolve([]); }
|
|
43
|
+
s.destroy();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
s.on('error', () => { clearTimeout(timer); resolve([]); });
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function main() {
|
|
51
|
+
const sockPath = findSock();
|
|
52
|
+
if (!sockPath) return; // no socket — not a Claws session
|
|
53
|
+
|
|
54
|
+
let terminals = [];
|
|
55
|
+
try { terminals = await listTerminals(sockPath); } catch (e) {
|
|
56
|
+
log(`list failed: ${e.message}`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const wrapped = terminals.filter((t) => t.logPath || t.wrapped);
|
|
61
|
+
if (wrapped.length > 0) {
|
|
62
|
+
const names = wrapped.map((t) => `#${t.id} ${t.name || '(unnamed)'}`).join(', ');
|
|
63
|
+
console.warn(
|
|
64
|
+
`\n⚠️ [claws-dev-hook] ${wrapped.length} wrapped terminal(s) still open: ${names}\n` +
|
|
65
|
+
` Close them before ending your session to avoid stale pty logs.\n`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
main().catch((e) => log(`uncaught: ${e.message}`)).then(() => process.exit(0));
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SessionStart hook: warn if local main/current branch is behind origin.
|
|
3
|
+
// Always exits 0 — warnings only. Timeout < 5s. Logs misfires to /tmp/claws-dev-hooks.log.
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
const LOG = '/tmp/claws-dev-hooks.log';
|
|
11
|
+
|
|
12
|
+
function log(msg) {
|
|
13
|
+
const ts = new Date().toISOString();
|
|
14
|
+
try { fs.appendFileSync(LOG, `${ts} [check-stale-main] ${msg}\n`); } catch (_) {}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function run(cmd, opts = {}) {
|
|
18
|
+
return execSync(cmd, { timeout: 4000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], ...opts }).trim();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function main() {
|
|
22
|
+
const cwd = process.env.PROJECT_ROOT || process.cwd();
|
|
23
|
+
|
|
24
|
+
// Not a git repo — skip silently
|
|
25
|
+
try { run('git rev-parse --git-dir', { cwd }); } catch (_) { return; }
|
|
26
|
+
|
|
27
|
+
// Fetch with a tight timeout; if offline, exit silently
|
|
28
|
+
try {
|
|
29
|
+
run('git fetch origin --quiet --no-tags --depth=1', { cwd, timeout: 4000 });
|
|
30
|
+
} catch (e) {
|
|
31
|
+
log(`fetch failed (offline?): ${e.message}`);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let behind = 0;
|
|
36
|
+
try {
|
|
37
|
+
const branch = run('git rev-parse --abbrev-ref HEAD', { cwd });
|
|
38
|
+
const upstream = `origin/${branch}`;
|
|
39
|
+
const count = run(`git rev-list --count HEAD..${upstream}`, { cwd });
|
|
40
|
+
behind = parseInt(count, 10) || 0;
|
|
41
|
+
} catch (e) {
|
|
42
|
+
log(`rev-list failed: ${e.message}`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (behind > 0) {
|
|
47
|
+
console.warn(
|
|
48
|
+
`\n⚠️ [claws-dev-hook] Your branch is ${behind} commit(s) behind origin.\n` +
|
|
49
|
+
` Run: git pull --ff-only origin\n`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try { main(); } catch (e) { log(`uncaught: ${e.message}`); }
|
|
55
|
+
process.exit(0);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// PostToolUse Bash hook (git push): verify the latest local tag exists on origin.
|
|
3
|
+
// Always exits 0 — warnings only. Timeout < 5s. Logs misfires to /tmp/claws-dev-hooks.log.
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
|
|
9
|
+
const LOG = '/tmp/claws-dev-hooks.log';
|
|
10
|
+
|
|
11
|
+
function log(msg) {
|
|
12
|
+
const ts = new Date().toISOString();
|
|
13
|
+
try { fs.appendFileSync(LOG, `${ts} [check-tag-pushed] ${msg}\n`); } catch (_) {}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function run(cmd, opts = {}) {
|
|
17
|
+
return execSync(cmd, { timeout: 4000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], ...opts }).trim();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function main() {
|
|
21
|
+
const cwd = process.env.PROJECT_ROOT || process.cwd();
|
|
22
|
+
|
|
23
|
+
// Not a git repo — skip silently
|
|
24
|
+
try { run('git rev-parse --git-dir', { cwd }); } catch (_) { return; }
|
|
25
|
+
|
|
26
|
+
let latestTag = '';
|
|
27
|
+
try {
|
|
28
|
+
latestTag = run('git describe --tags --abbrev=0', { cwd });
|
|
29
|
+
} catch (_) {
|
|
30
|
+
return; // no tags yet — skip
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let remoteTags = '';
|
|
34
|
+
try {
|
|
35
|
+
remoteTags = run(`git ls-remote --tags origin refs/tags/${latestTag}`, { cwd, timeout: 4000 });
|
|
36
|
+
} catch (e) {
|
|
37
|
+
log(`ls-remote failed: ${e.message}`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!remoteTags.includes(latestTag)) {
|
|
42
|
+
console.warn(
|
|
43
|
+
`\n⚠️ [claws-dev-hook] Local tag ${latestTag} is NOT on origin.\n` +
|
|
44
|
+
` Run: git push origin ${latestTag}\n` +
|
|
45
|
+
` Or: git push --tags\n`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try { main(); } catch (e) { log(`uncaught: ${e.message}`); }
|
|
51
|
+
process.exit(0);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// PostToolUse Bash hook (git commit): warn if commits on main are past the last tag.
|
|
3
|
+
// Always exits 0 — warnings only. Timeout < 5s. Logs misfires to /tmp/claws-dev-hooks.log.
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
|
|
9
|
+
const LOG = '/tmp/claws-dev-hooks.log';
|
|
10
|
+
|
|
11
|
+
function log(msg) {
|
|
12
|
+
const ts = new Date().toISOString();
|
|
13
|
+
try { fs.appendFileSync(LOG, `${ts} [check-tag-vs-main] ${msg}\n`); } catch (_) {}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function run(cmd, opts = {}) {
|
|
17
|
+
return execSync(cmd, { timeout: 4000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], ...opts }).trim();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function main() {
|
|
21
|
+
const cwd = process.env.PROJECT_ROOT || process.cwd();
|
|
22
|
+
|
|
23
|
+
// Not a git repo — skip silently
|
|
24
|
+
try { run('git rev-parse --git-dir', { cwd }); } catch (_) { return; }
|
|
25
|
+
|
|
26
|
+
let latestTag = '';
|
|
27
|
+
try {
|
|
28
|
+
latestTag = run('git describe --tags --abbrev=0', { cwd });
|
|
29
|
+
} catch (_) {
|
|
30
|
+
return; // no tags yet
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let aheadCount = 0;
|
|
34
|
+
try {
|
|
35
|
+
const count = run(`git rev-list --count ${latestTag}..HEAD`, { cwd });
|
|
36
|
+
aheadCount = parseInt(count, 10) || 0;
|
|
37
|
+
} catch (e) {
|
|
38
|
+
log(`rev-list failed: ${e.message}`);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (aheadCount > 0) {
|
|
43
|
+
// Check if we're on main/master
|
|
44
|
+
let branch = '';
|
|
45
|
+
try { branch = run('git rev-parse --abbrev-ref HEAD', { cwd }); } catch (_) {}
|
|
46
|
+
if (branch === 'main' || branch === 'master') {
|
|
47
|
+
console.warn(
|
|
48
|
+
`\n⚠️ [claws-dev-hook] ${aheadCount} commit(s) on ${branch} past last tag (${latestTag}).\n` +
|
|
49
|
+
` Remember to tag your release: git tag vX.Y.Z && git push --tags\n`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try { main(); } catch (e) { log(`uncaught: ${e.message}`); }
|
|
56
|
+
process.exit(0);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# scripts/dev-vsix-install.sh
|
|
3
|
+
#
|
|
4
|
+
# Rebuild + repackage + reinstall the Claws extension as a fresh VSIX —
|
|
5
|
+
# the missing dev-loop step that complements `npm run deploy:dev`.
|
|
6
|
+
#
|
|
7
|
+
# Why both exist:
|
|
8
|
+
# deploy:dev (fast, ~5s) — copies new dist into installed dir; does NOT
|
|
9
|
+
# refresh extensions.json metadata. Panel keeps
|
|
10
|
+
# showing original VSIX date — silent staleness risk.
|
|
11
|
+
# dev-vsix-install (~25s) — full vsce package + code --install-extension.
|
|
12
|
+
# Refreshes installedTimestamp, version label, and
|
|
13
|
+
# panel date. Use after material extension changes
|
|
14
|
+
# or whenever you want a clean dev-install.
|
|
15
|
+
#
|
|
16
|
+
# After this finishes: Cmd+Shift+P → Developer: Reload Window.
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
21
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
22
|
+
EXT_DIR="$REPO_ROOT/extension"
|
|
23
|
+
VSIX_OUT="${TMPDIR:-/tmp}/claws-dev-$(date +%s).vsix"
|
|
24
|
+
|
|
25
|
+
[ -d "$EXT_DIR" ] || { echo "[dev-vsix-install] FATAL: $EXT_DIR not found" >&2; exit 1; }
|
|
26
|
+
|
|
27
|
+
# Resolve the VS Code CLI. Mirrors install.sh::_find_editor_cli — PATH first,
|
|
28
|
+
# then macOS app-bundle fallback. Lets the script work from worker terminals
|
|
29
|
+
# whose PATH may not include /usr/local/bin.
|
|
30
|
+
_find_code_cli() {
|
|
31
|
+
command -v code 2>/dev/null && return 0
|
|
32
|
+
case "$(uname -s)" in
|
|
33
|
+
Darwin)
|
|
34
|
+
local p="/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"
|
|
35
|
+
[ -x "$p" ] && echo "$p" && return 0
|
|
36
|
+
;;
|
|
37
|
+
esac
|
|
38
|
+
return 1
|
|
39
|
+
}
|
|
40
|
+
CODE_CLI="$(_find_code_cli)" || {
|
|
41
|
+
echo "[dev-vsix-install] FATAL: 'code' CLI not found" >&2
|
|
42
|
+
echo "[dev-vsix-install] tried: PATH, /Applications/Visual Studio Code.app/Contents/Resources/app/bin/code" >&2
|
|
43
|
+
echo "[dev-vsix-install] install via VS Code: Cmd+Shift+P -> 'Shell Command: Install code in PATH'" >&2
|
|
44
|
+
exit 1
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
echo "[dev-vsix-install] step 1/3 — rebuilding extension"
|
|
48
|
+
( cd "$EXT_DIR" && npm run build )
|
|
49
|
+
|
|
50
|
+
echo "[dev-vsix-install] step 2/3 — packaging VSIX → $VSIX_OUT"
|
|
51
|
+
( cd "$EXT_DIR" && npx -y @vscode/vsce package \
|
|
52
|
+
--skip-license --no-git-tag-version --no-update-package-json \
|
|
53
|
+
--out "$VSIX_OUT" )
|
|
54
|
+
|
|
55
|
+
echo "[dev-vsix-install] step 3/3 — installing into VS Code via $CODE_CLI"
|
|
56
|
+
"$CODE_CLI" --install-extension "$VSIX_OUT" --force
|
|
57
|
+
echo
|
|
58
|
+
echo "[dev-vsix-install] install complete — reload required:"
|
|
59
|
+
echo "[dev-vsix-install] Cmd+Shift+P -> Developer: Reload Window"
|
|
60
|
+
echo "[dev-vsix-install] vsix kept at: $VSIX_OUT"
|