@h1veframework/cli 0.5.2 → 0.7.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.
Files changed (3) hide show
  1. package/README.md +26 -24
  2. package/dist/index.js +101 -47
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
- # @h1veframework/cli · `nf`
1
+ # @h1veframework/cli · `h1ve`
2
2
 
3
3
  **The command-line companion for [H1VE](https://h1ve.org) — the governance & memory layer for teams building with AI.**
4
4
 
5
5
  Your team ships with AI (Claude Code, Cursor, Copilot). As the codebase grows, the AI and your teammates start
6
6
  **losing context and drifting from decisions you already made**. H1VE keeps every feature aligned — a shared,
7
7
  **eternal project memory** plus an **anti-drift engine** that checks each change against what's been decided.
8
- `nf` drives that workflow straight from your terminal.
8
+ `h1ve` drives that workflow straight from your terminal.
9
9
 
10
10
  Part of the H1VE toolchain, alongside the **[MCP server](https://www.npmjs.com/package/@h1veframework/mcp)** for
11
11
  Claude Code / Cursor.
@@ -16,46 +16,48 @@ Claude Code / Cursor.
16
16
 
17
17
  ```bash
18
18
  npm i -g @h1veframework/cli
19
- nf login # opens your browser → you click Authorize → done
20
- nf status # state of the current branch's feature
19
+ h1ve login # opens your browser → you click Authorize → done
20
+ h1ve status # state of the current branch's feature
21
21
  ```
22
22
 
23
- `nf login` stores the credential locally (`~/.config/h1ve/credentials.json`, `600`) — the MCP server reads the
23
+ `h1ve login` stores the credential locally (`~/.config/h1ve/credentials.json`, `600`) — the MCP server reads the
24
24
  same one, so **one login sets up both**. The project **auto-resolves from your git remote**, so there's nothing
25
- to paste and no `H1VE_PROJECT_ID` to set. `nf logout` removes it.
25
+ to paste and no `H1VE_PROJECT_ID` to set. `h1ve logout` removes it.
26
26
 
27
- > `nf health` saying "no snapshots yet" is **success** (you're connected; the project just has no metrics yet).
27
+ > The legacy `nf` command still works as an alias every `h1ve <cmd>` below can be run as `nf <cmd>`.
28
+
29
+ > `h1ve health` saying "no snapshots yet" is **success** (you're connected; the project just has no metrics yet).
28
30
 
29
31
  ## Commands
30
32
 
31
33
  | Command | What it does |
32
34
  |---|---|
33
- | `nf login` / `nf logout` | Authorize in the browser and store the credential locally / remove it |
34
- | `nf status` | State of the current branch's feature (stage, days active, blockers, sign-offs) |
35
- | `nf start [<#\|id>] [--slug <s>]` | Start an assigned feature: create the `feat/{you}/{slug}` branch and record the slug |
36
- | `nf spec` | Print the feature's spec (markdown) |
37
- | `nf move <stage> [--note]` | Move the feature to another stage |
38
- | `nf done [--from <file>] [--no-move]` | Submit the AI declaration (JSON) and move `dev → pr` |
39
- | `nf blocker "<desc>"` | Open a blocker on the feature (you become its owner) |
40
- | `nf health` | Latest technical-health snapshots for the project |
41
- | `nf connect --kind <k> --label <l> --env KEY=VAL` | Write a credential to your **local** `.env.local` and register the inventory (never sent to the server) |
42
- | `nf serve [--port 7391]` | Run the local agent (`127.0.0.1`) so the dashboard can apply credentials from the browser |
35
+ | `h1ve login` / `h1ve logout` | Authorize in the browser and store the credential locally / remove it |
36
+ | `h1ve status` | State of the current branch's feature (stage, days active, blockers, sign-offs) |
37
+ | `h1ve start [<#\|id>] [--slug <s>]` | Start an assigned feature: create the `feat/{you}/{slug}` branch and record the slug |
38
+ | `h1ve spec` | Print the feature's spec (markdown) |
39
+ | `h1ve move <stage> [--note]` | Move the feature to another stage |
40
+ | `h1ve done [--from <file>] [--no-move]` | Submit the AI declaration (JSON) and move `dev → pr` |
41
+ | `h1ve blocker "<desc>"` | Open a blocker on the feature (you become its owner) |
42
+ | `h1ve health` | Latest technical-health snapshots for the project |
43
+ | `h1ve connect --kind <k> --label <l> --env KEY=VAL` | Write a credential to your **local** `.env.local` and register the inventory (never sent to the server) |
44
+ | `h1ve serve [--port 7391]` | Run the local agent (`127.0.0.1`) so the dashboard can apply credentials from the browser |
43
45
 
44
46
  Flags: `--json` (raw output for scripts) · `--project <name\|id>` (if you belong to more than one project) · `-h`.
45
47
 
46
48
  ## Example
47
49
 
48
50
  ```bash
49
- nf start # start your assigned feature (creates the branch)
51
+ h1ve start # start your assigned feature (creates the branch)
50
52
  # ... work: git, code, commits ...
51
- nf status # check state anytime
52
- nf blocker "waiting on the Neon credential" # blocked? open a blocker
53
- nf done --from ai-declaration.json # submit the AI declaration + move dev → pr
53
+ h1ve status # check state anytime
54
+ h1ve blocker "waiting on the Neon credential" # blocked? open a blocker
55
+ h1ve done --from ai-declaration.json # submit the AI declaration + move dev → pr
54
56
  ```
55
57
 
56
58
  ## CI / headless (env vars)
57
59
 
58
- No browser? Configure by env (takes **precedence** over `nf login`):
60
+ No browser? Configure by env (takes **precedence** over `h1ve login`):
59
61
 
60
62
  ```bash
61
63
  export H1VE_API_URL="https://app.h1ve.org" # optional (this is the default)
@@ -67,12 +69,12 @@ export H1VE_API_KEY="nf_pat_..." # a PAT from app.h1ve.org/api-token
67
69
 
68
70
  | Symptom | Fix |
69
71
  |---|---|
70
- | `nf: command not found` | Node missing or wrong terminal. Check `node --version`. On Windows, reopen the shell or use the VS Code terminal. |
72
+ | `h1ve: command not found` | Node missing or wrong terminal. Check `node --version`. On Windows, reopen the shell or use the VS Code terminal. |
71
73
  | `404` on install | npm propagation right after a publish — wait a few minutes. |
72
74
  | `NO_PROJECT` | You belong to more than one project — pass `--project <name\|id>`. |
73
75
  | `401` / `403` | Wrong/missing token. Make sure `H1VE_API_KEY` is a PAT (`nf_pat_…`). `403 SERVICE_CANNOT_WRITE` = a read-only service key used on a write → use a PAT. |
74
76
 
75
- Requires **Node.js 18.18+**. Legacy env names `NEXUS_FLOW_API_URL` / `NEXUS_FLOW_API_KEY` are still accepted.
77
+ Requires **Node.js 18.18+**. The legacy `nf` command and env names `NEXUS_FLOW_API_URL` / `NEXUS_FLOW_API_KEY` are still accepted.
76
78
 
77
79
  ---
78
80
 
package/dist/index.js CHANGED
@@ -50,6 +50,24 @@ async function createBranch(name, runner = defaultGitRunner) {
50
50
  throw new Error("GIT_BRANCH_FAILED");
51
51
  }
52
52
  }
53
+ async function switchBranch(name, runner = defaultGitRunner) {
54
+ try {
55
+ await runner(["switch", name]);
56
+ } catch (err) {
57
+ const text = gitErrText(err);
58
+ if (/not a git repository/i.test(text)) throw new Error("NOT_A_GIT_REPO");
59
+ throw new Error("GIT_SWITCH_FAILED");
60
+ }
61
+ }
62
+ async function listLocalBranches(runner = defaultGitRunner) {
63
+ let out;
64
+ try {
65
+ out = await runner(["for-each-ref", "--format=%(refname:short)", "refs/heads"]);
66
+ } catch {
67
+ return [];
68
+ }
69
+ return out.split("\n").map((l) => l.trim()).filter(Boolean);
70
+ }
53
71
 
54
72
  // ../core/src/client.ts
55
73
  var NexusApiError = class extends Error {
@@ -77,7 +95,7 @@ function errorForStatus(status2, code) {
77
95
  case 422:
78
96
  return new NexusApiError("INVALID_INPUT", "Branch inv\xE1lida.");
79
97
  default:
80
- return new NexusApiError("API_ERROR", `Falha ao consultar o Nexus Flow (HTTP ${status2}).`);
98
+ return new NexusApiError("API_ERROR", `Falha ao consultar o H1VE (HTTP ${status2}).`);
81
99
  }
82
100
  }
83
101
  function mapWriteError(status2, code) {
@@ -106,7 +124,7 @@ function mapWriteError(status2, code) {
106
124
  case 422:
107
125
  return new NexusApiError(code ?? "INVALID_INPUT", "Entrada inv\xE1lida para esta a\xE7\xE3o.");
108
126
  default:
109
- return new NexusApiError("API_ERROR", `Falha ao escrever no Nexus Flow (HTTP ${status2}).`);
127
+ return new NexusApiError("API_ERROR", `Falha ao escrever no H1VE (HTTP ${status2}).`);
110
128
  }
111
129
  }
112
130
  async function readErrorCode(res) {
@@ -416,7 +434,7 @@ async function resolveConfig(env = process.env, store = defaultCredentialStore)
416
434
  }
417
435
  if (!apiKey) {
418
436
  throw new CliError(
419
- "Voc\xEA n\xE3o est\xE1 logado. Rode `nf login` (abre o navegador) \u2014 ou defina H1VE_API_KEY.\n (o nome legado NEXUS_FLOW_API_KEY tamb\xE9m \xE9 aceito)",
437
+ "Voc\xEA n\xE3o est\xE1 logado. Rode `h1ve login` (abre o navegador) \u2014 ou defina H1VE_API_KEY.\n (o nome legado NEXUS_FLOW_API_KEY tamb\xE9m \xE9 aceito)",
420
438
  2
421
439
  );
422
440
  }
@@ -472,17 +490,45 @@ function formatBlocker(r) {
472
490
  return `\u2713 Blocker aberto: ${r.description}`;
473
491
  }
474
492
  function formatStartList(list) {
475
- const header = "Features atribu\xEDdas a iniciar \u2014 escolha: nf start <n\xBA>";
476
- const rows = list.map(
477
- (f, i) => ` ${String(i + 1).padStart(2)}. ${f.name} [${stageLabel(f.stage)}]`
478
- );
493
+ const header = "Features para iniciar ou retomar \u2014 escolha: h1ve start <n\xBA>";
494
+ const rows = list.map((f, i) => {
495
+ const tag = f.branch_slug !== null ? " (retomar)" : "";
496
+ return ` ${String(i + 1).padStart(2)}. ${f.name} [${stageLabel(f.stage)}]${tag}`;
497
+ });
479
498
  return [header, ...rows].join("\n");
480
499
  }
481
- function formatStart(r) {
500
+ var PRE_DEV_STAGES = /* @__PURE__ */ new Set(["backlog", "spec", "blocked"]);
501
+ function startFlowLines(r) {
502
+ const stage = r.landed_stage ?? r.feature.stage;
503
+ if (!PRE_DEV_STAGES.has(stage)) {
504
+ return [
505
+ `Fluxo: card em ${stageLabel(stage)} \u2014 pronto para codar.`,
506
+ "Pr\xF3ximo: codar \u2192 'h1ve status' \u2192 'h1ve done' (move dev \u2192 pr)"
507
+ ];
508
+ }
509
+ const blocked = r.advance?.blocked_by;
510
+ if (blocked === "SPEC_REQUIRED" || blocked === "SPEC_MALFORMED") {
511
+ return [
512
+ "Fluxo: card em Spec (aguarda a SPEC \u2014 Modo Estrito).",
513
+ "Pr\xF3ximo: escreva a SPEC no card \u2192 'h1ve start' de novo para avan\xE7ar at\xE9 Dev."
514
+ ];
515
+ }
516
+ if (blocked === "INVALID_TRANSITION") {
517
+ return [
518
+ `Fluxo: card em ${stageLabel(stage)}.`,
519
+ "Pr\xF3ximo: pe\xE7a ao arquiteto para mover o card at\xE9 Dev (voc\xEA n\xE3o tem permiss\xE3o)."
520
+ ];
521
+ }
522
+ return [
523
+ `Fluxo: card em ${stageLabel(stage)}.`,
524
+ "Pr\xF3ximo: mova o card at\xE9 Dev no board para come\xE7ar."
525
+ ];
526
+ }
527
+ function formatStart(r, opts) {
482
528
  return [
483
- `\u2713 Iniciada: ${r.feature.name}`,
484
- `Branch: ${r.branch_name} (criada e ativa)`,
485
- "Pr\xF3ximo: codar \u2192 'nf status' \u2192 'nf done' (move dev \u2192 pr)"
529
+ `\u2713 ${opts?.resumed ? "Retomada" : "Iniciada"}: ${r.feature.name}`,
530
+ `Branch: ${r.branch_name} (${opts?.resumed ? "pronta e ativa" : "criada e ativa"})`,
531
+ ...startFlowLines(r)
486
532
  ].join("\n");
487
533
  }
488
534
  function formatHealth(snaps) {
@@ -538,7 +584,7 @@ function isStage(s) {
538
584
  }
539
585
  async function move(io, args) {
540
586
  const stage = args.positional;
541
- if (!stage) throw new CliError("Uso: nf move <stage>");
587
+ if (!stage) throw new CliError("Uso: h1ve move <stage>");
542
588
  if (!isStage(stage)) {
543
589
  throw new CliError(`Stage inv\xE1lido: ${stage}. V\xE1lidos: ${STAGES.join(", ")}`);
544
590
  }
@@ -551,7 +597,7 @@ async function move(io, args) {
551
597
  // src/commands/blocker.ts
552
598
  async function blocker(io, args) {
553
599
  const description = args.positional;
554
- if (!description) throw new CliError('Uso: nf blocker "<descri\xE7\xE3o>"');
600
+ if (!description) throw new CliError('Uso: h1ve blocker "<descri\xE7\xE3o>"');
555
601
  const branch = await io.resolveBranch();
556
602
  const digest = await io.client.getContext(branch);
557
603
  const result = await io.client.createBlocker(digest.feature.id, description);
@@ -591,7 +637,7 @@ ${movedLine}`, data: { declaration, move: moved } };
591
637
  throw new CliError(
592
638
  `${sent}
593
639
  \u2717 Move dev \u2192 pr falhou: ${reason}
594
- (a declaration J\xC1 foi enviada \u2014 rode \`nf move pr\` para concluir; N\xC3O repita \`nf done\`, pois enviaria a declaration de novo.)`
640
+ (a declaration J\xC1 foi enviada \u2014 rode \`h1ve move pr\` para concluir; N\xC3O repita \`h1ve done\`, pois enviaria a declaration de novo.)`
595
641
  );
596
642
  }
597
643
  }
@@ -603,8 +649,15 @@ async function health(io) {
603
649
  }
604
650
 
605
651
  // src/commands/start.ts
606
- function startable(features) {
607
- return features.filter((f) => f.branch_slug === null && f.stage !== "main");
652
+ function branchSlugOf(branch) {
653
+ return branch.match(/^feat\/[^/]+\/(.+)$/)?.[1] ?? null;
654
+ }
655
+ function startable(features, localBranches) {
656
+ const localSlugs = new Set(
657
+ localBranches.map(branchSlugOf).filter((s) => s !== null)
658
+ );
659
+ const hasLocalBranch = (f) => f.branch_slug !== null && localSlugs.has(f.branch_slug);
660
+ return features.filter((f) => f.stage !== "main" && !hasLocalBranch(f));
608
661
  }
609
662
  function pick(list, arg) {
610
663
  if (!arg) return list.length === 1 ? list[0] ?? null : null;
@@ -612,30 +665,28 @@ function pick(list, arg) {
612
665
  if (byId) return byId;
613
666
  const idx = Number(arg);
614
667
  if (Number.isInteger(idx) && idx >= 1 && idx <= list.length) return list[idx - 1] ?? null;
615
- throw new CliError(`Feature n\xE3o encontrada: ${arg}. Rode 'nf start' para ver a lista.`);
668
+ throw new CliError(`Feature n\xE3o encontrada: ${arg}. Rode 'h1ve start' para ver a lista.`);
616
669
  }
617
670
  async function start(io, args) {
618
- const list = startable(await io.client.listFeatures());
671
+ const [features, localBranches] = await Promise.all([io.client.listFeatures(), io.listBranches()]);
672
+ const list = startable(features, localBranches);
619
673
  if (list.length === 0) {
620
- throw new CliError("Nenhuma feature atribu\xEDda a iniciar (sem branch e fora de main).");
674
+ throw new CliError("Nenhuma feature para iniciar ou retomar (sem branch local e fora de main).");
621
675
  }
622
676
  const selected = pick(list, args.positional);
623
677
  if (!selected) {
624
678
  return { human: formatStartList(list), data: { features: list } };
625
679
  }
680
+ const resuming = selected.branch_slug !== null;
626
681
  const result = await io.client.startFeature(selected.id, args.slug);
627
682
  try {
628
683
  await io.createBranch(result.branch_name);
629
684
  } catch (err) {
630
685
  const code = err instanceof Error ? err.message : "";
631
- if (code === "BRANCH_EXISTS") {
632
- throw new CliError(
633
- `branch_slug gravado, mas a branch '${result.branch_name}' j\xE1 existe. Rode: git switch ${result.branch_name}`
634
- );
635
- }
636
- throw err;
686
+ if (code === "BRANCH_EXISTS") await io.switchBranch(result.branch_name);
687
+ else throw err;
637
688
  }
638
- return { human: formatStart(result), data: result };
689
+ return { human: formatStart(result, { resumed: resuming }), data: result };
639
690
  }
640
691
 
641
692
  // src/commands/connect.ts
@@ -1212,7 +1263,7 @@ async function startCallbackServer(expectedState) {
1212
1263
  const waitForCode = () => new Promise((resolve, reject) => {
1213
1264
  const timer = setTimeout(() => {
1214
1265
  server.close();
1215
- reject(new CliError("Tempo esgotado esperando a autoriza\xE7\xE3o. Rode `nf login` de novo."));
1266
+ reject(new CliError("Tempo esgotado esperando a autoriza\xE7\xE3o. Rode `h1ve login` de novo."));
1216
1267
  }, LOGIN_TIMEOUT_MS);
1217
1268
  void codePromise.then((code) => {
1218
1269
  clearTimeout(timer);
@@ -1262,31 +1313,32 @@ async function logout(io, _args) {
1262
1313
  }
1263
1314
 
1264
1315
  // src/index.ts
1265
- var VERSION = "0.5.0";
1266
- var HELP = `nf \u2014 CLI do Nexus Flow
1316
+ var VERSION = "0.7.0";
1317
+ var HELP = `h1ve \u2014 CLI do H1VE
1318
+ (o comando legado \`nf\` continua funcionando como alias)
1267
1319
 
1268
1320
  Uso:
1269
- nf login autoriza no navegador e salva a credencial local (sem colar nada)
1270
- nf logout remove a credencial local
1271
- nf start [<n\xBA|id>] [--slug <s>]
1272
- inicia uma feature atribu\xEDda: cria a branch e grava o slug
1273
- nf status estado da feature da branch atual
1274
- nf spec imprime a spec da feature
1275
- nf move <stage> [--note] move a feature de stage
1276
- nf blocker "<desc>" abre um blocker na feature
1277
- nf done [--from <arq>] [--no-move]
1321
+ h1ve login autoriza no navegador e salva a credencial local (sem colar nada)
1322
+ h1ve logout remove a credencial local
1323
+ h1ve start [<n\xBA|id>] [--slug <s>]
1324
+ inicia (ou retoma) uma feature: cria/entra na branch e grava o slug
1325
+ h1ve status estado da feature da branch atual
1326
+ h1ve spec imprime a spec da feature
1327
+ h1ve move <stage> [--note] move a feature de stage
1328
+ h1ve blocker "<desc>" abre um blocker na feature
1329
+ h1ve done [--from <arq>] [--no-move]
1278
1330
  envia a AI declaration (JSON) e move dev \u2192 pr
1279
- nf health \xFAltimos snapshots de sa\xFAde t\xE9cnica
1280
- nf connect --kind <k> --label <l> --env KEY=VAL [...]
1331
+ h1ve health \xFAltimos snapshots de sa\xFAde t\xE9cnica
1332
+ h1ve connect --kind <k> --label <l> --env KEY=VAL [...]
1281
1333
  aplica a credencial no .env.local LOCAL (nunca ao servidor)
1282
1334
  e registra o invent\xE1rio da conex\xE3o (Jeito B)
1283
- nf serve [--port 7391] [--origin http://localhost:3000]
1335
+ h1ve serve [--port 7391] [--origin http://localhost:3000]
1284
1336
  sobe o agente local (127.0.0.1) p/ o menu visual aplicar
1285
1337
  credenciais pelo navegador \u2014 imprime o c\xF3digo de pareamento
1286
1338
 
1287
1339
  Flags:
1288
1340
  --json sa\xEDda em JSON cru (comp\xF5e em scripts)
1289
- --slug <s> slug custom para 'nf start' (default = derivado do nome)
1341
+ --slug <s> slug custom para 'h1ve start' (default = derivado do nome)
1290
1342
  --kind <k> tipo da conex\xE3o (database|deploy|observability|api|auth|other)
1291
1343
  --label <l> nome da conex\xE3o (ex.: "Neon (prod)")
1292
1344
  --env KEY=VAL vari\xE1vel a escrever no .env.local (repet\xEDvel)
@@ -1295,7 +1347,7 @@ Flags:
1295
1347
  -h, --help esta ajuda
1296
1348
  -v, --version vers\xE3o do CLI
1297
1349
 
1298
- Ambiente (opcional \u2014 'nf login' dispensa):
1350
+ Ambiente (opcional \u2014 'h1ve login' dispensa):
1299
1351
  H1VE_API_URL URL do H1VE Flow (default https://app.h1ve.org)
1300
1352
  H1VE_API_KEY PAT (nf_pat_\u2026) p/ escrever, ou a chave de servi\xE7o (s\xF3 leitura)
1301
1353
  (nomes legados aceitos: NEXUS_FLOW_API_URL / NEXUS_FLOW_API_KEY)
@@ -1321,7 +1373,7 @@ function parse(argv) {
1321
1373
  json: { type: "boolean" },
1322
1374
  help: { type: "boolean", short: "h" },
1323
1375
  version: { type: "boolean", short: "v" },
1324
- // nf connect (SPEC-050)
1376
+ // h1ve connect (SPEC-050)
1325
1377
  kind: { type: "string" },
1326
1378
  label: { type: "string" },
1327
1379
  url: { type: "string" },
@@ -1329,13 +1381,13 @@ function parse(argv) {
1329
1381
  project: { type: "string" },
1330
1382
  file: { type: "string" },
1331
1383
  env: { type: "string", multiple: true },
1332
- // nf serve (SPEC-051)
1384
+ // h1ve serve (SPEC-051)
1333
1385
  port: { type: "string" },
1334
1386
  origin: { type: "string" }
1335
1387
  }
1336
1388
  });
1337
1389
  } catch {
1338
- throw new CliError("Argumentos inv\xE1lidos. Veja `nf --help`.", 2);
1390
+ throw new CliError("Argumentos inv\xE1lidos. Veja `h1ve --help`.", 2);
1339
1391
  }
1340
1392
  }
1341
1393
  async function main(argv) {
@@ -1363,6 +1415,8 @@ ${HELP}`);
1363
1415
  client,
1364
1416
  resolveBranch: () => currentBranch(defaultGitRunner),
1365
1417
  createBranch: (name) => createBranch(name, defaultGitRunner),
1418
+ switchBranch: (name) => switchBranch(name, defaultGitRunner),
1419
+ listBranches: () => listLocalBranches(defaultGitRunner),
1366
1420
  readFile: (path) => readFile(path, "utf8"),
1367
1421
  readStdin,
1368
1422
  writeEnvVars: (pairs, opts) => writeEnvVars(pairs, { file: opts?.file }),
@@ -1397,7 +1451,7 @@ function messageFor(err) {
1397
1451
  if (err instanceof Error && (err.message === "NOT_A_GIT_REPO" || err.message === "GIT_BRANCH_FAILED")) {
1398
1452
  return "N\xE3o consegui criar a branch git. Rode dentro do reposit\xF3rio (git) da feature.";
1399
1453
  }
1400
- return "Erro inesperado ao falar com o Nexus Flow.";
1454
+ return "Erro inesperado ao falar com o H1VE.";
1401
1455
  }
1402
1456
  main(process.argv.slice(2)).then((code) => {
1403
1457
  process.exitCode = code;
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@h1veframework/cli",
3
- "version": "0.5.2",
3
+ "version": "0.7.0",
4
4
  "description": "The CLI for H1VE — the governance & memory layer for teams building with AI. Drive your feature flow (start, status, move, spec, done) from the terminal. Works with Claude Code, Cursor and Copilot.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "bin": {
8
+ "h1ve": "dist/index.js",
8
9
  "nf": "dist/index.js"
9
10
  },
10
11
  "files": [