or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-management.mdcode-generation.mdindex.mdpackaging.mdprogrammatic-api.mdupload-deployment.md

programmatic-api.mddocs/

0

# Programmatic API

1

2

Direct access to oclif functionality for programmatic usage, custom integrations, and embedding CLIs within applications.

3

4

## Capabilities

5

6

### Run Function

7

8

Execute oclif CLI programmatically with custom arguments and options.

9

10

```typescript { .api }

11

/**

12

* Execute oclif CLI programmatically

13

* @param argv - Command line arguments array

14

* @param options - Load options for CLI execution

15

* @returns Promise that resolves when command completes

16

*/

17

function run(argv?: string[], options?: LoadOptions): Promise<void>;

18

19

interface LoadOptions {

20

/** Root directory of the CLI project */

21

root?: string;

22

/** Release channel to use (stable, beta, alpha) */

23

channel?: string;

24

/** Enable development mode with enhanced debugging */

25

development?: boolean;

26

}

27

```

28

29

**Usage Examples:**

30

31

```typescript

32

import { run } from "oclif";

33

34

// Execute help command

35

await run(["help"]);

36

37

// Execute specific command with arguments

38

await run(["generate", "my-new-cli", "--author=John Doe"]);

39

40

// Execute with custom options

41

await run(["pack", "tarballs"], {

42

root: "/path/to/cli/project",

43

development: true

44

});

45

46

// Handle command execution in try-catch

47

try {

48

await run(["invalid-command"]);

49

} catch (error) {

50

console.error("Command failed:", error.message);

51

}

52

```

53

54

### Error Handling

55

56

The run function throws errors for various failure conditions:

57

58

```typescript { .api }

59

// Command execution can throw these error types:

60

// - CommandNotFoundError: Command does not exist

61

// - ValidationError: Invalid arguments or flags

62

// - ExecutionError: Command execution failed

63

// - ConfigError: CLI configuration issues

64

65

try {

66

await run(["nonexistent-command"]);

67

} catch (error) {

68

if (error.code === 'EEXIT') {

69

// Command exited with non-zero code

70

console.log(`Command failed with exit code: ${error.exit}`);

71

} else {

72

// Other execution errors

73

console.error("Execution error:", error);

74

}

75

}

76

```

77

78

## Integration Patterns

79

80

### Embedding in Applications

81

82

Embed oclif CLI functionality within Node.js applications:

83

84

```typescript

85

import { run } from "oclif";

86

87

class CLIService {

88

private projectRoot: string;

89

90

constructor(projectRoot: string) {

91

this.projectRoot = projectRoot;

92

}

93

94

async generateProject(name: string, options: GenerateOptions): Promise<void> {

95

const args = ["generate", name];

96

97

if (options.author) args.push(`--author=${options.author}`);

98

if (options.license) args.push(`--license=${options.license}`);

99

if (options.yes) args.push("--yes");

100

101

await run(args, { root: this.projectRoot });

102

}

103

104

async buildPackages(targets: string[]): Promise<void> {

105

await run(["pack", "tarballs", `--targets=${targets.join(",")}`], {

106

root: this.projectRoot

107

});

108

}

109

}

110

111

interface GenerateOptions {

112

author?: string;

113

license?: string;

114

yes?: boolean;

115

}

116

```

117

118

### Custom CLI Wrapper

119

120

Create wrapper functions for specific oclif operations:

121

122

```typescript

123

import { run } from "oclif";

124

125

export class OclifWrapper {

126

static async createCLI(config: CLIConfig): Promise<void> {

127

const args = ["generate", config.name];

128

129

Object.entries(config).forEach(([key, value]) => {

130

if (key !== "name" && value !== undefined) {

131

args.push(`--${key}=${value}`);

132

}

133

});

134

135

if (config.skipPrompts) {

136

args.push("--yes");

137

}

138

139

await run(args);

140

}

141

142

static async generateCommand(name: string, force: boolean = false): Promise<void> {

143

const args = ["generate", "command", name];

144

if (force) args.push("--force");

145

146

await run(args);

147

}

148

149

static async updateReadme(): Promise<void> {

150

await run(["readme"]);

151

}

152

153

static async createManifest(path?: string): Promise<void> {

154

const args = ["manifest"];

155

if (path) args.push(path);

156

157

await run(args);

158

}

159

}

160

161

interface CLIConfig {

162

name: string;

163

author?: string;

164

description?: string;

165

license?: string;

166

bin?: string;

167

repository?: string;

168

skipPrompts?: boolean;

169

}

170

```

171

172

### Build and Deploy Automation

173

174

Automate the build and deployment process:

175

176

```typescript

177

import { run } from "oclif";

178

179

export class BuildPipeline {

180

private projectRoot: string;

181

182

constructor(projectRoot: string) {

183

this.projectRoot = projectRoot;

184

}

185

186

async buildAll(targets: string[] = ["linux-x64", "darwin-x64", "win32-x64"]): Promise<void> {

187

console.log("Building tarballs...");

188

await run(["pack", "tarballs", `--targets=${targets.join(",")}`], {

189

root: this.projectRoot

190

});

191

192

console.log("Building platform packages...");

193

await Promise.all([

194

run(["pack", "deb"], { root: this.projectRoot }),

195

run(["pack", "macos"], { root: this.projectRoot }),

196

run(["pack", "win"], { root: this.projectRoot })

197

]);

198

}

199

200

async deploy(channel: string = "stable"): Promise<void> {

201

console.log("Uploading packages...");

202

await Promise.all([

203

run(["upload", "tarballs"], { root: this.projectRoot }),

204

run(["upload", "deb"], { root: this.projectRoot }),

205

run(["upload", "macos"], { root: this.projectRoot }),

206

run(["upload", "win"], { root: this.projectRoot })

207

]);

208

209

console.log(`Promoting to ${channel} channel...`);

210

await run(["promote", `--channel=${channel}`], {

211

root: this.projectRoot

212

});

213

}

214

215

async fullPipeline(targets?: string[], channel: string = "beta"): Promise<void> {

216

await this.buildAll(targets);

217

await this.deploy(channel);

218

console.log("Pipeline completed successfully!");

219

}

220

}

221

```

222

223

### Testing Integration

224

225

Use programmatic API for testing CLI functionality:

226

227

```typescript

228

import { run } from "oclif";

229

import { promises as fs } from "fs";

230

import { tmpdir } from "os";

231

import { join } from "path";

232

233

describe("CLI Integration Tests", () => {

234

let testDir: string;

235

236

beforeEach(async () => {

237

testDir = await fs.mkdtemp(join(tmpdir(), "oclif-test-"));

238

});

239

240

afterEach(async () => {

241

await fs.rmdir(testDir, { recursive: true });

242

});

243

244

it("should generate a new CLI project", async () => {

245

const projectName = "test-cli";

246

247

await run([

248

"generate",

249

projectName,

250

"--author=Test Author",

251

"--license=MIT",

252

"--yes"

253

], { root: testDir });

254

255

// Verify project was created

256

const projectPath = join(testDir, projectName);

257

const packageJsonExists = await fs.access(join(projectPath, "package.json"))

258

.then(() => true)

259

.catch(() => false);

260

261

expect(packageJsonExists).toBe(true);

262

});

263

264

it("should generate README documentation", async () => {

265

// First create a CLI project

266

await run(["generate", "test-cli", "--yes"], { root: testDir });

267

268

const projectPath = join(testDir, "test-cli");

269

270

// Generate README

271

await run(["readme"], { root: projectPath });

272

273

// Verify README was updated

274

const readmeContent = await fs.readFile(join(projectPath, "README.md"), "utf-8");

275

expect(readmeContent).toContain("Usage");

276

expect(readmeContent).toContain("Commands");

277

});

278

});

279

```

280

281

## Advanced Usage

282

283

### Custom Configuration

284

285

Override default configuration for programmatic usage:

286

287

```typescript

288

import { run } from "oclif";

289

290

// Set environment variables for custom configuration

291

process.env.OCLIF_CLI_ROOT = "/custom/cli/path";

292

process.env.OCLIF_DEVELOPMENT = "true";

293

294

await run(["help"], {

295

development: true,

296

root: process.env.OCLIF_CLI_ROOT

297

});

298

```

299

300

### Output Capture

301

302

Capture command output for processing:

303

304

```typescript

305

import { run } from "oclif";

306

307

// Capture stdout and stderr

308

const originalWrite = process.stdout.write;

309

const originalError = process.stderr.write;

310

311

let output = "";

312

let errors = "";

313

314

process.stdout.write = (chunk: any) => {

315

output += chunk.toString();

316

return true;

317

};

318

319

process.stderr.write = (chunk: any) => {

320

errors += chunk.toString();

321

return true;

322

};

323

324

try {

325

await run(["help"]);

326

console.log("Command output:", output);

327

} catch (error) {

328

console.log("Command errors:", errors);

329

} finally {

330

// Restore original functions

331

process.stdout.write = originalWrite;

332

process.stderr.write = originalError;

333

}

334

```

335

336

### Process Management

337

338

Handle CLI execution in different process contexts:

339

340

```typescript

341

import { run } from "oclif";

342

import { spawn } from "child_process";

343

344

// Execute in current process

345

await run(["generate", "my-cli"]);

346

347

// Execute in separate process for isolation

348

function runInSeparateProcess(args: string[]): Promise<number> {

349

return new Promise((resolve, reject) => {

350

const child = spawn("oclif", args, { stdio: "inherit" });

351

352

child.on("close", (code) => {

353

if (code === 0) {

354

resolve(code);

355

} else {

356

reject(new Error(`Process exited with code ${code}`));

357

}

358

});

359

360

child.on("error", reject);

361

});

362

}

363

364

// Usage

365

await runInSeparateProcess(["pack", "tarballs"]);

366

```