diff --git a/cursor/skills b/cursor/skills deleted file mode 120000 index c157dac..0000000 --- a/cursor/skills +++ /dev/null @@ -1 +0,0 @@ -../grok/skills \ No newline at end of file diff --git a/cursor/skills/asset-import b/cursor/skills/asset-import new file mode 120000 index 0000000..575cb59 --- /dev/null +++ b/cursor/skills/asset-import @@ -0,0 +1 @@ +../../grok/skills/asset-import \ No newline at end of file diff --git a/cursor/skills/chatcut-plugin-basics/SKILL.md b/cursor/skills/chatcut-plugin-basics/SKILL.md new file mode 100644 index 0000000..eaafa16 --- /dev/null +++ b/cursor/skills/chatcut-plugin-basics/SKILL.md @@ -0,0 +1,257 @@ +--- +name: chatcut-plugin-basics +description: "Must read before using the hosted ChatCut plugin in Grok Bot, including creating projects, opening the editor, or editing/creating videos. Also use whenever video editing or creation should stay editable in ChatCut, even if the user does not mention ChatCut: edit or cut a video (剪视频、剪辑), add captions or subtitles (加字幕), clean up a talking-head recording (剪口播), add B-roll, music or motion graphics, or recreate, clone or remake a viral video with the user's own footage (复刻爆款、做同款). Also use when ChatCut tools are missing or need authentication. For ChatCut Desktop, follow its own instructions unless the user explicitly chooses the hosted plugin/web surface." +--- + +# ChatCut Plugin Basics + +## Purpose + +Host scope: this skill is written for Grok Bot using the Cursor-compatible plugin format. Use the host's native plugin authentication, browser, attachment, ordinary-chat, and image-bubble capabilities within the limits defined by `widget-forms`. + +Surface scope: this skill covers the hosted ChatCut plugin (`chatcut` MCP server) only. When the conversation uses ChatCut Desktop (`chatcut_desktop*` servers), follow the desktop server's own instructions and skip this skill unless the user explicitly chooses the plugin/web surface — desktop media is registered locally (no uploads) and delivery happens in the ChatCut Desktop window, not a browser. + +Use this as the base operating context whenever the agent works with a ChatCut project through the ChatCut plugin. + +This skill provides the common ChatCut project model, editing operating context, project onboarding flow, editor handoff rules, and connector boundaries. It does not provide detailed tool parameters, full task playbooks, or generation prompt recipes; load the matching ChatCut skill and use tool schemas for task-specific workflows. + +### MCP setup and authentication + +MCP-only setup rule: check the hosted `chatcut` MCP registration and +authentication first and use that connection exclusively. Do not check, install, +open, or troubleshoot ChatCut Desktop from this plugin, including when hosted +tools are missing or unauthenticated. + +ChatCut tools are served through the plugin's hosted `chatcut` MCP server. Treat the active MCP manifest and returned tool schemas as the runtime contract; do not assume a host-specific tool-name prefix. + +If the tools are available and authenticated, continue normally without discussing installation. If ChatCut is not installed, ask the user to add ChatCut from Grok Bot's **Connect apps** (sidebar on a computer; avatar at the top left, then Connect apps, in the phone app), or from Cursor's plugin marketplace when running in Cursor. If authentication is required, ask the user to use the host's Authorize or Authenticate control and complete ChatCut OAuth in the browser; if the host shows Waiting for authorization, use Reopen on the in-chat card or Reconnect on the installed app. If the plugin is installed but tools remain unavailable after authorization, start a fresh conversation and inspect the host's plugin/MCP connection status. Do not register a duplicate server, run another host's CLI, store tokens in configuration, or install ChatCut Desktop as a workaround. + +Explain whether installation, authentication, or connection failed and give the matching host-visible next step rather than only saying ChatCut is unavailable. + +In no-source validation, do not inspect ChatCut source code to learn parameters or hidden behavior. Use the MCP schema, HTTP tool manifest, these skills, and project/editor state. + +## Role + +When working in ChatCut projects, act as a professional video editing assistant. The user thinks in clips, cuts, stories, and visible outcomes, not data structures. Use video-editing judgment to clarify needs, recommend a concrete strategy, and execute the requested edit. + +Align on needs and concrete strategy before creative or strategic work that shapes the output: video use case, content form, output format, source-material strategy, creative direction, or editing approach. Mechanical operations such as renames, small property changes, obvious undo, and user-specified item edits can execute directly. + +## Your Environment + +ChatCut is a browser-based multi-track non-linear video editor. A project holds one or more timelines, each with its own canvas (fps, width, height), video tracks, audio tracks, timeline items, and a shared asset library. + +The MCP surface derives `userId` from connector auth. Project tools can list/create/target accessible projects; project-scoped tools should use the project id from those tool results or from the editor URL. + +Tool calls write through ChatCut Zero/DB/S3 paths, so editor changes should be real and visible. Do not write directly to the database. Do not infer hidden IDs; read them from the matching project, timeline, item, or asset tool result. A project-specific connect failure is an access/session problem, not a request to try repo debugging. Confirm the editor is signed in as the same account used by the connector, verify the project id exactly, and confirm the user has access to that project. + +The preview surface is the live ChatCut editor. The user can have the project open while the agent works through the plugin. Project changes should become visible in the editor; the visible editor is part of the user experience, not just a proof surface. + +The agent works from project data, tool results, transcripts, assets, and composed timeline proof. Do not assume the browser view, project state, or timeline layout is still the same after time has passed; the user may have edited the project manually. + +Visual understanding has two distinct surfaces: + +- To inspect raw imported or attached source media, use host-native visual/file capabilities on the source bytes when available. Do not create a temporary timeline just to inspect source assets. +- To inspect media as it currently appears on the ChatCut timeline or editor, use `preview_timeline` with `views:["viewer"]` and bounded frames. This includes placed clips, trims, crops, captions, overlays, effects, and final framing. + +Export is a connector boundary in plugin sessions: load `export`, call +`submit_export`, then use `track_export`. The default browser export downloads on +the rendering computer and has no `downloadUrl`; deliver only the actual completed +result according to the export Skill. + +## Data Model + +### Project + +A project is the top-level container. It owns a shared asset library and one or more timelines. Each timeline defines its own canvas and contains tracks, items, and timeline-local structure. + +Unless the user says otherwise, edits should target the intended active or targeted project and timeline. If the target is ambiguous, establish the project before doing nontrivial work. + +### Assets + +Assets are source media in the project library. One asset can be referenced by many timeline items. + +Agent-facing asset types include video, audio, image, gif, motion-graphic, and svg. Content-level properties such as source media, filename, remote readiness, and Motion Graphic code/properties belong to the asset. + +If the user asks to use, edit, place, replace, caption, trim, inspect, or otherwise work with an asset but does not attach or explicitly provide the source in the current conversation, do not immediately treat it as missing. Users can upload media directly in the ChatCut editor, so first inspect the targeted project's asset library with `browse_assets` and match by filename, type, visible content, transcript state, or other available metadata. Ask the user to upload or provide the asset only when it is not present, not ready, inaccessible, or ambiguous after checking project assets. + +### Tracks + +Tracks are lanes on the timeline. + +Video tracks stack. Higher video tracks render above lower tracks; an item on an upper track covers lower video during its duration, and lower video shows through where the upper track is empty. If audio continues while no video item is visible, the rendered canvas can show black. + +Audio tracks mix in parallel. Audio tracks do not cover each other; multiple audio tracks playing at the same moment are audible together. + +Items on the same track must not overlap. Locked tracks should not be edited until the user unlocks them. + +Sequential clips belong on the same track in increasing time order. Layered visuals such as overlays, B-roll, and Motion Graphics belong on higher video tracks above the content they cover. + +### Items + +Items are timeline instances of assets. Each item references an asset and owns placement and timing. + +Change an item to change when or where something appears: timeline start, duration, track, position, size, opacity, fades, source offset, or playback speed. Change an asset to change reusable source content, Motion Graphic code, or Motion Graphic property defaults. + +Timeline placement and duration are frame-native. User-facing summaries may use seconds, but timeline edits should preserve exact frame state from project data when available. + +Motion Graphics follow the same split: visual code and editable properties belong to the asset; timing, position, size, and per-instance property overrides belong to the item. + +### Editing operations - defaults and ripple + +Timeline edits leave gaps by default. + +Deleting an item removes it without automatically moving later items unless ripple behavior is explicitly used. Shortening an item leaves a gap; later items must be moved intentionally if the gap should close. Adding into an occupied same-track range is rejected unless the edit makes room. + +Ripple affects only the same track. After ripple or other structural edits, related tracks such as captions, Motion Graphics, B-roll, and music may no longer align with the edited speech or video and should be checked. + +On overlap conflicts, first decide whether the content is sequential or layered. Sequential content belongs in time order on the same track. Layered content belongs on a higher video track. + +## Alignment & Execution + +### How to Align Before Acting + +Understanding the user's intended outcome is the foundation of creative editing. Clarify before committing to creative or strategic choices. + +Alignment calibrates to how much the user has already given: + +- "Make a 1-minute YouTube cut of this interview" gives platform and length, but may still need confirmation on what to keep. +- "Cut this podcast into highlights" is vague; align on target platform, length, and what counts as a highlight. +- "Make a promo for our app" with a product URL but no brand assets may need alignment on logo/assets, platform, aspect ratio, duration, production approach, and tone. +- "Add English subtitles" is clear and narrow; execute. +- "Make it shorter" or "keep going" after prior alignment usually does not need a new alignment round. +- "Make a promo video for my product" without product type is ambiguous; clarify product type, target platform, and use case before choosing a scenario. + +### When to align + +Align when the request involves a new project, vague creative intent, paid or time-consuming generation with missing creative details, multi-shot or multi-asset consistency, or a major fork such as voiceover versus music-only, cinematic versus casual, what to keep, or which features to highlight. + +For dependent major steps, confirm the foundation before building downstream work when practical. Motion Graphics, music, and captions depend on the speech/structure edit; image and video generation depend on the approved script or direction. + +### When to skip + +Proceed without a new alignment round when the user already gave a clear brief with target, style, and constraints; the task is mechanical and reversible; the user said to continue; the user gave a follow-up correction; or the user explicitly asked to run end-to-end. + +### How to align well + +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`. Use Grok Bot's native option cards or concise ordinary text choices. The only media-choice enhancement is downloaded image bubbles for MG references or Design Style thumbnails, followed by those choices. Ask for missing source media separately through a supported import path or the host's readable-file import path (see `asset-import`). + +Establish a sample before batching related creative outputs when style consistency matters. + +## Verify Before Modifying + +Before changing timeline items, tracks, or assets, refresh only the relevant discovery stage when it may be stale or unknown. The user may have changed the project manually in the browser since the last turn. + +Do not rely on stale item ids, track layout, asset readiness, transcript state, or previous timeline placement when making project-scoped edits. + +`read_project` returns only the project map and timeline directory; omitted details are unknown, not empty. Use `preview_timeline` for timeline tracks, paginated items, gaps, markers, composed frames, and bounded speech. Request only the needed `views`, and narrow timeline reads with `tracks`, `itemIds`, `fromFrame`, or `toFrame`. Use `inspect_item` for complete placed-item detail (up to 10 items per call via `itemIds`), `browse_assets` for the source library, `inspect_asset` for source-asset detail, and `manage_media_pool` for folders. Follow `nextOffset` when the needed timeline entry is not on the current page. Do not call several discovery stages in parallel or reconstruct the full topology by default. + +## Do Only What Was Asked + +Execute the user's request, then stop. Do not silently add unrequested music, captions, transitions, B-roll, color grading, or other enhancements. Suggest additions when useful, but do not perform them without user intent. + +At editing checkpoints, prioritize the live ChatCut project as the review surface. Do not turn a checkpoint into an export just because the timeline changed. Export only after the user asks for export/render/download/final delivery, after all planned editing stages are approved and the current step is final delivery, or when the user requested a standalone deliverable and no further review checkpoint is pending. + +Do not infer export intent from broad editing requests such as "edit this video", "cut this down", "clean this up", "make a version", or similar phrasing. By default, a ChatCut editing request delivers an editable timeline for review, not a downloadable MP4. Agent verification is not user approval; after verification, keep the live project available and let the user decide whether to continue editing or export. + +When reporting a reviewable edit, pair the concise result summary with a natural next step based on the visible surface. If the editor is open or available, it is appropriate to mention that the user can click Play in the editor to watch the result; phrase it conversationally and contextually, not as a fixed approval script. + +For a ChatCut review checkpoint, "project", "version", "cut", "montage", or "put it in ChatCut" means an editable ChatCut timeline unless the user explicitly asks for a standalone finished file. Do not satisfy a ChatCut editing request by locally rendering one flattened MP4 and placing only that finished MP4 on the timeline. For multi-source work such as B-roll, highlight reels, or travel montages, build from original sources in ChatCut timeline items with trims, source offsets, ordering, layers, captions, audio, and effects. Use judgment on sequencing and scope; do not make local source screening a mandatory step before import when obvious or likely-needed originals can be uploaded while inspection continues. A flattened clip may be an extra reference only after the editable timeline exists, not the primary deliverable. + +## How You Think About Editing + +Start from the project context: what assets exist, where they are on the timeline, what is said, and what the viewer sees and hears. Go deeper only when needed. + +Editing has a natural order: get the structure right first, then refine timing, then add finishing touches. Doing this out of order creates rework because captions, Motion Graphics, B-roll, and music depend on the final structure. + +Think in terms of what the viewer sees and hears, not just individual tracks. + +Before reporting done, verify the actual result. For timeline edits, check that the intended items changed and that no unintended gaps, overlaps, or misplaced layers remain. After significant structural edits, check dependent elements such as captions, Motion Graphics, B-roll, and music. For generated or visual work, inspect an actual composed result before claiming it looks correct. + +## Design Style Consistency + +A Design Style is the project's visual identity: colors, fonts, style guidance, and real logos or reference images. It mainly shapes Motion Graphics and can also influence other on-screen text such as captions. + +When work spans several related visual outputs, align on or follow one coherent design style before batch production so the project reads as one family. Do not lock in a design style from an unconfirmed guess. + +Skip design-style work for one-off quick fixes unless the user asks for it. A single lower-third or small overlay is not automatically a project-wide design-style decision. + +## Project Onboarding And Editor Handoff + +### Establish the target project + +Before nontrivial ChatCut work, ensure the agent is operating on the intended project. + +"Switch project" means create or target a different ChatCut project, not a new timeline, unless the user explicitly says timeline or version. + +First action for a new ChatCut task: use `list_projects`, `create_project`, `target_project`, or `get_editor_url` through the ChatCut MCP tools. Do not start by debugging the repo, starting local dev services, or opening external browsers. + +1. If the user asks for a new project, call `create_project` and surface the clean live editor link immediately so the user can open it and watch progress. +2. If the user asks to use ChatCut for attached media, imported files, filler removal, captions, export, or motion graphics and no project is targeted, create or target the project before long analysis, generation, transcription waiting, or clarification that is not required to choose the project. +3. For a generic new job ("my videos", attached files, imported files, "use ChatCut for this") create a fresh project shell unless the user names an existing project, the prompt clearly says to continue/switch to an existing project, or an existing editor URL/context clearly identifies the active project. Do not pick a plausible-looking existing project from `list_projects` just because its name matches the task category. +4. If the user refers to an existing project and no project is targeted, call `list_projects`, choose the intended accessible project, then call `target_project`. +5. If the user asks to duplicate/copy a whole project (safety copy before risky edits, a language or variant version), call `duplicate_project`. It defaults to the currently targeted project. To edit the copy afterwards, pass the returned `newProjectId` as `projectId` explicitly on subsequent tool calls — an explicit per-call `projectId` always wins over session targeting. Pass `activate: false` to keep the source targeted. Owner-only; markers and chat history are not copied. For a variant of one cut inside the same project, use `manage_timelines` `action: "duplicate"` instead. +6. If the user asks to delete a project, call `delete_project` with an explicit full projectId — it never defaults to the targeted project. This is the dashboard's soft delete: data is retained and `restore_project` undoes it; `list_projects` with `includeDeleted: true` shows restorable projects. + +### Use the current editor project + +If a ChatCut project is already available from an editor URL, read the `projectId` from the `/editor/` URL and pass it directly to project-scoped tools. + +If `chatcut` asks for authentication or project access, ask the user to select Reconnect on ChatCut under Grok Bot's Connect apps (or re-authorize ChatCut in Cursor's plugin settings), then retry with the exact `projectId` from the editor URL. + +### Open the visible editor + +Surfacing the editor link early is part of the user experience: the user can open the NLE, media pool, transcription, generation, and timeline placement while work continues. + +`list_projects` is discovery, so it should not pick or retarget to one listed project unless the user chose it or the active context clearly identifies it. Once a specific project is created, targeted, or chosen for visible work, always present the clean project/editor URL returned by the tool as a named link. Do not depend on a preview tool, popup, card, or browser handoff opening automatically. + +When a ChatCut tool result includes a live project/editor URL, `liveProject`, `browserHandoff`, `structuredContent.browserHandoff.required=true`, or `browserHandoff.required=true`, use the clean returned `editorUrl` for the user-facing named link. A browser-control capability may additionally open the handoff URL, but that is optional and never replaces sending the clean editor link. + +ChatCut can take a while to load after the tab opens, especially for a new project, a cold session, or media-heavy editor state. If the browser-control tool reports that it successfully opened or focused the tab, treat the handoff as complete; do not wait for the page to fully load, keep polling the browser, or perform extra careful visual checks just to prove the editor opened. Continue with the ChatCut plugin workflow and only inspect the browser when the task itself requires visible verification. + +Present the clean `editorUrl` as a named link whether or not browser or computer-control tools are available. Preserve all query parameters only in an internal handoff URL when they are needed for opening the browser; do not copy short-lived authentication or editor boot tokens into the user-facing link, and do not replace the returned URL with a guessed generic ChatCut URL. + +When sending or opening any editor URL, localize the editor-site path based on the language the user is using. Apply the same locale path rule to both the clean direct `editorUrl` and the internal-browser URL (`browserHandoff.url`): Chinese users should use `/zh/`, Spanish users should use `/es/`, and all other users should use the default English URL with no locale prefix. Preserve the same editor-site domain and the full remaining path, query string, and hash for each URL variant. + +Use the exact browser handoff or editor URL returned by the tools. Do not call guessed ChatCut MCP URLs, deprecated MCP routes, or app-bridge endpoints to drive a browser. + +### Keep the visible editor aligned + +The editor is a live workbench, not a popup-preview contract. Before long-running visible work such as import, transcription waiting, generation, timeline assembly, export preparation, or final visual verification, ensure the clean editor link still targets the latest project id. Internal preview tools remain valid for agent verification, but final delivery must include the clean editor link and must not claim that a preview automatically opened. + +### Billing and pricing exception + +If a ChatCut tool returns a pricing or billing URL, present it as an external browser link via `open ` / system browser. Do not treat billing as an editor handoff. + +## Recreating A Viral Video + +Requests to recreate, clone, or remake a viral or reference video with the user's own people, product, or footage (复刻爆款、做同款) happen in the ChatCut Desktop app, and generating them needs a membership; this host cannot install it. Say so plainly and give the user https://chatcut.io/viralvideocloner, which has the download and a message they can send to a local agent such as Codex or Claude Code. Keep using the hosted tools for any ordinary editing in the same request. Work only with media the user owns or is licensed to use. + +## Connector Boundaries + +ChatCut plugin access is based on connector authentication and the user's accessible projects. Project-scoped operations should use project ids from tool results, editor URLs, or current project state. Do not guess hidden ids. + +The connector cannot ask the editor UI to pick, relink, upload, export, or capture local files for it unless the current host explicitly exposes that capability. Local files, attached files, browser-held files, and public URLs must enter the project through the appropriate media import or asset acquisition path before timeline use: + +- The `asset-import` skill for files the current host can read locally. +- `import_media` for client-held bytes. +- For public URLs, download the selected media locally first, then use `import_media` for that file. + +If a local-file upload/import request is denied by host policy or review because it would transfer private file contents to ChatCut's external API, stop the ChatCut workflow immediately. Do not fall back to local editing, local-only registration, local rendering, source inspection, or extra workaround steps. Tell the user permission to upload the file was denied and instruct them to upload the media directly in the ChatCut editor or adjust the host permission. + +For raw source-frame inspection, use the local source file directly with host-native tools such as `ffmpeg` when the file is available. If the agent has the original path, including an import-helper `sourcePath`, do not call remote ChatCut tools just to inspect source frames. If the agent does not have the original file because the asset was uploaded in the editor or only exists in project storage/cache, use `inspect_asset` with the project asset id. Hosted frame tools return each rendered frame as a separate temporary image resource link. If the host cannot inspect a signed URL directly, download each complete URL into a temporary folder, then inspect the local files individually or stitch the temporary copies into a contact sheet. Use `preview_timeline` with `views:["viewer"]` for composed timeline proof, and never claim visual verification without inspecting the pixels. + +In ChatCut plugin workflows, local `ffmpeg`/`ffprobe` is for read-only source inspection and non-editorial diagnostics only: probing metadata, checking streams, or extracting still frames from locally readable source files. Do not use local `ffmpeg` to create a pre-edited, pre-composited, caption-burned, mixed-down, or otherwise flattened video as the main artifact for a ChatCut editing task. Upload/processing time, many source clips, or a desire to make review faster is not a reason to flatten locally. User-visible edits must remain editable ChatCut project state: source assets plus timeline items, trims, captions, audio items, overlays, effects, and ChatCut export when a rendered file is needed. + +Do not assume the browser/editor tab can pick, relink, upload, export, or capture local files as a substitute for connector import/export flows. + +ChatCut native internal chat components may not render in every host. Convert those moments into ordinary chat or an available structured follow-up/form capability. + +If an edit changes spoken words, pauses, retakes, or transcript selection, use the Script-based speech editing workflow from `talking-head-guide` rather than physical timeline deletion as the main edit method. + +When captions are enabled, complete one coherent stage of timeline or transcript work before refreshing them: after batched `apply_script`, `clean_script`, or `manage_transcript` with `action:"fix"` calls, run `edit_captions` with `action:"refresh"` once before caption-specific edits or claiming caption correctness. Do not refresh between individual mutations or when captions are disabled; honor a tool-returned caption-refresh notice at the next completed work boundary. + +For Motion Graphics, load `create-motion-graphics` and follow the current ChatCut tool schema. Do not stage Motion Graphic JSX in the repository, local HTTP servers, temporary files, or guessed backend workspaces. + +Use the relevant ChatCut task skill for media import, transcription, talking-head editing, Motion Graphics, generation, voice, music, verification, export, product help, and error recovery. Shared craft comes from the canonical agent tree; host-specific behavior stays in this plugin's adapters. diff --git a/cursor/skills/create-motion-graphics b/cursor/skills/create-motion-graphics new file mode 120000 index 0000000..92baa20 --- /dev/null +++ b/cursor/skills/create-motion-graphics @@ -0,0 +1 @@ +../../grok/skills/create-motion-graphics \ No newline at end of file diff --git a/cursor/skills/digital-human b/cursor/skills/digital-human new file mode 120000 index 0000000..1a21c6a --- /dev/null +++ b/cursor/skills/digital-human @@ -0,0 +1 @@ +../../grok/skills/digital-human \ No newline at end of file diff --git a/cursor/skills/export/SKILL.md b/cursor/skills/export/SKILL.md new file mode 100644 index 0000000..9ec5b1a --- /dev/null +++ b/cursor/skills/export/SKILL.md @@ -0,0 +1,93 @@ +--- +name: export +description: Hosted ChatCut plugin sessions only (the `chatcut` MCP server). If the conversation is driving ChatCut Desktop (a `chatcut_desktop*` MCP server), load this skill only when the user explicitly chooses the plugin/web surface — desktop sessions otherwise ship their own instructions and tools. Export or deliver a ChatCut project through the hosted connector, including video, audio, subtitles, XML, and render-status checks. +--- + +# Export + +Export only when the user asks for a render, download, or final standalone deliverable. A review checkpoint normally stays as an editable ChatCut timeline. + +Use `submit_export` with the current tool schema. Confirm the target timeline, range, resolution, codec, and format from project state and user intent; do not guess a non-active timeline. Record every returned `renderId`. + +Video and audio default to `renderMode:"local"`: the connected ChatCut editor +tab renders the timeline. Open the returned editor URL, activate the requested +timeline, and keep that tab open through completion. If no capable editor is +connected, resolve that error before retrying. There is no automatic cloud retry. +Media already readable by that editor does not need another upload for this route. +If the user explicitly chooses cloud, use that choice directly without requiring +browser or Desktop setup first. + +A server-side active-timeline result does not prove that an already-open browser +tab switched timelines. Confirm the intended timeline in that tab, or ask the +user to select it, and pass its explicit ID when submitting the export. + +Use `track_export` for browser and cloud export status; do not use +generation/transcription `track_progress`. Pass the returned `renderId` for an +accepted job. A `wait` call is a single status read; honor its check-back guidance. +If submission timed out, follow Local Export Recovery before resubmitting to +avoid duplicate jobs. + +## Local Export Recovery + +For video/audio recovery, consume `details.exportRequest` and `details.recovery` from the tool error when present. Keep the exact project, timeline, full or partial range, format, codec, resolution, output frame rate, and existing request/render identifiers. Do not substitute the visible project or another timeline. `details.exportRequest.range` describes the entire timeline, source-timeline frames, or seconds; it is metadata, not a `submit_export` argument. Frame bounds use the timeline rate, not output `fps`. If an older server returns only an error and hint, preserve those details and read the intended scope from the original request. + +Follow the reported recovery action: `restore_local`, `wait_for_capacity`, `check_existing_export`, or `resolve_export_error`. When `details.recovery.track` is present, call `details.recovery.track.tool` with `details.recovery.track.arguments`; do not replace them with an unrelated latest export or the new request's key. A legacy `details.requestId` is a correlation ID, not a `renderId` or protocol-v2 `idempotencyKey`. A busy browser needs time to finish its accepted work. An uncertain acknowledgement needs the original export's outcome known before another local, Desktop, or cloud submission. Missing or unreadable media needs its reported source issue resolved; do not upload files or switch renderers without addressing that issue. These cases do not justify an automatic cloud retry. + +When browser-local export is unavailable, explain the specific blocker briefly. If this host exposes ChatCut Desktop tools or the user has a suitable computer, offer the existing Desktop path as a local alternative. Cloud remains available when no usable local path exists or the user chooses it, provided the original request permits cloud rendering. Call `details.recovery.cloudFallback.tool` with `details.recovery.cloudFallback.arguments` when supplied; do not pass the descriptive `exportRequest` object as tool arguments. Follow Cloud Rendering to disclose the actual quote; a free cloud quote needs no extra confirmation and a nonzero charge needs one explicit confirmation. Honor explicit local-only, no-upload, and other original constraints; do not require Desktop installation or a failed Desktop attempt. If recovery instead reports `cloudLimitation`, explain it rather than inventing a fallback or changing the requested range, format, or quality. For an older server without recovery metadata, use the current tool schema and preserved request with `renderMode:"cloud"` only after establishing the same local-unavailability and authorization conditions. Never select cloud merely to obtain a download URL. + +For a Desktop handoff, honor `details.recovery.desktopLimitation`. Desktop video supports H.264 MP4, not VP8/WebM: keep VP8 in a supported Browser/cloud path rather than silently changing its format. `details.recovery.desktopExportSettings`, when present, contains only compatible output settings, not a complete callable request. For H.264 use `videoProfile:"sdr_h264"` and `videoBitrateMode:"recommended"` so old Desktop export preferences do not change the handoff. For audio use `format:"audio",codec:"mp3"` without video fps, resolution or profile. Older servers without these fields require the same compatibility checks against the actual Desktop schema. + +Use `details.recovery.desktopUrl` when returned for a compatible Desktop handoff; otherwise use Desktop's existing project library only after checking that it can produce the requested output. `details.recovery.editorUrl` opens the browser project. Hosted `submit_export(renderMode:"local")` renders in a browser; it does not become a Desktop tool. Open the source project in Desktop with an account that can access it and wait for the required media to be readable. An existing local project with the same ID may contain older or different edits: check the intended content and never overwrite that copy automatically. + +If actual Desktop tools are available, call `target_project` with the preserved `projectId` and `openWindow:true`, then `read_project` to confirm the local content and target timeline. Name the same `projectId` on every Desktop read/export/track call; targeting does not replace that per-call scope. Call Desktop `export` with the intended `timelineId`, compatible output settings and an appropriate path on that computer. Preserve the video resolution and desired output fps explicitly when its schema accepts them. Desktop fps accepts 24, 25, 30, 50 and 60; omission inherits Desktop's current export preference, not necessarily the source rate. Never pass an unsupported fps such as 29.97 or silently round it to 30: retain Browser/cloud or verify a matching manual Desktop output. + +For a partial range, read the actual local project `frameRate` before converting the source-frame or seconds boundaries. Desktop frame bounds use that local rate, independently of output fps; Web summaries' inclusive end needs +1 before mapping to `endFrameExclusive`. A full export omits both bounds. Check the intended content, dimensions and range before exporting; an old local copy must not become a different export just because its range was clamped. + +Use Desktop `track_progress` with `target:"export"` and `exportTaskIds` set to the returned task ID. A queued `outputPath` is not a completed file. Wait for a successful terminal result and verify the file on that computer. If this host cannot call Desktop tools, provide the project-opening action and a concise export summary for the user to complete in Desktop's existing UI or Agent; do not promise remote control or file access on another device. + +## Delivery + +Deliver according to the completed result: + +- `source:"browser"`: relay `statusMessage`, filename, and available metadata. + The rendering tab downloads the file on its computer or writes to the chosen + file. This result has no `downloadUrl` or verified filesystem path. A tab on + Grok Bot's cloud computer downloads there, not to the user's laptop. Attach a + file only after the host locates and reads it; otherwise link the editor and + explain where to check its Export queue. +- A completed result with a `downloadUrl`: use the host's normal file/link + delivery. Download it only through a permitted host route when a local artifact + is needed. Do not invent a download URL for a browser export. + +Queued or running exports are not delivered. Report any render warnings and +their effect on the output. + +## Other Formats + +For subtitle export, first use `manage_timelines` to confirm the agent's active +timeline. If it differs from the requested timeline, use its `action:"switch"` +with that target and read back the active state before submitting. The hosted +subtitle path tested on 2026-10-16 reads captions from the agent's active timeline +even when `submit_export.timelineId` names another timeline; switching only the +browser tab does not resolve this. This is a compatibility guard, not a backend +fix. Keep the explicit export timeline ID and check the actual subtitle file's +text and timing before delivery. If captions are readable but export still +reports none after alignment, report the failure instead of regenerating captions +or constructing a replacement SRT and calling it a successful tool export. + +For NLE XML export, use the corresponding `submit_export` format and report +warnings about unsupported or dropped elements. `fcp_xml` is legacy `xmeml`, not +modern `.fcpxml`; do not promise a lossless project round trip or target-NLE +compatibility without testing it. For transparent Motion Graphic delivery, use +the dedicated MG export tool exposed by the current manifest and track the +returned render ids. + +## Cloud Rendering + +Use `renderMode:"cloud"` when the user asks for it or no usable local path exists and the original request permits it, following Local Export Recovery above. Cloud remains a supported fallback. Do not require a Desktop attempt or invent account entitlements. + +When `submit_export` returns `CLOUD_EXPORT_QUOTE_REQUIRED` with `details.quote`, it has not accepted a render. Tell the user the quoted duration, free allowance and `estimatedCredits` before starting. Retry the same export with `cloudQuoteId` set to that quote's `id`. A zero-credit quote starts directly without another confirmation. For a nonzero charge, obtain one explicit confirmation of that quoted amount, then set `confirmCloudCharge:true`; choosing cloud alone does not approve an unknown charge. Use the account policy returned by the server rather than assuming a free allowance or changing old benefits. + +Keep the same project, timeline, range, format and output settings for that quote. If it expires or the service requires a new quote, preserve the request and omit the stale `cloudQuoteId` to request a fresh quote. A larger charge needs new consent. If submission was accepted or uncertain, check the original job before retrying; never obtain a new quote to duplicate an in-progress export. + +If cloud rendering is blocked by media that is not remotely readable, use `asset-import` when the user permits upload, or report the blocker. Do not flatten or substitute the edit, upload sources, or switch a local export to cloud merely to obtain a download URL. diff --git a/cursor/skills/known-errors b/cursor/skills/known-errors new file mode 120000 index 0000000..6991617 --- /dev/null +++ b/cursor/skills/known-errors @@ -0,0 +1 @@ +../../grok/skills/known-errors \ No newline at end of file diff --git a/cursor/skills/lipsync b/cursor/skills/lipsync new file mode 120000 index 0000000..2292887 --- /dev/null +++ b/cursor/skills/lipsync @@ -0,0 +1 @@ +../../grok/skills/lipsync \ No newline at end of file diff --git a/cursor/skills/multicam-sync b/cursor/skills/multicam-sync new file mode 120000 index 0000000..c601fba --- /dev/null +++ b/cursor/skills/multicam-sync @@ -0,0 +1 @@ +../../grok/skills/multicam-sync \ No newline at end of file diff --git a/cursor/skills/music b/cursor/skills/music new file mode 120000 index 0000000..d8e6efd --- /dev/null +++ b/cursor/skills/music @@ -0,0 +1 @@ +../../grok/skills/music \ No newline at end of file diff --git a/cursor/skills/product-help b/cursor/skills/product-help new file mode 120000 index 0000000..b580393 --- /dev/null +++ b/cursor/skills/product-help @@ -0,0 +1 @@ +../../grok/skills/product-help \ No newline at end of file diff --git a/cursor/skills/shader-gen b/cursor/skills/shader-gen new file mode 120000 index 0000000..cf9f2ca --- /dev/null +++ b/cursor/skills/shader-gen @@ -0,0 +1 @@ +../../grok/skills/shader-gen \ No newline at end of file diff --git a/cursor/skills/talking-head-guide b/cursor/skills/talking-head-guide new file mode 120000 index 0000000..2148c34 --- /dev/null +++ b/cursor/skills/talking-head-guide @@ -0,0 +1 @@ +../../grok/skills/talking-head-guide \ No newline at end of file diff --git a/cursor/skills/transcription b/cursor/skills/transcription new file mode 120000 index 0000000..542e7b2 --- /dev/null +++ b/cursor/skills/transcription @@ -0,0 +1 @@ +../../grok/skills/transcription \ No newline at end of file diff --git a/cursor/skills/verification b/cursor/skills/verification new file mode 120000 index 0000000..f03826c --- /dev/null +++ b/cursor/skills/verification @@ -0,0 +1 @@ +../../grok/skills/verification \ No newline at end of file diff --git a/cursor/skills/video-gen b/cursor/skills/video-gen new file mode 120000 index 0000000..d6ba412 --- /dev/null +++ b/cursor/skills/video-gen @@ -0,0 +1 @@ +../../grok/skills/video-gen \ No newline at end of file diff --git a/cursor/skills/video-translation b/cursor/skills/video-translation new file mode 120000 index 0000000..d6211d8 --- /dev/null +++ b/cursor/skills/video-translation @@ -0,0 +1 @@ +../../grok/skills/video-translation \ No newline at end of file diff --git a/cursor/skills/visual-analysis b/cursor/skills/visual-analysis new file mode 120000 index 0000000..79edc9b --- /dev/null +++ b/cursor/skills/visual-analysis @@ -0,0 +1 @@ +../../grok/skills/visual-analysis \ No newline at end of file diff --git a/cursor/skills/voice b/cursor/skills/voice new file mode 120000 index 0000000..562c923 --- /dev/null +++ b/cursor/skills/voice @@ -0,0 +1 @@ +../../grok/skills/voice \ No newline at end of file diff --git a/cursor/skills/widget-forms b/cursor/skills/widget-forms new file mode 120000 index 0000000..428c3fc --- /dev/null +++ b/cursor/skills/widget-forms @@ -0,0 +1 @@ +../../grok/skills/widget-forms \ No newline at end of file diff --git a/grok/.cursor-plugin/plugin.json b/grok/.cursor-plugin/plugin.json index 0543f9a..915e8e9 100644 --- a/grok/.cursor-plugin/plugin.json +++ b/grok/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "chatcut", "displayName": "ChatCut", - "version": "1.10.20", + "version": "1.10.21", "description": "Edit videos in ChatCut from Grok Bot: cut footage, add captions and subtitles, clean up talking-head recordings, add motion graphics and generated media, and export editable timelines.", "minClientVersions": { "cursor": "never" diff --git a/grok/mcp.json b/grok/mcp.json index 5d23974..a5c5a1e 100644 --- a/grok/mcp.json +++ b/grok/mcp.json @@ -5,7 +5,7 @@ "headers": { "x-chatcut-mcp-client": "grok", "x-chatcut-mcp-surface": "embedded-preview", - "x-chatcut-plugin-version": "1.10.20", + "x-chatcut-plugin-version": "1.10.21", "x-chatcut-install-source": "cursor_marketplace" } } diff --git a/grok/skills/chatcut-plugin-basics/SKILL.md b/grok/skills/chatcut-plugin-basics/SKILL.md index eaafa16..2ef2b32 100644 --- a/grok/skills/chatcut-plugin-basics/SKILL.md +++ b/grok/skills/chatcut-plugin-basics/SKILL.md @@ -54,8 +54,10 @@ Visual understanding has two distinct surfaces: - To inspect media as it currently appears on the ChatCut timeline or editor, use `preview_timeline` with `views:["viewer"]` and bounded frames. This includes placed clips, trims, crops, captions, overlays, effects, and final framing. Export is a connector boundary in plugin sessions: load `export`, call -`submit_export`, then use `track_export`. The default browser export downloads on -the rendering computer and has no `downloadUrl`; deliver only the actual completed +`submit_export`, then use `track_export`. In Grok, video and audio render in the +cloud by default: tell the user the returned quote, then fetch the completed +`downloadUrl` with `curl -fL` and send the file in this conversation. Use a local +browser export only when the user asks for it. Deliver only the actual completed result according to the export Skill. ## Data Model diff --git a/grok/skills/export/SKILL.md b/grok/skills/export/SKILL.md index 9ec5b1a..1804caf 100644 --- a/grok/skills/export/SKILL.md +++ b/grok/skills/export/SKILL.md @@ -9,17 +9,24 @@ Export only when the user asks for a render, download, or final standalone deliv Use `submit_export` with the current tool schema. Confirm the target timeline, range, resolution, codec, and format from project state and user intent; do not guess a non-active timeline. Record every returned `renderId`. -Video and audio default to `renderMode:"local"`: the connected ChatCut editor -tab renders the timeline. Open the returned editor URL, activate the requested -timeline, and keep that tab open through completion. If no capable editor is -connected, resolve that error before retrying. There is no automatic cloud retry. -Media already readable by that editor does not need another upload for this route. -If the user explicitly chooses cloud, use that choice directly without requiring -browser or Desktop setup first. - -A server-side active-timeline result does not prove that an already-open browser -tab switched timelines. Confirm the intended timeline in that tab, or ask the -user to select it, and pass its explicit ID when submitting the export. +In Grok, video and audio render in the cloud by default: call `submit_export` +without `renderMode` and ChatCut renders on its servers (up to 1080p), so no +browser tab has to stay connected. The project's media must already be in +ChatCut: files sent through the ChatCut upload page already are; for files you +imported with the upload helper, wait until `track_progress` with +`target:"upload"` reports them uploaded. Follow Cloud Rendering for the quote and +Delivery for the finished file. + +Use `renderMode:"local"` only when the user explicitly asks for a local export +or for 4K. The connected ChatCut editor tab then renders the timeline: open the +returned editor URL, activate the requested timeline, and keep that tab open +through completion. With `delivery:"host"` (Grok's default) it uploads the +finished file for you to fetch instead of downloading it on the cloud computer. + +For a local export, a server-side active-timeline result does not prove that an +already-open browser tab switched timelines. Confirm the intended timeline in +that tab, or ask the user to select it, and pass its explicit ID when submitting +the export. Use `track_export` for browser and cloud export status; do not use generation/transcription `track_progress`. Pass the returned `renderId` for an @@ -49,15 +56,19 @@ Use Desktop `track_progress` with `target:"export"` and `exportTaskIds` set to t Deliver according to the completed result: -- `source:"browser"`: relay `statusMessage`, filename, and available metadata. - The rendering tab downloads the file on its computer or writes to the chosen - file. This result has no `downloadUrl` or verified filesystem path. A tab on - Grok Bot's cloud computer downloads there, not to the user's laptop. Attach a - file only after the host locates and reads it; otherwise link the editor and - explain where to check its Export queue. -- A completed result with a `downloadUrl`: use the host's normal file/link - delivery. Download it only through a permitted host route when a local artifact - is needed. Do not invent a download URL for a browser export. +- A completed cloud result with a `downloadUrl` (the default): fetch it into + your own workspace with `curl -fL -o "" ""`, check the + saved file is `outputSizeBytes` bytes when reported, and send that file to the + user in this conversation as the result, following `cloudDownloadGuidance`. If + the download fails, call `track_export` once more and retry with its link; if + you cannot attach the file, give the user the `downloadUrl`. +- A local result with `delivery.status:"ready"`: fetch `delivery.downloadUrl` + the same way, check `delivery.sizeBytes`, and send the file, following + `hostDeliveryGuidance`. +- `source:"browser"` without host delivery: relay `statusMessage`, filename, + and available metadata. The rendering tab downloads the file on its computer; + a tab on Grok Bot's cloud computer downloads there, not to the user's device. + This result has no `downloadUrl`; do not invent one. Queued or running exports are not delivered. Report any render warnings and their effect on the output. @@ -84,10 +95,10 @@ returned render ids. ## Cloud Rendering -Use `renderMode:"cloud"` when the user asks for it or no usable local path exists and the original request permits it, following Local Export Recovery above. Cloud remains a supported fallback. Do not require a Desktop attempt or invent account entitlements. +Cloud is Grok's default for video and audio: omit `renderMode` (or pass `"cloud"`). It renders up to 1080p; 4K needs a local export the user asks for. Do not require a Desktop attempt or invent account entitlements. -When `submit_export` returns `CLOUD_EXPORT_QUOTE_REQUIRED` with `details.quote`, it has not accepted a render. Tell the user the quoted duration, free allowance and `estimatedCredits` before starting. Retry the same export with `cloudQuoteId` set to that quote's `id`. A zero-credit quote starts directly without another confirmation. For a nonzero charge, obtain one explicit confirmation of that quoted amount, then set `confirmCloudCharge:true`; choosing cloud alone does not approve an unknown charge. Use the account policy returned by the server rather than assuming a free allowance or changing old benefits. +When `submit_export` returns `CLOUD_EXPORT_QUOTE_REQUIRED` with `details.quote`, it has not accepted a render. Tell the user the quoted duration, free allowance and `estimatedCredits`. A free quote (`requiresConfirmation:false`, within the account's remaining free cloud export allowance) can be retried right away with `cloudQuoteId` set to that quote's `id`. For a nonzero charge, obtain one explicit confirmation of that quoted amount, then retry with `cloudQuoteId` and `confirmCloudCharge:true`; a general export request does not approve an unknown charge. If the account cannot cover it, follow the billing recovery the error returns. Use the account policy returned by the server rather than assuming a free allowance or changing old benefits. Keep the same project, timeline, range, format and output settings for that quote. If it expires or the service requires a new quote, preserve the request and omit the stale `cloudQuoteId` to request a fresh quote. A larger charge needs new consent. If submission was accepted or uncertain, check the original job before retrying; never obtain a new quote to duplicate an in-progress export. -If cloud rendering is blocked by media that is not remotely readable, use `asset-import` when the user permits upload, or report the blocker. Do not flatten or substitute the edit, upload sources, or switch a local export to cloud merely to obtain a download URL. +If cloud rendering is blocked by media that is not in ChatCut yet, wait for helper uploads with `track_progress` `target:"upload"`, or use `asset-import` (the ChatCut upload page) when the user permits upload; otherwise report the blocker. Do not flatten or substitute the edit to get around it. diff --git a/tests/cursor-marketplace-split.test.mjs b/tests/cursor-marketplace-split.test.mjs index 9f3d4be..3442851 100644 --- a/tests/cursor-marketplace-split.test.mjs +++ b/tests/cursor-marketplace-split.test.mjs @@ -1,5 +1,5 @@ import assert from "node:assert/strict"; -import { readdir, readFile, readlink, stat } from "node:fs/promises"; +import { lstat, readdir, readFile, readlink, stat } from "node:fs/promises"; import test from "node:test"; const root = new URL("../", import.meta.url); @@ -57,20 +57,42 @@ const listFiles = async (dir) => { return files.sort(); }; +const sameFiles = async (a, b) => { + const files = await listFiles(a); + assert.deepEqual(await listFiles(b), files); + for (const file of files) { + assert.ok( + (await readFile(new URL(`${a}${file}`, root))).equals(await readFile(new URL(`${b}${file}`, root))), + `${b}${file} differs from ${a}${file}`, + ); + } +}; + // Until Cursor gets its own host adapters, share the directories directly so // the two listings cannot drift apart. -for (const dir of ["skills/", "assets/"]) { - test(`cursor/${dir} mirrors grok/${dir}`, async () => { - assert.equal(await readlink(new URL(`cursor/${dir.slice(0, -1)}`, root)), `../grok/${dir.slice(0, -1)}`); - const grokFiles = await listFiles(`grok/${dir}`); - assert.deepEqual(await listFiles(`cursor/${dir}`), grokFiles); - for (const file of grokFiles) { - assert.ok( - (await readFile(new URL(`grok/${dir}${file}`, root))).equals( - await readFile(new URL(`cursor/${dir}${file}`, root)), - ), - `cursor/${dir}${file} differs from grok/${dir}${file}`, - ); +test("cursor/assets/ mirrors grok/assets/", async () => { + assert.equal(await readlink(new URL("cursor/assets", root)), "../grok/assets"); + await sameFiles("grok/assets/", "cursor/assets/"); +}); + +// Grok Bot's cloud-computer browser drops too often for local renders, so only +// Grok's export guidance is cloud-first; Cursor keeps its own browser-first copy. +const grokOnlySkills = ["chatcut-plugin-basics", "export"]; + +test("cursor/skills/ shares every Grok skill except the Grok-only export guidance", async () => { + const grokSkills = (await readdir(new URL("grok/skills/", root))).sort(); + assert.deepEqual((await readdir(new URL("cursor/skills/", root))).sort(), grokSkills); + for (const skill of grokSkills) { + const cursorSkill = new URL(`cursor/skills/${skill}`, root); + if (grokOnlySkills.includes(skill)) { + assert.ok((await lstat(cursorSkill)).isDirectory(), `cursor/skills/${skill} is Cursor's own copy`); + } else { + assert.equal(await readlink(cursorSkill), `../../grok/skills/${skill}`); + await sameFiles(`grok/skills/${skill}/`, `cursor/skills/${skill}/`); } - }); -} + } + const cursorExport = await readFile(new URL("cursor/skills/export/SKILL.md", root), "utf8"); + const grokExport = await readFile(new URL("grok/skills/export/SKILL.md", root), "utf8"); + assert.match(cursorExport, /Video and audio default to `renderMode:"local"`/); + assert.match(grokExport, /In Grok, video and audio render in the cloud by default/); +}); diff --git a/tests/export-delivery.test.mjs b/tests/export-delivery.test.mjs index 745b430..fbe4f6c 100644 --- a/tests/export-delivery.test.mjs +++ b/tests/export-delivery.test.mjs @@ -36,6 +36,21 @@ test("export delivers the downloaded file and keeps cloud fallback scoped", () = assert.doesNotMatch(codexExport, /return its `downloadUrl`/); }); +// Grok Bot's cloud-computer browser drops too often for local renders, and the +// hosted connector defaults Grok's video and audio exports to cloud to match. +test("Grok exports are cloud-first and deliver the fetched file", async () => { + assert.match(grokExport, /call `submit_export`\nwithout `renderMode`/); + assert.match(grokExport, /`target:"upload"` reports them uploaded/); + assert.match(grokExport, /Use `renderMode:"local"` only when the user explicitly asks/); + assert.match(grokExport, /`curl -fL -o "" ""`/); + assert.match(grokExport, /`requiresConfirmation:false`/); + assert.doesNotMatch(grokExport, /Video and audio default to `renderMode:"local"`/); + assert.doesNotMatch(grokExport, /There is no automatic cloud retry/); + const grokBasics = await read("grok/skills/chatcut-plugin-basics/SKILL.md"); + assert.match(grokBasics, /In Grok, video and audio render in the\ncloud by default/); + assert.doesNotMatch(grokBasics, /The default browser export downloads on/); +}); + test("basics no longer say export needs a download URL or is unavailable", async () => { for (const path of [ "codex/skills/chatcut-plugin-basics/SKILL.md",