Features
Command Discovery Strategies
Support three strategies for command discovery:
pattern
- this is the current behavior that finds commands based on glob patternsexplicit
- find commands that are exported from a specified file. This is to support developers who wish to bundle their CLI into a single file.single
- CLI contains a single command executed by top-level bin
pattern
Strategy
For pattern
, plugins could continue to do this:
{
"oclif": {
"commands": "./dist/commands",
}
}
which will tell oclif to look for commands in that directory (this is skipped if an oclif.manifest.json
is present)
Alternatively, plugins could set this configuration:
{
"oclif": {
"commands": {
"strategy": "pattern",
"target": "./dist/commands"
}
}
}
And they could even add globPatterns
to override the glob patterns that oclif uses when searching for command files:
{
"oclif": {
"commands": {
"strategy": "pattern",
"target": "./dist/commands",
"globPatterns": [
"**/*.+(js|cjs|mjs|ts|tsx|mts|cts)",
"!**/*.+(d.*|test.*|spec.*|helpers.*)?(x)"
]
}
}
}
explicit
Strategy
For explicit
, plugins would add a new file (e.g. src/commands.ts
) and then add this configuration to the package.json
{
"oclif": {
"commands": {
"strategy": "explicit",
"target": "./dist/index.js",
"identifier": "COMMANDS",
}
}
}
src/index.ts
would then need to have an export with the same name as the identifier
(if not set, it defaults to default
) that's an object of command names to command classes, e.g.
import Hello from './commands/hello'
import HelloWorld from './commands/hello/world'
export const COMMANDS = {
hello: Hello,
'hello:world': HelloWorld,
howdy: Hello, // alias the `hello` command to `howdy`
}
The explicit
strategy is useful to those who can't rely on file paths because they've bundled their code (oclif/oclif#653) but it can also be used if you simply prefer to be more explicit about your commands instead of relying on oclif "magically" finding commands from the file system.
It can also be leveraged to create or modify commands at runtime (e.g. add flags to a command based on an API spec - see oclif + dynamic commands
section below).
Unfortunately, there is no notable performance improvement for development since most of the time is spent auto-transpiling typescript with ts-node
single
Strategy
This strategy is for single command CLIs, i.e. CLIs whose bin invokes a single command.
The current way to achieve this to set this in the package.json
{
"oclif": {
"default": ".",
"commands": "./dist",
}
}
The default
tells oclif to use .
as the command id when no command is found and commands
tells oclif where to find the command file. In the example, ./dist
will resolve to to ./dist/index.js
The default
property has always been a less-than-ideal workaround and will be deprecated in favor of these settings:
{
"oclif": {
"commands": {
"strategy": "single",
"target": "./dist"
}
}
}
Note about oclif.manifest.json
For all strategies, the oclif.manifest.json
will be used to load the commands instead of the default behavior of the strategy.