Files
gh-vanman2024-cli-builder-p…/skills/oclif-patterns/examples/basic-cli-example.md
2025-11-30 09:04:14 +08:00

189 lines
3.4 KiB
Markdown

# Basic CLI Example
Complete example of a simple oclif CLI with multiple commands.
## Project Structure
```
mycli/
├── package.json
├── tsconfig.json
├── src/
│ ├── commands/
│ │ ├── hello.ts
│ │ ├── goodbye.ts
│ │ └── config.ts
│ └── index.ts
├── test/
│ └── commands/
│ └── hello.test.ts
└── bin/
└── run.js
```
## Step-by-Step Setup
### 1. Initialize Project
```bash
mkdir mycli && cd mycli
npm init -y
npm install @oclif/core
npm install --save-dev @oclif/test @types/node typescript ts-node oclif
```
### 2. Create package.json Configuration
Add oclif configuration:
```json
{
"name": "mycli",
"version": "1.0.0",
"oclif": {
"bin": "mycli",
"commands": "./lib/commands",
"plugins": [
"@oclif/plugin-help"
]
}
}
```
### 3. Create Hello Command
File: `src/commands/hello.ts`
```typescript
import { Command, Flags, Args } from '@oclif/core'
export default class Hello extends Command {
static description = 'Say hello to someone'
static examples = [
'<%= config.bin %> <%= command.id %> Alice',
'<%= config.bin %> <%= command.id %> Bob --greeting="Hi"',
]
static flags = {
greeting: Flags.string({
char: 'g',
description: 'Greeting to use',
default: 'Hello',
}),
excited: Flags.boolean({
char: 'e',
description: 'Add exclamation',
default: false,
}),
}
static args = {
name: Args.string({
description: 'Name to greet',
required: true,
}),
}
async run(): Promise<void> {
const { args, flags } = await this.parse(Hello)
const punctuation = flags.excited ? '!' : '.'
this.log(`${flags.greeting}, ${args.name}${punctuation}`)
}
}
```
### 4. Build and Test
```bash
npm run build
./bin/run.js hello World
# Output: Hello, World.
./bin/run.js hello World --greeting="Hi" --excited
# Output: Hi, World!
```
### 5. Add Help Documentation
```bash
./bin/run.js hello --help
# Output:
# Say hello to someone
#
# USAGE
# $ mycli hello NAME [-g <value>] [-e]
#
# ARGUMENTS
# NAME Name to greet
#
# FLAGS
# -e, --excited Add exclamation
# -g, --greeting=<value> [default: Hello] Greeting to use
```
## Testing
File: `test/commands/hello.test.ts`
```typescript
import { expect, test } from '@oclif/test'
describe('hello', () => {
test
.stdout()
.command(['hello', 'World'])
.it('says hello', ctx => {
expect(ctx.stdout).to.contain('Hello, World.')
})
test
.stdout()
.command(['hello', 'Alice', '--excited'])
.it('says hello with excitement', ctx => {
expect(ctx.stdout).to.contain('Hello, Alice!')
})
test
.stdout()
.command(['hello', 'Bob', '--greeting=Hi'])
.it('uses custom greeting', ctx => {
expect(ctx.stdout).to.contain('Hi, Bob.')
})
})
```
## Run Tests
```bash
npm test
```
## Distribution
### Package for npm
```bash
npm pack
npm publish
```
### Install Globally
```bash
npm install -g .
mycli hello World
```
## Key Concepts Demonstrated
1. **Command Structure**: Basic command with flags and args
2. **Flag Types**: String and boolean flags with defaults
3. **Arguments**: Required string argument
4. **Help Documentation**: Auto-generated from metadata
5. **Testing**: Using @oclif/test for command testing
6. **Build Process**: TypeScript compilation to lib/
7. **CLI Binary**: bin/run.js entry point