From af10ece953f7e166d3f716672c0466a82b4b1771 Mon Sep 17 00:00:00 2001 From: sungdark Date: Thu, 26 Feb 2026 16:33:02 +0000 Subject: [PATCH 01/11] feat(desktop): extend deeplink actions and add Raycast extension scaffold --- .../desktop/src-tauri/src/deeplink_actions.rs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/apps/desktop/src-tauri/src/deeplink_actions.rs b/apps/desktop/src-tauri/src/deeplink_actions.rs index fce75b4a84..8bfb27bbe6 100644 --- a/apps/desktop/src-tauri/src/deeplink_actions.rs +++ b/apps/desktop/src-tauri/src/deeplink_actions.rs @@ -26,6 +26,15 @@ pub enum DeepLinkAction { mode: RecordingMode, }, StopRecording, + PauseRecording, + ResumeRecording, + TogglePauseRecording, + SwitchMicrophone { + mic_label: Option, + }, + SwitchCamera { + camera: Option, + }, OpenEditor { project_path: PathBuf, }, @@ -146,6 +155,21 @@ 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::TogglePauseRecording => { + crate::recording::toggle_pause_recording(app.clone(), app.state()).await + } + DeepLinkAction::SwitchMicrophone { mic_label } => { + crate::set_mic_input(app.state(), mic_label).await + } + DeepLinkAction::SwitchCamera { camera } => { + crate::set_camera_input(app.clone(), app.state(), camera, None).await + } DeepLinkAction::OpenEditor { project_path } => { crate::open_project_from_path(Path::new(&project_path), app.clone()) } From 586e195a0bf06e613248be522f3a3934b5a01e46 Mon Sep 17 00:00:00 2001 From: sungdark Date: Thu, 26 Feb 2026 16:33:03 +0000 Subject: [PATCH 02/11] feat(desktop): extend deeplink actions and add Raycast extension scaffold --- apps/raycast/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 apps/raycast/README.md diff --git a/apps/raycast/README.md b/apps/raycast/README.md new file mode 100644 index 0000000000..deaaa36744 --- /dev/null +++ b/apps/raycast/README.md @@ -0,0 +1,22 @@ +# Cap Raycast Extension (WIP) + +This extension controls the Cap desktop app through `cap-desktop://action?value=...` deeplinks. + +## Supported actions + +- `start_recording` +- `stop_recording` +- `pause_recording` +- `resume_recording` +- `toggle_pause_recording` +- `switch_microphone` +- `switch_camera` + +## Development + +```bash +pnpm install +pnpm dev +``` + +> Requires the Cap desktop app to be installed and registered for the `cap-desktop://` URL scheme. From af1bf7da44d4247941de2d341fb521e1573f34a2 Mon Sep 17 00:00:00 2001 From: sungdark Date: Thu, 26 Feb 2026 16:33:04 +0000 Subject: [PATCH 03/11] feat(desktop): extend deeplink actions and add Raycast extension scaffold --- apps/raycast/package.json | 68 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 apps/raycast/package.json diff --git a/apps/raycast/package.json b/apps/raycast/package.json new file mode 100644 index 0000000000..c6591ac3fa --- /dev/null +++ b/apps/raycast/package.json @@ -0,0 +1,68 @@ +{ + "name": "cap-raycast", + "title": "Cap", + "description": "Control Cap desktop recording via deeplinks", + "version": "0.0.1", + "author": "Cap Contributors", + "license": "MIT", + "commands": [ + { + "name": "start-recording", + "title": "Start Recording", + "description": "Start a Cap recording from Raycast", + "mode": "view" + }, + { + "name": "stop-recording", + "title": "Stop Recording", + "description": "Stop an active Cap recording", + "mode": "no-view" + }, + { + "name": "pause-recording", + "title": "Pause Recording", + "description": "Pause active recording", + "mode": "no-view" + }, + { + "name": "resume-recording", + "title": "Resume Recording", + "description": "Resume paused recording", + "mode": "no-view" + }, + { + "name": "toggle-pause-recording", + "title": "Toggle Pause Recording", + "description": "Toggle pause state", + "mode": "no-view" + }, + { + "name": "switch-microphone", + "title": "Switch Microphone", + "description": "Switch Cap microphone by label", + "mode": "form" + }, + { + "name": "switch-camera", + "title": "Switch Camera", + "description": "Switch Cap camera by id/model", + "mode": "form" + } + ], + "dependencies": { + "@raycast/api": "^1.99.0" + }, + "devDependencies": { + "@raycast/eslint-config": "^2.0.0", + "@types/node": "20.17.24", + "eslint": "^8.57.0", + "prettier": "^3.5.3", + "typescript": "^5.8.2" + }, + "scripts": { + "build": "ray build -e dist", + "dev": "ray dev", + "lint": "ray lint", + "publish": "ray publish" + } +} From 11b91eb9987738ed5c18146b3c98c1f547508004 Mon Sep 17 00:00:00 2001 From: sungdark Date: Thu, 26 Feb 2026 16:33:05 +0000 Subject: [PATCH 04/11] feat(desktop): extend deeplink actions and add Raycast extension scaffold --- apps/raycast/src/lib/cap.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 apps/raycast/src/lib/cap.ts diff --git a/apps/raycast/src/lib/cap.ts b/apps/raycast/src/lib/cap.ts new file mode 100644 index 0000000000..0b4393921e --- /dev/null +++ b/apps/raycast/src/lib/cap.ts @@ -0,0 +1,16 @@ +import { closeMainWindow, open, showHUD } from "@raycast/api"; + +const CAP_DEEPLINK_ACTION_HOST = "action"; + +export async function dispatchAction(action: unknown) { + const value = encodeURIComponent(JSON.stringify(action)); + const url = `cap-desktop://${CAP_DEEPLINK_ACTION_HOST}?value=${value}`; + + await open(url); + await closeMainWindow(); +} + +export async function fireSimpleAction(action: string) { + await dispatchAction({ type: action }); + await showHUD(`Cap: ${action}`); +} From 4450b8a143678889691fe660b0b91a3106d7e371 Mon Sep 17 00:00:00 2001 From: sungdark Date: Thu, 26 Feb 2026 16:33:06 +0000 Subject: [PATCH 05/11] feat(desktop): extend deeplink actions and add Raycast extension scaffold --- apps/raycast/src/pause-recording.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 apps/raycast/src/pause-recording.ts diff --git a/apps/raycast/src/pause-recording.ts b/apps/raycast/src/pause-recording.ts new file mode 100644 index 0000000000..dfdd96c5e1 --- /dev/null +++ b/apps/raycast/src/pause-recording.ts @@ -0,0 +1,5 @@ +import { fireSimpleAction } from "./lib/cap"; + +export default async function Command() { + await fireSimpleAction("pause_recording"); +} From 356da34e7c2a0082d50e13f0e79077ed7d1ed8de Mon Sep 17 00:00:00 2001 From: sungdark Date: Thu, 26 Feb 2026 16:33:07 +0000 Subject: [PATCH 06/11] feat(desktop): extend deeplink actions and add Raycast extension scaffold --- apps/raycast/src/resume-recording.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 apps/raycast/src/resume-recording.ts diff --git a/apps/raycast/src/resume-recording.ts b/apps/raycast/src/resume-recording.ts new file mode 100644 index 0000000000..6a35f43d9c --- /dev/null +++ b/apps/raycast/src/resume-recording.ts @@ -0,0 +1,5 @@ +import { fireSimpleAction } from "./lib/cap"; + +export default async function Command() { + await fireSimpleAction("resume_recording"); +} From fbaad7d2ed8d9a38723b348faf18d5dffff5da43 Mon Sep 17 00:00:00 2001 From: sungdark Date: Thu, 26 Feb 2026 16:33:08 +0000 Subject: [PATCH 07/11] feat(desktop): extend deeplink actions and add Raycast extension scaffold --- apps/raycast/src/start-recording.tsx | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 apps/raycast/src/start-recording.tsx diff --git a/apps/raycast/src/start-recording.tsx b/apps/raycast/src/start-recording.tsx new file mode 100644 index 0000000000..86a0122ff6 --- /dev/null +++ b/apps/raycast/src/start-recording.tsx @@ -0,0 +1,55 @@ +import { Action, ActionPanel, Form, showHUD } from "@raycast/api"; +import { dispatchAction } from "./lib/cap"; + +type Values = { + captureType: "screen" | "window"; + captureName: string; + camera: string; + microphone: string; + captureSystemAudio: boolean; + mode: "studio" | "instant"; +}; + +export default function Command() { + return ( +
+ + + } + > + + + + + + + + + + + + + + ); +} + +async function onSubmit(values: Values) { + const captureMode = + values.captureType === "screen" + ? { screen: values.captureName } + : { window: values.captureName }; + + await dispatchAction({ + start_recording: { + capture_mode: captureMode, + camera: values.camera ? { DeviceID: values.camera } : null, + mic_label: values.microphone || null, + capture_system_audio: values.captureSystemAudio, + mode: values.mode, + }, + }); + + await showHUD("Cap: start_recording"); +} From cf1c7f21d3ac5bc853a822b40e20d74e65d61426 Mon Sep 17 00:00:00 2001 From: sungdark Date: Thu, 26 Feb 2026 16:33:10 +0000 Subject: [PATCH 08/11] feat(desktop): extend deeplink actions and add Raycast extension scaffold --- apps/raycast/src/stop-recording.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 apps/raycast/src/stop-recording.ts diff --git a/apps/raycast/src/stop-recording.ts b/apps/raycast/src/stop-recording.ts new file mode 100644 index 0000000000..2722b61693 --- /dev/null +++ b/apps/raycast/src/stop-recording.ts @@ -0,0 +1,5 @@ +import { fireSimpleAction } from "./lib/cap"; + +export default async function Command() { + await fireSimpleAction("stop_recording"); +} From 8459cb6ae35fafe81d630864ed96e3b8b5ec7165 Mon Sep 17 00:00:00 2001 From: sungdark Date: Thu, 26 Feb 2026 16:33:11 +0000 Subject: [PATCH 09/11] feat(desktop): extend deeplink actions and add Raycast extension scaffold --- apps/raycast/src/switch-camera.tsx | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 apps/raycast/src/switch-camera.tsx diff --git a/apps/raycast/src/switch-camera.tsx b/apps/raycast/src/switch-camera.tsx new file mode 100644 index 0000000000..828bff9496 --- /dev/null +++ b/apps/raycast/src/switch-camera.tsx @@ -0,0 +1,28 @@ +import { Action, ActionPanel, Form, showHUD } from "@raycast/api"; +import { dispatchAction } from "./lib/cap"; + +type Values = { camera: string }; + +export default function Command() { + return ( +
+ + + } + > + + + ); +} + +async function onSubmit(values: Values) { + await dispatchAction({ + switch_camera: { + camera: values.camera ? { DeviceID: values.camera } : null, + }, + }); + + await showHUD("Cap: switch_camera"); +} From f8cfb8002b6651030ee771958079a285b509a8b7 Mon Sep 17 00:00:00 2001 From: sungdark Date: Thu, 26 Feb 2026 16:33:12 +0000 Subject: [PATCH 10/11] feat(desktop): extend deeplink actions and add Raycast extension scaffold --- apps/raycast/src/switch-microphone.tsx | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 apps/raycast/src/switch-microphone.tsx diff --git a/apps/raycast/src/switch-microphone.tsx b/apps/raycast/src/switch-microphone.tsx new file mode 100644 index 0000000000..ba8c2a612b --- /dev/null +++ b/apps/raycast/src/switch-microphone.tsx @@ -0,0 +1,28 @@ +import { Action, ActionPanel, Form, showHUD } from "@raycast/api"; +import { dispatchAction } from "./lib/cap"; + +type Values = { micLabel: string }; + +export default function Command() { + return ( +
+ + + } + > + + + ); +} + +async function onSubmit(values: Values) { + await dispatchAction({ + switch_microphone: { + mic_label: values.micLabel || null, + }, + }); + + await showHUD("Cap: switch_microphone"); +} From a595e0ee3e3669cebfd0f5f34814769e9e79af0d Mon Sep 17 00:00:00 2001 From: sungdark Date: Thu, 26 Feb 2026 16:33:13 +0000 Subject: [PATCH 11/11] feat(desktop): extend deeplink actions and add Raycast extension scaffold --- apps/raycast/src/toggle-pause-recording.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 apps/raycast/src/toggle-pause-recording.ts diff --git a/apps/raycast/src/toggle-pause-recording.ts b/apps/raycast/src/toggle-pause-recording.ts new file mode 100644 index 0000000000..cadf31b283 --- /dev/null +++ b/apps/raycast/src/toggle-pause-recording.ts @@ -0,0 +1,5 @@ +import { fireSimpleAction } from "./lib/cap"; + +export default async function Command() { + await fireSimpleAction("toggle_pause_recording"); +}