TypeScript CLI application built with oclif framework for DevCycle feature flag management.
- CLI Binary:
bin/run- Main CLI entry point - MCP Server:
dist/mcp/index.js- Model Context Protocol server - Source Root:
src/index.ts- TypeScript entry point
src/commands/- All CLI commands organized by featuresrc/api/- API client code and schemassrc/auth/- Auth handling (API keys, SSO, tokens)src/ui/- Interactive prompts and output formattingsrc/utils/- Shared utilities and helperssrc/mcp/- Model Context Protocol implementation
- Uses Yarn with workspaces
- Always use
yarnnotnpm
- Defer all formatting to Prettier for supported file types (JavaScript, TypeScript, JSON, Markdown, etc.)
- Follow Conventional Commits specification:
<type>: <description>(scopes rarely used) - Valid types:
feat,fix,docs,style,refactor,perf,test,build,ci,chore,revert - Description should be imperative mood, lowercase, single sentence
- Examples:
feat: add support for multi-threaded tests,fix: correct response for invalid input
- Use Aviator CLI (
av) for managing stacked branches:av branch chore-fix-invalid-input - Sync and push changes:
av sync --push=yes - Create PR:
av pr --title "<title>" --body "<body>"- Title follows Conventional Commits, body uses markdown/bullets
av prwill push the branch
- GitHub PR descriptions should be short and focus on why changes were made, not what changed, limit describing files and tests changed.
- Use camelCase for files, folders, and variables (starting with lowercase)
- PascalCase for classes and interfaces
- SCREAMING_SNAKE_CASE for constants
- kebab-case for CLI flags and file names
- Never use
anycasting to fix TypeScript errors - Fix root cause: update type definitions, use type guards, add missing properties, use union types
- Use
unknowninstead ofanywhen type is genuinely unknown - Prefer type narrowing over type assertions
- Always use async/await over Promises
- Handle errors with try/catch
- Throw descriptive errors with clear messages
- Use Zod for runtime validation
- Validate user inputs before API calls
- Provide clear validation error messages
src/api/apiClient.ts- Axios-based HTTP clientsrc/api/zodClient.ts- Type-safe API clientsrc/api/schemas.ts- Generated TypeScript types from OpenAPI spec
- All API functions are async and return typed responses
- Pass
authTokenas parameter; useAuthorization: Bearer ${token}header - Use axios interceptors for global error handling
- Validate responses with Zod schemas
- Use consistent parameter naming (projectKey, featureKey, etc.)
- Support pagination where applicable
All commands extend src/commands/base.ts which provides:
- Authentication handling:
authRequired,authSuggested,userAuthRequired - Configuration management:
userConfig,repoConfig - Common flags:
--project,--headless,--client-id,--client-secret - Parameter validation:
populateParameters()andpopulateParametersWithZod()
features/- Feature flag managementvariables/- Variable managementtargeting/- Targeting rule managementprojects/- Project managementorganizations/- Organization managementauth/- Authentication commands
- Use
this.writerfor user-facing output - Use
this.tableOutputfor tabular data - Support
--headlessflag for machine-readable JSON output - Handle interactive prompts with fallbacks for headless mode
src/ui/writer.ts- Output formatting and user messagessrc/ui/prompts/- Interactive user inputsrc/ui/tableOutput.ts- Tabular data display
Use promptFor() from src/ui/prompts for user input:
type: 'input'- Text inputtype: 'list'- Selection from choicestype: 'autocomplete'- Searchable selection
Check flags.headless to output machine-readable JSON instead of interactive prompts
- Test runner: Vitest
- CLI testing: @oclif/test utilities
- HTTP mocking: nock for API mocking
- Custom wrapper:
test-utils/dvcTest.ts
Use dvcTest() wrapper with chained methods:
.nock(BASE_URL, (api) => ...)- Mock API calls.stdout()/.stderr()- Capture output.command([...])- Run command with args.it('description', (ctx) => ...)- Test assertion
- Create reusable mock objects with realistic data structures
- Store snapshots in
__snapshots__/directories - Update with
yarn test:update-snapshots - Group related tests in
describeblocks - Test both success and error cases
MCP tools without parameters should use empty properties in inputSchema (not dummy parameters) and pass null to executeWithLogging().