From 785167690772af40b6ba93b44cad07d1c451e6ff Mon Sep 17 00:00:00 2001 From: 769066112-ops <769066112-ops@users.noreply.github.com> Date: Fri, 27 Feb 2026 15:19:28 +0800 Subject: [PATCH 1/2] feat: extend deeplinks support + add Raycast extension Extends the existing deeplink infrastructure with new actions: - PauseRecording, ResumeRecording, TogglePause - TakeScreenshot (with capture mode) - SetCamera, SetMicrophone Adds a Raycast extension (apps/raycast) with commands: - Start Instant Recording - Start Studio Recording - Stop Recording - Toggle Pause Recording - Take Screenshot - Open Settings All commands communicate with Cap via the cap-desktop:// deeplink scheme. Closes #1540 --- .../desktop/src-tauri/src/deeplink_actions.rs | 47 +++++++++++ apps/raycast/README.md | 44 +++++++++++ apps/raycast/assets/cap-icon.png | Bin 0 -> 20350 bytes apps/raycast/package.json | 74 ++++++++++++++++++ apps/raycast/src/open-settings.ts | 8 ++ apps/raycast/src/start-instant-recording.ts | 16 ++++ apps/raycast/src/start-studio-recording.ts | 16 ++++ apps/raycast/src/stop-recording.ts | 5 ++ apps/raycast/src/take-screenshot.ts | 12 +++ apps/raycast/src/toggle-pause.ts | 5 ++ apps/raycast/src/utils.ts | 34 ++++++++ apps/raycast/tsconfig.json | 19 +++++ 12 files changed, 280 insertions(+) create mode 100644 apps/raycast/README.md create mode 100644 apps/raycast/assets/cap-icon.png create mode 100644 apps/raycast/package.json create mode 100644 apps/raycast/src/open-settings.ts create mode 100644 apps/raycast/src/start-instant-recording.ts create mode 100644 apps/raycast/src/start-studio-recording.ts create mode 100644 apps/raycast/src/stop-recording.ts create mode 100644 apps/raycast/src/take-screenshot.ts create mode 100644 apps/raycast/src/toggle-pause.ts create mode 100644 apps/raycast/src/utils.ts create mode 100644 apps/raycast/tsconfig.json diff --git a/apps/desktop/src-tauri/src/deeplink_actions.rs b/apps/desktop/src-tauri/src/deeplink_actions.rs index fce75b4a84..a575050b50 100644 --- a/apps/desktop/src-tauri/src/deeplink_actions.rs +++ b/apps/desktop/src-tauri/src/deeplink_actions.rs @@ -26,6 +26,18 @@ pub enum DeepLinkAction { mode: RecordingMode, }, StopRecording, + PauseRecording, + ResumeRecording, + TogglePause, + TakeScreenshot { + capture_mode: CaptureMode, + }, + SetCamera { + camera: Option, + }, + SetMicrophone { + mic_label: Option, + }, OpenEditor { project_path: PathBuf, }, @@ -146,6 +158,41 @@ impl DeepLinkAction { DeepLinkAction::StopRecording => { crate::recording::stop_recording(app.clone(), app.state()).await } + DeepLinkAction::PauseRecording => { + crate::recording::pause_recording(app.clone(), app.state()).await + } + DeepLinkAction::ResumeRecording => { + crate::recording::resume_recording(app.clone(), app.state()).await + } + DeepLinkAction::TogglePause => { + crate::recording::toggle_pause_recording(app.clone(), app.state()).await + } + DeepLinkAction::TakeScreenshot { capture_mode } => { + let capture_target: ScreenCaptureTarget = match capture_mode { + CaptureMode::Screen(name) => cap_recording::screen_capture::list_displays() + .into_iter() + .find(|(s, _)| s.name == name) + .map(|(s, _)| ScreenCaptureTarget::Display { id: s.id }) + .ok_or(format!("No screen with name \"{}\"", &name))?, + CaptureMode::Window(name) => cap_recording::screen_capture::list_windows() + .into_iter() + .find(|(w, _)| w.name == name) + .map(|(w, _)| ScreenCaptureTarget::Window { id: w.id }) + .ok_or(format!("No window with name \"{}\"", &name))?, + }; + + crate::recording::take_screenshot(app.clone(), capture_target) + .await + .map(|_| ()) + } + DeepLinkAction::SetCamera { camera } => { + let state = app.state::>(); + crate::set_camera_input(app.clone(), state, camera, None).await + } + DeepLinkAction::SetMicrophone { mic_label } => { + let state = app.state::>(); + crate::set_mic_input(state, mic_label).await + } DeepLinkAction::OpenEditor { project_path } => { crate::open_project_from_path(Path::new(&project_path), app.clone()) } diff --git a/apps/raycast/README.md b/apps/raycast/README.md new file mode 100644 index 0000000000..fa264970cd --- /dev/null +++ b/apps/raycast/README.md @@ -0,0 +1,44 @@ +# Cap Raycast Extension + +Control [Cap](https://cap.so) screen recording directly from [Raycast](https://raycast.com). + +## Commands + +| Command | Description | +|---------|-------------| +| Start Instant Recording | Start an instant screen recording | +| Start Studio Recording | Start a studio screen recording | +| Stop Recording | Stop the current recording | +| Toggle Pause Recording | Pause or resume the current recording | +| Take Screenshot | Take a screenshot | +| Open Settings | Open Cap settings | + +## How It Works + +This extension communicates with the Cap desktop app via deeplinks (`cap-desktop://action?value=...`). The Cap app must be running for commands to work. + +## Supported Deeplink Actions + +The following deeplink actions are available: + +- `start_recording` — Start a recording (instant or studio mode) +- `stop_recording` — Stop the current recording +- `pause_recording` — Pause the current recording +- `resume_recording` — Resume a paused recording +- `toggle_pause` — Toggle pause/resume +- `take_screenshot` — Capture a screenshot +- `set_camera` — Switch camera input +- `set_microphone` — Switch microphone input +- `open_editor` — Open the editor for a project +- `open_settings` — Open the settings window + +### Deeplink Format + +``` +cap-desktop://action?value= +``` + +Example: +``` +cap-desktop://action?value=%7B%22stop_recording%22%3A%7B%7D%7D +``` diff --git a/apps/raycast/assets/cap-icon.png b/apps/raycast/assets/cap-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..81a7775e9a9b9ee4a6a47c81b2bba7c0346d1952 GIT binary patch literal 20350 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 + */ +export function buildDeepLink(action: Record): string { + const json = JSON.stringify(action); + return `${DEEPLINK_SCHEME}://action?value=${encodeURIComponent(json)}`; +} + +/** + * Open a Cap deeplink and show appropriate toast feedback. + */ +export async function executeDeepLink( + action: Record, + successMessage: string, +): Promise { + const url = buildDeepLink(action); + + try { + await open(url); + await showToast({ style: Toast.Style.Success, title: successMessage }); + } catch (error) { + await showToast({ + style: Toast.Style.Failure, + title: "Failed to communicate with Cap", + message: String(error), + }); + } +} diff --git a/apps/raycast/tsconfig.json b/apps/raycast/tsconfig.json new file mode 100644 index 0000000000..a0867c9d72 --- /dev/null +++ b/apps/raycast/tsconfig.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://www.raycast.com/schemas/extension.json", + "compilerOptions": { + "allowJs": true, + "checkJs": false, + "declaration": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "jsx": "react-jsx", + "lib": ["ES2023"], + "module": "Node16", + "moduleResolution": "Node16", + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "ES2022" + }, + "include": ["src/**/*", "env.d.ts"] +} From fb96479677b29a03e3cbed941edb72438ea5e215 Mon Sep 17 00:00:00 2001 From: 769066112-ops <769066112-ops@users.noreply.github.com> Date: Sat, 28 Feb 2026 03:54:39 +0800 Subject: [PATCH 2/2] fix: address review feedback --- .../desktop/src-tauri/src/deeplink_actions.rs | 41 ++++++++----------- apps/raycast/package.json | 10 +++++ apps/raycast/src/start-instant-recording.ts | 4 +- apps/raycast/src/start-studio-recording.ts | 4 +- apps/raycast/src/take-screenshot.ts | 4 +- apps/raycast/src/utils.ts | 19 +++++---- apps/raycast/tsconfig.json | 2 +- 7 files changed, 44 insertions(+), 40 deletions(-) diff --git a/apps/desktop/src-tauri/src/deeplink_actions.rs b/apps/desktop/src-tauri/src/deeplink_actions.rs index a575050b50..231c7ab0b4 100644 --- a/apps/desktop/src-tauri/src/deeplink_actions.rs +++ b/apps/desktop/src-tauri/src/deeplink_actions.rs @@ -116,6 +116,21 @@ impl TryFrom<&Url> for DeepLinkAction { } } +fn resolve_capture_target(capture_mode: CaptureMode) -> Result { + match capture_mode { + CaptureMode::Screen(name) => cap_recording::screen_capture::list_displays() + .into_iter() + .find(|(s, _)| s.name == name) + .map(|(s, _)| ScreenCaptureTarget::Display { id: s.id }) + .ok_or_else(|| format!("No screen with name \"{}\"", &name)), + CaptureMode::Window(name) => cap_recording::screen_capture::list_windows() + .into_iter() + .find(|(w, _)| w.name == name) + .map(|(w, _)| ScreenCaptureTarget::Window { id: w.id }) + .ok_or_else(|| format!("No window with name \"{}\"", &name)), + } +} + impl DeepLinkAction { pub async fn execute(self, app: &AppHandle) -> Result<(), String> { match self { @@ -131,18 +146,7 @@ impl DeepLinkAction { crate::set_camera_input(app.clone(), state.clone(), camera, None).await?; crate::set_mic_input(state.clone(), mic_label).await?; - let capture_target: ScreenCaptureTarget = match capture_mode { - CaptureMode::Screen(name) => cap_recording::screen_capture::list_displays() - .into_iter() - .find(|(s, _)| s.name == name) - .map(|(s, _)| ScreenCaptureTarget::Display { id: s.id }) - .ok_or(format!("No screen with name \"{}\"", &name))?, - CaptureMode::Window(name) => cap_recording::screen_capture::list_windows() - .into_iter() - .find(|(w, _)| w.name == name) - .map(|(w, _)| ScreenCaptureTarget::Window { id: w.id }) - .ok_or(format!("No window with name \"{}\"", &name))?, - }; + let capture_target = resolve_capture_target(capture_mode)?; let inputs = StartRecordingInputs { mode, @@ -168,18 +172,7 @@ impl DeepLinkAction { crate::recording::toggle_pause_recording(app.clone(), app.state()).await } DeepLinkAction::TakeScreenshot { capture_mode } => { - let capture_target: ScreenCaptureTarget = match capture_mode { - CaptureMode::Screen(name) => cap_recording::screen_capture::list_displays() - .into_iter() - .find(|(s, _)| s.name == name) - .map(|(s, _)| ScreenCaptureTarget::Display { id: s.id }) - .ok_or(format!("No screen with name \"{}\"", &name))?, - CaptureMode::Window(name) => cap_recording::screen_capture::list_windows() - .into_iter() - .find(|(w, _)| w.name == name) - .map(|(w, _)| ScreenCaptureTarget::Window { id: w.id }) - .ok_or(format!("No window with name \"{}\"", &name))?, - }; + let capture_target = resolve_capture_target(capture_mode)?; crate::recording::take_screenshot(app.clone(), capture_target) .await diff --git a/apps/raycast/package.json b/apps/raycast/package.json index 8d918d6044..f2cfa823f5 100644 --- a/apps/raycast/package.json +++ b/apps/raycast/package.json @@ -7,6 +7,16 @@ "author": "cap", "categories": ["Productivity", "Applications"], "license": "MIT", + "preferences": [ + { + "name": "displayName", + "title": "Display Name", + "description": "Name of the display to capture (leave empty to use the main display)", + "type": "textfield", + "required": false, + "default": "" + } + ], "commands": [ { "name": "start-instant-recording", diff --git a/apps/raycast/src/start-instant-recording.ts b/apps/raycast/src/start-instant-recording.ts index 7db0f857f4..05ff162465 100644 --- a/apps/raycast/src/start-instant-recording.ts +++ b/apps/raycast/src/start-instant-recording.ts @@ -1,10 +1,10 @@ -import { executeDeepLink } from "./utils"; +import { executeDeepLink, getDisplayName } from "./utils"; export default async function command() { await executeDeepLink( { start_recording: { - capture_mode: { screen: "Main Display" }, + capture_mode: { screen: getDisplayName() }, camera: null, mic_label: null, capture_system_audio: false, diff --git a/apps/raycast/src/start-studio-recording.ts b/apps/raycast/src/start-studio-recording.ts index 4f9d116b14..7244ba9ec9 100644 --- a/apps/raycast/src/start-studio-recording.ts +++ b/apps/raycast/src/start-studio-recording.ts @@ -1,10 +1,10 @@ -import { executeDeepLink } from "./utils"; +import { executeDeepLink, getDisplayName } from "./utils"; export default async function command() { await executeDeepLink( { start_recording: { - capture_mode: { screen: "Main Display" }, + capture_mode: { screen: getDisplayName() }, camera: null, mic_label: null, capture_system_audio: false, diff --git a/apps/raycast/src/take-screenshot.ts b/apps/raycast/src/take-screenshot.ts index ba95fe2bc8..0485ab8183 100644 --- a/apps/raycast/src/take-screenshot.ts +++ b/apps/raycast/src/take-screenshot.ts @@ -1,10 +1,10 @@ -import { executeDeepLink } from "./utils"; +import { executeDeepLink, getDisplayName } from "./utils"; export default async function command() { await executeDeepLink( { take_screenshot: { - capture_mode: { screen: "Main Display" }, + capture_mode: { screen: getDisplayName() }, }, }, "Taking screenshot...", diff --git a/apps/raycast/src/utils.ts b/apps/raycast/src/utils.ts index 8417644477..37ddf048c6 100644 --- a/apps/raycast/src/utils.ts +++ b/apps/raycast/src/utils.ts @@ -1,20 +1,21 @@ -import { open, showToast, Toast } from "@raycast/api"; +import { getPreferenceValues, open, showToast, Toast } from "@raycast/api"; const DEEPLINK_SCHEME = "cap-desktop"; -/** - * Build a Cap deeplink URL for the given action. - * - * Format: cap-desktop://action?value= - */ +interface Preferences { + displayName: string; +} + +export function getDisplayName(): string { + const { displayName } = getPreferenceValues(); + return displayName || "Main Display"; +} + export function buildDeepLink(action: Record): string { const json = JSON.stringify(action); return `${DEEPLINK_SCHEME}://action?value=${encodeURIComponent(json)}`; } -/** - * Open a Cap deeplink and show appropriate toast feedback. - */ export async function executeDeepLink( action: Record, successMessage: string, diff --git a/apps/raycast/tsconfig.json b/apps/raycast/tsconfig.json index a0867c9d72..fffe58ee5a 100644 --- a/apps/raycast/tsconfig.json +++ b/apps/raycast/tsconfig.json @@ -1,5 +1,5 @@ { - "$schema": "https://www.raycast.com/schemas/extension.json", + "$schema": "https://json.schemastore.org/tsconfig", "compilerOptions": { "allowJs": true, "checkJs": false,