RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/Cursor rules/contentstack/cli

Cursor rule

.cursor/rules/contentstack-core.mdc

Contentstack core CLI package patterns — plugin aggregation, hooks, and entry point

Cursor rules

Quality

69/100

Scores the file, not the repository.

Length

1,336 words

31 headings · 14 code blocks

Repository

14

— · pushed 0 days ago

Last changed

3 days ago

First indexed 3 days ago.
contentstack/cli/.cursor/rules/contentstack-core.mdcRawGitHub
1---
2description: "Contentstack core CLI package patterns — plugin aggregation, hooks, and entry point"
3globs: ["packages/contentstack/src/**/*.ts", "packages/contentstack/src/**/*.js"]
4alwaysApply: false
5---
6 
7# Contentstack Core Package Standards
8 
9## Overview
10 
11The `@contentstack/cli` core package is the entry point for the entire CLI. Unlike plugin packages (auth, config), it:
12- **Aggregates all plugins** — declared in `oclif.plugins` array in `package.json`
13- **Implements hooks** — `init` and `prerun` hooks in `src/hooks/` for global behaviors
14- **Shares interfaces** — Core types used across all plugins in `src/interfaces/`
15- **Provides utilities** — Helper classes like `CsdxContext` in `src/utils/`
16- **Has no command files** — Commands are provided by plugin packages
17 
18## Architecture
19 
20### Entry Point
21 
22```typescript
23// ✅ GOOD - bin/run.js (CommonJS)
24// This is the executable entry point referenced in package.json "bin"
25// Standard OCLIF entry point pattern
26```
27 
28### Package Configuration
29 
30The `oclif` configuration in `package.json`:
31```json
32{
33 "oclif": {
34 "bin": "csdx",
35 "topicSeparator": ":",
36 "helpClass": "./lib/help.js",
37 "plugins": [
38 "@oclif/plugin-help",
39 "@oclif/plugin-not-found",
40 "@oclif/plugin-plugins",
41 "@contentstack/cli-config",
42 "@contentstack/cli-auth"
43 // ... more plugins
44 ],
45 "hooks": {
46 "init": [
47 "./lib/hooks/init/context-init",
48 "./lib/hooks/init/utils-init"
49 ],
50 "prerun": [
51 "./lib/hooks/prerun/init-context-for-command",
52 "./lib/hooks/prerun/command-deprecation-check",
53 "./lib/hooks/prerun/default-rate-limit-check",
54 "./lib/hooks/prerun/latest-version-warning"
55 ]
56 },
57 "topics": {
58 "auth": { "description": "Perform authentication-related activities" },
59 "config": { "description": "Perform configuration related activities" },
60 "cm": { "description": "Perform content management activities" }
61 }
62 }
63}
64```
65 
66## Hook Lifecycle
67 
68### OCLIF Hook Execution Order
69 
701. **CLI initialization** → Node process starts
712. **`init` hooks** → Set up global context and utilities (executed once)
723. **Command detection** → OCLIF matches command name to plugin
734. **`prerun` hooks** → Validate state, check auth, prepare for command execution (per command)
745. **Command execution** → Plugin command's `run()` method executes
75 
76### Init Hooks
77 
78Init hooks run once during CLI startup. Use them for expensive setup operations.
79 
80```typescript
81// ✅ GOOD - src/hooks/init/context-init.ts
82// Initialize CLI context that commands depend on
83import { CsdxContext } from '../../utils';
84import { configHandler } from '@contentstack/cli-utilities';
85 
86export default function (opts): void {
87 // Store command ID for session-based log organization
88 if (opts.id) {
89 configHandler.set('currentCommandId', opts.id);
90 }
91 // Make context available to all commands via this.config.context
92 this.config.context = new CsdxContext(opts, this.config);
93}
94```
95 
96### Prerun Hooks
97 
98Prerun hooks run before each command. Use them for validation and state checks.
99 
100```typescript
101// ✅ GOOD - src/hooks/prerun/auth-guard.ts
102// Validate authentication before running protected commands
103 
104import { cliux, isAuthenticated, managementSDKClient } from '@contentstack/cli-utilities';
105 
106export default async function (opts): Promise<void> {
107 const { context: { region = null } = {} } = this.config;
108
109 // Validate region is set (required for all non-region commands)
110 if (opts.Command.id !== 'config:set:region') {
111 if (!region) {
112 cliux.error('No region found, please set a region via config:set:region');
113 this.exit();
114 return;
115 }
116 }
117
118 // Example: Validate auth for protected commands
119 if (isProtectedCommand(opts.Command.id)) {
120 if (!isAuthenticated()) {
121 cliux.error('Please log in to execute this command');
122 this.exit();
123 }
124 }
125}
126```
127 
128### Hook Patterns
129 
130#### Accessing Configuration
131```typescript
132// ✅ GOOD - Access global config in hooks
133export default function (opts): void {
134 const { config } = this; // OCLIF Config object
135 const { context, region } = config; // Custom properties set by other hooks
136}
137```
138 
139#### Async Hooks
140```typescript
141// ✅ GOOD - Async hooks for operations requiring I/O
142export default async function (opts): Promise<void> {
143 const client = await managementSDKClient({ host: this.config.region.cma });
144 const user = await client.getUser();
145 // Hook runs to completion before command starts
146}
147```
148 
149#### Early Exit
150```typescript
151// ✅ GOOD - Exit hook execution when validation fails
152export default function (opts): void {
153 if (!isValid()) {
154 cliux.error('Validation failed');
155 this.exit(); // Stops command from executing
156 return;
157 }
158}
159```
160 
161## Context Object
162 
163The `CsdxContext` class wraps OCLIF config and adds CLI-specific state.
164 
165```typescript
166// ✅ GOOD - Accessing context in commands
167import { CLIConfig } from '../interfaces';
168 
169export default class MyCommand extends Command {
170 async run(): Promise<void> {
171 const config: CLIConfig = this.config;
172 const { context } = config;
173
174 // Available context properties:
175 // - context.id: unique session identifier
176 // - context.user: authenticated user info (authtoken, email)
177 // - context.region: current region configuration
178 // - context.config: regional configuration
179 // - context.plugin: current plugin metadata
180 }
181}
182```
183 
184## Shared Interfaces
185 
186Interfaces in `src/interfaces/index.ts` are exported and consumed by all plugins.
187 
188```typescript
189// ✅ GOOD - Define shared types
190export interface Context {
191 id: string;
192 user: {
193 authtoken: string;
194 email: string;
195 };
196 region: Region;
197 plugin: Plugin;
198 config: any;
199}
200 
201export interface CLIConfig extends Config {
202 context: Context;
203}
204 
205export interface Region {
206 name: string;
207 cma: string; // Content Management API endpoint
208 cda: string; // Content Delivery API endpoint
209}
210```
211 
212## Utilities
213 
214Core utilities in `src/utils/` provide shared functionality.
215 
216```typescript
217// ✅ GOOD - src/utils/context-handler.ts
218// Wrapper around context initialization and access
219export class CsdxContext {
220 constructor(opts: any, config: any) {
221 this.id = opts.id || generateId();
222 this.region = config.region;
223 this.user = extractUserFromToken();
224 }
225}
226 
227// Export utilities for use in hooks and contexts
228export { CsdxContext };
229```
230 
231## Plugin Registration
232 
233Plugins are registered via `oclif.plugins` in `package.json`. Each plugin package must:
234 
2351. **Provide commands** — via `oclif.commands` in its `package.json`
2362. **Be installed** — as a dependency in the core package
2373. **Be listed** — in `oclif.plugins` array for auto-discovery
238 
239```json
240{
241 "dependencies": {
242 "@contentstack/cli-config": "~1.20.0-beta.1",
243 "@contentstack/cli-auth": "~1.8.0-beta.1"
244 },
245 "oclif": {
246 "plugins": [
247 "@contentstack/cli-config",
248 "@contentstack/cli-auth"
249 ]
250 }
251}
252```
253 
254### Plugin Discovery
255 
256OCLIF automatically discovers commands in:
2571. Built-in plugins (`@oclif/plugin-help`, etc.)
2582. Core package commands (none in contentstack core)
2593. Registered plugins (listed in `oclif.plugins`)
260 
261## Differences from Plugin Packages
262 
263| Aspect | Core Package | Plugin Package |
264|--------|--------------|----------------|
265| **OCLIF config** | No `commands` field | Has `oclif.commands: "./lib/commands"` |
266| **Source structure** | `src/hooks/`, `src/interfaces/`, `src/utils/` | `src/commands/`, `src/services/` |
267| **Entry point** | `bin/run.js` | None |
268| **Dependencies** | References all plugins | Depends on `@contentstack/cli-command` |
269| **Execution role** | Aggregates and initializes | Implements business logic |
270 
271## Build Process
272 
273The core package build includes hook compilation and OCLIF manifest generation.
274 
275```bash
276# In package.json scripts
277&quot;build&quot;: &quot;pnpm compile && oclif manifest && oclif readme&quot;
278```
279 
280### Build Steps
281 
2821. **compile** — TypeScript → JavaScript in `lib/`
2832. **oclif manifest** — Generate `oclif.manifest.json` for plugin discovery
2843. **oclif readme** — Generate README with available commands
285 
286### Build Artifacts
287 
288- `lib/` — Compiled hooks, utilities, interfaces
289- `oclif.manifest.json` — Plugin and command registry
290- `bin/run.js` — Executable entry point
291- `README.md` — Generated command documentation
292 
293## Testing Hooks
294 
295Hooks cannot be tested with standard command testing. Test hook behavior by:
296 
2971. **Unit test hook functions** — Import and invoke directly
2982. **Integration test via CLI** — Run commands that trigger hooks
2993. **Mock OCLIF config** — Provide mocked `this.config` object
300 
301```typescript
302// ✅ GOOD - Test hook function directly
303import contextInit from '../src/hooks/init/context-init';
304 
305describe('context-init hook', () => {
306 it('should set context on config', () => {
307 const mockConfig = { context: null };
308 const hookContext = { config: mockConfig };
309 const opts = { id: 'test-command' };
310
311 contextInit.call(hookContext, opts);
312
313 expect(mockConfig.context).to.exist;
314 });
315});
316```
317 
318## Error Handling in Hooks
319 
320Hooks should fail fast and provide clear error messages to users.
321 
322```typescript
323// ✅ GOOD - Clear error messages with user guidance
324export default function (opts): void {
325 if (!isRegionSet()) {
326 cliux.error('No region configured');
327 cliux.print('Run: csdx config:set:region --region us', { color: 'blue' });
328 this.exit();
329 }
330}
331```
332 
333## Best Practices
334 
335### Hook Organization
336- Keep hooks focused on a single concern (validation, initialization, etc.)
337- Use descriptive names that indicate when they run (`prerun-`, `init-`)
338- Initialize dependencies in `init` hooks, not in `prerun` hooks
339 
340### Performance
341- Minimize work in `init` hooks (they run once per CLI session)
342- Cache expensive operations in context for reuse
343- Avoid repeated API calls across hooks
344 
345### Ordering
346- Place hooks that prepare data before hooks that consume it
347- Auth validation (`auth-guard`) should run after region validation
348- Version warnings can run last (non-critical)
349 
350### Context Usage
351- Store computed values in context to avoid recalculation
352- Make context available to all commands via `this.config.context`
353- Document context properties that plugins should expect
354 
355### Plugin Development
356- Ensure plugins depend on `@contentstack/cli-command`, not the core package
357- Commands should extend the shared Command base class
358- Plugins should not modify or depend on core hooks directly
359 

Sections

  • Contentstack Core Package Standards
  • Overview
  • Architecture
  • Entry Point
  • Package Configuration
  • Hook Lifecycle
  • OCLIF Hook Execution Order
  • Init Hooks
  • Prerun Hooks
  • Hook Patterns
  • Context Object
  • Shared Interfaces
  • Utilities
  • Plugin Registration
  • Plugin Discovery
  • Differences from Plugin Packages
  • Build Process
  • In package.json scripts
  • Build Steps
  • Build Artifacts
  • Testing Hooks
  • Error Handling in Hooks
  • Best Practices
  • Hook Organization
  • Performance
  • Ordering
  • Context Usage
  • Plugin Development

What it covers

buildtestcode-stylearchitecturetesting-strategydependenciesperformance

Stack — with the evidence

typescript

(1.00)

eslint

(1.00)

node

(0.95)

javascript

(0.60)

monorepo

(0.60)

pnpm

(0.60)

github-actions

(0.60)

Glob targeting

  • packages/contentstack/src/**/*.ts
  • packages/contentstack/src/**/*.js

Format

Cursor rules

The most expressive format here. Many small .mdc files, each with frontmatter declaring when it should load, so a rule about migrations only enters context when a migration is open. Costs the most to maintain and only one editor reads it.

What the corpus says about it

Repository

Owner
contentstack
Language
—
License
—
Archived
no

All configs in this repo

Also in contentstack/cli

Diff this repo’s formats

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?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
contentstack/cli.cursor/rules/oclif-commands.mdc · 14Cursor rulestypescripteslint+5setupteststylearch74/1003 days ago
contentstack/cli.cursor/rules/testing.mdc · 14Cursor rulestypescripteslint+5setupteststylearch+389/1003 days ago
contentstack/cli.cursor/rules/typescript.mdc · 14Cursor rulestypescripteslint+5stylearchtypessecurity+170/1003 days ago
Diff against .cursor/rules/oclif-commands.mdc Diff against .cursor/rules/testing.mdc Diff against .cursor/rules/typescript.mdc

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126Cursor rulesgobun+5setupbuildtestlint-format+6100/1003 days ago
TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45Cursor rulestypescriptpytest+15testlint-formatstylearch+5100/1003 days ago
markstev/mark-starter.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+14setuptestlint-formatstyle+699/1003 days ago
Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+13setuptestlint-formatstyle+799/1003 days ago
dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+15setuptestlint-formatstyle+799/1003 days ago
deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1Cursor rulestypescriptnextjs+5setuptestlint-formatstyle+799/1003 days ago
TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45Cursor rulestypescriptpytest+15teststyletesting-strategysecurity+397/1003 days ago
langflow-ai/langflow.cursor/rules/docs_development.mdc · 153kCursor rulespythonnode+16setupbuildtestlint-format+797/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack