@codacy/gate-cli 0.3.0 → 0.4.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.
Files changed (3) hide show
  1. package/README.md +31 -15
  2. package/bin/gate.js +80 -51
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,19 +1,46 @@
1
1
  # @codacy/gate-cli
2
2
 
3
- CLI for [GATE.md](https://gate.md) — the quality gate for AI-generated code.
3
+ CLI for [GATE.md](https://gatemd.lovable.app) — the quality gate for AI-generated code.
4
4
 
5
5
  ## Install
6
6
 
7
7
  ```bash
8
8
  npm install -g @codacy/gate-cli
9
+ cd your-project
10
+ gate init
9
11
  ```
10
12
 
11
- Requires Node.js 20+.
13
+ Then open the project in Claude Code and run `/gate-setup`.
14
+
15
+ ### Permission denied?
16
+
17
+ If `npm install -g` fails with `EACCES`, your npm global directory needs fixing. Pick one:
18
+
19
+ **Option A — Fix npm prefix (recommended, one-time):**
20
+ ```bash
21
+ mkdir -p ~/.npm-global
22
+ npm config set prefix ~/.npm-global
23
+ echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.zshrc # or ~/.bashrc
24
+ source ~/.zshrc
25
+ npm install -g @codacy/gate-cli
26
+ ```
12
27
 
13
- ## Commands
28
+ **Option B — Use npx (no global install):**
29
+ ```bash
30
+ npx @codacy/gate-cli init
31
+ npx @codacy/gate-cli hooks install
32
+ ```
33
+
34
+ **Option C — Use sudo (not recommended):**
35
+ ```bash
36
+ sudo npm install -g @codacy/gate-cli
37
+ ```
38
+
39
+ ## Quick reference
14
40
 
15
41
  | Command | Description |
16
42
  |---------|-------------|
43
+ | `gate init` | Initialize GATE.md in current project (skills + hooks) |
17
44
  | `gate analyze` | Run analysis on changed files (stop hook) |
18
45
  | `gate review --files <paths>` | On-demand analysis (advisory) |
19
46
  | `gate auth register` | Register a project |
@@ -23,7 +50,6 @@ Requires Node.js 20+.
23
50
  | `gate config push` | Upload analysis config |
24
51
  | `gate status` | Show project quality status |
25
52
  | `gate feedback <msg>` | Send feedback |
26
- | `gate intent capture` | Capture user intent (hook) |
27
53
 
28
54
  ## Global flags
29
55
 
@@ -43,14 +69,4 @@ GATE.md intercepts AI coding agent output, runs static analysis + independent Ge
43
69
  Agent writes code → gate analyze → codacy-analysis + Gemini → PASS/FAIL
44
70
  ```
45
71
 
46
- ## Setup
47
-
48
- ```bash
49
- # Install
50
- npm install -g @codacy/gate-cli @codacy/analysis-cli
51
-
52
- # Wire Claude Code hooks
53
- gate hooks install
54
-
55
- # Then run /gate-setup in Claude Code to register + configure
56
- ```
72
+ Requires Node.js 20+.
package/bin/gate.js CHANGED
@@ -10326,14 +10326,27 @@ var {
10326
10326
 
10327
10327
  // src/commands/auth.ts
10328
10328
  var import_promises3 = require("node:fs/promises");
10329
- var import_node_child_process2 = require("node:child_process");
10330
- var import_node_path = require("node:path");
10329
+ var import_node_child_process3 = require("node:child_process");
10330
+ var import_node_path2 = require("node:path");
10331
10331
 
10332
10332
  // src/lib/auth.ts
10333
10333
  var import_promises = require("node:fs/promises");
10334
- var import_node_child_process = require("node:child_process");
10334
+ var import_node_child_process2 = require("node:child_process");
10335
10335
 
10336
10336
  // src/constants.ts
10337
+ var import_node_child_process = require("node:child_process");
10338
+ var import_node_path = require("node:path");
10339
+ var _repoRoot = null;
10340
+ function repoRoot() {
10341
+ if (_repoRoot === null) {
10342
+ try {
10343
+ _repoRoot = (0, import_node_child_process.execSync)("git rev-parse --show-toplevel", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
10344
+ } catch {
10345
+ _repoRoot = process.cwd();
10346
+ }
10347
+ }
10348
+ return _repoRoot;
10349
+ }
10337
10350
  var GATE_DIR = ".gate";
10338
10351
  var CREDENTIALS_FILE = `${GATE_DIR}/credentials`;
10339
10352
  var GLOBAL_CREDENTIALS_FILE = `${process.env.HOME}/.gate/credentials`;
@@ -10346,6 +10359,9 @@ var GATE_MD_FILE = "GATE.md";
10346
10359
  var CLAUDE_SETTINGS_FILE = ".claude/settings.json";
10347
10360
  var STANDARD_FILE = `${GATE_DIR}/standard.yaml`;
10348
10361
  var CODACY_CONFIG_FILE = ".codacy/codacy.config.json";
10362
+ function projectPath(relativePath) {
10363
+ return (0, import_node_path.join)(repoRoot(), relativePath);
10364
+ }
10349
10365
  var MAX_DELTA_BYTES = 204800;
10350
10366
  var MAX_FILES = 20;
10351
10367
  var MAX_FILE_BYTES = 51200;
@@ -10460,7 +10476,7 @@ async function resolveToken(flagToken) {
10460
10476
  return { ok: true, data: { token: envToken, source: "env" } };
10461
10477
  }
10462
10478
  try {
10463
- const content = await (0, import_promises.readFile)(CREDENTIALS_FILE, "utf-8");
10479
+ const content = await (0, import_promises.readFile)(projectPath(CREDENTIALS_FILE), "utf-8");
10464
10480
  const match = content.match(/token:\s*(gate_[a-f0-9]+)/);
10465
10481
  if (match) {
10466
10482
  return { ok: true, data: { token: match[1], source: "local" } };
@@ -10472,7 +10488,7 @@ async function resolveToken(flagToken) {
10472
10488
  const content = await (0, import_promises.readFile)(globalCredentials, "utf-8");
10473
10489
  let remote = "";
10474
10490
  try {
10475
- remote = (0, import_node_child_process.execSync)("git remote get-url origin", { encoding: "utf-8" }).trim();
10491
+ remote = (0, import_node_child_process2.execSync)("git remote get-url origin", { encoding: "utf-8" }).trim();
10476
10492
  } catch {
10477
10493
  }
10478
10494
  if (remote) {
@@ -10504,7 +10520,7 @@ async function resolveServiceUrl(flagUrl) {
10504
10520
  return { ok: true, data: envUrl };
10505
10521
  }
10506
10522
  try {
10507
- const creds = await (0, import_promises2.readFile)(CREDENTIALS_FILE, "utf-8");
10523
+ const creds = await (0, import_promises2.readFile)(projectPath(CREDENTIALS_FILE), "utf-8");
10508
10524
  const match = creds.match(/service_url:\s*(https?:\/\/[^\s]+)/);
10509
10525
  if (match) {
10510
10526
  return { ok: true, data: match[1] };
@@ -10512,7 +10528,7 @@ async function resolveServiceUrl(flagUrl) {
10512
10528
  } catch {
10513
10529
  }
10514
10530
  try {
10515
- const content = await (0, import_promises2.readFile)(GATE_MD_FILE, "utf-8");
10531
+ const content = await (0, import_promises2.readFile)(projectPath(GATE_MD_FILE), "utf-8");
10516
10532
  const boldMatch = content.match(/\*\*url\*\*/i);
10517
10533
  if (boldMatch) {
10518
10534
  const lineMatch = content.split("\n").find((l) => /\*\*url\*\*/i.test(l));
@@ -10621,7 +10637,7 @@ function registerAuthCommands(program2) {
10621
10637
  let remote = opts.remote;
10622
10638
  if (!remote) {
10623
10639
  try {
10624
- remote = (0, import_node_child_process2.execSync)("git remote get-url origin", { encoding: "utf-8" }).trim();
10640
+ remote = (0, import_node_child_process3.execSync)("git remote get-url origin", { encoding: "utf-8" }).trim();
10625
10641
  } catch {
10626
10642
  printError("No git remote found. Use --remote to specify one.");
10627
10643
  process.exit(1);
@@ -10644,7 +10660,7 @@ function registerAuthCommands(program2) {
10644
10660
  service_url: ${service_url}
10645
10661
  `);
10646
10662
  try {
10647
- await (0, import_promises3.mkdir)((0, import_node_path.dirname)(GLOBAL_CREDENTIALS_FILE), { recursive: true });
10663
+ await (0, import_promises3.mkdir)((0, import_node_path2.dirname)(GLOBAL_CREDENTIALS_FILE), { recursive: true });
10648
10664
  await (0, import_promises3.appendFile)(GLOBAL_CREDENTIALS_FILE, `${remote} token: ${token}
10649
10665
  `);
10650
10666
  } catch {
@@ -10683,7 +10699,7 @@ service_url: ${service_url}
10683
10699
  let remote = opts.remote;
10684
10700
  if (!remote) {
10685
10701
  try {
10686
- remote = (0, import_node_child_process2.execSync)("git remote get-url origin", { encoding: "utf-8" }).trim();
10702
+ remote = (0, import_node_child_process3.execSync)("git remote get-url origin", { encoding: "utf-8" }).trim();
10687
10703
  } catch {
10688
10704
  printError("No git remote found. Use --remote to specify one.");
10689
10705
  process.exit(1);
@@ -10711,7 +10727,7 @@ service_url: ${service_url}
10711
10727
 
10712
10728
  // src/lib/hooks.ts
10713
10729
  var import_promises4 = require("node:fs/promises");
10714
- var import_node_path2 = require("node:path");
10730
+ var import_node_path3 = require("node:path");
10715
10731
  var GATE_STOP_HOOK = {
10716
10732
  type: "command",
10717
10733
  command: "gate analyze",
@@ -10734,7 +10750,7 @@ async function readSettings() {
10734
10750
  }
10735
10751
  }
10736
10752
  async function writeSettings(settings) {
10737
- await (0, import_promises4.mkdir)((0, import_node_path2.dirname)(CLAUDE_SETTINGS_FILE), { recursive: true });
10753
+ await (0, import_promises4.mkdir)((0, import_node_path3.dirname)(CLAUDE_SETTINGS_FILE), { recursive: true });
10738
10754
  await (0, import_promises4.writeFile)(CLAUDE_SETTINGS_FILE, JSON.stringify(settings, null, 2) + "\n");
10739
10755
  }
10740
10756
  function checkGateHooks(settings) {
@@ -11208,9 +11224,9 @@ function registerFeedbackCommand(program2) {
11208
11224
  }
11209
11225
 
11210
11226
  // src/lib/git.ts
11211
- var import_node_child_process3 = require("node:child_process");
11227
+ var import_node_child_process4 = require("node:child_process");
11212
11228
  var import_node_fs2 = require("node:fs");
11213
- var import_node_path3 = require("node:path");
11229
+ var import_node_path4 = require("node:path");
11214
11230
  function resolveFile(relpath) {
11215
11231
  if ((0, import_node_fs2.existsSync)(relpath)) return relpath;
11216
11232
  if ((0, import_node_fs2.existsSync)(".claude/worktrees")) {
@@ -11218,7 +11234,7 @@ function resolveFile(relpath) {
11218
11234
  const entries = (0, import_node_fs2.readdirSync)(".claude/worktrees", { withFileTypes: true });
11219
11235
  for (const entry of entries) {
11220
11236
  if (!entry.isDirectory()) continue;
11221
- const candidate = (0, import_node_path3.join)(".claude/worktrees", entry.name, relpath);
11237
+ const candidate = (0, import_node_path4.join)(".claude/worktrees", entry.name, relpath);
11222
11238
  if ((0, import_node_fs2.existsSync)(candidate)) return candidate;
11223
11239
  }
11224
11240
  } catch {
@@ -11228,7 +11244,7 @@ function resolveFile(relpath) {
11228
11244
  }
11229
11245
  function execGit(cmd) {
11230
11246
  try {
11231
- return (0, import_node_child_process3.execSync)(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
11247
+ return (0, import_node_child_process4.execSync)(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
11232
11248
  } catch {
11233
11249
  return "";
11234
11250
  }
@@ -11271,7 +11287,7 @@ function getWorktreeFiles() {
11271
11287
  const entries = (0, import_node_fs2.readdirSync)(worktreeDir, { withFileTypes: true });
11272
11288
  for (const entry of entries) {
11273
11289
  if (!entry.isDirectory()) continue;
11274
- const wtDir = (0, import_node_path3.join)(worktreeDir, entry.name);
11290
+ const wtDir = (0, import_node_path4.join)(worktreeDir, entry.name);
11275
11291
  scanDir(wtDir, wtDir, fiveMinAgo, result);
11276
11292
  }
11277
11293
  } catch {
@@ -11282,12 +11298,12 @@ function scanDir(baseDir, dir, minMtime, result) {
11282
11298
  try {
11283
11299
  const entries = (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true });
11284
11300
  for (const entry of entries) {
11285
- const fullPath = (0, import_node_path3.join)(dir, entry.name);
11301
+ const fullPath = (0, import_node_path4.join)(dir, entry.name);
11286
11302
  if (entry.isDirectory()) {
11287
11303
  if (entry.name === "node_modules" || entry.name === ".git") continue;
11288
11304
  scanDir(baseDir, fullPath, minMtime, result);
11289
11305
  } else if (entry.isFile()) {
11290
- const ext = (0, import_node_path3.extname)(entry.name).slice(1);
11306
+ const ext = (0, import_node_path4.extname)(entry.name).slice(1);
11291
11307
  if (!ANALYZABLE_EXTENSIONS.has(ext)) continue;
11292
11308
  try {
11293
11309
  const stat = (0, import_node_fs2.statSync)(fullPath);
@@ -11304,13 +11320,13 @@ function scanDir(baseDir, dir, minMtime, result) {
11304
11320
  }
11305
11321
  function filterAnalyzable(files) {
11306
11322
  return files.filter((f) => {
11307
- const ext = (0, import_node_path3.extname)(f).slice(1);
11323
+ const ext = (0, import_node_path4.extname)(f).slice(1);
11308
11324
  return ANALYZABLE_EXTENSIONS.has(ext);
11309
11325
  });
11310
11326
  }
11311
11327
  function filterReviewable(files) {
11312
11328
  return files.filter((f) => {
11313
- const ext = (0, import_node_path3.extname)(f).slice(1);
11329
+ const ext = (0, import_node_path4.extname)(f).slice(1);
11314
11330
  if (ANALYZABLE_EXTENSIONS.has(ext)) return false;
11315
11331
  if (REVIEWABLE_EXTENSIONS.has(ext)) return true;
11316
11332
  const basename2 = f.split("/").pop() ?? "";
@@ -11330,7 +11346,7 @@ function getCurrentCommit() {
11330
11346
 
11331
11347
  // src/lib/files.ts
11332
11348
  var import_node_fs3 = require("node:fs");
11333
- var import_node_path4 = require("node:path");
11349
+ var import_node_path5 = require("node:path");
11334
11350
  var LANG_MAP = {
11335
11351
  // Analyzable (static analysis + Gemini)
11336
11352
  ts: "typescript",
@@ -11398,7 +11414,7 @@ var LANG_MAP = {
11398
11414
  mk: "make"
11399
11415
  };
11400
11416
  function detectLanguage(filepath) {
11401
- const ext = (0, import_node_path4.extname)(filepath).slice(1);
11417
+ const ext = (0, import_node_path5.extname)(filepath).slice(1);
11402
11418
  return LANG_MAP[ext] ?? ext;
11403
11419
  }
11404
11420
  function sortByMtime(files) {
@@ -11577,7 +11593,7 @@ function writeIteration(iteration, commit) {
11577
11593
  }
11578
11594
 
11579
11595
  // src/lib/static-analysis.ts
11580
- var import_node_child_process4 = require("node:child_process");
11596
+ var import_node_child_process5 = require("node:child_process");
11581
11597
  var import_node_fs5 = require("node:fs");
11582
11598
  var SEVERITY_ORDER = {
11583
11599
  Error: 0,
@@ -11590,7 +11606,7 @@ var SEVERITY_ORDER = {
11590
11606
  };
11591
11607
  function isCodacyAvailable() {
11592
11608
  try {
11593
- (0, import_node_child_process4.execSync)("which codacy-analysis", { stdio: "pipe" });
11609
+ (0, import_node_child_process5.execSync)("which codacy-analysis", { stdio: "pipe" });
11594
11610
  return true;
11595
11611
  } catch {
11596
11612
  return false;
@@ -11614,7 +11630,7 @@ function runCodacyAnalysis(files) {
11614
11630
  const fileArgs = existingFiles.join(" ");
11615
11631
  let output;
11616
11632
  try {
11617
- output = (0, import_node_child_process4.execSync)(
11633
+ output = (0, import_node_child_process5.execSync)(
11618
11634
  `codacy-analysis analyze --install-dependencies --files ${fileArgs} --output-format json --log-level error --parallel-tools 3`,
11619
11635
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], maxBuffer: 10 * 1024 * 1024 }
11620
11636
  );
@@ -11668,7 +11684,7 @@ function runCodacyAnalysis(files) {
11668
11684
 
11669
11685
  // src/lib/specs.ts
11670
11686
  var import_node_fs6 = require("node:fs");
11671
- var import_node_path5 = require("node:path");
11687
+ var import_node_path6 = require("node:path");
11672
11688
  var SPEC_CANDIDATES = [
11673
11689
  "CLAUDE.md",
11674
11690
  "AGENTS.md",
@@ -11730,7 +11746,7 @@ function findMdFiles(dir, maxDepth, depth = 0) {
11730
11746
  try {
11731
11747
  const entries = (0, import_node_fs6.readdirSync)(dir, { withFileTypes: true });
11732
11748
  for (const entry of entries) {
11733
- const fullPath = (0, import_node_path5.join)(dir, entry.name);
11749
+ const fullPath = (0, import_node_path6.join)(dir, entry.name);
11734
11750
  if (entry.isFile() && entry.name.endsWith(".md")) {
11735
11751
  result.push(fullPath);
11736
11752
  } else if (entry.isDirectory() && depth < maxDepth - 1) {
@@ -11747,7 +11763,7 @@ function discoverPlans() {
11747
11763
  const result = [];
11748
11764
  try {
11749
11765
  const entries = (0, import_node_fs6.readdirSync)(plansDir).filter((f) => f.endsWith(".md")).map((f) => {
11750
- const fullPath = (0, import_node_path5.join)(plansDir, f);
11766
+ const fullPath = (0, import_node_path6.join)(plansDir, f);
11751
11767
  try {
11752
11768
  const stat = (0, import_node_fs6.statSync)(fullPath);
11753
11769
  return { name: f, path: fullPath, mtime: stat.mtimeMs, size: stat.size };
@@ -11847,11 +11863,11 @@ async function runAnalyze(opts, globals) {
11847
11863
  }
11848
11864
  const tokenResult = await resolveToken(globals.token);
11849
11865
  if (!tokenResult.ok) {
11850
- passAndExit("Not configured yet. Run /gate-setup to enable.");
11866
+ passAndExit("Not configured yet \u2014 run /gate-setup in Claude Code to enable quality gates.");
11851
11867
  }
11852
11868
  const urlResult = await resolveServiceUrl(globals.serviceUrl);
11853
11869
  if (!urlResult.ok) {
11854
- passAndExit("No GATE.md service URL found \u2014 skipping analysis");
11870
+ passAndExit("Not configured yet \u2014 run /gate-setup in Claude Code to enable quality gates.");
11855
11871
  }
11856
11872
  const currentCommit = getCurrentCommit();
11857
11873
  const maxIterations = parseInt(opts.maxIterations, 10);
@@ -12020,12 +12036,12 @@ async function runReview(opts, globals) {
12020
12036
  const codeDelta = collectCodeDelta(allFiles);
12021
12037
  const tokenResult = await resolveToken(globals.token);
12022
12038
  if (!tokenResult.ok) {
12023
- printError(tokenResult.error);
12039
+ printError("Not configured yet \u2014 run /gate-setup in Claude Code to enable quality gates.");
12024
12040
  process.exit(0);
12025
12041
  }
12026
12042
  const urlResult = await resolveServiceUrl(globals.serviceUrl);
12027
12043
  if (!urlResult.ok) {
12028
- printError(urlResult.error);
12044
+ printError("Not configured yet \u2014 run /gate-setup in Claude Code to enable quality gates.");
12029
12045
  process.exit(0);
12030
12046
  }
12031
12047
  let specs;
@@ -12096,19 +12112,19 @@ async function runReview(opts, globals) {
12096
12112
  // src/commands/init.ts
12097
12113
  var import_node_fs9 = require("node:fs");
12098
12114
  var import_promises8 = require("node:fs/promises");
12099
- var import_node_path6 = require("node:path");
12100
- var import_node_child_process5 = require("node:child_process");
12115
+ var import_node_path7 = require("node:path");
12116
+ var import_node_child_process6 = require("node:child_process");
12101
12117
  function resolveDataDir() {
12102
12118
  const candidates = [
12103
- (0, import_node_path6.join)(__dirname, "..", "data"),
12119
+ (0, import_node_path7.join)(__dirname, "..", "data"),
12104
12120
  // installed: node_modules/@codacy/gate-cli/data
12105
- (0, import_node_path6.join)(__dirname, "..", "..", "data"),
12121
+ (0, import_node_path7.join)(__dirname, "..", "..", "data"),
12106
12122
  // edge case: nested resolution
12107
- (0, import_node_path6.join)(process.cwd(), "cli", "data")
12123
+ (0, import_node_path7.join)(process.cwd(), "cli", "data")
12108
12124
  // local dev: running from repo root
12109
12125
  ];
12110
12126
  for (const candidate of candidates) {
12111
- if ((0, import_node_fs9.existsSync)((0, import_node_path6.join)(candidate, "skills"))) {
12127
+ if ((0, import_node_fs9.existsSync)((0, import_node_path7.join)(candidate, "skills"))) {
12112
12128
  return candidate;
12113
12129
  }
12114
12130
  }
@@ -12142,42 +12158,55 @@ function registerInitCommand(program2) {
12142
12158
  }
12143
12159
  printInfo(` Node.js ${nodeVersion} \u2713`);
12144
12160
  try {
12145
- const gitVersion = (0, import_node_child_process5.execSync)("git --version", { encoding: "utf-8" }).trim();
12161
+ const gitVersion = (0, import_node_child_process6.execSync)("git --version", { encoding: "utf-8" }).trim();
12146
12162
  printInfo(` ${gitVersion} \u2713`);
12147
12163
  } catch {
12148
12164
  printError("git is required but not installed. Install from https://git-scm.com");
12149
12165
  process.exit(1);
12150
12166
  }
12151
12167
  try {
12152
- (0, import_node_child_process5.execSync)("which claude", { encoding: "utf-8" });
12168
+ (0, import_node_child_process6.execSync)("which claude", { encoding: "utf-8" });
12153
12169
  printInfo(" Claude Code \u2713");
12154
12170
  } catch {
12155
12171
  printWarn(" Claude Code not found \u2014 hooks will be configured but need Claude Code to run.");
12156
12172
  }
12157
12173
  try {
12158
- (0, import_node_child_process5.execSync)("which codacy-analysis", { encoding: "utf-8" });
12174
+ (0, import_node_child_process6.execSync)("which codacy-analysis", { encoding: "utf-8", stdio: "pipe" });
12159
12175
  printInfo(" @codacy/analysis-cli \u2713");
12160
12176
  } catch {
12161
- printWarn(" @codacy/analysis-cli not found \u2014 static analysis will be unavailable.");
12162
- printWarn(" Install: npm install -g @codacy/analysis-cli");
12177
+ printInfo(" Installing @codacy/analysis-cli...");
12178
+ try {
12179
+ (0, import_node_child_process6.execSync)("npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "pipe", timeout: 12e4 });
12180
+ printInfo(" @codacy/analysis-cli installed \u2713");
12181
+ } catch {
12182
+ try {
12183
+ printWarn(" Retrying with sudo...");
12184
+ (0, import_node_child_process6.execSync)("sudo npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "inherit", timeout: 12e4 });
12185
+ printInfo(" @codacy/analysis-cli installed \u2713");
12186
+ } catch {
12187
+ printWarn(" Could not install @codacy/analysis-cli automatically.");
12188
+ printWarn(" Install manually: npm install -g @codacy/analysis-cli");
12189
+ printWarn(" Static analysis will be unavailable until installed.");
12190
+ }
12191
+ }
12163
12192
  }
12164
12193
  console.log("");
12165
12194
  printInfo("Installing skills...");
12166
12195
  const dataDir = resolveDataDir();
12167
- const skillsSource = (0, import_node_path6.join)(dataDir, "skills");
12196
+ const skillsSource = (0, import_node_path7.join)(dataDir, "skills");
12168
12197
  const skillsDest = ".claude/skills";
12169
12198
  const skills = ["gate-setup", "gate-analyze", "gate-status", "gate-feedback"];
12170
12199
  let skillsInstalled = 0;
12171
12200
  for (const skill of skills) {
12172
- const src = (0, import_node_path6.join)(skillsSource, skill);
12173
- const dest = (0, import_node_path6.join)(skillsDest, skill);
12201
+ const src = (0, import_node_path7.join)(skillsSource, skill);
12202
+ const dest = (0, import_node_path7.join)(skillsDest, skill);
12174
12203
  if (!(0, import_node_fs9.existsSync)(src)) {
12175
12204
  printWarn(` Skill data not found: ${skill}`);
12176
12205
  continue;
12177
12206
  }
12178
12207
  if ((0, import_node_fs9.existsSync)(dest) && !force) {
12179
- const srcSkill = (0, import_node_path6.join)(src, "SKILL.md");
12180
- const destSkill = (0, import_node_path6.join)(dest, "SKILL.md");
12208
+ const srcSkill = (0, import_node_path7.join)(src, "SKILL.md");
12209
+ const destSkill = (0, import_node_path7.join)(dest, "SKILL.md");
12181
12210
  if ((0, import_node_fs9.existsSync)(destSkill)) {
12182
12211
  try {
12183
12212
  const srcContent = await (0, import_promises8.readFile)(srcSkill, "utf-8");
@@ -12206,7 +12235,7 @@ function registerInitCommand(program2) {
12206
12235
  printInfo(' Run "gate hooks install --force" to overwrite.');
12207
12236
  }
12208
12237
  await (0, import_promises8.mkdir)(GATE_DIR, { recursive: true });
12209
- const globalGateDir = (0, import_node_path6.join)(process.env.HOME ?? "", ".gate");
12238
+ const globalGateDir = (0, import_node_path7.join)(process.env.HOME ?? "", ".gate");
12210
12239
  await (0, import_promises8.mkdir)(globalGateDir, { recursive: true });
12211
12240
  console.log("");
12212
12241
  printInfo("GATE.md initialized!");
@@ -12224,7 +12253,7 @@ function registerInitCommand(program2) {
12224
12253
  }
12225
12254
 
12226
12255
  // src/cli.ts
12227
- program.name("gate").description("CLI for GATE.md quality gate service").version("0.3.0").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr");
12256
+ program.name("gate").description("CLI for GATE.md quality gate service").version("0.4.0").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr");
12228
12257
  registerAuthCommands(program);
12229
12258
  registerHooksCommands(program);
12230
12259
  registerIntentCommands(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codacy/gate-cli",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "CLI for GATE.md quality gate service",
5
5
  "bin": {
6
6
  "gate": "./bin/gate.js"