Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,27 @@ Use it to import media, change a project timeline, create motion graphics, gener
- `claude/.claude-plugin/plugin.json` - Claude Code plugin metadata.
- `grok/.cursor-plugin/plugin.json` - Grok Bot and Cursor plugin metadata.
- `codex/.mcp.json` - Codex MCP server configuration.
- `codex/skills/` - host adapters plus direct symlinks to canonical craft skills in `apps/agent/.claude/skills/`.
- `claude/skills/` - Claude-specific adapters plus direct symlinks to the same canonical agent skills.
- `codex/assets/` - plugin icons and brand assets, shared with Claude through a symlink.
- `codex/skills/` - packaged craft skills and Codex host adapters.
- `claude/skills/` - packaged craft skills and Claude-specific host adapters.
- `codex/assets/` and `claude/assets/` - bundled plugin icons and public-media indexes.

## Skill release ownership

Hosted Web plugin skills ship from this repository's `codex/` and `claude/`
packages. Desktop-connected agents receive separate skills from the ChatCut
app's `packages/skills`; updating those does not update these plugin packages.
When a shared workflow changes, port its host-relevant contract here and retain
Codex's MCP App and Claude's `show_widget` adapters. Shared MCP schemas,
renderers and catalog fields ship from the ChatCut application repository and
must be available on the connected server before a skill can use them.

Public media manifests live at `<plugin>/assets/widget-media/manifest.json`.
Claude resolves them through `CLAUDE_PLUGIN_ROOT`; Desktop's standalone skill
resource path is a different installation contract. Public avatar CDN URLs
come from the live catalog, so the plugin has no hardcoded avatar list. Media
files stay in `ChatCut-Inc/chatcut-widget-media`; private media is never
published there. Update each changed package's version and matching MCP
version header together, then run `node --test tests/*.test.mjs`.

## Requirements

Expand Down
4 changes: 2 additions & 2 deletions claude/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "chatcut",
"displayName": "ChatCut",
"version": "1.10.23",
"version": "1.10.24",
"description": "ChatCut plugin for editable video editing and creation workflows from Claude Code.",
"author": {
"name": "ChatCut",
Expand Down Expand Up @@ -37,7 +37,7 @@
"headers": {
"x-chatcut-mcp-client": "claude_code",
"x-chatcut-mcp-surface": "embedded-preview",
"x-chatcut-plugin-version": "1.10.23"
"x-chatcut-plugin-version": "1.10.24"
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion claude/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Video and audio exports render in your open ChatCut editor tab and download
through that browser. To deliver the file, the agent looks for it by name in
your downloads folder; it does not read other files there.

Optional forms load public catalog images and audio previews directly from
Optional forms load public catalog images, audio previews and official-avatar videos directly from
`cdn.jsdelivr.net`, outside the declared MCP connection. These requests expose
normal network request metadata to the CDN. Project media and transcripts are
not embedded in those public preview URLs.
Expand Down
118 changes: 117 additions & 1 deletion claude/assets/widget-media/manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"baseUrl": "https://cdn.jsdelivr.net/gh/ChatCut-Inc/chatcut-widget-media@bb7529532b2f97922f980d38251772370ac9d68f/widget-media/",
"baseUrl": "https://cdn.jsdelivr.net/gh/ChatCut-Inc/chatcut-widget-media@115f757787461b9c43236c496bb18d5eaf188b30/widget-media/",
"entries": {
"design-style/01c302d0-3b90-51e3-ae43-4a8a9ce947b5": {
"kind": "image",
Expand Down Expand Up @@ -252,6 +252,122 @@
"voice/sully": {
"kind": "audio",
"path": "voice-samples/elevenlabs-sully.mp3"
},
"scenario/app-promo-mg": {
"kind": "image",
"path": "scenarios/app-promo-mg.jpg"
},
"scenario/explainer": {
"kind": "image",
"path": "scenarios/explainer.jpg"
},
"scenario/footage-to-shorts": {
"kind": "image",
"path": "scenarios/footage-to-shorts.jpg"
},
"scenario/motion-graphics": {
"kind": "image",
"path": "scenarios/motion-graphics.jpg"
},
"scenario/seedance-video": {
"kind": "image",
"path": "scenarios/seedance-video.jpg"
},
"scenario/talking-head": {
"kind": "image",
"path": "scenarios/talking-head.jpg"
},
"voice/baqiqingshu/ja": {
"kind": "audio",
"path": "voice-samples/doubao-baqiqingshu-ja.mp3"
},
"voice/dayi/ja": {
"kind": "audio",
"path": "voice-samples/doubao-dayi-ja.mp3"
},
"voice/houge/ja": {
"kind": "audio",
"path": "voice-samples/doubao-houge-ja.mp3"
},
"voice/huiben/ja": {
"kind": "audio",
"path": "voice-samples/doubao-huiben-ja.mp3"
},
"voice/jitangnv/ja": {
"kind": "audio",
"path": "voice-samples/doubao-jitangnv-ja.mp3"
},
"voice/liuchang/ja": {
"kind": "audio",
"path": "voice-samples/doubao-liuchang-ja.mp3"
},
"voice/morgan/ja": {
"kind": "audio",
"path": "voice-samples/doubao-morgan-ja.mp3"
},
"voice/naiqimengwa/ja": {
"kind": "audio",
"path": "voice-samples/doubao-naiqimengwa-ja.mp3"
},
"voice/popo/ja": {
"kind": "audio",
"path": "voice-samples/doubao-popo-ja.mp3"
},
"voice/qingcang/ja": {
"kind": "audio",
"path": "voice-samples/doubao-qingcang-ja.mp3"
},
"voice/ruyayichen/ja": {
"kind": "audio",
"path": "voice-samples/doubao-ruyayichen-ja.mp3"
},
"voice/silang/ja": {
"kind": "audio",
"path": "voice-samples/doubao-silang-ja.mp3"
},
"voice/tangseng/ja": {
"kind": "audio",
"path": "voice-samples/doubao-tangseng-ja.mp3"
},
"voice/vivi/ja": {
"kind": "audio",
"path": "voice-samples/doubao-vivi-ja.mp3"
},
"voice/wenroumama/ja": {
"kind": "audio",
"path": "voice-samples/doubao-wenroumama-ja.mp3"
},
"voice/xiaohe/ja": {
"kind": "audio",
"path": "voice-samples/doubao-xiaohe-ja.mp3"
},
"voice/xiaotian/ja": {
"kind": "audio",
"path": "voice-samples/doubao-xiaotian-ja.mp3"
},
"voice/xionger/ja": {
"kind": "audio",
"path": "voice-samples/doubao-xionger-ja.mp3"
},
"voice/yingtaowanzi/ja": {
"kind": "audio",
"path": "voice-samples/doubao-yingtaowanzi-ja.mp3"
},
"voice/yuanboxiaoshu/ja": {
"kind": "audio",
"path": "voice-samples/doubao-yuanboxiaoshu-ja.mp3"
},
"voice/yunzhou/ja": {
"kind": "audio",
"path": "voice-samples/doubao-yunzhou-ja.mp3"
},
"voice/zhishuaiyingzi/ja": {
"kind": "audio",
"path": "voice-samples/doubao-zhishuaiyingzi-ja.mp3"
},
"voice/zhixingnv/ja": {
"kind": "audio",
"path": "voice-samples/doubao-zhixingnv-ja.mp3"
}
}
}
2 changes: 1 addition & 1 deletion claude/skills/chatcut-plugin-basics-claude/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ Proceed without a new alignment round when the user already gave a clear brief w

Ask only for load-bearing information. Do not run a fixed checklist. Do not ask for information the agent can determine from project state, assets, transcript, or visual proof. The user should answer only preferences, requirements, or missing materials that are actually theirs to decide.

When structured input would reduce friction, load `widget-forms` and render one combined `visualize.show_widget` Elicitation form for all related fields. Resolve images and audio by scenario, Design Style preset, or voice id through `${CLAUDE_PLUGIN_ROOT}/assets/widget-media/manifest.json`; never put caller-provided S3, CloudFront, `app.chatcut.io`, relative, or other non-manifest media URLs into widget HTML. Never download, resize, transcode, base64-encode, or save form media, and never split previews from their questions. Submit only through `.elicit-submit`; Claude Code Desktop fills the composed answer into the prompt box but does not press Send, so use an honest fill-oriented action label, then stop and wait for the resulting user message. Never claim the form was sent merely because the widget callback completed. Do not use `sendPrompt(...)` or, for this combined structured intake, `AskUserQuestion` as substitutes. Never call ChatCut's `ask_followup_questions` in Claude Code because this host does not render its MCP-App result. If `show_widget` is genuinely unavailable, ask concisely in ordinary chat. Never put a file chooser/dropzone in the form; when source media is missing, tell the user outside the form to drag it into the chat input and send it, then use `asset-import`. Do not emit raw internal ChatCut chat tags directly to the user.
When structured input would reduce friction, load `widget-forms` and render one combined `visualize.show_widget` Elicitation form for all related fields. Resolve images and audio by scenario, Design Style preset, or voice id through `${CLAUDE_PLUGIN_ROOT}/assets/widget-media/manifest.json`; official avatars additionally use only the live catalog's `widgetPreviewVideoUrl` / `widgetPreviewImageUrl` on `https://cdn.jsdelivr.net`, as `widget-forms` specifies. Never put caller-provided S3, CloudFront, `app.chatcut.io`, relative, provider, or private/runtime media URLs into widget HTML; never invent CDN paths. Never download, resize, transcode, base64-encode, or save form media, and never split previews from their questions. Submit only through `.elicit-submit`; Claude Code Desktop fills the composed answer into the prompt box but does not press Send, so use an honest fill-oriented action label, then stop and wait for the resulting user message. Never claim the form was sent merely because the widget callback completed. Do not use `sendPrompt(...)` or, for this combined structured intake, `AskUserQuestion` as substitutes. Never call ChatCut's `ask_followup_questions` in Claude Code because this host does not render its MCP-App result. If `show_widget` is genuinely unavailable, ask concisely in ordinary chat. Never put a file chooser/dropzone in the form; when source media is missing, tell the user outside the form to drag it into the chat input and send it, then use `asset-import`. Do not emit raw internal ChatCut chat tags directly to the user.

Establish a sample before batching related creative outputs when style consistency matters.

Expand Down
18 changes: 14 additions & 4 deletions claude/skills/digital-human/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,21 @@ Ask one most important missing question at a time and do not repeat answered que
The raw tags below are the embedded ChatCut protocol only. In a published Codex or
Claude Code plugin, the Widget Forms Skill's host adapter takes priority: never emit
raw ChatCut tags. Map each live identity to the host's visual-choice surface using
`identityId` as its stable value and `name` as its label. In Codex, supply
`identityId` as its stable value and `name` as its label. In Codex, pass
`previewVideoUrl` as `previewVideo` and `previewImageUrl` as `preview` so the image is
the video's poster and failure fallback. Keep the create action
as a separate `create_avatar` value; plugin hosts return that value to the workflow
instead of opening ChatCut's native dialog automatically.
the video's poster and failure fallback. External avatar pickers use 4:5 portrait
framing. Claude uses only the official catalog's returned
`widgetPreviewVideoUrl` and `widgetPreviewImageUrl` on the public CDN; never embed
provider or private runtime URLs. Omit identities without public widget media
from Claude's media cards and explain that their preview is available in ChatCut.

After the identity cards, include both a localized `create_avatar` action and
Other with a text entry. Codex uses `id:"__other__"` and `otherPlaceholder`;
Claude uses Widget Forms' host-wired Other control. Keep both entries even when
suitable identities are available. `create_avatar` returns to the creation
workflow instead of opening ChatCut's native dialog automatically. Other
returns the desired presenter requirements for a refined live catalog search;
it is neither an identity nor permission to create an avatar or generate video.
For a saved identity whose `list` row has no preview URLs, call `manage_avatar
action=get` for that exact candidate before rendering it; use the selected ready
revision's returned preview media and do not invent or copy media from another avatar.
Expand Down
17 changes: 17 additions & 0 deletions claude/skills/transcription/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,20 @@ Use `trigger_transcript` when the user explicitly wants transcription started or
For an `idle` or explicitly failed (`error`) run, call `trigger_transcript` with the asset id, then check transcription progress again. If an in-progress run has genuinely exceeded the stuck threshold, use `manage_transcript` action `retry_transcription` because `trigger_transcript` intentionally leaves in-progress work unchanged. The manage tool also remains available for low-level recovery where an external MCP host must supply prepared `audioBase64`. Repair source words with the transcript-fix action instead of rewriting visible captions when the source transcript itself is wrong.

For semantic speech edits, load `talking-head-guide` and use the Script workflow. Use mechanical cleanup only for fixed fillers and pauses; do not replace transcript-aware editing with destructive physical timeline cuts.

## Caption style choices

Apply Plain directly for a simple "add captions" request, and apply concrete
requested edits directly. When the user asks to see, compare, or choose caption
styles, load `widget-forms` before changing the project. Its caption-preview
reference covers ordinary presets, custom candidates and published Web MG
templates, with exact catalog revisions and language codes: `en`, `zh-Hans`,
`es`, `ja`, `zh-Hant`. Keep one Other entry for new style requirements; do not
add More or browse-catalog choices.

A sample style preview does not require transcription or generating content.
Codex uses `ask_followup_questions` caption cards; Claude keeps its
`show_widget` flow and states its inline-animation limitation. Preserve sample
versus project labels and wait for selection before applying. Re-read the
caption target and published revision before mutation; selection alone is not
application, and changed revisions require a fresh preview.
33 changes: 24 additions & 9 deletions claude/skills/voice/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,14 @@ owns the current host's form, attachment, and media-card behavior. This skill
owns the voice candidates, required fields, safety rules, and the asset ids
passed to voice tools. Do not embed host-specific UI instructions here.

In published Codex and Claude plugins, every ordinary voice chooser also ends
with one localized Other entry after the clone action. Other collects different
voice requirements and returns to live catalog discovery; it is not a voice,
a clone request, or permission to generate. The Widget Forms adapter owns the
input and host media restrictions. In Claude, retain ready custom voices as
label-only choices and audition them through a supported host media surface or
ChatCut before applying; do not embed private runtime URLs in `show_widget`.

"help me generate ... voice over in Chinese" is an English conversation asking
for Chinese narration, so the audition widget copy stays in English while the
voice candidates come from Doubao.
Expand All @@ -411,20 +419,25 @@ For an official audition:
returned official voices.
3. Load `widget-forms` and request one required `playable_single_choice`. Give
every official option the `voiceId`, localized `name`, `summary`, and
matching `sampleUrl` from the same returned tuple. Supply `sampleUrl`
matching `sampleUrl` and `sampleMediaKey` from the same returned tuple. Supply
`sampleUrl`
verbatim; never prepend an inferred S3, CDN, editor, localhost, or production
base URL, and never reconstruct it from the filename pattern. This differs
from a custom voice's `previewUrl`, which must be used exactly as returned by
`manage_voice`.
4. Always add one no-media action option with stable value `clone_voice` as the
final card on every ordinary recommendation/selection surface. Label it
`manage_voice` on a supported media surface. Claude's form adapter resolves
official samples from `sampleMediaKey` instead; it never embeds these source
URLs directly.
4. Always include one no-media `clone_voice` action on every ordinary
recommendation/selection surface. Label it
`Clone my voice` when no ready custom voice exists, or `Clone another voice`
when one does; localize it using the meanings above. In native ChatCut this
is a compact `<visual-option>` without `media`, not a separate button. In
external hosts it is the equivalent label-only option. A scenario-specific
reference may explicitly replace this ordinary surface with a narrower one.
5. Wait for the user to choose. If the answer maps to `clone_voice`, render the
host-specific cloning entry/workflow on the next turn; do not start cloning
5. Wait for the user to choose. For Other, refine the live catalog search from
the submitted requirements and show the updated choices; do not submit TTS.
If the answer maps to `clone_voice`, render the host-specific cloning
entry/workflow on the next turn; do not start cloning
from the audition reply itself. In the native editor the clone card opens
the cloning dialog itself and returns the saved voice to the same picker, so
the submitted answer is already that custom voice with its attached voice
Expand All @@ -442,7 +455,9 @@ stored name as its display label, `previewText` as its summary when present,
and the exact tool-returned `previewUrl` as audio media. Do not copy, download,
rewrite, validate by hostname, or invent that URL. If a ready voice lacks a
preview, omit it from the audition surface rather than making an unplayable
text-only card.
text-only card. Claude's explicit private-media fallback above takes priority
for its Elicitation form; never remove a ready custom voice merely because its
runtime URL cannot be embedded there.

Keep every option's type, submission id, display label, preview, summary, and
capabilities tied to the same `manage_voice` tuple. The target narration
Expand Down Expand Up @@ -828,8 +843,8 @@ If you need a specific voice and a particular language:
voice `list` gate when no concrete voice was named.
3. Never use explicit or inferred voice traits to exclude a ready custom voice
with a playable preview from the combined audition surface.
4. Never omit the final clone action card from a voice recommendation or
selection surface.
4. Never omit the clone action from a voice recommendation or selection
surface, or the following Other entry in a published plugin chooser.
5. Never submit TTS when the voice is only described broadly and the user has
not confirmed a concrete preset.
6. Never recommend or render a TTS voice option before calling `manage_voice
Expand Down
Loading
Loading