@tanagram/cli 0.5.51 → 0.5.52

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.
Binary file
Binary file
Binary file
Binary file
Binary file
package/install.js CHANGED
@@ -135,19 +135,16 @@ function installClaudeSkill() {
135
135
  return;
136
136
  }
137
137
 
138
- console.error('Installing Tanagram skill for Claude Code...');
138
+ console.error('Installing Tanagram skill...');
139
139
 
140
140
  try {
141
141
  const skillsSourceDir = path.join(__dirname, 'skills', 'tanagram');
142
142
  const skillsTargetDir = path.join(os.homedir(), '.claude', 'skills', 'tanagram');
143
143
 
144
- // Check if this is a first-time install (skill didn't exist before)
145
144
  const isFirstTime = !fs.existsSync(path.join(skillsTargetDir, 'SKILL.md'));
146
145
 
147
- // Create target directory
148
146
  fs.mkdirSync(skillsTargetDir, { recursive: true });
149
147
 
150
- // Copy skill files
151
148
  const files = ['SKILL.md'];
152
149
  for (const file of files) {
153
150
  const srcPath = path.join(skillsSourceDir, file);
@@ -174,6 +171,59 @@ function installClaudeSkill() {
174
171
  }
175
172
  }
176
173
 
174
+ function installClaudeHook() {
175
+ if (process.env.TANAGRAM_SKIP_HOOK === '1' || process.env.TANAGRAM_SKIP_HOOK === 'true') {
176
+ console.error('Skipping Tanagram hook installation (TANAGRAM_SKIP_HOOK set).');
177
+ return;
178
+ }
179
+ if (isCIEnvironment()) {
180
+ console.error('Skipping Tanagram hook installation (CI environment).');
181
+ return;
182
+ }
183
+
184
+ console.error('Installing Tanagram hook for Claude Code...');
185
+
186
+ try {
187
+ const settingsPath = path.join(os.homedir(), '.claude', 'settings.json');
188
+ let settings = {};
189
+
190
+ if (fs.existsSync(settingsPath)) {
191
+ const raw = fs.readFileSync(settingsPath, 'utf8');
192
+ settings = JSON.parse(raw);
193
+ }
194
+
195
+ if (!settings.hooks) settings.hooks = {};
196
+ if (!Array.isArray(settings.hooks.PreToolUse)) settings.hooks.PreToolUse = [];
197
+
198
+ const hasTanagramHook = settings.hooks.PreToolUse.some(entry =>
199
+ entry.hooks && entry.hooks.some(h => h.command && h.command.includes('tanagram eval'))
200
+ );
201
+
202
+ if (hasTanagramHook) {
203
+ console.error('✓ Tanagram hook already installed');
204
+ track('cli.hook.install.success', { already_installed: true });
205
+ return;
206
+ }
207
+
208
+ settings.hooks.PreToolUse.push({
209
+ matcher: 'Write|Edit|NotebookEdit',
210
+ hooks: [{
211
+ type: 'command',
212
+ command: 'tanagram eval',
213
+ }],
214
+ });
215
+
216
+ fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
217
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
218
+
219
+ console.error(`✓ Tanagram hook installed to ${settingsPath}`);
220
+ track('cli.hook.install.success', { first_time: true });
221
+ } catch (err) {
222
+ console.error('Warning: Failed to install Claude hook:', err.message);
223
+ track('cli.hook.install.failure', { error: err.message });
224
+ }
225
+ }
226
+
177
227
  function ensureOpenCode() {
178
228
  if (isCIEnvironment()) {
179
229
  return;
@@ -217,8 +267,9 @@ function ensureOpenCode() {
217
267
  const prebuiltPath = findPrebuiltBinary();
218
268
  installPrebuiltBinary(prebuiltPath);
219
269
 
220
- // Install Claude skill
270
+ // Install Claude Code skill (for Codex/Amp soft guidance) + hook (for Claude Code hard blocking)
221
271
  installClaudeSkill();
272
+ installClaudeHook();
222
273
 
223
274
  // Install OpenCode (LLM agent for eval)
224
275
  ensureOpenCode();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanagram/cli",
3
- "version": "0.5.51",
3
+ "version": "0.5.52",
4
4
  "description": "Tanagram - Catch sloppy code before it ships",
5
5
  "main": "index.js",
6
6
  "bin": {