

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1234567# OCLIF Command Standards89## Command Structure1011### Standard Command Pattern12```typescript13// ✅ GOOD - Standard command structure14import { Command } from '@contentstack/cli-command';15import { cliux, flags, FlagInput, handleAndLogError } from '@contentstack/cli-utilities';1617export default class ConfigSetCommand extends Command {18 static description = 'Set CLI configuration values';1920 static flags: FlagInput = {21 region: flags.string({22 char: 'r',23 description: 'Set region (us/eu)',24 }),25 alias: flags.string({26 char: 'a',27 description: 'Configuration alias',28 }),29 };3031 static examples = [32 'csdx config:set --region eu',33 'csdx config:set --region us --alias default',34 ];3536 async run(): Promise<void> {37 try {38 const { flags: configFlags } = await this.parse(ConfigSetCommand);39 // Command logic here40 } catch (error) {41 handleAndLogError(error, { module: 'config-set' });42 }43 }44}45```4647## Base Classes4849### Command Base Class50```typescript51// ✅ GOOD - Extend Command from @contentstack/cli-command52import { Command } from '@contentstack/cli-command';5354export default class MyCommand extends Command {55 async run(): Promise<void> {56 // Command implementation57 }58}59```6061### Custom Base Classes62```typescript63// ✅ GOOD - Create custom base classes for shared functionality64export abstract class BaseCommand<T extends typeof Command> extends Command {65 protected contextDetails = {66 command: this.id || 'unknown',67 };6869 async init(): Promise<void> {70 await super.init();71 log.debug('Command initialized', this.contextDetails);72 }73}74```7576## OCLIF Configuration7778### Package.json Setup79```json80{81 "oclif": {82 "commands": "./lib/commands",83 "bin": "csdx",84 "topicSeparator": ":"85 }86}87```8889### Command Topics90- All commands use `cm` topic: `cm:config:set`, `cm:auth:login`91- Built commands live in `lib/commands` (compiled from `src/commands`)92- Commands use nested directories: `src/commands/config/set.ts` → `cm:config:set`9394### Command Naming95- **Topic hierarchy**: `config/remove/proxy.ts` → `cm:config:remove:proxy`96- **Descriptive names**: Use verb-noun pattern (`set`, `remove`, `show`)97- **Grouping**: Related commands share parent topics9899## Flag Management100101### Flag Definition Patterns102```typescript103// ✅ GOOD - Define flags clearly104static flags: FlagInput = {105 'stack-api-key': flags.string({106 char: 'k',107 description: 'Stack API key',108 required: false,109 }),110 region: flags.string({111 char: 'r',112 description: 'Set region',113 options: ['us', 'eu'],114 }),115 verbose: flags.boolean({116 char: 'v',117 description: 'Show verbose output',118 default: false,119 }),120};121```122123### Flag Parsing124```typescript125// ✅ GOOD - Parse and validate flags126async run(): Promise<void> {127 const { flags: parsedFlags } = await this.parse(MyCommand);128129 // Validate flag combinations130 if (!parsedFlags['stack-api-key'] && !parsedFlags.alias) {131 this.error('Either --stack-api-key or --alias is required');132 }133134 // Use parsed flags135 const region = parsedFlags.region || 'us';136}137```138139## Error Handling140141### Standard Error Pattern142```typescript143// ✅ GOOD - Use handleAndLogError from utilities144try {145 await this.executeCommand();146} catch (error) {147 handleAndLogError(error, { module: 'my-command' });148}149```150151### User-Friendly Messages152```typescript153// ✅ GOOD - Clear user feedback154import { cliux } from '@contentstack/cli-utilities';155156// Success message157cliux.success('Configuration updated successfully', { color: 'green' });158159// Error message160cliux.error('Invalid region specified', { color: 'red' });161162// Info message163cliux.print('Setting region to eu', { color: 'blue' });164```165166## Validation Patterns167168### Early Validation169```typescript170// ✅ GOOD - Validate flags early171async run(): Promise<void> {172 const { flags } = await this.parse(MyCommand);173174 // Validate required flags175 if (!flags.region) {176 this.error('--region is required');177 }178179 // Validate flag values180 if (!['us', 'eu'].includes(flags.region)) {181 this.error('Region must be "us" or "eu"');182 }183184 // Proceed with validated input185}186```187188## Progress and Logging189190### User Feedback191```typescript192// ✅ GOOD - Provide user feedback193import { log, cliux } from '@contentstack/cli-utilities';194195// Regular logging196this.log('Starting configuration update...');197198// Debug logging199log.debug('Detailed operation information', { context: 'data' });200201// Status messages202cliux.print('Processing...', { color: 'blue' });203```204205### Progress Indication206```typescript207// ✅ GOOD - Show progress for long operations208cliux.print('Processing items...', { color: 'blue' });209let count = 0;210for (const item of items) {211 await this.processItem(item);212 count++;213 cliux.print(`Processed ${count}/${items.length} items`, { color: 'blue' });214}215```216217## Command Delegation218219### Service Layer Separation220```typescript221// ✅ GOOD - Commands orchestrate, services implement222async run(): Promise<void> {223 try {224 const { flags } = await this.parse(MyCommand);225 const config = this.buildConfig(flags);226 const service = new ConfigService(config);227228 await service.execute();229 cliux.success('Operation completed successfully');230 } catch (error) {231 this.handleError(error);232 }233}234```235236## Testing Commands237238### OCLIF Test Support239```typescript240// ✅ GOOD - Use @oclif/test for command testing241import { test } from '@oclif/test';242243describe('cm:config:set', () => {244 test245 .stdout()246 .command(['cm:config:set', '--help'])247 .it('shows help', ctx => {248 expect(ctx.stdout).to.contain('Set CLI configuration');249 });250251 test252 .stdout()253 .command(['cm:config:set', '--region', 'eu'])254 .it('sets region to eu', ctx => {255 expect(ctx.stdout).to.contain('success');256 });257});258```259260## Log Integration261262### Debug Logging263```typescript264// ✅ GOOD - Use structured debug logging265import { log } from '@contentstack/cli-utilities';266267log.debug('Command started', {268 command: this.id,269 flags: this.flags,270 timestamp: new Date().toISOString(),271});272273log.debug('Processing complete', {274 itemsProcessed: count,275 module: 'my-command',276});277```278279### Error Context280```typescript281// ✅ GOOD - Include context in error handling282try {283 await operation();284} catch (error) {285 handleAndLogError(error, {286 module: 'config-set',287 command: 'cm:config:set',288 flags: { region: 'eu' },289 });290}291```292293## Multi-Topic Commands294295### Nested Command Structure296```typescript297// File: src/commands/config/show.ts298export default class ShowConfigCommand extends Command {299 static description = 'Show current configuration';300 static examples = ['csdx config:show'];301 async run(): Promise<void> { }302}303304// File: src/commands/config/set.ts305export default class SetConfigCommand extends Command {306 static description = 'Set configuration values';307 static examples = ['csdx config:set --region eu'];308 async run(): Promise<void> { }309}310311// Generated commands:312// - cm:config:show313// - cm:config:set314```315316## Best Practices317318### Command Organization319```typescript320// ✅ GOOD - Well-organized command321export default class MyCommand extends Command {322 static description = 'Clear, concise description';323324 static flags: FlagInput = {325 // Define all flags326 };327328 static examples = [329 'csdx my:command',330 'csdx my:command --flag value',331 ];332333 async run(): Promise<void> {334 try {335 const { flags } = await this.parse(MyCommand);336 await this.execute(flags);337 } catch (error) {338 handleAndLogError(error, { module: 'my-command' });339 }340 }341342 private async execute(flags: Flags<typeof MyCommand>): Promise<void> {343 // Implementation344 }345}346```347348### Clear Help Text349- Write description as action-oriented statement350- Provide multiple examples for common use cases351- Document each flag with clear description352- Show output format or examples of results353
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| contentstack/cli.cursor/rules/contentstack-core.mdc · 14 | Cursor rules | buildteststylearch+3 | 69/100 | 14 days ago | |
| contentstack/cli.cursor/rules/testing.mdc · 14 | Cursor rules | setupteststylearch+3 | 89/100 | 14 days ago | |
| contentstack/cli.cursor/rules/typescript.mdc · 14 | Cursor rules | stylearchtypessecurity+1 | 70/100 | 14 days ago |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 14 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 14 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45 | Cursor rules | teststyletesting-strategysecurity+3 | 97/100 | 14 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/contentstack-cli-cursor-rules-oclif-commands)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.
Directory