Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ cat .cursor/rules/AI-Assistance.mdc
5. **Remove tests without asking** - Always get permission first
6. **NODE_ENV** - To check if the CLI is in test mode, use the `isTestMode()` helper function.
7. **`process.exit`** - When creating a command, use `this.exit()` for consistent test mode handling.
8. **`console.log` / `console.error`** - In commands, always use `this.log()` (stdout) and `this.logToStderr()` (stderr). `console.*` bypasses oclif and can't be captured by tests.

## ✅ Correct Practices

Expand Down Expand Up @@ -204,6 +205,46 @@ If this is part of a workspace, there may be:

But focus on THIS project unless specifically asked about others.

## CLI Output & Flag Conventions

### Output patterns (use helpers from src/utils/output.ts)
- **Progress**: `progress("Attaching to channel: " + resource(name))` — no color on action text, `progress()` appends `...` automatically. Never manually write `"Doing something..."` — always use `progress("Doing something")`.
- **Success**: `success("Message published to channel " + resource(name) + ".")` — green ✓, **must** end with `.` (not `!`). Never use `chalk.green("✓ ...")` directly — always use the `success()` helper.
- **Listening**: `listening("Listening for messages.")` — dim, includes "Press Ctrl+C to exit." Don't combine listening text inside a `success()` call — use a separate `listening()` call.
- **Resource names**: Always `resource(name)` (cyan), never quoted — including in `logCliEvent` messages.
- **Timestamps**: `formatTimestamp(ts)` — dim `[timestamp]` for event streams. Exported as `formatTimestamp` to avoid clashing with local `timestamp` variables.
- **JSON guard**: All human-readable output (progress, success, listening messages) must be wrapped in `if (!this.shouldOutputJson(flags))` so it doesn't pollute `--json` output. Only JSON payloads should be emitted when `--json` is active.

### Additional output patterns (direct chalk, not helpers)
- **Secondary labels**: `chalk.dim("Label:")` — for field names in structured output (e.g., `${chalk.dim("Profile:")} ${value}`)
- **Client IDs**: `chalk.blue(clientId)` — for user/client identifiers in events
- **Event types**: `chalk.yellow(eventType)` — for action/event type labels
- **Warnings**: `chalk.yellow("Warning: ...")` — for non-fatal warnings
- **Errors**: Use `this.error()` (oclif standard) for fatal errors, not `this.log(chalk.red(...))`
- **No app error**: `'No app specified. Use --app flag or select an app with "ably apps switch"'`

### Help output theme
Help colors are configured via `package.json > oclif.theme` (oclif's built-in theme system). The custom help class in `src/help.ts` also applies colors to COMMANDS sections it builds manually. Color scheme:
- **Commands/bin/topics**: cyan — primary actionable items
- **Flags/args**: whiteBright — bright but secondary to commands
- **Section headers**: bold — USAGE, FLAGS, COMMANDS, etc.
- **Command summaries**: whiteBright — descriptions in command listings
- **Defaults/options**: yellow — `[default: N]`, `<options: ...>`
- **Required flags**: red — `(required)` marker
- **`$` prompt**: green — shell prompt in examples/usage
- **Flag separator**: dim — comma between `-c, --count`

When adding COMMANDS sections in `src/help.ts`, use `chalk.bold()` for headers, `chalk.cyan()` for command names, and `chalk.whiteBright()` for descriptions to stay consistent.

### Flag conventions
- All flags kebab-case: `--my-flag` (never camelCase)
- `--app`: `"The app ID or name (defaults to current app)"` (for commands with `resolveAppId`), `"The app ID (defaults to current app)"` (for commands without)
- `--limit`: `"Maximum number of results to return (default: N)"`
- `--duration`: `"Automatically exit after N seconds (0 = run indefinitely)"`, alias `-D`
- `--rewind`: `"Number of messages to rewind when subscribing (default: 0)"`
- Channels use "publish", Rooms use "send" (matches SDK terminology)
- Command descriptions: imperative mood, sentence case, no trailing period (e.g., `"Subscribe to presence events on a channel"`)

## ✓ Before Marking Complete

- [ ] `pnpm prepare` succeeds
Expand Down
26 changes: 26 additions & 0 deletions .cursor/rules/AI-Assistance.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,32 @@ This document provides guidance for AI assistants working with the Ably CLI code
const url = `https://${controlHost}/v1/apps`
```

## CLI Output & Flag Conventions

### Output patterns (use helpers from src/utils/output.ts)
- **Progress**: `progress("Attaching to channel: " + resource(name))` — no color on action text, ends with `...`
- **Success**: `success("Message published to channel " + resource(name) + ".")` — green ✓, ends with `.`
- **Listening**: `listening("Listening for messages.")` — dim, includes "Press Ctrl+C to exit."
- **Resource names**: Always `resource(name)` (cyan), never quoted
- **Timestamps**: `formatTimestamp(ts)` — dim `[timestamp]` for event streams. Import as `formatTimestamp` to avoid clashing with local `timestamp` variables.

### Additional output patterns (direct chalk, not helpers)
- **Secondary labels**: `chalk.dim("Label:")` — for field names in structured output (e.g., `${chalk.dim("Profile:")} ${value}`)
- **Client IDs**: `chalk.blue(clientId)` — for user/client identifiers in events
- **Event types**: `chalk.yellow(eventType)` — for action/event type labels
- **Warnings**: `chalk.yellow("Warning: ...")` — for non-fatal warnings
- **Errors**: Use `this.error()` (oclif standard) for fatal errors, not `this.log(chalk.red(...))`
- **No app error**: `'No app specified. Use --app flag or select an app with "ably apps switch"'`

### Flag conventions
- All flags kebab-case: `--my-flag` (never camelCase)
- `--app`: `"The app ID or name (defaults to current app)"` (for commands with `resolveAppId`), `"The app ID (defaults to current app)"` (for commands without)
- `--limit`: `"Maximum number of results to return (default: N)"`
- `--duration`: `"Automatically exit after N seconds (0 = run indefinitely)"`, alias `-D`
- `--rewind`: `"Number of messages to rewind when subscribing (default: 0)"`
- Channels use "publish", Rooms use "send" (matches SDK terminology)
- Command descriptions: imperative mood, sentence case, no trailing period (e.g., `"Subscribe to presence events on a channel"`)

## Effective Testing

1. **Mocking Ably SDK Example**:
Expand Down
Loading
Loading