Skip to main content

rayfin-cli-ux

Mandatory for Rayfin CLI UX work. Load before designing, speccing, implementing, or reviewing CLI commands, flags, output, or errors.

소스 정보

저장소
microsoft/rayfin
최근 소스 활동
2026년 10월 8일 20:46
감지된 SKILL.md 언어
영어
스타
651
포크
71

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
2 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
rayfin-cli-ux
description
Mandatory for Rayfin CLI UX work. Load before designing, speccing, implementing, or reviewing CLI commands, flags, output, or errors.
# Rayfin CLI UX Guidelines Standards for consistent, high-quality CLI experiences in `@microsoft/rayfin-cli`. **Full reference**: [references/cli-ux-guidelines.md](./references/cli-ux-guidelines.md) — load on demand for depth, examples, and rationale. ## Architecture Status These rules define *what* a good CLI experience must deliver — they stay in force regardless of wiring. *How* output is wired is mid-migration to the workflow + adapter architecture ([`docs/rfc/rayfin-tools-architecture.md`](../../../docs/rfc/rayfin-tools-architecture.md), tracked in [`rayfin-tools-architecture-migration.md`](../../../docs/rfc/rayfin-tools-architecture-migration.md)). - **New or migrated commands** use a `common/src/workflows/<name>/` workflow returning a typed `Result<T>`, with a thin Layer-1 Commander wrapper rendering via `Logger`/`Progress` adapters selected from `--output <mode>`. Do **not** import `output-mode.ts`, branch on raw `--json`/`--verbose`, or use `CliHandledError`/`process.exit`. - **Legacy (un-migrated) commands** use `output-mode.ts` (`modeLog`/`emitJson`/`resolveOutputMode`). This machinery is scheduled for removal in Phase 6. - When this skill and the architecture RFC disagree, the RFC wins. ## Constitutional Rules Non-negotiable for every CLI command. Each rule has a stable ID (R1–R12) for cross-referencing. | ID | Rule | One-liner | |----|------|-----------| | R1 | Three output modes | Every command supports `interactive`, `plain`, and `json`. See [reference §1](./references/cli-ux-guidelines.md). | | R2 | No `console.log` | All output goes through mode-aware utilities (or v2 `Logger`/`Progress` adapters). | | R3 | Recovery hints | Every `❌` error includes an indented next-step action. | | R4 | `--force` for destructive ops | Operations risking data loss fail by default; `--force` opts in. | | R5 | Respect non-interactive | No prompts when `--yes`, non-TTY stdin, or `CI=true`. | | R6 | Valid JSON output | `--json` → exactly one JSON object on stdout, no ANSI/emoji. `--verbose` + `--json` → reject with error. | | R7 | Standard flags | `--output <mode>` (canonical), `--json` (shorthand), `-y/--yes`, `--verbose`, `--dry-run`, `--force`, `--env-file <path>`. | | R8 | Clear progress text | Every step uses `ProgressIndicator` with action-oriented text. | | R9 | No credentials/PII | Truncate tokens, use boolean indicators, never log emails/OIDs. | | R10 | `--dry-run` explains | Lists planned ops without mutations; viable previews exit `0`, validation failures exit nonzero. | | R11 | `--help` everywhere | `.description()` on every command/option/argument. See [reference §5](./references/cli-ux-guidelines.md) for canonical descriptions. | | R12 | Semantic exit codes | `0` = success, `1` = error, `2` = cancelled. | ## Decision Shortcuts - "Command or flag?" → Changes **what** = command. Changes **how** = flag. - "`dev` or `up`?" → Local Docker / no auth → `dev`. Authenticated cloud → `up`. - "Child service or connector?" → Owned/deployed with app → `rayfin <service> init`. External → `rayfin connector add`. - "`init` create this?" → Only minimal base app (auth, data, static). Otherwise explicit follow-up command. - "Implicit?" → Only required system actions in `dev`/`up`. User-facing = explicit. ## Common Patterns (keep — action-oriented) ### Standard action handler (legacy path) ```typescript .action(async (cmdOptions) => { const mode = resolveOutputMode({ json: cmdOptions.json }); const interactive = isInteractive({ yes: cmdOptions.yes }); const verbose = createVerboseLogger(cmdOptions.verbose); try { // ...work... if (mode === 'json') { emitJson({ status: 'success', ...result }); } } catch (err) { if (mode === 'json') { emitJsonError(mode, (err as Error).message); } modeError(mode, `❌ ${(err as Error).message}`); modeError(mode, ' <recovery hint>'); throw new CliHandledError(err); } }) ``` ### Error with recovery hint ```typescript modeError(mode, '❌ Project name not found in rayfin.yml configuration'); modeError(mode, " Run 'rayfin init' to create a new project configuration"); throw new CliHandledError(new Error('...')); ``` ### Progress step ```typescript const spinner = showProgress('Deploying configuration', '🔄', mode); try { await doWork(); spinner.succeed('Configuration deployed'); } catch (err) { spinner.fail('Configuration deployment failed'); throw err; } ``` ## Implementing a New Command > **First decide: v2 workflow or legacy path?** New commands target the workflow + adapter architecture (see [migration plan](../../../docs/rfc/rayfin-tools-architecture-migration.md)). > The legacy steps below are for un-migrated commands only. **V2 command** (preferred): orchestration in `common/src/workflows/<name>/`, Commander `.action()` is a thin wrapper that parses → builds deps → calls workflow → renders `Result` via adapters → maps exit code. **Legacy path** (un-migrated commands): 1. Create command file in `packages/tools/cli/src/commands/`. 2. Import utilities from `../utils/output-mode.js`. 3. Add `--json`, `-y/--yes`, `--verbose` options. 4. Add `--dry-run`/`--force` when applicable. 5. Wrap progress in `ProgressIndicator`. 6. Follow the standard action handler skeleton above. 7. Register in parent `index.ts`. ## Reviewing a Command (checklist by rule ID) - [ ] R1 — supports interactive, plain, json modes - [ ] R2 — no bare `console.log` - [ ] R3 — every `❌` has a recovery hint - [ ] R6 — `--json` emits valid JSON only; no ANSI/emoji - [ ] R4 — destructive ops gated on `--force` - [ ] R5 — prompts respect `isInteractive()` - [ ] R8 — progress uses `ProgressIndicator` with action text - [ ] R10 — `--dry-run` lists ops without mutations and uses a semantic exit code - [ ] R9 — no PII in verbose output - [ ] R11 — `--help` descriptions present, canonical wording for standard flags - [ ] R12 — exit codes are semantic - [ ] Spec includes user intent, behavior contract, validation/failures, error wording, examples, cross-cutting impacts ## Command Topology: `dev` vs `up` See [reference §12](./references/cli-ux-guidelines.md) for full rationale and patterns. Key rules: 1. Mirror nouns under both `dev` and `up` when capability exists in both worlds. 2. `dev` = local Docker, offline, single env, lifecycle via flags (`--stop`, `--down`, etc.). 3. `up` = Fabric cloud, requires auth (except inspection), multi-env via subcommands. 4. `dev` never authenticates. Inspection commands (`status`, `list`) never block on auth. 5. `--force` means "allow destructive schema changes" — not "skip prompt" (that's `--yes`). ## Pre-flight Checklist (OpenSpec CLI changes) Every `tasks.md` for a CLI-touching OpenSpec change MUST begin with this block: ```markdown ## Pre-flight - [ ] Loaded `.github/skills/rayfin-cli-ux/SKILL.md`. Cite one rule applied: <ID and restatement>. - [ ] Loaded `.github/skills/rayfin-cli-ux/references/cli-ux-guidelines.md`. Cite one section: <name>. - [ ] Every new/changed command, option, argument has a `.description()` (R11). - [ ] Every `❌` error has a recovery hint (R3). - [ ] All three output modes covered in scenarios (R1). - [ ] Destructive ops gated on `--force` (R4). - [ ] Non-interactive behavior preserved (R5). - [ ] `dev` vs `up` topology rules respected if adding lifecycle commands. ``` ## Final Scan (Guardrails) Before submitting, verify none of the NEVER/ALWAYS rules are violated: - NEVER: bare `console.log` (R2), prompt when non-interactive (R5), partial/multiple JSON (R6), error without recovery (R3), destructive without `--force` (R4), PII in logs (R9), emoji outside interactive (R1), mutating API calls in dry-run (R10), auth in `dev` commands. - ALWAYS: action-oriented progress text (R8), standard flag names (R7), mirror `dev`/`up` nouns, regenerate `.env.local` after lifecycle commands. Dry-run reads require an explicit documented contract. `rayfin up` authenticates and reads workspace metadata so its preview can identify the resolved target; it validates local static inputs first and never runs builds or deployment writes. See reference section 7 for this exception to the otherwise offline dry-run contract.
GitHub에서 보기