feat(cli): add feedback, the anonymous CLI feedback command#119
Conversation
Top-level command that posts a message to the CLI team's feedback service: anonymous by default, --email opts into being contactable, and every submission carries only non-PII context (CLI version, node version, OS platform/arch). No auth, workspace, project, or prompts. Validation failures are usage errors before any network call; delivery failures (unreachable, 3s timeout, non-2xx) fail with FEEDBACK_SEND_FAILED and surface the service's error detail. PRISMA_CLI_FEEDBACK_URL overrides the endpoint for tests and staging.
WalkthroughAdds a new top-level 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/product/command-spec.md`:
- Line 443: Update the `prisma-cli feedback` command synopsis in the command
specification to wrap `--email <email>` in brackets, documenting it as optional
while preserving the required message argument.
In `@packages/cli/src/controllers/feedback.ts`:
- Around line 94-108: Update the feedback request flow around the AbortSignal
passed to the request to use a manual AbortController with a timer for
FEEDBACK_TIMEOUT_MS instead of AbortSignal.any(). Ensure the timer aborts the
controller when the timeout expires, preserve propagation of
context.runtime.signal cancellation, and clear the timer after the request
completes so timeout errors still produce the existing TimeoutError detail.
In `@packages/cli/tests/feedback.test.ts`:
- Around line 112-124: Add a feedback CLI test alongside the existing
empty-message test that submits a message exceeding MAX_MESSAGE_LENGTH, asserts
a USAGE_ERROR with exit code 2, and verifies no request is sent to the feedback
service. Reuse the existing startFeedbackService and runFeedbackCli helpers.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: cbe37086-462b-45f7-b124-3620dc5d8578
📒 Files selected for processing (9)
docs/product/command-spec.mdpackages/cli/src/cli.tspackages/cli/src/commands/feedback/index.tspackages/cli/src/controllers/feedback.tspackages/cli/src/presenters/feedback.tspackages/cli/src/shell/command-meta.tspackages/cli/src/types/feedback.tspackages/cli/tests/database.test.tspackages/cli/tests/feedback.test.ts
Do not treat a stalled or cancelled response-body read as success: only a fully received non-JSON body maps to a null id; timeouts map to FEEDBACK_SEND_FAILED and runtime cancellation propagates. Mirror the service's 320-character email limit locally. Disclose the attached context in the command help, and state in the spec that the service uses the client IP transiently for rate limiting and never stores it. Register feedback in the Global Rules top-level list, the output pattern mapping, and the MVP error-code registry.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/product/error-conventions.md`:
- Line 162: Add a one-line “Recommended meaning” entry for FEEDBACK_SEND_FAILED
in the MVP error-code list, matching the format and placement used by
USAGE_ERROR, AUTH_REQUIRED, and the other codes. Describe the
feedback-submission failure without changing the code name or surrounding
entries.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: c1382b71-5ebd-40bb-ad7f-877564322bd6
📒 Files selected for processing (6)
docs/product/command-spec.mddocs/product/error-conventions.mddocs/product/output-conventions.mdpackages/cli/src/controllers/feedback.tspackages/cli/src/shell/command-meta.tspackages/cli/tests/feedback.test.ts
Crashes no longer break the --json contract: the outermost boundary emits a standard UNEXPECTED_ERROR envelope whose nextActions carries a recover run-command pre-filled with the failing command and error line (prisma-cli feedback "..."). Human crash output ends with the same hint, suppressed by --quiet. Expected failures and usage errors never advertise feedback.
|
@coderabbitai approve |
✅ Action performedComments resolved and changes approved. |
What this adds
prisma-cli feedbacksends a message to the Prisma CLI team. It is a top-level command likeversion: it needs no auth, no workspace, no project, no config, and it never prompts, so it works identically for humans, CI, and agents.Anonymous by default
Without
--email, nothing identifying leaves the machine. This is the entire wire payload:{ "message": "loving the new deploy flow", "meta": { "cliVersion": "3.0.0-development", "nodeVersion": "v24.18.0", "platform": "darwin", "arch": "arm64" } }The command help discloses exactly that list ("Anonymous unless --email is passed. Every submission includes the CLI version, node version, and OS platform/arch, and nothing else."). The service uses the client IP transiently, in memory, to rate limit; it is never stored, and the spec says so.
--emailis the only way to become contactable, validated before anything is sent (shape and the service's 320-char limit):Agent output
--jsonreturns the standard envelope;idis the service's stored submission id (null when the response has none),emailis null when anonymous:{ "ok": true, "command": "feedback", "result": { "id": "fb_...", "email": null, "context": { "cliVersion": "...", "nodeVersion": "...", "platform": "...", "arch": "..." } } }Failure behavior
Validation happens before any network call and exits 2 as
USAGE_ERROR: empty or whitespace-only message, message over 4000 characters, email invalid or over 320 characters. Nothing is sent in those cases.Delivery problems exit 1 as
FEEDBACK_SEND_FAILEDand surface the service's own detail:Requests time out after 3 seconds, and the timeout covers the body read too: a 201 whose body stalls is a delivery failure, not a fake success, and user cancellation propagates instead of exiting 0. Only a fully received non-JSON 2xx body maps to a null id.
PRISMA_CLI_FEEDBACK_URLoverrides the endpoint for tests and staging.Crashes point here (and stop breaking --json)
Unexpected crashes previously wrote plain text even under
--json. The outermost boundary now emits the standard envelope with codeUNEXPECTED_ERROR, and both output modes advertise the feedback command pre-filled with the failing command and error line:{ "ok": false, "command": "project.list", "error": { "code": "UNEXPECTED_ERROR", "domain": "cli", "why": "ENOENT: ..." }, "nextSteps": ["prisma-cli feedback 'project list crashed: ENOENT: ...'"], "nextActions": [ { "kind": "run-command", "journey": "recover", "label": "Report this crash to the Prisma team", "command": "prisma-cli feedback 'project list crashed: ENOENT: ...'" } ] }--quietsuppresses the human hint. Usage errors and expected failures never advertise feedback, so the pointer stays a signal rather than wallpaper. The pre-filled command is shell-escaped and runnable verbatim; a companion PR (prisma/skills#21) teaches the prisma-compute skill to run it.Where feedback goes
A small Bun server on Prisma Compute in the Prisma DevRel workspace, storing to Prisma Postgres (repo:
~/dev/work/prisma-cli-feedback, appcli-feedback), with the same limits enforced server-side plus per-IP rate limiting and a token-gated admin read endpoint.Docs (spec-first)
command-spec.md:feedbacksection, top-level command lists (Scope and Global Rules), privacy wording including IP handling, crash-pointer bullet.error-conventions.md:FEEDBACK_SEND_FAILEDandUNEXPECTED_ERRORregistered with recommended meanings; crash-boundary rule updated.output-conventions.md:feedbackadded to the pattern mapping.Testing
tests/feedback.test.ts: 10 tests against a real local HTTP server: anonymous payload shape, email inclusion, empty/oversized message, invalid and over-long email (nothing sent in each case), service 5xx, unreachable service, stalled 2xx body (fails at 3s), null id.tests/shell.test.ts: crash-boundary tests for the feedback hint, command labeling, pre-filled report escaping, and theUNEXPECTED_ERRORJSON envelope with itsrecoveraction.