Skip to content

Commit 26a44f2

Browse files
committed
docs: add usage section
1 parent f4c4447 commit 26a44f2

File tree

1 file changed

+155
-10
lines changed

1 file changed

+155
-10
lines changed

README.md

+155-10
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,39 @@
1717

1818
🚧 This project is under heavy development. More features are coming soon!
1919

20-
## Usage
20+
## Install
2121

2222
Install package:
2323

2424
```sh
25-
# npm
2625
npm install citty
26+
```
2727

28-
# yarn
28+
```sh
2929
yarn add citty
30+
```
3031

31-
# pnpm
32+
```sh
3233
pnpm install citty
3334
```
3435

35-
Import:
36+
## Usage
37+
38+
### Import Package
3639

3740
```js
3841
// ESM
3942
import { defineCommand, runMain } from "citty";
43+
```
4044

45+
```js
4146
// CommonJS
4247
const { defineCommand, runMain } = require("citty");
4348
```
4449

45-
Define main command to run:
50+
### Main Command
4651

47-
```ts
52+
```js
4853
import { defineCommand, runMain } from "citty";
4954

5055
const main = defineCommand({
@@ -64,27 +69,167 @@ const main = defineCommand({
6469
description: "Use friendly greeting",
6570
},
6671
},
67-
run({ args }) {
72+
run({ args }) { // Command can be async
6873
console.log(`${args.friendly ? "Hi" : "Greetings"} ${args.name}!`);
6974
},
7075
});
7176

7277
runMain(main);
7378
```
7479

80+
### Sub Commands
81+
82+
You can define sub commands and attach them to main command to create a nested command structure. This is recursive so you can attach sub commands to sub commands, etc.
83+
84+
```js
85+
import { defineCommand, runMain } from "citty";
86+
87+
// First, you define a new command
88+
const sub = defineCommand({
89+
meta: {
90+
name: "sub",
91+
description: "Sub command",
92+
},
93+
args: { // Sub commands can have their own arguments like any other command
94+
name: {
95+
type: "positional",
96+
description: "Your name",
97+
required: true,
98+
},
99+
},
100+
run({ args }) { // Command can be async
101+
console.log(`Hello ${args.name}!`);
102+
},
103+
});
104+
105+
// Then, you define a main command and attach sub command to it
106+
const main = defineCommand({
107+
meta: {
108+
name: "hello",
109+
version: "1.0.0",
110+
description: "My Awesome CLI App",
111+
},
112+
commands: {
113+
sub, // Attach sub command to main command
114+
},
115+
});
116+
117+
runMain(main);
118+
```
119+
120+
### Hooks
121+
122+
`citty` supports a `setup` and `cleanup` functions that are called before and after command execution. This is useful for setting up and cleaning up resources.
123+
124+
Only the `setup` and `cleanup` functions from the command called are executed. For example, if you run `hello sub`, only the `setup` and `cleanup` functions from `sub` command are executed and not the ones from `hello` command.
125+
126+
```js
127+
import { defineCommand, runMain } from "citty";
128+
129+
const main = defineCommand({
130+
meta: {
131+
name: "hello",
132+
version: "1.0.0",
133+
description: "My Awesome CLI App",
134+
},
135+
setup() { // Setup function is called before command execution or before any sub command execution
136+
console.log("Setting up...");
137+
},
138+
cleanup() { // Cleanup function is called after command execution or after any sub command execution
139+
console.log("Cleaning up...");
140+
},
141+
run() {
142+
console.log("Hello World!");
143+
},
144+
});
145+
146+
runMain(main);
147+
```
148+
149+
### Lazy Load Commands
150+
151+
For large CLI apps, you may want to only load the command that is being executed.
152+
153+
First, create a command in a file and export it.
154+
155+
```js
156+
import { defineCommand } from "citty";
157+
158+
export default defineCommand({
159+
meta: {
160+
name: "sub",
161+
description: "Sub command",
162+
},
163+
run({ args }) {
164+
console.log(`Hello ${args.name}!`);
165+
},
166+
});
167+
```
168+
169+
Then, create the main command and import the sub command.
170+
171+
```js
172+
const main = defineCommand({
173+
meta: {
174+
name: "hello",
175+
version: "1.0.0",
176+
description: "My Awesome CLI App",
177+
},
178+
commands: {
179+
sub: () => import("./sub.js").then((m) => m.default), // Lazy Import Sub Command
180+
},
181+
});
182+
```
183+
184+
Now, when you run `hello sub`, the sub command will be loaded and executed. This avoid to load all commands at once.
185+
186+
### Publish CLI App as an Executable
187+
188+
You must first bundle your CLI app. To do so, you can use [`unjs/unbuild`](https://github.com/unjs/unbuild).
189+
190+
Then, you must create a file named `index.mjs` in a folder named `bin` at the root of your package. This file must export the main command from the `dist` build.
191+
192+
```js
193+
#!/usr/bin/env node
194+
195+
import { runMain } from '../dist/index.mjs'
196+
197+
runMain()
198+
```
199+
200+
Then, you will need to update your `package.json` file to enable the usage as a CLI:
201+
202+
```json
203+
{
204+
"type": "module",
205+
"bin": "./bin/index.mjs",
206+
// Name of the CLI will be the name of the package. You can provide an object to change the name.
207+
// @see https://docs.npmjs.com/cli/v10/configuring-npm/package-json#bin
208+
// "bin": {
209+
// "my-cli": "./bin/index.mjs"
210+
// },
211+
"files": [
212+
"bin",
213+
"dist"
214+
]
215+
}
216+
```
217+
218+
You're ready to publish your CLI app to npm!
219+
75220
## Utils
76221

77222
### `defineCommand`
78223

79-
`defineCommand` is a type helper for defining commands.
224+
A type helper for defining commands.
80225

81226
### `runMain`
82227

83228
Runs a command with usage support and graceful error handling.
84229

85230
### `createMain`
86231

87-
Create a wrapper around command that calls `runMain` when called.
232+
Create the main command that can be executed later. Return a [`runMain`](#runmain) function.
88233

89234
### `runCommand`
90235

0 commit comments

Comments
 (0)