@flowmind/cli 0.2.0 → 0.2.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.
package/README.md CHANGED
@@ -13,7 +13,11 @@ flowmind hooks install
13
13
 
14
14
  `hooks install` copies the Flowmind skill to Codex and Claude Code and adds session hooks to
15
15
  `~/.codex/hooks.json` and `~/.claude/settings.json`. Other hooks in those files stay as they are.
16
- The hooks run `flowmind agent hook`, which records each agent turn under the CLI config folder.
16
+ The hooks run `agent hook` through the absolute paths of the installing Node binary and CLI file,
17
+ because hooks start without your shell profile and a version manager may not put `node` on PATH.
18
+ Codex on Windows gets a PowerShell command (`& '<node>' '<cli>' agent hook --agent codex`).
19
+ After you upgrade Node or move the CLI, `hooks status` shows `outdated`; run `hooks install` again
20
+ and trust the changed hooks. The hook records each agent turn under the CLI config folder.
17
21
  In a linked repository, the session-start hook tells the agent which project it works on.
18
22
  Codex runs new hooks only after you trust them once in `/hooks`. `hooks status` shows both installs,
19
23
  and `hooks uninstall` removes only the Flowmind entries.
@@ -63,6 +63,7 @@ Ask only for missing fields. A natural-language entry (`flowmind log "2h on the
63
63
 
64
64
  - `flowmind auth status` shows the API URL. A normal install uses `https://api.flowmind.pro`.
65
65
  - `flowmind hooks status` shows whether the skill and hooks are installed for Codex and Claude Code.
66
+ - `outdated` hooks: run `flowmind hooks install` again (for example after a Node upgrade) and trust the changed hooks.
66
67
  - "No recorded agent time": the hooks are missing or not trusted, or the session started before installation. Stage with observed `--minutes` and `--started-at`, or stage in the next session.
67
68
  - "Several agent sessions have a turn in progress": pass `--session-id`.
68
69
  - "No project given": run `flowmind link <project>` in the repository, or pass `--project`.
package/dist/index.js CHANGED
@@ -3440,9 +3440,11 @@ var logCommand = new Command3("log").description("Log time with natural language
3440
3440
 
3441
3441
  // src/commands/hooks.ts
3442
3442
  import { createHash as createHash3 } from "node:crypto";
3443
+ import { realpathSync } from "node:fs";
3443
3444
  import { readFile as readFile3, lstat, mkdir as mkdir2, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
3444
3445
  import { homedir } from "node:os";
3445
3446
  import { dirname as dirname3, join as join3 } from "node:path";
3447
+ import { fileURLToPath } from "node:url";
3446
3448
  import { Command as Command4, InvalidArgumentError as InvalidArgumentError2 } from "commander";
3447
3449
  var agents = ["codex", "claude"];
3448
3450
  var installedHashFile = ".flowmind-installed.sha256";
@@ -3477,31 +3479,40 @@ async function inspect(agent) {
3477
3479
  }
3478
3480
  return { state: savedHash === contentHash ? "installed" : "modified", path, markerPath, contentHash };
3479
3481
  }
3480
- var HOOK_COMMAND = "flowmind agent hook";
3482
+ var FLOWMIND_HOOK = /(?:^flowmind|index\.js') agent hook --agent (?:codex|claude)$/;
3483
+ var portablePath = (path) => realpathSync(path).replaceAll("\\", "/");
3484
+ function hookCommand(agent) {
3485
+ const node = portablePath(process.execPath);
3486
+ const cli = portablePath(fileURLToPath(import.meta.url));
3487
+ const args = `agent hook --agent ${agent}`;
3488
+ if (process.platform === "win32" && agent === "codex") {
3489
+ const quote2 = (value) => `'${value.replaceAll("'", "''")}'`;
3490
+ return `& ${quote2(node)} ${quote2(cli)} ${args}`;
3491
+ }
3492
+ const quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
3493
+ return `${quote(node)} ${quote(cli)} ${args}`;
3494
+ }
3481
3495
  var handler = (agent, timeout, background = false) => ({
3482
3496
  type: "command",
3483
- command: `${HOOK_COMMAND} --agent ${agent}`,
3497
+ command: hookCommand(agent),
3484
3498
  timeout,
3485
3499
  ...background ? { async: true } : {}
3486
3500
  });
3487
- var hookEvents = {
3488
- codex: {
3489
- SessionStart: { hooks: [handler("codex", 10)] },
3490
- UserPromptSubmit: { hooks: [handler("codex", 10, true)] },
3491
- Stop: { hooks: [handler("codex", 10)] },
3492
- Interrupt: { hooks: [handler("codex", 3)] }
3493
- },
3494
- claude: {
3495
- SessionStart: { hooks: [handler("claude", 10)] },
3496
- UserPromptSubmit: { hooks: [handler("claude", 10)] },
3497
- Stop: { hooks: [handler("claude", 10)] }
3498
- }
3501
+ var hookEvents = (agent) => agent === "codex" ? {
3502
+ SessionStart: { hooks: [handler("codex", 10)] },
3503
+ UserPromptSubmit: { hooks: [handler("codex", 10, true)] },
3504
+ Stop: { hooks: [handler("codex", 10)] },
3505
+ Interrupt: { hooks: [handler("codex", 3)] }
3506
+ } : {
3507
+ SessionStart: { hooks: [handler("claude", 10)] },
3508
+ UserPromptSubmit: { hooks: [handler("claude", 10)] },
3509
+ Stop: { hooks: [handler("claude", 10)] }
3499
3510
  };
3500
3511
  function hookConfigPath(agent) {
3501
3512
  return agent === "codex" ? join3(homedir(), ".codex", "hooks.json") : join3(homedir(), ".claude", "settings.json");
3502
3513
  }
3503
3514
  var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3504
- var isFlowmindGroup = (group) => isObject(group) && Array.isArray(group.hooks) && group.hooks.length > 0 && group.hooks.every((hook) => isObject(hook) && typeof hook.command === "string" && hook.command.startsWith(HOOK_COMMAND));
3515
+ var isFlowmindGroup = (group) => isObject(group) && Array.isArray(group.hooks) && group.hooks.length > 0 && group.hooks.every((hook) => isObject(hook) && typeof hook.command === "string" && FLOWMIND_HOOK.test(hook.command));
3505
3516
  async function readHookConfig(agent) {
3506
3517
  const path = hookConfigPath(agent);
3507
3518
  let text;
@@ -3532,7 +3543,7 @@ function hookState(config2, agent) {
3532
3543
  ([event, groups]) => groups.filter(isFlowmindGroup).map((group) => `${event}:${JSON.stringify(group)}`)
3533
3544
  );
3534
3545
  if (ours.length === 0) return "absent";
3535
- const expected = Object.entries(hookEvents[agent]).map(([event, group]) => `${event}:${JSON.stringify(group)}`);
3546
+ const expected = Object.entries(hookEvents(agent)).map(([event, group]) => `${event}:${JSON.stringify(group)}`);
3536
3547
  const exact = ours.length === expected.length && expected.every((entry) => ours.includes(entry));
3537
3548
  return exact ? "installed" : "outdated";
3538
3549
  }
@@ -3551,7 +3562,7 @@ function withoutFlowmindHooks(config2) {
3551
3562
  function withFlowmindHooks(config2, agent) {
3552
3563
  const next = withoutFlowmindHooks(config2);
3553
3564
  const hooks = isObject(next.hooks) ? { ...next.hooks } : {};
3554
- for (const [event, group] of Object.entries(hookEvents[agent])) {
3565
+ for (const [event, group] of Object.entries(hookEvents(agent))) {
3555
3566
  hooks[event] = [...hooks[event] ?? [], group];
3556
3567
  }
3557
3568
  return { ...next, hooks };
@@ -5258,7 +5269,7 @@ var shipLogCommand = new Command10("ship-log").description("Read a project ship
5258
5269
 
5259
5270
  // src/index.ts
5260
5271
  var program = new Command11();
5261
- program.name("flowmind").description("Flowmind CLI (also installed as fm)").version("0.2.0").enablePositionalOptions();
5272
+ program.name("flowmind").description("Flowmind CLI (also installed as fm)").version("0.2.1").enablePositionalOptions();
5262
5273
  program.addCommand(agentCommand);
5263
5274
  program.addCommand(authCommand);
5264
5275
  program.addCommand(logCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowmind/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "CLI for Flowmind — proof-of-effort hour ledger",
5
5
  "homepage": "https://www.flowmind.pro",
6
6
  "repository": {
@@ -14,10 +14,13 @@
14
14
  "publishConfig": {
15
15
  "access": "public"
16
16
  },
17
- "files": ["dist/index.js", "dist/flowmind/SKILL.md"],
17
+ "files": [
18
+ "dist/index.js",
19
+ "dist/flowmind/SKILL.md"
20
+ ],
18
21
  "bin": {
19
- "fm": "./dist/index.js",
20
- "flowmind": "./dist/index.js"
22
+ "fm": "dist/index.js",
23
+ "flowmind": "dist/index.js"
21
24
  },
22
25
  "type": "module",
23
26
  "scripts": {