delimit-cli 4.1.30 → 4.1.31
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 -0
- package/bin/delimit-cli.js +134 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -156,6 +156,8 @@ npx delimit-cli diff old.yaml new.yaml # Compare two specs
|
|
|
156
156
|
npx delimit-cli explain old.yaml new.yaml # Generate migration guide
|
|
157
157
|
npx delimit-cli check # Pre-commit governance check
|
|
158
158
|
npx delimit-cli check --staged --fix # Check staged files + show guidance
|
|
159
|
+
npx delimit-cli hooks install # Install git pre-commit hook
|
|
160
|
+
npx delimit-cli hooks install --pre-push # Also add pre-push hook
|
|
159
161
|
npx delimit-cli ci # Generate GitHub Action workflow
|
|
160
162
|
npx delimit-cli ci --strict --dry-run # Preview strict workflow
|
|
161
163
|
npx delimit-cli doctor # Check setup health
|
package/bin/delimit-cli.js
CHANGED
|
@@ -3044,6 +3044,140 @@ program
|
|
|
3044
3044
|
}
|
|
3045
3045
|
});
|
|
3046
3046
|
|
|
3047
|
+
// Hooks command — install/remove git hooks for governance
|
|
3048
|
+
program
|
|
3049
|
+
.command('hooks <action>')
|
|
3050
|
+
.description('Install or remove git hooks (install | remove | status)')
|
|
3051
|
+
.option('--pre-push', 'Also add pre-push hook')
|
|
3052
|
+
.action(async (action, opts) => {
|
|
3053
|
+
const projectDir = process.cwd();
|
|
3054
|
+
const gitDir = path.join(projectDir, '.git');
|
|
3055
|
+
|
|
3056
|
+
if (!fs.existsSync(gitDir)) {
|
|
3057
|
+
console.log(chalk.red('\n Not a git repository. Run git init first.\n'));
|
|
3058
|
+
process.exitCode = 1;
|
|
3059
|
+
return;
|
|
3060
|
+
}
|
|
3061
|
+
|
|
3062
|
+
const hooksDir = path.join(gitDir, 'hooks');
|
|
3063
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
3064
|
+
|
|
3065
|
+
const preCommitPath = path.join(hooksDir, 'pre-commit');
|
|
3066
|
+
const prePushPath = path.join(hooksDir, 'pre-push');
|
|
3067
|
+
const marker = '# delimit-governance-hook';
|
|
3068
|
+
|
|
3069
|
+
const preCommitHook = `#!/bin/sh
|
|
3070
|
+
${marker}
|
|
3071
|
+
# Delimit API governance gate
|
|
3072
|
+
# Blocks commits with breaking API changes
|
|
3073
|
+
npx delimit-cli check --staged
|
|
3074
|
+
`;
|
|
3075
|
+
|
|
3076
|
+
const prePushHook = `#!/bin/sh
|
|
3077
|
+
${marker}
|
|
3078
|
+
# Delimit API governance gate
|
|
3079
|
+
# Blocks pushes with breaking API changes
|
|
3080
|
+
npx delimit-cli check --base origin/main
|
|
3081
|
+
`;
|
|
3082
|
+
|
|
3083
|
+
if (action === 'install') {
|
|
3084
|
+
console.log(chalk.bold('\n Delimit Hooks\n'));
|
|
3085
|
+
|
|
3086
|
+
let installed = 0;
|
|
3087
|
+
|
|
3088
|
+
// Pre-commit hook
|
|
3089
|
+
if (fs.existsSync(preCommitPath)) {
|
|
3090
|
+
const existing = fs.readFileSync(preCommitPath, 'utf-8');
|
|
3091
|
+
if (existing.includes(marker)) {
|
|
3092
|
+
console.log(chalk.gray(' pre-commit hook already installed'));
|
|
3093
|
+
} else {
|
|
3094
|
+
// Append to existing hook
|
|
3095
|
+
fs.appendFileSync(preCommitPath, '\n' + preCommitHook.split('\n').slice(1).join('\n'));
|
|
3096
|
+
console.log(chalk.green(' + pre-commit hook added (appended to existing)'));
|
|
3097
|
+
installed++;
|
|
3098
|
+
}
|
|
3099
|
+
} else {
|
|
3100
|
+
fs.writeFileSync(preCommitPath, preCommitHook);
|
|
3101
|
+
fs.chmodSync(preCommitPath, '755');
|
|
3102
|
+
console.log(chalk.green(' + pre-commit hook installed'));
|
|
3103
|
+
installed++;
|
|
3104
|
+
}
|
|
3105
|
+
|
|
3106
|
+
// Pre-push hook (optional)
|
|
3107
|
+
if (opts.prePush) {
|
|
3108
|
+
if (fs.existsSync(prePushPath)) {
|
|
3109
|
+
const existing = fs.readFileSync(prePushPath, 'utf-8');
|
|
3110
|
+
if (existing.includes(marker)) {
|
|
3111
|
+
console.log(chalk.gray(' pre-push hook already installed'));
|
|
3112
|
+
} else {
|
|
3113
|
+
fs.appendFileSync(prePushPath, '\n' + prePushHook.split('\n').slice(1).join('\n'));
|
|
3114
|
+
console.log(chalk.green(' + pre-push hook added (appended to existing)'));
|
|
3115
|
+
installed++;
|
|
3116
|
+
}
|
|
3117
|
+
} else {
|
|
3118
|
+
fs.writeFileSync(prePushPath, prePushHook);
|
|
3119
|
+
fs.chmodSync(prePushPath, '755');
|
|
3120
|
+
console.log(chalk.green(' + pre-push hook installed'));
|
|
3121
|
+
installed++;
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
if (installed > 0) {
|
|
3126
|
+
console.log(chalk.bold(`\n ${installed} hook(s) installed.`));
|
|
3127
|
+
console.log(chalk.gray(' Commits that introduce breaking API changes will be blocked.'));
|
|
3128
|
+
console.log(chalk.gray(' Override with: git commit --no-verify\n'));
|
|
3129
|
+
} else {
|
|
3130
|
+
console.log(chalk.gray('\n All hooks already installed.\n'));
|
|
3131
|
+
}
|
|
3132
|
+
|
|
3133
|
+
} else if (action === 'remove') {
|
|
3134
|
+
console.log(chalk.bold('\n Delimit Hooks — Remove\n'));
|
|
3135
|
+
let removed = 0;
|
|
3136
|
+
|
|
3137
|
+
for (const [hookPath, name] of [[preCommitPath, 'pre-commit'], [prePushPath, 'pre-push']]) {
|
|
3138
|
+
if (fs.existsSync(hookPath)) {
|
|
3139
|
+
const content = fs.readFileSync(hookPath, 'utf-8');
|
|
3140
|
+
if (content.includes(marker)) {
|
|
3141
|
+
// If the entire hook is ours, remove it
|
|
3142
|
+
const lines = content.split('\n');
|
|
3143
|
+
const delimitStart = lines.findIndex(l => l.includes(marker));
|
|
3144
|
+
if (delimitStart <= 1) {
|
|
3145
|
+
// Whole file is ours
|
|
3146
|
+
fs.unlinkSync(hookPath);
|
|
3147
|
+
console.log(chalk.yellow(` - ${name} hook removed`));
|
|
3148
|
+
} else {
|
|
3149
|
+
// Remove just our section
|
|
3150
|
+
const before = lines.slice(0, delimitStart).join('\n');
|
|
3151
|
+
fs.writeFileSync(hookPath, before + '\n');
|
|
3152
|
+
console.log(chalk.yellow(` - ${name} Delimit section removed`));
|
|
3153
|
+
}
|
|
3154
|
+
removed++;
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
if (removed === 0) {
|
|
3159
|
+
console.log(chalk.gray(' No Delimit hooks found.\n'));
|
|
3160
|
+
} else {
|
|
3161
|
+
console.log(chalk.bold(`\n ${removed} hook(s) removed.\n`));
|
|
3162
|
+
}
|
|
3163
|
+
|
|
3164
|
+
} else if (action === 'status') {
|
|
3165
|
+
console.log(chalk.bold('\n Delimit Hooks — Status\n'));
|
|
3166
|
+
for (const [hookPath, name] of [[preCommitPath, 'pre-commit'], [prePushPath, 'pre-push']]) {
|
|
3167
|
+
if (fs.existsSync(hookPath) && fs.readFileSync(hookPath, 'utf-8').includes(marker)) {
|
|
3168
|
+
console.log(` ${chalk.green('●')} ${name} — installed`);
|
|
3169
|
+
} else {
|
|
3170
|
+
console.log(` ${chalk.gray('○')} ${name} — not installed`);
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
3173
|
+
console.log('');
|
|
3174
|
+
|
|
3175
|
+
} else {
|
|
3176
|
+
console.log(chalk.red(`\n Unknown action: ${action}`));
|
|
3177
|
+
console.log(chalk.gray(' Usage: delimit hooks install | remove | status\n'));
|
|
3178
|
+
}
|
|
3179
|
+
});
|
|
3180
|
+
|
|
3047
3181
|
// Check command — pre-commit/pre-push governance check
|
|
3048
3182
|
program
|
|
3049
3183
|
.command('check')
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "delimit-cli",
|
|
3
3
|
"mcpName": "io.github.delimit-ai/delimit-mcp-server",
|
|
4
|
-
"version": "4.1.
|
|
4
|
+
"version": "4.1.31",
|
|
5
5
|
"description": "Unify Claude Code, Codex, Cursor, and Gemini CLI with persistent context, governance, and multi-model debate.",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"files": [
|