Omniscio documentation
Browse all documentation
  1. Getting Started13
  2. Sessions & Agents115
  3. Inbox & Notifications59
  4. Projects & Tasks95
  5. Automation & Scheduling75
  6. Knowledge & Memory26
  7. AI Features60
  8. Integrations100
  9. Plugins & Marketplace33
  10. Cloud & Teams56
  11. Settings & Customization58
  12. Account & Billing28
  13. Troubleshooting84
  14. CLI & API Reference22
  15. Legal & Policies4
  16. Uncategorised22

CLI Feedback Submission (file bugs / feature requests from external AI)

How to file a bug, feature request, feedback or question from an outside AI: the in-app Send Feedback button and the local HTTP route that mirrors it, what each response code means, how diagnostics get collected, and the rules an agent should follow so a report is actually useful to the developer reading it.

What it is

Omniscio has a bug-icon toolbar button ("Send Feedback") that opens a small dialog where you pick a category — Bug, Feature, Feedback, or Question — type a description, optionally drop in screenshots, and optionally leave a contact email — leave it blank and Omniscio fills it in from the account you are signed in with, so a report always carries an address the developer can reply to. Hitting "Send Bug Report" / "Send Feature Request" / etc. runs the payload through the shared report-delivery chain (report-delivery.ts), which sends to Resend (an email to the Omniscio developer) and/or Firestore (the developer's bug-report database) according to the bugReportTransport setting (default both). Both stop when the user turns off Email bug reports & feedback (RT-F024): nothing leaves the computer, and the report is kept locally and re-sent automatically once the switch is back on (or once the failing leg recovers) — no resend needed from you. Device / version diagnostics (app version, Electron version, OS, arch, Node version, current active-session count, status breakdown, recent error log lines, a recent-crashes summary from the last 48h — crash-signature log lines + crash-evidence files, scrubbed and bounded, shown only when the app has actually crashed, see recent-crashes-contract.md, process uptime) are auto-collected and attached so the report is actionable without follow-up. The report counts as delivered if any leg succeeds — email or Firestore alone; only if every leg fails is it kept in the <userData>/bug-reports/ outbox, so it is never silently lost, and the hourly outbox drain retries it later automatically.

That same flow is now reachable over the 127.0.0.1:19519 localhost HTTP control server — POST /feedback — so an external AI agent (Claude Code in another project, ChatGPT with the omniscio-control skill, a curl script, the in-app sandboxed Claude session) holding the Omniscio bearer token can file a bug report on the user's behalf without piping the form through the renderer.

Where to find it

The way in is a bug icon in the app's toolbar — the Send Feedback button — which opens a small dialog where you choose a category, write the description, and optionally attach screenshots. There is no sidebar entry and no settings page for this; the button is the whole surface. The rest of this page describes how to reach the same flow without touching the interface at all, which is only useful if you are an AI agent or writing a script.

How it behaves

Sending feedback is a single one-shot action: pick a category, write the description, attach anything useful, and press send. Nothing is saved as a draft and nothing is queued for later on your end — the report goes out on the spot. If every leg rejects it, Omniscio keeps it in a local outbox rather than silently losing it, and an hourly background drain retries it automatically — you do not need to send it again. Because the destination is the developer's inbox rather than your own data, the send is not put behind an approval prompt the way a destructive action would be.

For agents

How to use it

Method Path Approval-gated? Status Purpose
POST /feedback No 200 OK Submit a bug / feature / feedback / question — runs the shared report-delivery chain (email, Firestore) immediately. Mirrors the bug-icon UI.
POST /feedback/with-video No 200 OK The same report with ONE full-length video attached by share link — see below.

Gating model. Apply-immediately (NOT approval-gated). Trade-off the user explicitly chose on 2026-05-11: the "file this bug for me" flow needs to be fast, and the receiving inbox is the developer's, not a destructive operation on the user's data. The shared 10-mutations-per-minute rate-limit bucket caps blast radius if a session goes off the rails.

Auth. Standard CLI bearer token in Authorization: Bearer <token> (or ?token=<token> query param). The dispatcher returns 401 Unauthorized on missing/invalid token before the route handler runs — no body validation happens for unauthenticated requests. A spawned agent's scoped agent-session token is also admitted here (both routes opt into it), so an agent can file a report with the $AMC_CLI_TOKEN it already holds rather than reading the full-trust token. That is a deliberate widening — the receiving inbox is the developer's, and recipients are chosen server-side, so a leaked agent token can at most mail the developer.

Body size. POST /feedback accepts a request body up to ~8.5 MB, so the schema's own 8 MB combined attachment budget actually fits through the transport. (The cap is derived from that schema budget and kept under the cloud relay's 10 MB ceiling; it used to inherit the server's 1 MB default, ~8× tighter than the schema it carried.) POST /feedback/with-video sends only a path or an id, so it stays under the 1 MB default.

Body schema — mirrors the in-app feedbackSendSchema exactly so a fixture from the IPC transport works on the CLI transport:

{
  "type": "bug" | "feature" | "feedback" | "question",
  "message": "string, 1–10000 chars, required",
  "email": "user@example.com (optional — omit it and the signed-in account email is used; valid RFC email or empty string)",
  "screenshots": [ /* optional, max 5 attachments */ ],
  "diagnostics": { /* optional — server auto-collects if omitted */ }
}

Diagnostics auto-collection. If the caller omits the diagnostics field, the server collects them itself (collectDiagnostics() — the same call the in-app dialog makes when you click the bug icon) and attaches them to the outgoing email. The receiving inbox always has device/version context regardless of whether the agent took the trouble to gather it. Caller-supplied diagnostics win — if the field is present, no server-side collection happens, so an agent that wants to override (e.g. include a custom recentErrors filter) can.

Response shape.

  • 200 OK → { "ok": true, "correlationId": "<uuid>", "delivered": ["email"] } — delivered names the ONE leg that confirmed delivery ("email" or "firestore"). With both email and Firestore on, the email goes out in the background and is not named here.
  • 400 Bad Request → { "ok": false, "error": "<field>: <reason>; …" } — validation failed (missing/empty message, unknown type, malformed email, message over 10000 chars, etc.).
  • 401 Unauthorized → { "ok": false, "error": "unauthorized" } — missing or wrong bearer token (dispatcher-level gate).
  • 429 Too Many Requests → { "ok": false, "error": "Rate limit exceeded (10 mutations/minute)" } — rolling 60-second mutation cap hit.
  • 202 Accepted → { "ok": false, "queued": true, "correlationId": "<uuid>", "error": "<message>" } — every leg failed, or sending is turned off, but the report was safely kept on this computer. The hourly outbox drain retries it automatically, so the agent should NOT resend — the error text says sending is off when that is why it was kept, otherwise it is the generic "saved locally and will retry" copy. A repeated X-Client-Request-Id replays this exact 202 rather than queuing a second copy.
  • 502 Bad Gateway → { "ok": false, "queued": false, "error": "Feedback could not be delivered or saved. Please retry." } — the report could neither be sent NOR saved (every leg failed AND the local write also failed) — genuinely lost. Not cacheable, so a retried request re-attempts for real.

Examples

# Read the bearer token from Omniscio's auto-delivered file
TOKEN=$(<~/.amc/cli-token)

# 1. Minimal bug report — server auto-attaches diagnostics
curl -X POST http://127.0.0.1:19519/feedback \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "bug",
    "message": "After archiving a session via middle-click, the sidebar list does not refresh until I press F5."
  }'
# Returns: { "ok": true }

# 2. Feature request with a contact email
curl -X POST http://127.0.0.1:19519/feedback \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "feature",
    "message": "It would be useful to filter the inbox by tag.",
    "email": "user@example.com"
  }'

# 3. Question (no contact email, agent-collected diagnostics)
curl -X POST http://127.0.0.1:19519/feedback \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "question",
    "message": "How do I rebind Ctrl+T to skip blank-session reuse?"
  }'

Attaching a full-length video

POST /feedback/with-video files the same report with one video attached. The video does not travel inside the request — Omniscio publishes it as a never-expiring video share and appends the link to the report body, so both delivery legs carry it and a multi-minute recording attaches fine even though it is far larger than any attachment limit. The upload runs inside the request and gets about four minutes; a video too large to upload in that time is refused with 502 (the error says it ran out of time), and nothing is published or filed.

Name the video exactly one of two ways. Sending both, or neither, is a 400:

Field Use it for
recordingId A recording already in the Omniscio library (e.g. one the user just made). Resolved server-side from the library row, so no caller-supplied path at all.
videoPath A video file on this machine. A scoped token may only read inside the share allow-list — an active session workdir, ~/Claude, or <userData>/published-pastes (the refusal names the exact roots).

videoTitle is optional and labels the share. The recording must be type video and finished baking — a screenshot snip, or a recording still transcoding, is refused rather than published as a broken link.

TOKEN=$(<~/.amc/cli-token)

curl -X POST http://127.0.0.1:19519/feedback/with-video \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "type": "bug", "message": "<what the user said>", "recordingId": "<library id>" }'

Read the response. On success it carries videoShareUrl (now in the report) and videoShareToken — the only handle for taking the share down, since it never expires. Tell the user they can revoke it with that token.

A refused publish files NOTHING. The whole request fails so the user is never told they sent evidence they did not. Fix the cause and send again rather than silently falling back to the text-only route.

With sending turned off, nothing is published. If the user has turned off Email bug reports & feedback, the route answers 403 before publishing: the recording is never made public and nothing is filed. A public share is one more way a report leaves the computer, so the same switch governs it.

Route-specific outcomes beyond the shared ones: 400 when the recording is not a finished video, the path is outside the allow-list (outside-allowlist, with roots), or both/neither source is given; 422 when the app is signed out (the caller authenticated fine — the app's state is wrong); 500 when something failed after the share was published, in which case the token is still returned so the orphan stays revocable.

Guidance for agents

  • Use the bug-icon flow only when the user has explicitly said "file a bug" / "send feedback" / "report this to the developer." Agents should not file unsolicited bug reports — every send is a real email to the developer's inbox.
  • Quote the user's own description in message verbatim when possible. Resist paraphrasing or "improving" what the user said — the developer needs the raw words to diagnose.
  • Default to type: "bug" for problem reports, "feature" for "it would be nice if…", "feedback" for general opinions about the app, "question" for "how do I…".
  • Do NOT include the bearer token, the user's API keys, or credentials in the message field. Diagnostics are scrubbed by collectDiagnostics() — the message field is not.
  • The screenshots array maxes at 5 attachments, together at most about 6 MB of real file (the schema caps their base64 at 8 MB combined); the in-app dialog refuses a file that would go over that before you press Send. If you're submitting from a script, encode as base64 dataURL per the in-app pattern; if you don't have screenshots, omit the field entirely.

Related

The two neighbours most worth knowing are where Omniscio's own logs live, which is usually the first thing to consult before filing anything, and the startup trace you can paste into a slow-startup report. Both are named in the list below. The page also sits within the wider CLI surface, so if what you want is to drive Omniscio over HTTP generally rather than just file a report, start from CLI control.

Boundary with bug-report-intake

This page covers the outbound "send a bug to the Omniscio developer" path — exposed at POST /feedback, dispatched via the shared report-delivery chain (email, Firestore), no per-project routing.

The inbound "tester emails a bug to MY project's intake address" path (subject [BUG: <slug>] <title>, parsed and routed to the matching project's Claude session) is a separate feature documented at bug-report-intake.md. The two share no code and do not interact.

See also

  • logs-and-debugging.md — where Omniscio's local logs live; useful to consult before filing a bug
  • startup-trace.md — the self-contained startup.log you can paste into the bug body for slow-startup reports
  • .claude/memory/cli-server-gating.md — full CLI endpoint gating reference
  • tests/unit/cli-server-feedback.test.ts — 43 cases across /feedback and /feedback/bug-report covering auth gating, validation, happy path, diagnostics auto-attach + caller-supplied preservation, delivery outcomes (200 delivered / 202 kept-and-queued / 502 genuinely lost), the kept-202's sending-off-vs-will-retry error text, X-Client-Request-Id replay (delivered AND kept), concurrent-duplicate coalescing, and rate-limit
  • tests/unit/services/cli-feedback-routes.test.ts — the body cap (a >1 MB attachment is accepted; over the cap still 413s), and the video route's promises: the link reaches the delivered message, a refused publish files nothing, a screenshot is refused, the share token comes back even when a later step throws, a retry never publishes twice, and an agent token is both admitted and confined
  • .claude/memory/contracts/feedback-video-attachment-contract.md — the binding contract for the video route

Last verified 2026-09-28