ruvnet/ruflo · error · Error
statusline-generator: could not locate .claude/helpers/statu
Error message
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).
What it means
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.
Source
Thrown at v3/@claude-flow/cli/src/init/statusline-generator.ts:133
for (let i = 0; i < 6; i++) {
try {
const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf-8'));
if (pkg && pkg.name === '@claude-flow/cli') {
const candidate = path.join(dir, '.claude', 'helpers', 'statusline.cjs');
if (fs.existsSync(candidate)) {
helperPackageRoot = dir;
helperContent = fs.readFileSync(candidate, 'utf-8');
break;
}
}
} catch { /* keep climbing */ }
const parent = path.dirname(dir);
if (parent === dir) break;
dir = parent;
}
}
if (helperContent === null) {
throw new Error(
'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).'
);
}
// Two known interpolation points — both single-line, both idempotent
// string replacements. If a future edit to the helper renames either
// token, this replace() is a no-op and the fallback default (15,
// whatever the helper hard-codes) ships. Add a paired test in
// statusline-cost-display.test.ts before changing either token.
helperContent = helperContent.replace(/maxAgents: \d+,/, `maxAgents: ${maxAgents},`);
helperContent = helperContent.replace(
/const BAKED_INSTALL_ROOT = "[^"]*";/,
`const BAKED_INSTALL_ROOT = ${JSON.stringify(helperPackageRoot)};`,
);
// Only overwrite the helper's baked version if OURS resolves higher.
// Otherwise the substitution could DOWNGRADE (test environments whereView on GitHub (pinned to 6b01dc5a68)
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).
Example fix
// before (package.json missing the entry) "files": ["dist", "src", "README.md"] // after "files": ["dist", "src", ".claude", "README.md"]
Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from 'node:fs';
import { createRequire } from 'node:module';
function helperShips(): boolean {
try {
const r = createRequire(import.meta.url);
const pkgJson = r.resolve('@claude-flow/cli/package.json');
const helper = path.join(path.dirname(pkgJson), '.claude', 'helpers', 'statusline.cjs');
return existsSync(helper);
} catch { return false; }
}
if (!helperShips()) console.warn('install is missing the statusline helper — republish with .claude in files'); Type guard
null
Try / catch
null
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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`.
Related errors
- Invalid embedding model name: ${embeddingModel}
- embedding failed
- dimension is required when creating a new memory file
- Installation failed
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/ab4ecdf76218bb84.
Report an issue: GitHub.