{"record":{"id":"ab4ecdf76218bb84","repo":"ruvnet/ruflo","slug":"statusline-generator-could-not-locate-claude-hel","errorCode":null,"errorMessage":"statusline-generator: could not locate .claude/helpers/statusline.cjs relative to @claude-flow/cli. This is a packaging bug — the helper must ship with the CLI (see package.json files entry for .claude).","messagePattern":"statusline-generator: could not locate \\.claude/helpers/statusline\\.cjs relative to @claude-flow/cli\\. This is a packaging bug — the helper must ship with the CLI \\(see package\\.json files entry for \\.claude\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/init/statusline-generator.ts","lineNumber":133,"sourceCode":"    for (let i = 0; i < 6; i++) {\n      try {\n        const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf-8'));\n        if (pkg && pkg.name === '@claude-flow/cli') {\n          const candidate = path.join(dir, '.claude', 'helpers', 'statusline.cjs');\n          if (fs.existsSync(candidate)) {\n            helperPackageRoot = dir;\n            helperContent = fs.readFileSync(candidate, 'utf-8');\n            break;\n          }\n        }\n      } catch { /* keep climbing */ }\n      const parent = path.dirname(dir);\n      if (parent === dir) break;\n      dir = parent;\n    }\n  }\n  if (helperContent === null) {\n    throw new Error(\n      'statusline-generator: could not locate .claude/helpers/statusline.cjs '\n      + 'relative to @claude-flow/cli. This is a packaging bug — the helper '\n      + 'must ship with the CLI (see package.json files entry for .claude).'\n    );\n  }\n\n  // Two known interpolation points — both single-line, both idempotent\n  // string replacements. If a future edit to the helper renames either\n  // token, this replace() is a no-op and the fallback default (15,\n  // whatever the helper hard-codes) ships. Add a paired test in\n  // statusline-cost-display.test.ts before changing either token.\n  helperContent = helperContent.replace(/maxAgents: \\d+,/, `maxAgents: ${maxAgents},`);\n  helperContent = helperContent.replace(\n    /const BAKED_INSTALL_ROOT = \"[^\"]*\";/,\n    `const BAKED_INSTALL_ROOT = ${JSON.stringify(helperPackageRoot)};`,\n  );\n  // Only overwrite the helper's baked version if OURS resolves higher.\n  // Otherwise the substitution could DOWNGRADE (test environments where","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/init/statusline-generator.ts#L115-L151","documentation":"Thrown by generateStatusline() when neither the createRequire.resolve path nor the 6-step __dirname walk-up fallback could find `.claude/helpers/statusline.cjs` inside the resolved @claude-flow/cli package root. The helper file is the single source of truth for the statusline template (read since #2679); without it the generator cannot substitute maxAgents or bakedVersion. The message itself names it a packaging bug because the file must be present in the published tarball via the package.json `files` entry.","triggerScenarios":"Invoking the statusline generator (the `hooks statusline` command, or the Claude Code statusline hook that shells out to it) after a publish that omitted `.claude/` from the npm tarball; running inside a container/CI image built from a stripped dist checkout; or running from an ephemeral `npx` cache whose hash directory lacks the helper because the resolved version pre-dates the file being added.","commonSituations":"A release was cut without `.claude` in package.json `files`; a bundler/tree-shake step stripped the `.claude` directory; a fork or vendored copy of the CLI dropped the helpers folder; running against a dist-only Docker image that did not copy `.claude`.","solutions":["Verify the package.json `files` array includes `.claude` and republish: `npm pack` and inspect the tarball for `.claude/helpers/statusline.cjs`.","Run from a source checkout instead of the broken install: `node v3/@claude-flow/cli/dist/src/init/statusline-generator.js` or `pnpm --filter @claude-flow/cli build`.","If pinned to a known-bad published version, upgrade: `npm i -g @claude-flow/cli@latest` (the walk-up fallback only helps when the source tree is reachable).","As a last resort, copy the committed helper into the install dir: place `.claude/helpers/statusline.cjs` adjacent to the resolved package.json (diagnostic only — fix the publish, do not ship this patch)."],"exampleFix":"// before (package.json missing the entry)\n\"files\": [\"dist\", \"src\", \"README.md\"]\n// after\n\"files\": [\"dist\", \"src\", \".claude\", \"README.md\"]","handlingStrategy":"validation","validationCode":"import { existsSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nfunction helperShips(): boolean {\n  try {\n    const r = createRequire(import.meta.url);\n    const pkgJson = r.resolve('@claude-flow/cli/package.json');\n    const helper = path.join(path.dirname(pkgJson), '.claude', 'helpers', 'statusline.cjs');\n    return existsSync(helper);\n  } catch { return false; }\n}\nif (!helperShips()) console.warn('install is missing the statusline helper — republish with .claude in files');","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Add a `files`-inclusion assertion to the release pipeline: `npm pack --dry-run | grep .claude/helpers/statusline.cjs`.","Run the statusline generator once in CI on the packed tarball as a smoke test.","Keep the committed `.claude/helpers/statusline.cjs` under test (statusline-cost-display.test.ts) so a removal fails CI before publish."],"tags":["packaging","statusline","init","npm"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}