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

code-generation.mddocs/

0

# Code Generation

1

2

Generate CLI components including commands and hooks using oclif's template system and code generators.

3

4

## Capabilities

5

6

### Generate Command

7

8

Adds a new command to an existing oclif CLI or plugin using predefined templates.

9

10

```bash { .api }

11

oclif generate command [NAME]

12

```

13

14

**Arguments:**

15

- `NAME` (string, required) - Name of the command to create

16

17

**Flags:**

18

- `--commands-dir` (string) - Directory to create the command file in

19

- `--force` (boolean) - Overwrite existing command file if it exists

20

21

**Usage Examples:**

22

23

```bash

24

# Generate a simple command

25

oclif generate command hello

26

27

# Generate nested command

28

oclif generate command users:list

29

30

# Generate with custom directory

31

oclif generate command deploy --commands-dir=./src/commands

32

33

# Force overwrite existing command

34

oclif generate command existing-cmd --force

35

```

36

37

**Generated Command Structure:**

38

39

```typescript

40

import { Args, Command, Flags } from '@oclif/core'

41

42

export default class Hello extends Command {

43

static description = 'describe the command here'

44

45

static examples = [

46

'<%= config.bin %> <%= command.id %>',

47

]

48

49

static flags = {

50

// flag with a value (-n, --name=VALUE)

51

name: Flags.string({char: 'n', description: 'name to print'}),

52

// flag with no value (-f, --force)

53

force: Flags.boolean({char: 'f'}),

54

}

55

56

static args = {

57

file: Args.string({description: 'file to read'}),

58

}

59

60

async run(): Promise<void> {

61

const {args, flags} = await this.parse(Hello)

62

63

const name = flags.name ?? 'world'

64

this.log(`hello ${name} from ./src/commands/hello/world.ts`)

65

if (args.file && flags.force) {

66

this.log(`you input --force and --file: ${args.file}`)

67

}

68

}

69

}

70

```

71

72

### Generate Hook

73

74

Adds a new hook to an existing oclif CLI or plugin for extending functionality at specific lifecycle points.

75

76

```bash { .api }

77

oclif generate hook [NAME]

78

```

79

80

**Arguments:**

81

- `NAME` (string, required) - Name of the hook to create (snake_case)

82

83

**Flags:**

84

- `--event` (string) - Event to run hook on (default: "init")

85

- `--force` (boolean) - Overwrite existing hook file if it exists

86

87

**Usage Examples:**

88

89

```bash

90

# Generate a basic init hook

91

oclif generate hook analytics

92

93

# Generate hook for specific event

94

oclif generate hook my_prerun_hook --event=prerun

95

96

# Force overwrite existing hook

97

oclif generate hook existing_hook --force

98

```

99

100

**Generated Hook Structure:**

101

102

```typescript

103

import { Hook } from '@oclif/core'

104

105

const hook: Hook<'init'> = async function (opts) {

106

// Hook implementation

107

process.stdout.write(`example hook running ${opts.id}\n`)

108

}

109

110

export default hook

111

```

112

113

## Generator Base Classes

114

115

oclif provides base generator classes for creating custom generators and extending the template system.

116

117

### GeneratorCommand Class

118

119

Abstract base class for creating custom file generators using EJS templates.

120

121

```typescript { .api }

122

/**

123

* Base class for commands that generate files from templates

124

*/

125

abstract class GeneratorCommand<T extends typeof Command> extends Command {

126

/** Get flag value or prompt user interactively */

127

protected getFlagOrPrompt<K extends keyof FlagsOfPrompts<any>>(

128

options: GetFlagOrPromptOptions<K>

129

): Promise<any>;

130

131

/** Render EJS template to destination file */

132

protected template(

133

source: string,

134

destination: string,

135

data?: Record<string, any>

136

): Promise<void>;

137

}

138

139

interface GetFlagOrPromptOptions<K> {

140

/** Flag name to check */

141

flag: K;

142

/** Prompt configuration */

143

prompt: FlaggablePrompt;

144

/** Default value if no flag or prompt response */

145

default?: any;

146

}

147

148

interface FlaggablePrompt {

149

/** Prompt message */

150

message: string;

151

/** Prompt type (input, select, confirm) */

152

type: 'input' | 'select' | 'confirm';

153

/** Choices for select prompts */

154

choices?: Array<string | { name: string; value: any }>;

155

/** Initial/default value */

156

initial?: any;

157

}

158

```

159

160

### Utility Functions

161

162

Helper functions for generator implementations and custom generators.

163

164

```typescript { .api }

165

/**

166

* Execute shell command with promise wrapper

167

* @param command - Shell command to execute

168

* @param opts - Execution options

169

* @returns Promise resolving to command output

170

*/

171

function exec(command: string, opts?: ExecOptions): Promise<string>;

172

173

/**

174

* Read and parse package.json file

175

* @param location - Path to package.json

176

* @returns Parsed package.json object

177

*/

178

function readPJSON(location: string): Promise<any>;

179

180

/**

181

* Generate oclif flags from prompt definitions

182

* @param flaggablePrompts - Array of prompt configurations

183

* @returns oclif flag definitions object

184

*/

185

function makeFlags<T extends Record<string, FlaggablePrompt>>(

186

flaggablePrompts: T

187

): FlagsOfPrompts<T>;

188

189

interface ExecOptions {

190

cwd?: string;

191

env?: Record<string, string>;

192

shell?: boolean | string;

193

}

194

195

type FlagsOfPrompts<T extends Record<string, FlaggablePrompt>> = {

196

[K in keyof T]: T[K]['type'] extends 'confirm'

197

? BooleanFlag<boolean>

198

: StringFlag<string | undefined>;

199

};

200

```

201

202

## Template System

203

204

oclif uses EJS templates for code generation with built-in variables and helpers.

205

206

### Template Variables

207

208

```typescript { .api }

209

interface TemplateContext {

210

/** Package configuration */

211

config: {

212

name: string;

213

version: string;

214

bin: string;

215

};

216

/** Command information */

217

command: {

218

id: string;

219

name: string;

220

className: string;

221

};

222

/** User input */

223

answers: Record<string, any>;

224

/** Utility functions */

225

_: {

226

camelCase: (str: string) => string;

227

kebabCase: (str: string) => string;

228

pascalCase: (str: string) => string;

229

snakeCase: (str: string) => string;

230

};

231

}

232

```

233

234

### Template Locations

235

236

Templates are located in the oclif package and can be customized:

237

238

- Command templates: `templates/command/`

239

- Hook templates: `templates/hook/`

240

- Project templates: `templates/cli/`

241

242

**Custom Template Usage:**

243

244

```typescript

245

// In a custom generator command

246

await this.template(

247

path.join(__dirname, '../templates/my-template.ejs'),

248

path.join(this.config.root, 'generated-file.ts'),

249

{

250

className: 'MyClass',

251

description: 'Custom generated class'

252

}

253

);

254

```