oh-my-cassette
Health Gecti
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 138 GitHub stars
Code Gecti
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
你的随身 AI 剪辑搭档 | Pocket AI co-editor for video montage — AI video editing plugin & MCP server for Claude Code, Codex, Hermes & OpenCode
Oh My Cassette: Pocket AI Co-editor for Video Montage
简体中文 | English
Arm Codex, Claude, or Hermes with Cassette's amazing video editing power.
Add a friend, chat your video into shape.
🎥 Overview
Oh My Cassette is an open-source AI video editing plugin and local MCP server for Claude Code, Codex, Hermes Agent, and OpenCode. It turns natural-language chat into finished montage videos on Cassette — beat-synced cuts, auto-matched music, subtitles, transitions, and picture-in-picture — with minimal token overhead.
Just send your videos or audio files and chat with your agent from anywhere on your phone. Your agent will work with Cassette to understand your intent, organize your media, plan the edit, and turn your materials into a ready-to-share video with powerful montage capabilities.
We believe everyone carries a film of their own. Oh My Cassette helps you capture sparks of inspiration, shape scattered moments into a story, and turn raw clips into montage videos without wrestling with timelines or editing tools.
Be the director of your own story, effortlessly.
📱 Capture AnywhereSend clips, audio, and ideas to your AI editing friend anytime, anywhere. |
💬 Chat-to-EditDescribe the video you want in natural language instead of wrestling with timelines. |
🎵 Smart Music MatchingAutomatically match music to the mood, rhythm, and story of your footage. |
🌌 Montage StorytellingOrganize scattered moments into rhythmic, emotional, and memorable video stories. |
✨ Advanced Editing AbilitySupport title captions, picture-in-picture, beat sync, hard cuts, transitions, motion graphics, and stylized edits. |
✅ Ready to SharePreview, refine, and export polished videos ready to post on social platforms. |
🎬 Case Videos
Every case below was edited end-to-end by an AI agent through Oh My Cassette, from the exact prompt shown — real inputs, real processing times, and the output is what the agent delivered.
Daily Moments Vlog
🎞️ Input: 15 video clips · 1 audio track Prompt
|
Travel Vlog
🎞️ Input: 13 video clips · 1 audio track Prompt
|
Cinematic Mood Short
🎞️ Input: 15 video clips · 1 audio track Prompt
|
Cooking Tutorial
🎞️ Input: 12 video clips · 1 audio track Prompt
|
Commercial
🎞️ Input: 15 video clips · 15 sound effects · 1 audio track Prompt
|
Game Highlight Video
🎞️ Input: 5 video clips · 1 audio track Prompt
|
★ More cases are on the way. Star the project to follow along.
🏄 Try without installation
We host a public web demo so you can try the Oh My Cassette workflow from a desktop or mobile browser without installing Codex, Claude, or Hermes locally:
Deploy Web Demo Locally[!WARNING]
The public demo is for illustration and evaluation only. It is intentionally unauthenticated, so do not upload sensitive, private, confidential, illegal, copyrighted, regulated, or otherwise restricted content.Uploaded files, prompts, generated outputs, job state, and troubleshooting metadata may be processed by this demo server, Cassette, DeepSeek, and third-party music/search providers used by the BGM flow. Treat anything you upload as visible to the demo operator and external services involved in the workflow.
The demo may be reset, rate-limited, unavailable, or changed at any time. We do not guarantee data retention, deletion timing, confidentiality, fitness for production use, output quality, copyright compliance of generated/editing results, or uninterrupted service. You are responsible for the content you upload and for reviewing any generated output before sharing it.
Browser refreshes, tab closes, or navigation away from the web demo start a new web session and best-effort cleanup the previous web session's temporary uploads, chat history, and finished job files.
By default, the demo uses the server-side DeepSeek configuration when available. You can open Settings in the web UI and provide your own DeepSeek API key for testing. Your key is sent only with requests to this demo server and is not written to this repository or server-side disk by the web app, but it still transits the public demo server; use a key you can rotate and monitor.
The web demo is a single FastAPI service that keeps the existing Cassette gateway flow but replaces the chat surface with a browser UI. It stores runtime uploads, jobs, exports, screenshots, and outbox data under CASSETTE_ASSET_ROOT instead of the repository.
- Clone the repository and create a dedicated web environment:
git clone https://github.com/Cassette-Editor/oh-my-cassette.git
cd oh-my-cassette
python3 -m venv .venv-web
. .venv-web/bin/activate
pip install -U pip
pip install -r requirements-web.txt
python -m playwright install chromium
- Configure Cassette and DeepSeek runtime settings as process environment variables. The web demo does not require Hermes Agent or
~/.hermes/.env.
cp deploy/oh-my-cassette-web.env.example ./oh-my-cassette-web.env
$EDITOR ./oh-my-cassette-web.env
At minimum, set:
CASSETTE_URL=https://sg.trycassette.online/agent
[email protected]
CASSETTE_AUTH_PASSWORD='your-cassette-password'
CASSETTE_ASSET_ROOT=$HOME/.oh-my-cassette/cassette
CASSETTE_BROWSER_TIMEOUT_SEC=1800
DEEPSEEK_API_KEY='your_deepseek_api_key'
DEEPSEEK_BASE_URL=https://api.deepseek.com
DEEPSEEK_MODEL=deepseek-v4-flash
OMC_WEB_HOST=0.0.0.0
OMC_WEB_PORT=8080
OMC_WEB_LOG_DIR=./web_demo/logs
If you load the file with . ./oh-my-cassette-web.env, quote any value that contains shell-special characters, spaces, or #. The systemd EnvironmentFile format also accepts quoted values.
Cassette upload/analysis waits inherit CASSETTE_BROWSER_TIMEOUT_SEC by default. Set CASSETTE_UPLOAD_TIMEOUT_SEC only when you need a different upload timeout; 0 means wait forever.
Load the variables before starting the service:
set -a
. ./oh-my-cassette-web.env
set +a
If you do not want to put a DeepSeek key on the server, leave DEEPSEEK_API_KEY empty and enter a temporary key from the web UI Settings panel. That browser-provided key is attached to API requests for that session and is not persisted by the web app.
Web demo service logs are separate from Hermes Agent / OhMyCassette plugin logs. By default they are written to ./web_demo/logs/web_demo.log relative to the service working directory, or to $OMC_WEB_LOG_DIR/web_demo.log when OMC_WEB_LOG_DIR is set.
Cassette job records for the web demo are also separate when CASSETTE_ASSET_ROOT is set as above: raw job JSON lives in $CASSETTE_ASSET_ROOT/jobs/cassette_*.json, and the web UI exposes a per-job Log link for jobs owned by the current browser session.
- Build the browser UI (Vite + React →
web_demo/frontend/dist). Requires Node.js + npm at build time only:
./web_demo/build_frontend.sh
- Start the web demo:
. .venv-web/bin/activate
python -m web_demo.server
The server serves the built
web_demo/frontend/dist. If it has not been built yet,/returns a clear 503 telling you to run the build. Re-runweb_demo/build_frontend.shafter pulling changes underweb_demo/frontend.
Open http://127.0.0.1:8080/ for local testing, or http://<server-ip>:8080/ from another device if the host firewall/security group allows inbound TCP 8080.
- Optional systemd deployment:
sudo cp deploy/oh-my-cassette-web.service.example /etc/systemd/system/oh-my-cassette-web.service
sudo cp deploy/oh-my-cassette-web.env.example /etc/oh-my-cassette-web.env
sudo $EDITOR /etc/oh-my-cassette-web.env
sudo systemctl daemon-reload
sudo systemctl enable --now oh-my-cassette-web
sudo systemctl status oh-my-cassette-web
journalctl -u oh-my-cassette-web -f
Before enabling the service, edit /etc/systemd/system/oh-my-cassette-web.service if your repository or virtualenv path differs from the example.journalctl shows uvicorn stdout/access logs; Web demo business logs still go to $OMC_WEB_LOG_DIR/web_demo.log.
- Smoke test:
curl -fsS http://127.0.0.1:8080/ -o /dev/null
python3 -m compileall -q web_demo tools.py notifier.py browser.py
tail -f ./web_demo/logs/web_demo.log
Then open the browser UI, upload a small video, send an edit request, and watch the job card/events until the export download appears.
🚀 Quick Start
Before You Start 🎬
Oh My Cassette connects Codex, Claude, or Hermes to the Cassette Agent. You need:
- Codex, Claude Code, or a working Hermes Agent installation.
- A Cassette account.
- For Hermes only, a configured gateway such as QQ or Telegram.
[!TIP]
Apply for a Cassette account here: Cassette Sign Up
If you plan to use Hermes and it is not installed yet:
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
If the Hermes Agent gateway is not configured yet:
hermes gateway setup
Oh My Cassette currently supports QQ and Telegram gateways.
Requirements
- macOS, Linux, or Windows for the local MCP plugin (Codex, Claude Code, or OpenCode). The Hermes Agent gateway path is macOS/Linux only.
- Codex, Claude Code, or OpenCode for the local MCP plugin, or Hermes Agent with its gateway configured.
- Python 3.11–3.13.
ffmpeg, required for Hermes gateway normalization and optional API export thumbnails.
Install system tools:
# macOS
brew install uv ffmpeg
# Debian/Ubuntu Linux
sudo apt-get update
sudo apt-get install -y ffmpeg
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
winget install Python.Python.3.13
winget install Gyan.FFmpeg
Install
Codex
codex plugin marketplace add https://github.com/Cassette-Editor/oh-my-cassette.git
codex plugin add oh-my-cassette@cassette-editor
Start a new Codex task after installation so plugin discovery runs again. The plugin contributes the host-neutral cassette-video-edit skill and a local MCP process named cassette.
Claude Code
claude plugin marketplace add Cassette-Editor/oh-my-cassette
claude plugin install oh-my-cassette@cassette-editor
Restart Claude Code after installation. You can verify the installation with:
claude plugin details oh-my-cassette@cassette-editor
OpenCode
OpenCode has no plugin marketplace for MCP servers, so add the server and skill from a checkout. Clone the repository, then point OpenCode at the launcher from your project's opencode.json (a copy is committed at the repo root):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"cassette": {
"type": "local",
"command": ["python3", "/absolute/path/to/oh-my-cassette/scripts/run_local_mcp.py"],
"enabled": true,
"environment": { "CASSETTE_MCP_HOST": "opencode" }
}
}
}
OpenCode discovers the host-neutral cassette-video-edit skill from the repository's .agents/skills/ directory, or copy it to ~/.config/opencode/skills/cassette-video-edit/ for global use. On Windows, use "python" instead of "python3" in command.
Any other MCP host
The runtime is host-neutral, so any client that launches a local stdio MCP server can use it. Point the client at scripts/run_local_mcp.py (run with python3, or python on Windows) and set CASSETTE_RUNTIME_ADAPTER=mcp. The server ships full workflow guidance in its MCP instructions, and every tool returns a typed phase/next_action so a host without the packaged skill can still drive the flow. For the best experience, also install the cassette-video-edit skill (or equivalent system prompt) so the guided-choice and review steps are followed.
Hermes
Install through the Hermes plugin manager (recommended):
hermes plugins install Cassette-Editor/oh-my-cassette
The Hermes installer prompts for your Cassette account email and password and saves them to ~/.hermes/.env. Then run the setup finisher — it installs Playwright Chromium into the Hermes Python environment, detects ffmpeg/ffprobe, and lets you pick the Cassette region — and enable the plugin:
python3 ~/.hermes/plugins/cassette/scripts/install_plugin.py --setup-only
hermes plugins enable cassette
hermes gateway restart
You can check the install status anytime from the Diagnose section.
Alternative: guided installer from a git checkout (for development)git clone https://github.com/Cassette-Editor/oh-my-cassette.git
cd oh-my-cassette
python3 scripts/install_plugin.py
Run the installer and follow the prompts to set up Oh My Cassette with your Cassette account.
The installer:
- installs the plugin into
~/.hermes/plugins/cassetteas a symlink by default; - asks whether to enable the plugin with
hermes plugins enable cassette; - asks which Cassette URL to use:
https://sg.trycassette.online/agent(Asia, default)https://trycassette.online/agent(America)
- optionally saves Cassette login and Jamendo credentials into
~/.hermes/.env; - detects
ffmpegandffprobepaths for service environments; - installs Python Playwright and Chromium into the Hermes Python environment;
- restarts the Hermes gateway service.
To copy files instead of creating a symlink:
python3 scripts/install_plugin.py --copy --force
For non-interactive installs:
python3 scripts/install_plugin.py \
--skip-plugin-enable \
--skip-cassette-url \
--skip-cassette-auth \
--skip-jamendo-auth
Use with Codex or Claude over local MCP
Codex and Claude use the same self-contained runtime. In this README, MCP server means a local child process connected over stdin/stdout: it opens no port and does not depend on the FastAPI web-demo service. The separate Cassette backend remains the editing engine and continues to handle authentication, media processing, agent runs, project state, and rendering.
The web demo is intentionally different. Browsers still need the retained FastAPI server for uploads, chat sessions, and frontend endpoints; none of that behavior is removed by the local MCP plugin.
First-run authentication
Missing credentials do not prevent the MCP process from starting. The first tool that needs Cassette returns auth_required and an exact private-terminal setup command. Run that command outside the agent conversation; it prompts for the password with getpass, verifies the account before writing anything, and stores credentials in the platform-standard Oh My Cassette config directory.
From a git checkout, the equivalent command is:
python3 scripts/setup_local_mcp.py --email [email protected]
Credentials may also come from process environment variables. Environment values take precedence over protected local config. Importing an existing Hermes .env is explicit and optional:
python3 scripts/setup_local_mcp.py --import-hermes
The setup command creates config directories with mode 0700 and credential files with mode 0600, rejects symlinks and permissive files, and never persists access or refresh tokens. If the account does not have full API access, setup reports the optional browser path instead of silently changing transports.
Guided editing flow
- Ask Codex or Claude to edit one or more media files in the current project.
- The plugin ingests only media inside the active project or another explicitly trusted root. It canonicalizes paths and rejects traversal and symlink escapes.
- Describe the edit, answer any guided choices, and start the job. MCP jobs run in the background by default.
- The host checks status with bounded 30-second long polls. During a long poll the runtime emits MCP progress notifications (visible in hosts that request them), so the wait shows live stage updates instead of a silent block. The skill monitors for up to 25 minutes, then returns the still-running job ID so you can continue later without tight-polling.
- If Cassette needs a real user decision, answer it with the returned job ID. On hosts that support MCP elicitation,
cassette_job_statuscollects the answer inline and returns the already-resumed status; other hosts use thecassette_answer_questionround-trip. API jobs persist their private continuation metadata across host restarts. - When editing completes, review the result. Rendering starts only after an explicit
exportdecision. - The result contains validated absolute paths, file URIs, MIME type, size, and an MCP resource link for each exported artifact. Large media bytes are never embedded in the tool response.
When a background job reaches a terminal state (finished, needs input, failed, or cancelled), the MCP runtime posts a best-effort local desktop notification — osascript on macOS, notify-send on Linux — so you learn a long render is done even after the monitor budget hands the job back. Set CASSETTE_MCP_NOTIFY=0 to disable it.
Sessions are isolated by a cryptographically random session ID. Codex and Claude share host-neutral storage, so you can deliberately hand a session or job ID from one host to the other; nothing is shared implicitly.
Additional trusted media directories can be registered during setup:
python3 scripts/setup_local_mcp.py --allowed-root /absolute/path/to/media
Exports stay under the shared Oh My Cassette data directory at cassette/exports/<job_id>/. Only files contained in that job-specific directory can be returned.
API and optional browser transports
The API transport is the default. It connects directly to the separate Cassette backend, retries authentication once after a 401, and keeps access tokens in memory only. Because API continuation metadata is persisted, paused API jobs can resume after Codex or Claude restarts.
Browser transport is an explicit fallback for accounts without full API access and for parity diagnostics. Install pinned Playwright and Chromium only when needed:
python3 scripts/setup_local_mcp.py --with-browser
Browser jobs can resume while the same MCP process is alive. After a host restart they return browser_session_lost, because live browser objects cannot be persisted.
MCP tools
The local MCP runtime exposes the same 14 tool names as Hermes:
| Tool | Purpose |
|---|---|
cassette_ingest_media |
Safely ingest trusted project media into an isolated session |
cassette_list_assets |
Read the session's media manifest |
cassette_make_prompt |
(legacy, browser transport) Build a full edit brief |
cassette_match_bgm |
Match Free To Use background music |
cassette_match_exact_bgm |
Match a specific title and artist |
jamendo_music_matcher |
Match structured Jamendo preferences |
cassette_answer_question |
Answer a guided question or resume a paused job |
cassette_run_job |
Run one conversational turn (message = the user's verbatim words); export=true renders |
cassette_job_status |
Read status or wait briefly for a change |
cassette_review_completion |
Review completion and explicitly approve export |
cassette_cancel_job |
Request cooperative cancellation |
cassette_timeline |
Read the live project timeline as a bounded text digest (+ optional contact sheet) |
cassette_edit |
Surgical no-LLM edit / undo through the manual command lane (CASSETTE_DIRECT_EDIT=1) |
cassette_config |
Get/set the session's model + thinking level (static product list, applies next turn) |
Every tool returns a structured envelope with ok, typed data or error, session_id, job_id, the current phase, and a runtime-derived next_action.
The live editor deep link and plan review
Every session on the API transport carries ONE stable editor_url — a …/try?projectSessionId=<id>&chatSessionId=<uuid> link that opens the real Cassette editor on the session's live conversation: the timeline repaints as edits land, the preview plays without any server render, and the plan-review card is interactive. The link stays the same across every turn of the session (jobs are conversational turns on one persistent agent thread with memory). Anyone with the link can view and edit that one project (the same capability-URL posture as Cassette's public try page), so treat it like a share link.
Two concurrency semantics worth knowing: a plugin turn never cancels a run started from the open editor tab (it fails typed as thread_busy instead — wait and retry), while typing a fresh message in the tab DOES cancel an in-flight plugin turn (the tab takes over; existing product behavior).
Behavior change (0.4.1): the agent now receives the user's message verbatim (no brief wrapper), sessions are multi-turn on one thread, and a turn ends with the edit committed but nothing rendered — the envelope carries timeline_delta, quality.timeline_ctl, and a contact-sheet preview instead; pass export=true on the turn where the user asks to finish (browser transport keeps its render-per-job behavior). Model/thinking are session preferences via cassette_config — never asked upfront, defaults match the web editor.
Behavior change (0.4.0): on MCP hosts, edit_plan_review now surfaces as a real question by default (CASSETTE_PLAN_REVIEW=user) instead of being silently auto-approved — answer with approve, revise <feedback>, or reject, in chat or in the open editor tab (first answer wins). Set CASSETTE_UNATTENDED=1 to restore the previous fully headless behavior. Status envelopes additionally carry timeline_delta (what changed) and plan_progress, fed by the run's SSE event stream (CASSETTE_API_STREAM=0 disables).
Ready to Use with Hermes 📼
Now you can pick up your phone and DM your agent! Don't forget to keep your agent alive and network connected.
In QQ or Telegram:
- Send one or more video, image, or audio files.
- Wait for the saved-material acknowledgement.
- Send an edit instruction in the same conversation, or prefix it with
/edit. Your words go to the Cassette agent verbatim — no model/optimization/BGM questionnaire. Use/refine,/music, or/cassette_modelwhen you want those. - Each turn ends with the edit saved (timeline delta + contact-sheet preview + live link, no render). Keep editing in the same conversation — the agent remembers. Say "export" when you want the video, and the plugin renders and delivers it through the gateway when supported.
| Command | Explanation |
|---|---|
/new or /reset |
Clear your assets and start a new conversation with Hermes |
/edit <instruction> |
Edit the current video based on your instruction. |
/refine <instruction> |
Refine your edit instruction and start editing. |
/music <BGM request> |
Match and add a BGM to your assets based on your request. |
/cut |
Stop the current Cassette edit. |
/check_assets |
Check the uploaded assets and their status. |
/cassette_model |
Select the current Cassette model and thinking level. |
/cassette language zh |
Set Cassette’s response language to Chinese. |
/cassette language en |
Set Cassette’s response language to English. |
/cassette status <job_id> |
Check the status of a specific job. |
/cassette cancel <job_id> |
Cancel a specific job. |
Assets and video state are preserved within the same conversation session. You can send additional messages in the same session to further modify the edited video results.
Use
/newor/resetto start a fresh Hermes session and clear the live Cassette browser session and your assets for that conversation.QQ is set to Chinese and Telegram is set to English by default, you can set language by command
/cassette language zh/enmanually.
Update
For Codex:
codex plugin marketplace upgrade cassette-editor
codex plugin add oh-my-cassette@cassette-editor
For Claude Code:
claude plugin marketplace update cassette-editor
claude plugin update oh-my-cassette@cassette-editor
The local launcher updates its locked, plugin-managed virtual environment automatically on the next start. Browser binaries are installed only when requested.
If installed through the Hermes plugin manager:
hermes plugins update cassette
hermes gateway restart
If installed from a git checkout (symlink install), update the checkout:
git pull --ff-only
hermes gateway restart
If the plugin was installed with --copy, reinstall the copied plugin after pulling:
git pull --ff-only
python3 scripts/install_plugin.py --copy --force
hermes gateway restart
See CHANGELOG.md for what changed in each release.
Migrating a symlink install to the Hermes plugin manager (optional)Existing symlink installs keep working — migration is optional. To switch:
rm ~/.hermes/plugins/cassette # removes only the symlink, not your checkout
hermes plugins install Cassette-Editor/oh-my-cassette
hermes gateway restart
Your credentials in ~/.hermes/.env and the plugin's enabled state carry over;
already-set values are not prompted again. Don't runhermes plugins install --force on top of a symlink — it fails with a
confusing error instead of replacing it.
❓ FAQ
Which AI agents does Oh My Cassette work with?
Claude Code, Codex, OpenCode, and Hermes Agent are supported out of the box, and any other MCP host can connect to the local cassette MCP server. Sessions live in a host-agnostic data directory, so you can start an edit in one host and continue it in another.
Does it edit videos locally or in the cloud?
The plugin runs locally beside your agent and handles media ingestion, edit planning, and job supervision. The actual editing and rendering happen on Cassette, so you don't need a GPU or any editing software installed.
Do I need a Cassette account?
Yes. The installer asks for your Cassette account email and password on first run and stores them locally; the plugin authenticates with Cassette on your behalf.
What kinds of videos can it make?
Montage and story edits — vlogs, travel videos, music-driven shorts, cooking tutorials, product commercials, and game highlights — with beat-synced cuts, subtitles, picture-in-picture, transitions, and auto-matched background music. See Case Videos for real examples with prompts and processing times.
Can I see what the agent is doing mid-edit?
Yes. After each editing turn you get a timeline contact sheet, a per-turn preview, and a live editor deep link into the Cassette timeline; before the edit runs, the agent surfaces the plan as a storyboard sheet (one source frame per planned beat) for review.
Can I try it without installing anything?
Yes — the public web demo runs the full workflow in your browser. It is unauthenticated and for evaluation only, so don't upload sensitive content.
Is Oh My Cassette free and open source?
The plugin is open source under the MIT license. Cassette itself is a separate hosted service with its own account and terms.
🔨 Development & Troubleshooting
[!TIP]
Join our Discord community to connect with contributors and fellowoh-my-cassetteusers.
Common Q&A
1. Why does my Hermes Agent fail to respond on QQ or Telegram?
Please check your Hermes Agent model setup, network connectivity, and API connectivity. You can also restart the gateway:
hermes gateway stop
hermes gateway restart
2. Why is there a network issue when connecting to Cassette?
Please check if you can access https://sg.trycassette.online/agent or https://trycassette.online/agent. If not, you may check your network settings to open Cassette.
3. Why is the runtime slow?
The editing process depends on Hermes Agent API latency and Cassette service load. An edit task may take approximately 5–20 minutes depending on the complexity of the task, the selected model, and the thinking level.
If Hermes or Cassette gets stuck, first send /cut to stop the current Cassette edit, then send /stop to stop Hermes. After that, try again in the same session.
Diagnose
For the Codex and Claude local MCP plugin, run:
python3 scripts/diagnose_local_mcp.py
It reports runtime bootstrap, protected config, transport, project/media roots, and host-neutral data paths without printing credentials. Common MCP errors are actionable: auth_required includes the private setup command, source_path_not_allowed identifies the trusted-root problem, and browser_session_lost explains when a browser job cannot survive a restart.
For Hermes, run:
python3 scripts/diagnose_install.py
The diagnostic checks:
- plugin install path (symlink installs and
hermes plugins installgit clones are both recognized); - whether the plugin is enabled in Hermes;
~/.hermes/.envvalues, with secrets redacted;ffmpegandffprobe;- Playwright in the Hermes Python environment;
- Cassette URL reachability;
- Cassette login credentials by opening the Agent page in Chromium;
- Hermes gateway status.
If incoming media fails with transcoder_missing, run the installer again so it records explicit CASSETTE_FFMPEG_BIN and CASSETTE_FFPROBE_BIN paths:
python3 scripts/install_plugin.py \
--skip-plugin-enable \
--skip-cassette-url \
--skip-cassette-auth \
--skip-jamendo-auth \
--skip-playwright-install
Configuration
Codex and Claude share the platform-standard Oh My Cassette config and data directories. Their credentials and job state are separate from Hermes. The active host project is trusted automatically; add any other media directory explicitly with setup_local_mcp.py --allowed-root. The web demo reads only its process environment and does not use either plugin's stored credentials.
The installer writes normal runtime settings to ~/.hermes/.env. You can also edit that file manually.
CASSETTE_URL=https://sg.trycassette.online/agent
[email protected]
CASSETTE_AUTH_PASSWORD=your-generated-cassette-password
CASSETTE_ASSET_ROOT=$HOME/.hermes/cassette
CASSETTE_HEADLESS=true
CASSETTE_FORCE_H264=true
Default media source roots:
~/.hermes/qqbot
~/.hermes/telegram
~/.hermes/weixin
~/.hermes/cache
~/.hermes/tmp
If your gateway stores media elsewhere:
CASSETTE_ALLOWED_SOURCE_ROOTS="$HOME/.hermes/qqbot:$HOME/.hermes/telegram:$HOME/.hermes/cache:$HOME/.hermes/tmp:/path/to/media"
Optional Jamendo smart BGM configuration:
JAMENDO_CLIENT_ID=your_client_id
JAMENDO_CLIENT_SECRET=your_client_secret
JAMENDO_CLIENT_SECRET is reserved for future use. It is not sent to Jamendo and is not written to job metadata.
Transparency and direct-edit flags (API transport):
| Flag | Default | Effect |
|---|---|---|
CASSETTE_API_STREAM |
on | SSE run-event listener feeding timeline_delta/plan_progress; 0 = pure polling |
CASSETTE_PLAN_REVIEW |
user on MCP, auto on gateway |
surface edit_plan_review as a question vs auto-approve |
CASSETTE_UNATTENDED |
off | 1 restores fully headless auto-approve semantics |
CASSETTE_DIRECT_EDIT |
off | enable the cassette_edit surgical no-LLM lane |
CASSETTE_AUTH_TOKEN |
unset | pre-issued bearer, skips /api/agent-auth/verify (local dev/CI) |
CASSETTE_WEB_URL |
origin of CASSETTE_URL |
web origin used for editor_url deep links |
Development
Click here to expand development details Create a local test environment:uv venv .venv
uv pip install --python .venv/bin/python pytest playwright
.venv/bin/python -m playwright install chromium
Run checks:
python3 -m compileall -q .
.venv/bin/python -m pytest -q
Run the real stdio MCP process against the development environment:
CASSETTE_MCP_SKIP_BOOTSTRAP=1 \
CASSETTE_MCP_PYTHON="$PWD/.venv/bin/python" \
.venv/bin/python scripts/run_local_mcp.py
The deterministic test suite covers core parity, all 11 tools, real stdio protocol calls, long-polling, restart/resume behavior, state transitions, resource links, auth and filesystem security, both plugin manifests, the existing Hermes/web suite, and frontend builds. Maintainer-triggered live E2E uses repository secrets through ephemeral environment variables; PR CI stays credential-free.
Run the local Cassette E2E harness:
.venv/bin/python scripts/e2e_local_cassette.py \
--media tests/fixtures/sample.mp4 \
--instruction "Make a short captioned video under 10 seconds."
Cassette transport
The plugin can reach Cassette two ways, selected by CASSETTE_TRANSPORT, and both are fully supported — pick whichever fits your deployment:
api(default) — calls the Cassette server APIs directly (auth → media upload → LangGraph agent run → render-from-stored-project export), no browser. This is the default because it avoids the reliability weakness of DOM scraping and needs no Playwright/Chromium. It reuses your existingCASSETTE_AUTH_EMAIL/CASSETTE_AUTH_PASSWORD; the API origin defaults to the deployed Cassette (override withCASSETTE_API_URLonly for self-hosted). Requirement: the account must have full API access (for/api/projectsand/api/export) — a403/forbiddenerror reported by the transport indicates it does not, in which case setCASSETTE_TRANSPORT=browser.browser— drives the Cassette web UI with Playwright (the original, battle-tested path). SetCASSETTE_TRANSPORT=browserto use it. Requires Playwright/Chromium installed. Behavior is byte-identical to the pre-transport-seam plugin.
Switching is a single env var and nothing downstream changes: both transports return the identical job-result dict, so notifications, delivery, and reporting are the same either way.
Uploaded media is linked to the agent run by session id (the upload x-session-id equals the run's mediaSessionId), and the run carries the same full session/project/run context the editor sends. Before starting the run, the transport waits for uploaded media to be fully processed — analysis evidence/embeddings (which the agent reads) and the render-source derivative (which the export needs) — so it never commits an empty edit or hits an "render-source is missing" export (tunable via CASSETTE_API_MEDIA_READY_TIMEOUT_SEC). Cancellation (/cut) is honored mid-run, agent timeouts report timed_out, and a run whose queue never starts fails fast as agent_run_not_started (tunable via CASSETTE_API_RUN_START_TIMEOUT_SEC) instead of hanging until the job timeout. The transport requires the Cassette backend's LangGraph run queue to be draining runs and its media render-source pipeline to be healthy.
The API path aims for behavioral parity with the browser path: it honors the user's model choice (mapping the UI label to a model id, and failing loudly under CASSETTE_REQUIRE_MODEL_SELECTION if unmappable) and CASSETTE_DEFAULT_THINKING_LEVEL; sends the model-selection notice; records live stage progress (current_stage, stage_timings, progress_events) and delivers a periodic text progress heartbeat (there is no browser to screenshot); classifies Cassette questions so routine ones auto-continue while genuine choices/missing-assets return needs_user; dedupes uploads across a reused session; and, like the browser path, routes a completed edit through the Hermes supervisor completion review (cassette_review_completion) before exporting — set CASSETTE_API_AUTO_EXPORT=1 to export directly on agent success instead. The one irreducible difference is final_screenshot: with no browser, the transport substitutes a still frame extracted from the exported mp4 (CASSETTE_API_EXPORT_THUMBNAIL).
The same E2E flow can run on either transport, and a parity harness diffs the two outcomes (terminal status, deliverable-output count, error-code set):
# single transport
.venv/bin/python scripts/e2e_local_cassette.py --transport api \
--media tests/fixtures/sample.mp4 --instruction "Make a short captioned video."
# browser-vs-api parity (requires a full-access account; the render-from-project export endpoint
# must be live on the Cassette server)
.venv/bin/python scripts/e2e_transport_parity.py \
--media tests/fixtures/sample.mp4 --instruction "Make a short captioned video."
Run the web demo service:
uv venv .venv-web
uv pip install --python .venv-web/bin/python -r requirements-web.txt
.venv-web/bin/python -m playwright install chromium
# Build the browser UI (Vite/React -> web_demo/frontend/dist); requires Node.js + npm.
./web_demo/build_frontend.sh
set -a
. ./oh-my-cassette-web.env
set +a
.venv-web/bin/python -m web_demo.server
The browser UI is a Vite + React + TypeScript app under web_demo/frontend; web_demo/build_frontend.sh compiles it to web_demo/frontend/dist, which the server serves under /static. The build output is not committed, so build it on each deploy (and re-run it after pulling frontend changes). For live frontend iteration, cd web_demo/frontend && npm run dev runs Vite with /api proxied to http://127.0.0.1:8088, so run the FastAPI server alongside it.
The web demo reads CASSETTE_*, DEEPSEEK_*, and OMC_WEB_* from process environment variables. Users can also enter a temporary DeepSeek API key in the browser settings; it is sent only with requests to this server and is not written to the repository or server disk. A systemd template lives at deploy/oh-my-cassette-web.service.example, with an environment template at deploy/oh-my-cassette-web.env.example.
Real gateway E2E tests are opt-in only and are skipped by default:
RUN_CASSETTE_E2E=1 .venv/bin/python -m pytest -q -m e2e
Public Repository Safety
Do not commit:
.envor.env.e2e;- real gateway tokens, account IDs, chat IDs, or raw
wxidvalues; - Cassette credentials;
- Jamendo credentials;
- downloaded media, exports, job state, browser traces, or local runtime cache.
Hermes runtime state belongs under ~/.hermes/cassette; Codex and Claude runtime state belongs under the platform-standard Oh My Cassette data directory. Neither belongs in this repository.
License
MIT. See LICENSE.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi