Summary

Extends Cap’s existing deeplink system with recording control actions and adds a complete Raycast extension.

Deeplink Actions Added

Action URL Example
Pause Recording cap-desktop://action?value=%22pause_recording%22
Resume Recording cap-desktop://action?value=%22resume_recording%22
Toggle Pause cap-desktop://action?value=%22toggle_pause_recording%22
Set Camera cap-desktop://action?value={%22set_camera%22:{%22camera%22:{%22ModelID%22:%22vid:pid%22}}}
Set Microphone cap-desktop://action?value={%22set_microphone%22:{%22mic_label%22:%22Mic%20Name%22}}

Implementation

All new variants are added to the existing DeepLinkAction Rust enum with serde deserialization, reusing the established cap-desktop://action?value={json} URL scheme. Each action delegates to existing public functions:

  • pause_recording() / resume_recording() / toggle_pause_recording() from recording.rs
  • set_camera_input() / set_mic_input() from lib.rs

Zero frontend changes required — the existing TryFrom<&Url> parser automatically deserializes the new variants via serde.

Raycast Extension (apps/raycast/)

8 commands built with @raycast/api:

Command Mode Description
Start Recording Form Configure capture mode, camera, mic, system audio
Stop Recording Instant One-click stop
Pause Recording Instant Pause current recording
Resume Recording Instant Resume paused recording
Toggle Pause Instant Toggle pause/resume
Set Camera Argument Switch camera by model name
Set Microphone Argument Switch mic by label
Open Settings Instant Open Cap settings

Files Changed

  • apps/desktop/src-tauri/src/deeplink_actions.rs — 5 new enum variants + execute handlers
  • apps/raycast/ — Complete Raycast extension (8 commands, README, TypeScript types)

Closes #1540

/claim #1540

Greptile Summary

Extends Cap’s deeplink system with 5 new DeepLinkAction enum variants (pause, resume, toggle-pause, set-camera, set-microphone) and adds a complete Raycast extension with 8 commands that invoke these deeplinks. The Rust-side changes are clean and follow existing patterns well.

  • Critical: ModelID format mismatch causes panic — The Raycast set-camera and start-recording commands pass human-readable camera names (e.g., “FaceTime HD Camera”) as ModelID, but the Rust ModelID deserializer expects a "vid:pid" format string and calls split_once(":").unwrap(), which will panic if the input lacks a colon. This affects set-camera.tsx, start-recording.tsx, and the README examples.
  • Code comments in utils.ts — The repo convention (CLAUDE.md) prohibits all code comments. utils.ts contains a JSDoc block and a single-line comment that should be removed.
  • Simple deeplink commands look good — The pause, resume, toggle-pause, stop, open-settings, and set-microphone commands all correctly serialize their actions and match the Rust-side expectations.

Confidence Score: 2/5

  • The camera-related commands will crash the desktop app at runtime due to a ModelID deserialization panic; must be fixed before merging.
  • The Rust deeplink additions are well-structured and safe. However, the Raycast extension has a critical bug: camera name strings are passed as ModelID values, but ModelID::deserialize calls unwrap() on split_once(“:”) — any camera name without a colon will panic and crash the app. This affects two commands (set-camera and start-recording) and the README documentation.
  • apps/raycast/src/set-camera.tsx and apps/raycast/src/start-recording.tsx — both pass camera names where vid:pid format is required, causing a runtime panic

Important Files Changed

Filename Overview
apps/desktop/src-tauri/src/deeplink_actions.rs Adds 5 new DeepLinkAction enum variants (PauseRecording, ResumeRecording, TogglePauseRecording, SetCamera, SetMicrophone) with execute handlers that correctly delegate to existing crate functions. Clean, consistent with existing patterns.
apps/raycast/src/utils.ts Core deeplink URL builder with TypeScript types mirroring the Rust DeepLinkAction enum. Contains code comments that violate repo conventions. The CameraId type definition is correct but the consuming commands misuse it.
apps/raycast/src/set-camera.tsx Passes user-provided camera name directly as ModelID, but Rust ModelID expects “vid:pid” format — will cause a panic (unwrap on None) when the input lacks a colon separator.
apps/raycast/src/start-recording.tsx Start recording form with capture mode, camera, mic, and system audio options. Same ModelID format mismatch issue as set-camera — camera name input will panic the Rust deserializer.
apps/raycast/package.json Raycast extension manifest with 8 commands. Dependencies and configuration look standard for a Raycast extension.
apps/raycast/README.md Documentation with deeplink reference. Contains misleading ModelID examples that show camera names instead of the required “vid:pid” format.

Sequence Diagram

sequenceDiagram
participant R as Raycast Extension
participant OS as macOS URL Handler
participant T as Tauri Deep Link Handler
participant DL as DeepLinkAction
participant Rec as recording.rs
participant Lib as lib.rs
R->>OS: open cap-desktop://action?value=json
OS->>T: handle(urls)
T->>T: parse URL and deserialize JSON
T->>DL: action.execute(app)
alt PauseRecording / ResumeRecording / TogglePauseRecording
DL->>Rec: pause/resume/toggle recording
end
alt SetCamera
DL->>Lib: set_camera_input(app, state, camera, None)
end
alt SetMicrophone
DL->>Lib: set_mic_input(state, mic_label)
end
alt StartRecording
DL->>Lib: set_camera_input + set_mic_input
DL->>Rec: start_recording(app, state, inputs)
end
Prompt To Fix All With AI
This is a comment left during a code review.
Path: apps/raycast/src/set-camera.tsx
Line: 13
Comment:
**`ModelID` expects `vid:pid` format, not a camera name**
The Rust `ModelID` deserializer at `crates/camera/src/lib.rs:144` splits on `:` with an `unwrap()`:
```rust
let (vid, pid) = s.split_once(":").unwrap();
```
If a user enters a human-readable name like "FaceTime HD Camera" (which the placeholder text `"Camera name or model"` suggests), the deeplink will produce `{"ModelID": "FaceTime HD Camera"}`. Since there's no `:` in that string, `split_once(":").unwrap()` will **panic** and crash the desktop app.
The `ModelID` type requires a vendor-ID:product-ID string (e.g., `"0x1234:0x5678"`), not a friendly camera name. Either the Raycast command should explain this format requirement to the user, or it should use `DeviceID` instead if that accepts friendly names.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: apps/raycast/src/start-recording.tsx
Line: 44
Comment:
**Same `ModelID` panic risk as set-camera**
This line has the same issue as `set-camera.tsx`: the form placeholder says "Camera name or model" but wraps the input in `{ ModelID: values.camera }`. The Rust `ModelID` deserializer expects a `"vid:pid"` format string and will **panic** (`unwrap()` on `split_once(":")`) if the user enters a human-readable camera name like "FaceTime HD Camera".
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: apps/raycast/src/utils.ts
Line: 1-14
Comment:
**Code comments violate repo convention**
Per the project's CLAUDE.md: "CRITICAL: NO CODE COMMENTS: Never add any form of comments to code." This file contains a JSDoc block (lines 1-8) and a single-line comment on line 14 (`// Unit variants serialize as plain strings`). These should be removed — the types and function names are already self-explanatory.
**Rule Used:** CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=9a906542-f1fe-42c1-89a2-9f252d96d9f0))
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: apps/raycast/README.md
Line: 45
Comment:
**Misleading `ModelID` example in docs**
The example shows `"ModelID": "FaceTime HD Camera"`, but in the Rust codebase `ModelID` actually deserializes from a `"vid:pid"` format string (e.g., `"0x1234:0x5678"`). This applies to both the "Start recording" and "Switch camera" examples (lines 45 and 56). Using a friendly camera name here would crash the desktop app due to an `unwrap()` panic in the `ModelID` deserializer.
How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: ac714dc

Greptile also left 4 inline comments on this PR.

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

Context used:

  • Rule used - CLAUDE.md (source)

Claim

Total prize pool $200.10
Total paid $0
Status Pending
Submitted March 16, 2026
Last updated March 16, 2026

Contributors

QI

qiridigital

@qiridigital

100%

Sponsors

CA

Cap

@CapSoftware

$200
AB

Abhishek Verma

@w3Abhishek

$0.10