ruvnet/ruflo · error
cannot locate the ruflo CLI entrypoint for supervised…
Error message
cannot locate the ruflo CLI entrypoint for supervised service mode
What it means
startBackground() re-execs the CLI as `node <cliEntry> proxy supervise`, taking the entrypoint from process.argv[1]. When argv[1] is empty — Node invoked without a script path — the CLI cannot locate itself for supervised service mode and aborts. This indicates ruflo is being driven through a non-standard entrypoint rather than its bin.
Solutions
- Invoke the CLI the normal way: run `ruflo proxy start --service` from a shell
- If calling programmatically, set process.argv[1] to the resolved ruflo bin path before calling startBackground()
- Prefer spawning `ruflo proxy start --service` as a subprocess from host code rather than importing internals
Example fix
// before (argv[1] missing, e.g. node -e / library context)
await startBackground(); // throws 'cannot locate the ruflo CLI entrypoint'
// after
process.argv[1] = createRequire(import.meta.url).resolve('@claude-flow/cli/bin/ruflo');
await startBackground(); Defensive patterns
Strategy: validation
Validate before calling
if (!process.argv[1]) {
throw new Error('startBackground needs a CLI entrypoint — run `ruflo proxy start --service` instead');
}
await startBackground(); Type guard
const isMissingEntrypoint = (e: unknown): e is Error => e instanceof Error && /cannot locate the ruflo CLI entrypoint/.test(e.message);
Try / catch
try {
await startBackground();
} catch (e) {
if (isMissingEntrypoint(e)) {
// fall back to spawning the CLI as a subprocess instead of embedding
spawnSync('ruflo', ['proxy', 'start', '--service'], { stdio: 'inherit' });
} else throw e;
} Prevention
- Prefer shelling out to `ruflo proxy start --service` over importing lifecycle internals
- In embedded contexts, set process.argv[1] to the resolved bin path before calling startBackground()
- Avoid REPL / `node -e` entrypoints for service-mode operations
When it happens
Trigger: Calling startBackground() programmatically from code embedding the CLI as a library where process.argv[1] is undefined; launch contexts like `node -e`, REPLs, or wrappers that strip argv entries.
Common situations: Custom automation importing lifecycle functions directly instead of shelling out to `ruflo`; test harnesses that stub or truncate process.argv; patched runtimes/bundlers altering argv.
Related errors
- no log file yet — meta-proxy has never been started in…
- ruflo proxy supervisor failed to spawn — no PID returned
- archive did not contain the expected binary at its root
- Competing Meta-Proxy pid
- Expand-Archive failed
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/0641146b560be99c.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/proxy/lifecycle.ts:222
* `ruflo` invocation, redirecting stdout/stderr to a real log file (not
* buffered in-process). Returns once the child's PID is confirmed written,
* without waiting for the process to exit.
*/
export async function startBackground(): Promise<{ pid: number }> {
requireBinary();
const status = getProxyStatus();
if (status.running && status.pid) throw new ProxyAlreadyRunningError(status.pid);
const lockFd = acquireStartLock();
try {
// Re-check under the lock — the dedup above raced a concurrent starter.
const rechecked = getProxyStatus();
if (rechecked.running && rechecked.pid) throw new ProxyAlreadyRunningError(rechecked.pid);
if (rechecked.stalePidFile) clearStalePidFile();
const logFd = fs.openSync(proxyLogFilePath(), 'a');
const cliEntry = process.argv[1];
if (!cliEntry) throw new Error('cannot locate the ruflo CLI entrypoint for supervised service mode');
const child = spawn(process.execPath, [cliEntry, 'proxy', 'supervise'], {
stdio: ['ignore', logFd, logFd],
detached: true,
windowsHide: true,
});
fs.closeSync(logFd); // the child holds its own duplicated fd; safe to close ours
if (!child.pid) throw new Error('ruflo proxy supervisor failed to spawn — no PID returned');
writePidFile(child.pid);
child.unref();
return { pid: child.pid };
} finally {
releaseStartLock(lockFd);
}
}
export interface StopResult {
wasRunning: boolean;View on GitHub (pinned to fa13ee4ad6)