-
Notifications
You must be signed in to change notification settings - Fork 85
Description
Describe the bug
When using the execute() function in development mode with the ignoreManifest option set to true, the option is not properly passed through to the config loader, resulting in commands still being loaded from the manifest file (oclif.manifest.json) instead of from the filesystem. Additionally, when only ignoreManifest: true is provided without other options, it causes a TypeError due to missing required options that should be inferred automatically.
To Reproduce
- Create a basic oclif CLI with a development entry point (dev.js):
#!/usr/bin/env node
import { execute } from '@oclif/core'
await execute({
development: true,
dir: import.meta.url,
loadOptions: {
ignoreManifest: true,
}
})- Modify a command's description in the source file (e.g., add extra characters to make it visually different from the manifest)
- Run the command:
dev.js your-command --help - Observe the error:
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined
at dirname (node:path:1457:5)
at up (/node_modules/@oclif/core/lib/util/find-root.js:13:36)
...
- To work around the first issue, add
rootoption:
await execute({
development: true,
dir: import.meta.url,
loadOptions: {
ignoreManifest: true,
root: import.meta.dirname
}
})- Run the command again:
dev.js your-command --help - Note that the command description matches the manifest file, not the source file (the
ignoreManifestoption is not being respected)
Expected behavior
- When
ignoreManifest: trueis provided inloadOptions, it should be passed through to the config loader and commands should be loaded from the filesystem - Default options (like
rootandpjson) should be automatically inferred whenignoreManifestis provided, similar to how they're inferred when not usingloadOptions - The command help should display the description from the source file, not from the cached manifest
Or, an alternate expected behavior would be when development: true, it ignores the manifest so that it is always loading directly from source.
Screenshots
Debug output showing the issue:
With ignoreManifest: true only:
this.options {
"ignoreManifest": true
}
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined
With both ignoreManifest: true and root:
this.options {
"ignoreManifest": true,
"root": "/path/to/bin"
}
ignoreManifest false ← Still shows false despite being set to true
The ignoreManifest is logged before this line: config/plugin.ts
Environment (please complete the following information):
- OS & version: macOS Sequoia 15.2
- Shell/terminal & version: zsh 5.9
- Node.js version: v22.21.1
- @oclif/core version: 4.8.0
Additional context
The issue appears to be in how execute() handles the loadOptions parameter. It seems like:
- When
loadOptionsis provided, default options that would normally be inferred are not merged in - The
ignoreManifestoption fromloadOptionsis not being passed down to the appropriate Config initialization
This makes it difficult to use development mode with changes to command files not reflected without rebuilding the manifest.
Workaround
Currently, there's no clean workaround. Even with explicitly providing root, the ignoreManifest flag doesn't get passed through, so developers must delete the oclif.manifest.json file manually during development to ensure commands load from source files.