jackwener/OpenCLI · error
Could not find opencli entrypoint under ${projectRoot}. Expe
Error message
Could not find opencli entrypoint under ${projectRoot}. Expected built entry from package.json or src/main.ts. What it means
opencli failed to locate its own entrypoint script when resolving how to launch the CLI for a project. It looks for a built entry declared in package.json (bin/main) and falls back to src/main.ts; if neither exists under the resolved projectRoot, it throws. This is a project-structure/setup error, not a runtime logic bug.
Source
Thrown at src/cli.ts:3737
} = {}): BrowserVerifyInvocation {
const platform = opts.platform ?? process.platform;
const fileExists = opts.fileExists ?? fs.existsSync;
const readFile = opts.readFile ?? ((filePath: string) => fs.readFileSync(filePath, 'utf-8'));
const projectRoot = opts.projectRoot ?? findPackageRoot(CLI_FILE, fileExists);
for (const builtEntry of getBuiltEntryCandidates(projectRoot, readFile)) {
if (fileExists(builtEntry)) {
return {
binary: process.execPath,
args: [builtEntry],
cwd: projectRoot,
};
}
}
const sourceEntry = path.join(projectRoot, 'src', 'main.ts');
if (!fileExists(sourceEntry)) {
throw new Error(`Could not find opencli entrypoint under ${projectRoot}. Expected built entry from package.json or src/main.ts.`);
}
const localTsxBin = path.join(projectRoot, 'node_modules', '.bin', platform === 'win32' ? 'tsx.cmd' : 'tsx');
if (fileExists(localTsxBin)) {
return {
binary: localTsxBin,
args: [sourceEntry],
cwd: projectRoot,
...(platform === 'win32' ? { shell: true } : {}),
};
}
return {
binary: platform === 'win32' ? 'npx.cmd' : 'npx',
args: ['tsx', sourceEntry],
cwd: projectRoot,
...(platform === 'win32' ? { shell: true } : {}),
};View on GitHub (pinned to 49907e53dc)
Solutions
- Run the command from the project root that actually contains src/main.ts (or the built entry).
- Build the project so the entrypoint declared in package.json exists.
- Verify package.json declares the correct main/bin entrypoint path.
- Create or restore src/main.ts if it was renamed or deleted.
Example fix
// before (package.json, no entry declared)
{
"name": "my-cli"
}
// after
{
"name": "my-cli",
"main": "dist/main.js",
"bin": { "opencli": "dist/main.js" }
} Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:fs';
import path from 'node:path';
const projectRoot = process.cwd();
const hasBuiltEntry = (() => {
const pkg = JSON.parse(fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8'));
return Boolean(pkg.main || pkg.bin);
})();
if (!hasBuiltEntry && !fs.existsSync(path.join(projectRoot, 'src', 'main.ts'))) {
throw new Error(`No opencli entrypoint under ${projectRoot}; build the project or add src/main.ts`);
} Type guard
function hasEntrypoint(root: string): boolean {
return fs.existsSync(path.join(root, 'src', 'main.ts')) || fs.existsSync(path.join(root, 'package.json'));
} Try / catch
try {
await opencli.run(args);
} catch (e) {
if (e.message.includes('Could not find opencli entrypoint')) {
console.error('Run from the project root and build first: npm run build');
process.exitCode = 1;
} else throw e;
} Prevention
- Always run opencli from the directory containing src/main.ts or a valid package.json entry.
- Build (npm run build) after cloning before invoking CLI commands.
- Keep package.json main/bin in sync when moving or renaming the entry file.
When it happens
Trigger: Running an opencli command in a directory (or against a projectRoot) that has no src/main.ts and no package.json entry pointing at a built entrypoint; running from a parent/child directory so projectRoot resolves to the wrong folder; a monorepo where main.ts lives in a package subdirectory.
Common situations: Cloning a repo and running the CLI before building; invoking opencli from the wrong working directory; renaming or moving main.ts without updating package.json; fresh checkout missing generated/built files.
Related errors
- Not a git repository
- Working tree not clean: ${status}
- Stale .git/index.lock found — remove it first
- 12306 whoami failed: ${probe.detail}
- <train-no> "${trainNo}" does not look like a 12306 internal
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/dc338f637ea6377b.
Report an issue: GitHub.