cli4ai 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +275 -0
- package/package.json +49 -0
- package/src/bin.ts +120 -0
- package/src/cli.ts +256 -0
- package/src/commands/add.ts +530 -0
- package/src/commands/browse.ts +449 -0
- package/src/commands/config.ts +126 -0
- package/src/commands/info.ts +102 -0
- package/src/commands/init.test.ts +163 -0
- package/src/commands/init.ts +560 -0
- package/src/commands/list.ts +89 -0
- package/src/commands/mcp-config.ts +59 -0
- package/src/commands/remove.ts +72 -0
- package/src/commands/routines.ts +393 -0
- package/src/commands/run.ts +45 -0
- package/src/commands/search.ts +148 -0
- package/src/commands/secrets.ts +273 -0
- package/src/commands/start.ts +40 -0
- package/src/commands/update.ts +218 -0
- package/src/core/config.test.ts +188 -0
- package/src/core/config.ts +649 -0
- package/src/core/execute.ts +507 -0
- package/src/core/link.test.ts +238 -0
- package/src/core/link.ts +190 -0
- package/src/core/lockfile.test.ts +337 -0
- package/src/core/lockfile.ts +308 -0
- package/src/core/manifest.test.ts +327 -0
- package/src/core/manifest.ts +319 -0
- package/src/core/routine-engine.test.ts +139 -0
- package/src/core/routine-engine.ts +725 -0
- package/src/core/routines.ts +111 -0
- package/src/core/secrets.test.ts +79 -0
- package/src/core/secrets.ts +430 -0
- package/src/lib/cli.ts +234 -0
- package/src/mcp/adapter.test.ts +132 -0
- package/src/mcp/adapter.ts +123 -0
- package/src/mcp/config-gen.test.ts +214 -0
- package/src/mcp/config-gen.ts +106 -0
- package/src/mcp/server.ts +363 -0
package/README.md
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# cli4ai
|
|
2
|
+
|
|
3
|
+
> Official CLI4AI package • https://cli4ai.com
|
|
4
|
+
|
|
5
|
+
The package manager for AI CLI tools.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Install cli4ai
|
|
11
|
+
npm i -g cli4ai
|
|
12
|
+
# or (optional)
|
|
13
|
+
bun install -g cli4ai
|
|
14
|
+
|
|
15
|
+
# Install a package
|
|
16
|
+
cli4ai add -g github
|
|
17
|
+
|
|
18
|
+
# Run it
|
|
19
|
+
cli4ai run github notifs
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Why cli4ai?
|
|
23
|
+
|
|
24
|
+
AI agents need tools. MCP servers are complex to set up. cli4ai makes it simple:
|
|
25
|
+
|
|
26
|
+
- **Install tools in seconds** - `cli4ai add github` just works
|
|
27
|
+
- **Run from anywhere** - `cli4ai run <tool> <command>`
|
|
28
|
+
- **No MCP boilerplate** - cli4ai wraps CLI tools as MCP servers automatically
|
|
29
|
+
- **Local-first** - Tools are just scripts, no cloud required
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Add a local registry (directory containing tools)
|
|
35
|
+
cli4ai config --add-registry ~/my-tools
|
|
36
|
+
|
|
37
|
+
# Search for tools
|
|
38
|
+
cli4ai search github
|
|
39
|
+
|
|
40
|
+
# Install globally (available everywhere)
|
|
41
|
+
cli4ai add -g github
|
|
42
|
+
|
|
43
|
+
# Install locally (project-scoped)
|
|
44
|
+
cd ~/my-project
|
|
45
|
+
cli4ai add mongodb
|
|
46
|
+
|
|
47
|
+
# Run tools
|
|
48
|
+
cli4ai run github notifs
|
|
49
|
+
cli4ai run mongodb databases
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Commands
|
|
53
|
+
|
|
54
|
+
### Package Management
|
|
55
|
+
|
|
56
|
+
| Command | Description |
|
|
57
|
+
|---------|-------------|
|
|
58
|
+
| `cli4ai add <pkg>` | Install package locally |
|
|
59
|
+
| `cli4ai add -g <pkg>` | Install package globally |
|
|
60
|
+
| `cli4ai remove <pkg>` | Uninstall package |
|
|
61
|
+
| `cli4ai remove -g <pkg>` | Uninstall global package |
|
|
62
|
+
| `cli4ai list` | List local packages |
|
|
63
|
+
| `cli4ai list -g` | List global packages |
|
|
64
|
+
|
|
65
|
+
### Discovery
|
|
66
|
+
|
|
67
|
+
| Command | Description |
|
|
68
|
+
|---------|-------------|
|
|
69
|
+
| `cli4ai search <query>` | Search for packages |
|
|
70
|
+
| `cli4ai info <pkg>` | Show package details |
|
|
71
|
+
|
|
72
|
+
### Execution
|
|
73
|
+
|
|
74
|
+
| Command | Description |
|
|
75
|
+
|---------|-------------|
|
|
76
|
+
| `cli4ai run <pkg> <cmd> [args]` | Run a tool command |
|
|
77
|
+
| `cli4ai start <pkg>` | Start package as MCP server |
|
|
78
|
+
|
|
79
|
+
Notes:
|
|
80
|
+
- Tool flags are supported: `cli4ai run chrome screenshot https://example.com --full-page`
|
|
81
|
+
- If a flag conflicts with `cli4ai run` options, use `--` to pass-through: `cli4ai run <pkg> <cmd> -- --help`
|
|
82
|
+
|
|
83
|
+
### Configuration
|
|
84
|
+
|
|
85
|
+
| Command | Description |
|
|
86
|
+
|---------|-------------|
|
|
87
|
+
| `cli4ai config` | Show current config |
|
|
88
|
+
| `cli4ai config --add-registry <path>` | Add local registry |
|
|
89
|
+
| `cli4ai config --remove-registry <path>` | Remove registry |
|
|
90
|
+
|
|
91
|
+
### Project Setup
|
|
92
|
+
|
|
93
|
+
| Command | Description |
|
|
94
|
+
|---------|-------------|
|
|
95
|
+
| `cli4ai init [name]` | Create a new tool project |
|
|
96
|
+
| `cli4ai mcp-config` | Generate Claude Code MCP config |
|
|
97
|
+
|
|
98
|
+
## Package Format
|
|
99
|
+
|
|
100
|
+
Tools are defined by a `cli4ai.json` manifest:
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"name": "github",
|
|
105
|
+
"version": "1.0.0",
|
|
106
|
+
"description": "GitHub CLI wrapper",
|
|
107
|
+
"entry": "run.ts",
|
|
108
|
+
"runtime": "bun",
|
|
109
|
+
"commands": {
|
|
110
|
+
"notifs": {
|
|
111
|
+
"description": "Your notifications"
|
|
112
|
+
},
|
|
113
|
+
"repos": {
|
|
114
|
+
"description": "List repositories",
|
|
115
|
+
"args": [
|
|
116
|
+
{ "name": "user", "required": false }
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"env": {
|
|
121
|
+
"GITHUB_TOKEN": {
|
|
122
|
+
"required": false,
|
|
123
|
+
"description": "Personal access token"
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"mcp": {
|
|
127
|
+
"enabled": true
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Manifest Fields
|
|
133
|
+
|
|
134
|
+
| Field | Required | Description |
|
|
135
|
+
|-------|----------|-------------|
|
|
136
|
+
| `name` | Yes | Package name (lowercase, hyphens ok) |
|
|
137
|
+
| `version` | Yes | Semver version |
|
|
138
|
+
| `entry` | Yes | Entry point script |
|
|
139
|
+
| `description` | No | Package description |
|
|
140
|
+
| `runtime` | No | Runtime: `bun` (default), `node`, `deno` |
|
|
141
|
+
| `commands` | No | Command definitions for MCP |
|
|
142
|
+
| `env` | No | Environment variable requirements |
|
|
143
|
+
| `mcp.enabled` | No | Enable MCP server mode |
|
|
144
|
+
|
|
145
|
+
## Storage Locations
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
~/.cli4ai/
|
|
149
|
+
├── config.json # Global configuration
|
|
150
|
+
├── packages/ # Globally installed packages
|
|
151
|
+
│ └── github/
|
|
152
|
+
└── bin/ # PATH-linked executables (optional)
|
|
153
|
+
|
|
154
|
+
./
|
|
155
|
+
├── cli4ai.json # Project manifest (if a tool)
|
|
156
|
+
├── cli4ai.lock # Lock file (reproducible installs)
|
|
157
|
+
└── .cli4ai/
|
|
158
|
+
└── packages/ # Locally installed packages
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## MCP Integration
|
|
162
|
+
|
|
163
|
+
cli4ai can generate configuration for Claude Code:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# Generate config for all installed packages
|
|
167
|
+
cli4ai mcp-config
|
|
168
|
+
|
|
169
|
+
# Generate for specific packages
|
|
170
|
+
cli4ai mcp-config --packages github,slack
|
|
171
|
+
|
|
172
|
+
# Get snippet for a single package
|
|
173
|
+
cli4ai mcp-config --package github --snippet
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Output:
|
|
177
|
+
```json
|
|
178
|
+
{
|
|
179
|
+
"mcpServers": {
|
|
180
|
+
"cli4ai-github": {
|
|
181
|
+
"command": "cli4ai",
|
|
182
|
+
"args": ["start", "github"]
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Add this to your Claude Code MCP settings.
|
|
189
|
+
|
|
190
|
+
## Local Registries
|
|
191
|
+
|
|
192
|
+
cli4ai discovers packages from local directories:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Add a registry
|
|
196
|
+
cli4ai config --add-registry ~/agent-tools
|
|
197
|
+
|
|
198
|
+
# Now packages in ~/agent-tools are discoverable
|
|
199
|
+
cli4ai search github # Finds ~/agent-tools/github/
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
A registry is just a directory containing tool folders, each with a `cli4ai.json`.
|
|
203
|
+
|
|
204
|
+
## Creating Tools
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# Create a new tool
|
|
208
|
+
cli4ai init my-tool
|
|
209
|
+
cd my-tool
|
|
210
|
+
|
|
211
|
+
# Edit `run.ts` and `cli4ai.json`
|
|
212
|
+
|
|
213
|
+
# Test locally
|
|
214
|
+
bun run run.ts hello world
|
|
215
|
+
|
|
216
|
+
# Install for testing
|
|
217
|
+
cd ~/some-project
|
|
218
|
+
cli4ai add --local ~/path/to/my-tool -y
|
|
219
|
+
cli4ai run my-tool hello world
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Tool Entry Point
|
|
223
|
+
|
|
224
|
+
Tools are simple CLI scripts that output JSON:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
#!/usr/bin/env bun
|
|
228
|
+
|
|
229
|
+
import { cli, output } from '@cli4ai/lib/cli.ts';
|
|
230
|
+
|
|
231
|
+
const program = cli('my-tool', '1.0.0', 'Example tool');
|
|
232
|
+
|
|
233
|
+
program
|
|
234
|
+
.command('hello [name]')
|
|
235
|
+
.description('Say hello')
|
|
236
|
+
.action((name?: string) => {
|
|
237
|
+
output({ message: `Hello, ${name || 'world'}!` });
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
program.parse();
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
When run via `cli4ai run`, these env vars are set for convenience:
|
|
244
|
+
- `CLI4AI_CWD`: directory where you invoked `cli4ai`
|
|
245
|
+
- `C4AI_PACKAGE_DIR`: installed package directory
|
|
246
|
+
- `C4AI_PACKAGE_NAME`: resolved package name
|
|
247
|
+
- `C4AI_ENTRY`: absolute path to the tool entry file
|
|
248
|
+
|
|
249
|
+
## Global vs Local Install
|
|
250
|
+
|
|
251
|
+
| Aspect | Global (`-g`) | Local (default) |
|
|
252
|
+
|--------|---------------|-----------------|
|
|
253
|
+
| Location | `~/.cli4ai/packages/` | `./.cli4ai/packages/` |
|
|
254
|
+
| Scope | Available everywhere | Project only |
|
|
255
|
+
| Lock file | No | Yes (`cli4ai.lock`) |
|
|
256
|
+
| Use case | Utilities (github, slack) | Project-specific (mongodb) |
|
|
257
|
+
|
|
258
|
+
## Environment Variables
|
|
259
|
+
|
|
260
|
+
Tools can require environment variables:
|
|
261
|
+
|
|
262
|
+
```json
|
|
263
|
+
{
|
|
264
|
+
"env": {
|
|
265
|
+
"API_KEY": { "required": true },
|
|
266
|
+
"DEBUG": { "required": false, "default": "false" }
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Set them in your shell or `.env` file.
|
|
272
|
+
|
|
273
|
+
## License
|
|
274
|
+
|
|
275
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cli4ai",
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "The package manager for AI CLI tools - cliforai.com",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"cli4ai": "./src/bin.ts"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "bun run src/bin.ts",
|
|
11
|
+
"build": "bun build src/bin.ts --outdir dist --target node",
|
|
12
|
+
"typecheck": "tsc --noEmit",
|
|
13
|
+
"test": "bun test",
|
|
14
|
+
"test:watch": "bun test --watch",
|
|
15
|
+
"test:coverage": "bun test --coverage"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"commander": "^14.0.0",
|
|
19
|
+
"semver": "^7.6.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/bun": "^1.3.4",
|
|
23
|
+
"@types/node": "^22.0.0",
|
|
24
|
+
"@types/semver": "^7.5.0",
|
|
25
|
+
"typescript": "^5.7.0"
|
|
26
|
+
},
|
|
27
|
+
"author": "cliforai",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/cliforai/framework"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://cliforai.com",
|
|
34
|
+
"keywords": [
|
|
35
|
+
"cli",
|
|
36
|
+
"ai",
|
|
37
|
+
"tools",
|
|
38
|
+
"mcp",
|
|
39
|
+
"package-manager",
|
|
40
|
+
"cli4ai"
|
|
41
|
+
],
|
|
42
|
+
"files": [
|
|
43
|
+
"src/**/*.ts",
|
|
44
|
+
"templates/**/*"
|
|
45
|
+
],
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
}
|
|
49
|
+
}
|
package/src/bin.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* cli4ai - The package manager for AI CLI tools
|
|
4
|
+
* cliforai.com
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createProgram } from './cli.js';
|
|
8
|
+
import { VERSION } from './lib/cli.js';
|
|
9
|
+
import { getNpmGlobalPackages } from './core/config.js';
|
|
10
|
+
|
|
11
|
+
// ANSI codes
|
|
12
|
+
const RESET = '\x1B[0m';
|
|
13
|
+
const BOLD = '\x1B[1m';
|
|
14
|
+
const DIM = '\x1B[2m';
|
|
15
|
+
const CYAN = '\x1B[36m';
|
|
16
|
+
const WHITE = '\x1B[37m';
|
|
17
|
+
const GREEN = '\x1B[32m';
|
|
18
|
+
const YELLOW = '\x1B[33m';
|
|
19
|
+
const MAGENTA = '\x1B[35m';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Sleep helper
|
|
23
|
+
*/
|
|
24
|
+
const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Robot eating dots animation
|
|
28
|
+
*/
|
|
29
|
+
async function showAnimation(): Promise<void> {
|
|
30
|
+
const width = 35;
|
|
31
|
+
const robot = ['[•_•]', '[•_•]', '[°_°]', '[•_•]'];
|
|
32
|
+
const food = '·';
|
|
33
|
+
|
|
34
|
+
for (let pos = 0; pos <= width; pos++) {
|
|
35
|
+
process.stdout.write('\r\x1B[K');
|
|
36
|
+
const frame = robot[pos % robot.length];
|
|
37
|
+
const trail = ' '.repeat(pos) + food.repeat(width - pos);
|
|
38
|
+
process.stdout.write(` ${CYAN}${frame}${RESET}${DIM}${trail}${RESET}`);
|
|
39
|
+
await sleep(20);
|
|
40
|
+
}
|
|
41
|
+
process.stdout.write('\r\x1B[K');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Animate the robot face (blinking)
|
|
46
|
+
*/
|
|
47
|
+
async function animateRobotFace(): Promise<void> {
|
|
48
|
+
const faces = ['[•_•]', '[•_•]', '[-_-]', '[•_•]', '[•_•]', '[°_°]', '[•_•]'];
|
|
49
|
+
const line = ` ${BOLD}${CYAN}cli4ai${RESET} ${DIM}─${RESET} ${WHITE}cliforai.com${RESET}`;
|
|
50
|
+
|
|
51
|
+
for (const face of faces) {
|
|
52
|
+
process.stdout.write(`\r ${CYAN}${face}${RESET}${line}`);
|
|
53
|
+
await sleep(120);
|
|
54
|
+
}
|
|
55
|
+
console.log('');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function showBanner(): Promise<void> {
|
|
59
|
+
if (!process.stdout.isTTY) return;
|
|
60
|
+
|
|
61
|
+
console.log('');
|
|
62
|
+
|
|
63
|
+
// Fun robot eating animation
|
|
64
|
+
await showAnimation();
|
|
65
|
+
|
|
66
|
+
// Animated robot branding (blinking)
|
|
67
|
+
await animateRobotFace();
|
|
68
|
+
|
|
69
|
+
console.log(` ${DIM}The package manager for AI CLI tools${RESET}`);
|
|
70
|
+
console.log(` ${DIM}v${VERSION}${RESET}`);
|
|
71
|
+
console.log('');
|
|
72
|
+
console.log(` ${BOLD}Commands${RESET}`);
|
|
73
|
+
console.log(` ${DIM}${'─'.repeat(40)}${RESET}`);
|
|
74
|
+
console.log(` ${GREEN}browse${RESET} ${DIM}Browse & install packages${RESET}`);
|
|
75
|
+
console.log(` ${GREEN}run${RESET} ${CYAN}<pkg> <cmd>${RESET} ${DIM}Run a tool command${RESET}`);
|
|
76
|
+
console.log(` ${GREEN}ls${RESET} ${DIM}List installed packages${RESET}`);
|
|
77
|
+
console.log(` ${GREEN}update${RESET} ${DIM}Update all packages${RESET}`);
|
|
78
|
+
console.log('');
|
|
79
|
+
console.log(` ${DIM}Run`${RESET} ${WHITE}cli4ai --help${RESET} ${DIM}for all commands${RESET}`);
|
|
80
|
+
console.log('');
|
|
81
|
+
|
|
82
|
+
// Check for updates in background (non-blocking)
|
|
83
|
+
checkUpdatesInBackground();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Check for updates without blocking - spawns detached process
|
|
88
|
+
*/
|
|
89
|
+
function checkUpdatesInBackground(): void {
|
|
90
|
+
// Quick local check only - don't hit network
|
|
91
|
+
try {
|
|
92
|
+
const packages = getNpmGlobalPackages();
|
|
93
|
+
if (packages.length > 0) {
|
|
94
|
+
// Spawn a background process to check updates and cache results
|
|
95
|
+
const child = Bun.spawn(['sh', '-c', `
|
|
96
|
+
# Quick npm check (with timeout)
|
|
97
|
+
timeout 3 npm view cli4ai version 2>/dev/null > /tmp/.cli4ai-update-check 2>&1 &
|
|
98
|
+
`], {
|
|
99
|
+
detached: true,
|
|
100
|
+
stdio: ['ignore', 'ignore', 'ignore']
|
|
101
|
+
});
|
|
102
|
+
child.unref();
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
// Ignore errors - this is best effort
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Check if running without command (just `cli4ai`)
|
|
110
|
+
const args = process.argv.slice(2);
|
|
111
|
+
const hasCommand = args.length > 0 && !args[0].startsWith('-');
|
|
112
|
+
const isHelp = args.includes('--help') || args.includes('-h');
|
|
113
|
+
const isVersion = args.includes('--version') || args.includes('-v');
|
|
114
|
+
|
|
115
|
+
if (!hasCommand && !isHelp && !isVersion) {
|
|
116
|
+
showBanner().then(() => process.exit(0));
|
|
117
|
+
} else {
|
|
118
|
+
const program = createProgram();
|
|
119
|
+
program.parse(process.argv);
|
|
120
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cli4ai CLI - Main program setup
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import { BRAND, VERSION, withErrorHandling } from './lib/cli.js';
|
|
7
|
+
|
|
8
|
+
// Commands
|
|
9
|
+
import { initCommand } from './commands/init.js';
|
|
10
|
+
import { addCommand } from './commands/add.js';
|
|
11
|
+
import { removeCommand } from './commands/remove.js';
|
|
12
|
+
import { listCommand } from './commands/list.js';
|
|
13
|
+
import { runCommand } from './commands/run.js';
|
|
14
|
+
import { infoCommand } from './commands/info.js';
|
|
15
|
+
import { searchCommand } from './commands/search.js';
|
|
16
|
+
import { configCommand } from './commands/config.js';
|
|
17
|
+
import { mcpConfigCommand } from './commands/mcp-config.js';
|
|
18
|
+
import { startCommand } from './commands/start.js';
|
|
19
|
+
import {
|
|
20
|
+
secretsSetCommand,
|
|
21
|
+
secretsGetCommand,
|
|
22
|
+
secretsListCommand,
|
|
23
|
+
secretsDeleteCommand,
|
|
24
|
+
secretsInitCommand
|
|
25
|
+
} from './commands/secrets.js';
|
|
26
|
+
import { browseCommand } from './commands/browse.js';
|
|
27
|
+
import { updateCommand } from './commands/update.js';
|
|
28
|
+
import { routinesListCommand, routinesRunCommand, routinesShowCommand, routinesCreateCommand, routinesEditCommand, routinesRemoveCommand } from './commands/routines.js';
|
|
29
|
+
|
|
30
|
+
export function createProgram(): Command {
|
|
31
|
+
const program = new Command()
|
|
32
|
+
.name('cli4ai')
|
|
33
|
+
.version(VERSION, '-v, --version', 'Show version')
|
|
34
|
+
.description('The package manager for AI CLI tools')
|
|
35
|
+
.addHelpText('beforeAll', `\n${BRAND}\n`)
|
|
36
|
+
.configureOutput({
|
|
37
|
+
writeErr: (str) => {
|
|
38
|
+
if (!str.includes('"error"')) {
|
|
39
|
+
process.stderr.write(str);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
45
|
+
// PACKAGE MANAGEMENT
|
|
46
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
47
|
+
|
|
48
|
+
program
|
|
49
|
+
.command('init [name]')
|
|
50
|
+
.description('Create a new cli4ai tool project')
|
|
51
|
+
.option('-t, --template <template>', 'Template to use (basic, api, browser)', 'basic')
|
|
52
|
+
.option('-r, --runtime <runtime>', 'Runtime (bun, node)', 'bun')
|
|
53
|
+
.option('-y, --yes', 'Skip prompts, use defaults')
|
|
54
|
+
.action(withErrorHandling(initCommand));
|
|
55
|
+
|
|
56
|
+
program
|
|
57
|
+
.command('add <packages...>')
|
|
58
|
+
.description('Install packages')
|
|
59
|
+
.option('-l, --local', 'Install from local path')
|
|
60
|
+
.option('-g, --global', 'Install globally')
|
|
61
|
+
.option('-D, --save-dev', 'Save as dev dependency')
|
|
62
|
+
.option('-y, --yes', 'Skip confirmation prompt')
|
|
63
|
+
.action(withErrorHandling(addCommand));
|
|
64
|
+
|
|
65
|
+
program
|
|
66
|
+
.command('remove <packages...>')
|
|
67
|
+
.alias('rm')
|
|
68
|
+
.alias('uninstall')
|
|
69
|
+
.description('Remove packages')
|
|
70
|
+
.option('-g, --global', 'Remove from global packages')
|
|
71
|
+
.action(withErrorHandling(removeCommand));
|
|
72
|
+
|
|
73
|
+
program
|
|
74
|
+
.command('list')
|
|
75
|
+
.alias('ls')
|
|
76
|
+
.description('List installed packages')
|
|
77
|
+
.option('-g, --global', 'List global packages')
|
|
78
|
+
.option('--json', 'Output as JSON')
|
|
79
|
+
.action(withErrorHandling(listCommand));
|
|
80
|
+
|
|
81
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
82
|
+
// EXECUTION
|
|
83
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
84
|
+
|
|
85
|
+
program
|
|
86
|
+
.command('run <package> [command] [args...]')
|
|
87
|
+
.description('Run a tool command')
|
|
88
|
+
.option('-e, --env <vars...>', 'Environment variables (KEY=value)')
|
|
89
|
+
// Allow passing tool flags through (e.g. `cli4ai run chrome screenshot --full-page`)
|
|
90
|
+
.allowUnknownOption(true)
|
|
91
|
+
.addHelpText('after', `
|
|
92
|
+
|
|
93
|
+
Examples:
|
|
94
|
+
cli4ai run github trending
|
|
95
|
+
cli4ai run chrome screenshot https://example.com --full-page
|
|
96
|
+
|
|
97
|
+
Pass-through:
|
|
98
|
+
Use "--" to pass flags that would otherwise be parsed by cli4ai:
|
|
99
|
+
cli4ai run <pkg> <cmd> -- --help
|
|
100
|
+
`)
|
|
101
|
+
.action(withErrorHandling(runCommand));
|
|
102
|
+
|
|
103
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
104
|
+
// DISCOVERY
|
|
105
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
106
|
+
|
|
107
|
+
program
|
|
108
|
+
.command('info <package>')
|
|
109
|
+
.description('Show package information')
|
|
110
|
+
.option('--versions', 'Show all available versions')
|
|
111
|
+
.action(withErrorHandling(infoCommand));
|
|
112
|
+
|
|
113
|
+
program
|
|
114
|
+
.command('search <query>')
|
|
115
|
+
.description('Search for packages')
|
|
116
|
+
.option('-l, --limit <n>', 'Max results', '20')
|
|
117
|
+
.action(withErrorHandling(searchCommand));
|
|
118
|
+
|
|
119
|
+
program
|
|
120
|
+
.command('browse')
|
|
121
|
+
.description('Interactive package browser')
|
|
122
|
+
.action(withErrorHandling(browseCommand));
|
|
123
|
+
|
|
124
|
+
program
|
|
125
|
+
.command('update')
|
|
126
|
+
.alias('upgrade')
|
|
127
|
+
.description('Update installed packages')
|
|
128
|
+
.option('-s, --self', 'Update cli4ai framework only')
|
|
129
|
+
.option('-a, --all', 'Update cli4ai framework and all packages')
|
|
130
|
+
.option('-y, --yes', 'Skip confirmation prompt')
|
|
131
|
+
.action(withErrorHandling(updateCommand));
|
|
132
|
+
|
|
133
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
134
|
+
// CONFIGURATION
|
|
135
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
136
|
+
|
|
137
|
+
program
|
|
138
|
+
.command('config [key] [value]')
|
|
139
|
+
.description('Get or set configuration')
|
|
140
|
+
.option('--list', 'List all config values')
|
|
141
|
+
.option('--add-registry <path>', 'Add local registry path')
|
|
142
|
+
.option('--remove-registry <path>', 'Remove local registry path')
|
|
143
|
+
.action(withErrorHandling(configCommand));
|
|
144
|
+
|
|
145
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
146
|
+
// MCP INTEGRATION
|
|
147
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
148
|
+
|
|
149
|
+
program
|
|
150
|
+
.command('mcp-config')
|
|
151
|
+
.description('Generate MCP configuration for Claude Code')
|
|
152
|
+
.option('-g, --global', 'Use global packages only')
|
|
153
|
+
.option('-p, --package <name>', 'Generate for specific package')
|
|
154
|
+
.option('--snippet', 'Output as config snippet (use with --package)')
|
|
155
|
+
.action(withErrorHandling(mcpConfigCommand));
|
|
156
|
+
|
|
157
|
+
program
|
|
158
|
+
.command('start <package>')
|
|
159
|
+
.description('Start MCP server for a package')
|
|
160
|
+
.option('--stdio', 'Use stdio transport (default)')
|
|
161
|
+
.action(withErrorHandling(startCommand));
|
|
162
|
+
|
|
163
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
164
|
+
// SECRETS MANAGEMENT
|
|
165
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
166
|
+
|
|
167
|
+
const secrets = program
|
|
168
|
+
.command('secrets')
|
|
169
|
+
.description('Manage secrets for CLI tools');
|
|
170
|
+
|
|
171
|
+
secrets
|
|
172
|
+
.command('set <key> [value]')
|
|
173
|
+
.description('Set a secret (prompts for value if not provided)')
|
|
174
|
+
.action(withErrorHandling(secretsSetCommand));
|
|
175
|
+
|
|
176
|
+
secrets
|
|
177
|
+
.command('get <key>')
|
|
178
|
+
.description('Get a secret value')
|
|
179
|
+
.action(withErrorHandling(secretsGetCommand));
|
|
180
|
+
|
|
181
|
+
secrets
|
|
182
|
+
.command('list')
|
|
183
|
+
.alias('ls')
|
|
184
|
+
.description('List all secrets')
|
|
185
|
+
.option('-p, --package <name>', 'Show secrets for a specific package')
|
|
186
|
+
.action(withErrorHandling(secretsListCommand));
|
|
187
|
+
|
|
188
|
+
secrets
|
|
189
|
+
.command('delete <key>')
|
|
190
|
+
.alias('rm')
|
|
191
|
+
.description('Delete a secret')
|
|
192
|
+
.action(withErrorHandling(secretsDeleteCommand));
|
|
193
|
+
|
|
194
|
+
secrets
|
|
195
|
+
.command('init <package>')
|
|
196
|
+
.description('Interactive setup for a package\'s required secrets')
|
|
197
|
+
.action(withErrorHandling(secretsInitCommand));
|
|
198
|
+
|
|
199
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
200
|
+
// HELP
|
|
201
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
202
|
+
|
|
203
|
+
program.addHelpCommand('help [command]', 'Show help for command');
|
|
204
|
+
|
|
205
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
206
|
+
// ROUTINES
|
|
207
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
208
|
+
|
|
209
|
+
const routines = program
|
|
210
|
+
.command('routines')
|
|
211
|
+
.description('Manage and run routines');
|
|
212
|
+
|
|
213
|
+
routines
|
|
214
|
+
.command('list')
|
|
215
|
+
.alias('ls')
|
|
216
|
+
.description('List available routines')
|
|
217
|
+
.option('-g, --global', 'Use global routines only')
|
|
218
|
+
.option('--json', 'Output as JSON')
|
|
219
|
+
.action(withErrorHandling(routinesListCommand));
|
|
220
|
+
|
|
221
|
+
routines
|
|
222
|
+
.command('show <name>')
|
|
223
|
+
.description('Show routine definition')
|
|
224
|
+
.option('-g, --global', 'Use global routines only')
|
|
225
|
+
.action(withErrorHandling(routinesShowCommand));
|
|
226
|
+
|
|
227
|
+
routines
|
|
228
|
+
.command('create <name>')
|
|
229
|
+
.description('Create a new routine')
|
|
230
|
+
.option('-g, --global', 'Create routine globally')
|
|
231
|
+
.option('--type <type>', 'Routine type (bash, json)', 'bash')
|
|
232
|
+
.action(withErrorHandling(routinesCreateCommand));
|
|
233
|
+
|
|
234
|
+
routines
|
|
235
|
+
.command('edit <name>')
|
|
236
|
+
.description('Edit a routine in $EDITOR')
|
|
237
|
+
.option('-g, --global', 'Use global routine only')
|
|
238
|
+
.action(withErrorHandling(routinesEditCommand));
|
|
239
|
+
|
|
240
|
+
routines
|
|
241
|
+
.command('remove <name>')
|
|
242
|
+
.alias('rm')
|
|
243
|
+
.description('Remove a routine')
|
|
244
|
+
.option('-g, --global', 'Use global routine only')
|
|
245
|
+
.action(withErrorHandling(routinesRemoveCommand));
|
|
246
|
+
|
|
247
|
+
routines
|
|
248
|
+
.command('run <name> [args...]')
|
|
249
|
+
.description('Run a routine')
|
|
250
|
+
.option('-g, --global', 'Use global routine only')
|
|
251
|
+
.option('--var <vars...>', 'Variables (KEY=value)')
|
|
252
|
+
.option('--dry-run', 'Show execution plan without running')
|
|
253
|
+
.action(withErrorHandling(routinesRunCommand));
|
|
254
|
+
|
|
255
|
+
return program;
|
|
256
|
+
}
|