Sketch companion for Codex with a canvas and voice based desing edits
SaferSkills independently audited Canvax (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use this skill when the user wants to collaborate visually instead of describing the design only with text. Canvax is for UI/UX, product flows, book spreads, storyboards, comic pages, posters, image composition, visual assets, and other sketch-driven design tasks.
This skill is the Codex-side wrapper for the local Canvax board. In practice:
./canvax is the local command that runs the board/canvax is the preferred command-style slash entry inside Codex. It should target the full Canvax board inside the Codex app's in-app browser when available.$canvax is the direct skill invocation fallback. Use it when the slash entry is not available; it should follow the same handoff.From the repo root:
./canvax --open-codex when the user invokes /canvax; it starts or reuses the local service and then uses macOS UI automation to activate Codex Desktop, run View > Open Browser Tab, focus the browser address bar, and load http://localhost:3210/.View > Open Browser Tab../canvax --close-codex when the user asks to close Canvax inside Codex. This toggles the Codex browser panel through the same documented shortcut. It is best-effort because Codex exposes a browser-panel toggle shortcut, not a documented close-browser API for skills../canvax when you only need to start or reuse the service without driving the Codex UI; the full board is available at http://localhost:3210.http://localhost:3210/ surface uses the full board. The optional ?host=codex-sidecar surface uses the same live board state and exports, but starts in a compact Workbench surface that is still being refined for narrow embedded panels../canvax --open-external or ./canvax --open only when the user explicitly wants the board opened in the default system browser../canvax --chrome only when the user explicitly wants Google Chrome../canvax --status to reuse the existing board URL instead of starting another port.Treat ./canvax as an attach command, not a fresh launch every time:
--restart.After /canvax or $canvax is invoked in a thread, assume that thread is attached to the live canvas and use the latest Canvax export automatically until the user switches context. Prefer /canvax in user-facing docs because it is the command-like entry point users expect in Codex.
If the user says "open Canvax", "use /canvax", or "make Canvax available here", the expected behavior is:
./canvax --open-codexhttp://localhost:3210/exports/canvax-checkpoint-latest.json and exports/canvax-live-latest.json for that threadIf the helper fails, say that macOS Accessibility permission is needed for click/keystroke automation, then provide the clickable board URL. Do not claim that Codex exposes a documented native skill API for closing or navigating the browser pane.
If the user says "open in Chrome", "external browser", or "outside Codex", use the explicit external flags instead.
Canvax now has Workbench as the simple path:
Make real generation passBuild code / Build with Codex, which saves a Codex-readable implementation request and now immediately binds a local no-API preview plus implementation starter bundle through the output manifestTalk after picking a target so spoken or pasted intent is bound to the outlined artifact, exported as target voice, and carried into rewrite/patch contextImage pack with normalized coordinates and an HTML/CSS placement scaffold for host-side image generationApply to Codex freezes the frame, writes a focus-apply checkpoint, and runs the local no-API rewrite executor so the attached output can refresh from the latest sketch/voice/correction contextWhen the user says they used Workbench, prefer the latest checkpoint over older advanced-board context because it represents the specific sketch + voice + output-correction edit they meant Codex to act on.
If the repo root contains DESIGN.md, treat it as the reusable design contract for Canvax. It is exposed through the service and included in task/image prompt packs, so use it before inventing visual style from scratch.
If the user wants Canvax to create that design contract, tell them to use Create DESIGN.md in Advanced mode. It generates a starter file from board mood, palette, labels, frame notes, and generation direction, and it does not overwrite an existing file.
If the user asks about microphone integration, be precise: the local board can use browser speech recognition or pasted macOS/Codex dictation. It cannot directly read the Codex chat microphone stream unless Canvax becomes a native Codex client surface or gains a first-party transcript bridge.
This repo now includes that practical transcript bridge. When /canvax is active and the user speaks design intent into the Codex chat instead of into the Canvax page, queue the transcript into Canvax with:
./canvax --transcript "spoken user text" --scope frameUse --scope session when the spoken instruction applies to the whole board. Use --frame <id> when a host bridge has an explicit frame target. The board imports queued transcript entries into its voice notes through preview-state polling, and Codex should also read exports/canvax-transcript-bridge.json if the board has not imported it yet.
If the user asks how this becomes native to ChatGPT/Codex, use docs/CHATGPT_APP_BRIDGE.md as the boundary. The local skill remains the current working path; npm run host-handoff -- --json gives Codex one no-API packet with the active frame, sketch, voice intent, rewrite queue, output binding, project-link, image host context, source files, and next actions. npm run mcp exposes the same packet through get_host_handoff, plus create_task_pack, create_image_prompt_pack, local MCP read tools, append_transcript for host transcript text, publish_codex_output for manifest publishing, and attach_generated_asset for no-API hosted-image returns, while future host bridges would still be needed for native image invocation and embedded UI. Do not claim that localhost Canvax can directly control ChatGPT, invoke ChatGPT Images, or read raw Codex microphone audio without that host bridge.
Prefer these files when they exist:
exports/canvax-live-latest.jsonexports/canvax-live-latest.mdexports/canvax-project-registry-latest.jsonexports/canvax-project-registry-latest.mdexports/canvax-voice-latest.mdexports/canvax-task-pack-latest.jsonexports/canvax-task-pack-latest.mdexports/canvax-rewrite-request-latest.jsonexports/canvax-rewrite-request-latest.mdexports/canvax-image-prompt-pack-latest.jsonexports/canvax-image-prompt-pack-latest.mdexports/canvax-asset-candidates-latest.jsonexports/canvax-asset-candidates-latest.mdexports/canvax-image-generation-brief-latest.jsonexports/canvax-image-generation-brief-latest.mdexports/canvax-image-host-task-latest.jsonexports/canvax-image-host-task-latest.mdexports/canvax-image-results-latest.jsonexports/canvax-image-results-latest.mdexports/canvax-transcript-bridge.jsonexports/canvax-transcript-bridge-latest.mdexports/canvax-host-handoff-latest.jsonexports/canvax-host-handoff-latest.mdexports/canvax-checkpoint-latest.jsonexports/canvax-preview-manifest.jsonartifacts/canvax/codex-output.jsonexports/canvax-storyboard-latest.jsonexports/canvax-storyboard-latest.mdThe live JSON export is the primary source because it includes frame metadata and the saved image paths.
When multiple local Canvax projects exist, keep using exports/canvax-live-latest.json for the active chat unless the user asks for a specific project. The file-backed project registry points to each project's latest handoff under exports/projects/<project-id>/. Codex output published through scripts/write-codex-output.mjs also mirrors to exports/projects/<project-id>/canvax-codex-output-latest.{json,md} when the active live export contains project metadata.
The task pack and image prompt pack may include actionMode, hostLane, and designContext. Use those fields to decide whether the user is asking for implementation, refinement, specs, image prompting, or variations, and to avoid promising native host features that the current local board does not expose.
If the user says they marked corrections, changed a generated output, or wants Codex to refresh an existing output from the latest sketch/voice, read exports/canvax-rewrite-request-latest.json after the live export. In Workbench, Apply to Codex already calls the local executor through /api/execute-rewrite-request. For a deterministic terminal refresh, run:
npm run execute-rewriteThat writes a refreshed frame-bound preview artifact under artifacts/preview/codex-rewrite/frames/... and publishes the standard Codex output manifest. It is local and does not require an API key.
If the user asks for image generation, illustration, poster composition, book spreads, or "where should the image model place things", read exports/canvax-image-prompt-pack-latest.json or .md after the live export. This pack is no-API by design: it gives Codex/ChatGPT host capabilities the prompt, coordinates, safe zones, and HTML/CSS placement scaffold without requiring Canvax to call a paid API.
When host image generation is available in the current chat/client, use exports/canvax-image-host-task-latest.json as the execution checklist, or ask the user to press Copy host task on a specific asset candidate card. It turns each candidate into a hosted-image task with prompt, placement contract, output slot, return instructions, and acceptance criteria. Use the image prompt pack, asset candidate pack, and image generation brief as supporting context, then attach the resulting file back through Canvax as an editable image element or asset candidate choice. When host image generation is not available, still produce the prompt pack and placement map; do not introduce an OPENAI_API_KEY requirement.
If a hosted image result already exists as a local file, URL, or data image, prefer importing it through npm run import-image-results -- --candidate <candidate-id> --slot <slot-id> --image <path-or-url>. That writes exports/canvax-image-results-latest.* and updates the matching asset candidate slot unless --no-update-candidates is passed. This is the no-API return path for ChatGPT/Codex-hosted image work.
If exports/canvax-checkpoint-latest.json exists and the user seems to be referring to a specific recent moment in the board workflow, prefer that checkpoint because it merges sketch, voice, and output context for that handoff moment.
When Codex has already produced an implementation target or changed files, also check:
artifacts/canvax/codex-output.jsonexports/canvax-preview-manifest.jsonUse the Codex output manifest as the canonical place to publish implementation results back to Canvax. The preview window and board inspector will merge it automatically with any manual preview attachment.
Even when no fresh manifest write has happened yet, the board and Preview will still mirror current git workspace changes live through preview-state polling. Use the manifest writer when you want that output context to be durable and richly annotated, not only transient.
If the user wants a quick styled local surface before any real app preview exists, tell them to use Materialize in the Canvax board. That writes a generated HTML preview under artifacts/preview/materialized/... and updates the manual preview manifest automatically.
If the user wants a more polished website/app-screen interpretation, prefer Generate screen in the board. That uses Canvax's local semantic renderer for hero-like frames: it infers navigation, headline, body copy, calls to action, proof chips, visual preview cards, and refinement notes from geometry, labels, frame notes, and voice context. It is still deterministic local generation, not a paid API call.
For a quick smoke demo of that path from the repo root:
npm run demo:heroWhen the Codex in-app browser is available, use it as the preferred visual inspection path:
http://localhost:3210/; use http://localhost:3210/?host=codex-sidecar only when explicitly testing the compact sidecarwrite-codex-output.mjsIf the user presses Build code in Workbench, Canvax writes exports/canvax-build-real-latest.* and calls its local no-API executor so the output manifest has a frame-bound preview plus implementation/ starter files. Treat that bundle as a bound starter target for visual inspection and Codex porting, but do not mistake it for production implementation unless the user explicitly accepts it.
If the user presses Apply to Codex in Workbench, Canvax writes the checkpoint and calls the local no-API rewrite executor so the output manifest can point at artifacts/preview/codex-rewrite/frames/.... Treat that as a refreshed bound preview artifact, not as final production code.
Canvax now also writes explicit transport metadata into its live payloads, exports, and checkpoints. Treat that as a contract:
local-companionapp-serverThat transport metadata exists so future richer Codex-client work does not have to guess which pieces are Canvax behavior versus current local transport details.
Do not ask the user to paste the file path again once this skill is active. Default to exports/canvax-live-latest.json.
If the user asks whether Canvax is a skill or a command, answer precisely:
After you implement something from the canvas, write the Codex output manifest so the board and preview can show what changed.
Preferred command when Codex has changed files in the workspace:
node scripts/write-codex-output.mjs --from-git-statusPreferred command when Codex also has a preview target to bind:
node scripts/write-codex-output.mjs --from-git-status --preview-path artifacts/preview/home.htmlIf you have a running local preview instead of a workspace HTML file:
node scripts/write-codex-output.mjs --from-git-status --url http://localhost:3000If a changed file or artifact is specific to one or more Canvax frames, append the frame ids in a third :: segment so the preview can highlight the current-frame context:
node scripts/write-codex-output.mjs --from-git-status --artifact artifacts/preview/home.html::Generated home preview::frame-home --frame frame-homeThat keeps the current chat, preview window, and board inspector aligned without asking the user to attach output manually.
Use --dry-run --json if you want to inspect the manifest that would be written before saving it.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.