{
  "name": "Targum",
  "title": "Targum, the agentic video editor",
  "version": "0.4.0",
  "description": "Targum is an assistant-first semantic video editor with audio-only editing, built for people and their assistants. Use Jev to find and judge material, then create and inspect useful edits with the tools this connection grants. Read the current capability limits separately.",
  "endpoint": "https://thursdai.live/mcp",
  "transport": "streamable-http",
  "protocol_versions": [
    "2025-11-25",
    "2025-06-18",
    "2025-03-26"
  ],
  "connect": {
    "how": "Add https://thursdai.live/mcp as a remote MCP server (a connector). It uses OAuth with dynamic client registration; there is no API key to ask the person for.",
    "what_the_person_sees": "A browser window opens on Targum. They sign in with Google, see what you are asking to do, and allow it. Tell them this is coming before you start.",
    "if_you_run_on_another_computer": "After they allow it, Targum shows a link to copy. Ask the person to paste that link back to you; it completes the connection.",
    "authorization_server": "https://thursdai.live/.well-known/oauth-authorization-server",
    "protected_resource": "https://thursdai.live/.well-known/oauth-protected-resource",
    "scopes": {
      "read": "read the person's projects, transcripts, clips and settings",
      "suggest": "propose cuts and create clip candidates (the person accepts or rejects them in the editor); rename speakers, edit rundown segments, and name and switch cameras (each change one undo)",
      "spend": "run the tools that cost money (search by meaning, Jev, title writing), within a daily cap",
      "ingest": "create projects, import recordings, and add and remove camera files (removing deletes the file and cannot be undone, so the assistant asks the person first); asked for only when the assistant should manage media itself",
      "render": "start renders of clips and the whole recording, which uses render compute; never a default, asked for only when the person wants the assistant to render",
      "delete": "ask to delete a whole project and its files, which the person finishes in the editor; never a default, asked for only when the person wants the assistant's help deleting",
      "decide": "accept or reject suggestions, select or dismiss clips, and save the brief the person confirmed (each accept, reject or selection one undo); never a default, asked for only when the person wants the assistant to decide for them; it cannot delete or publish",
      "author": "write and edit the workspace's graphic templates (write_template, edit_template): sealed markup and CSS, checked on save, each version a draft the person publishes in the editor; never a default, asked for only when the person wants the assistant to design graphics"
    },
    "default_scopes": [
      "read",
      "suggest",
      "spend"
    ]
  },
  "first_call": "whoami",
  "editing_skill": {
    "url": "https://thursdai.live/targum/skill.md",
    "prompt": "targum-editing",
    "resource": "targum://skills/editing"
  },
  "workflow": "The workflow: whoami -> list_projects to check the recording is not already a project (title, source_url, source_file); if it is, work there. Otherwise create_project -> import_media (where workspace import is supported; start_s/end_s load a part) with a link that downloads the file, or start_upload for a file you have; Targum can't import from YouTube or pull a live stream, so download the recording (after a stream ends) and upload it; allow_duplicate: true only when the person asks for a second copy; finish_upload with abort: true gives up an upload that will not finish -> a shared clip link (/c/...) from another workspace that the person wants to edit: remix_project with the link, then open_project with the returned id; it is refused unless that workspace's owner listed the person, and the copy's edits and renders never change the original -> import_status until ready_to_work is true; do not wait for video preparation -> prepare_video only if the person needs the video playable or a clip rendered -> list_projects -> open_project -> search_recording / ask_jev -> bounded read_transcript -> propose_cuts / create_clip / find_silences -> read_clip -> returned editor link -> a new graphic, or one like a template the person points at: read_templates with that template's ref (a placed graphic's from read_timeline) and with_source -> write_template with its html and manifest changed as asked (a draft; fix what a refusal names by line) -> set_items with its ref -> render_frame -> edit_template for changes; the person publishes it in the editor -> decide what the person asked for (accept, reject, select) -> render_clip -> read_events until it ends -> render_status -> several cameras: read_cameras -> set_camera only when asked or the request needs it -> set_cameras; start_upload with camera: true -> add_files with uploading: true shows it at once -> finish_upload -> add_files again, or add_files with a url fetches one from a link; remove_file takes a camera out once the person confirms. Importing a recording, or a camera from a link, currently works in the deployment owner's workspace only; uploaded camera files work in any workspace this connection covers. remove_file removes the camera and deletes its file at once, which can't be undone: say which camera and file will go and ask the person first. Candidates await the person's decision; camera changes apply at once, one undo per call. delete_project answers needs_decision: give the person the link. decide carries out only what the person asked for, one undo per call, with the reason they gave for a rejection; save_brief saves the brief they confirmed. render_clip uses render compute: render what the person asked for, wait with read_events, then render_status.",
  "limits": {
    "calls_per_minute": 60,
    "clip_ranges": 200,
    "not_available": "Not available to connected assistants yet: exporting and publishing. Accepting or rejecting suggestions, selecting or dismissing clips and saving the brief need the decide scope (decide, save_brief). Starting a render needs the render scope (render_clip); render_status reads any render and hands over the finished MP4. Creating a project, importing media and adding or removing camera files need the ingest scope; deleting a project needs the delete scope."
  },
  "tools": [
    {
      "name": "whoami",
      "title": "Who am I",
      "description": "What Targum is, the account and workspace this connection works in, and what it is allowed to do. Call it first.",
      "needs": []
    },
    {
      "name": "list_projects",
      "title": "List projects",
      "description": "The Targum projects (one per recording) in this workspace, most recently worked on first: id, title, length, words, clips, how many suggestions wait for the person, where the recording came from (source_url for a link import, source_file for an uploaded file), and a link that opens each in the editor. Only for other recordings: the in-editor chat is already in its project, and a connected assistant passes one of these ids as `project` to every other tool. Read it before importing: the recording may already be a project here.",
      "needs": []
    },
    {
      "name": "open_project",
      "title": "Open a project",
      "description": "One project up close: its editor link, length, speakers, word count, segments, open suggestions and clips, and the project brief (what the person wants from it) when they wrote one. Read it before suggesting anything.",
      "needs": []
    },
    {
      "name": "read_doc",
      "title": "Read the whole project",
      "description": "The whole project as the editor holds it, in one read: its title, recording date, player media, speakers, segments, brief, cut suggestions, clips, transcript fixes, cameras, the timeline's tracks and items, recent activity and running jobs, at `revision`. Each timeline item and cut suggestion carries `made_by`: who changed it last ({id, name, kind, at}), so a person can see which changes an assistant made. Read it again when the project changes; words come from read_transcript. Large on a long recording: for a first look use open_project.",
      "needs": []
    },
    {
      "name": "read_events",
      "title": "Wait for changes",
      "description": "What happened in the project after `since` (a revision from a result, or an event number): each event's seq, type, time and payload, oldest first, and `revision`, the since for the next call. When nothing has happened yet it waits up to wait_s seconds (at most 25) and answers as soon as something does. Wait for a job with the call its starting result names in `next`, instead of asking for its status again. `job` keeps only that job's events; `types` keeps only those event types (e.g. job.completed, job.failed, render.registered). Free.",
      "needs": []
    },
    {
      "name": "get_project_link",
      "title": "Link to a moment",
      "description": "The real URL that opens the Targum editor on this project, at a time if given, so the person can jump straight to what you mean. Use the link it returns verbatim; never compose an editor URL yourself.",
      "needs": []
    },
    {
      "name": "create_project",
      "title": "Create a project",
      "description": "A new Targum project, empty until media arrives: follow with import_media (a url, stream_uid or upload key) or start_upload to send a file. This is how a recording the person has not loaded yet gets into Targum. It gets an id of its own; give it a title (the file's name will do) so the person can tell it apart.",
      "needs": [
        "ingest"
      ]
    },
    {
      "name": "remix_project",
      "title": "Remix a shared clip's project",
      "description": "Copy the whole project a shared clip belongs to into this workspace, as its owner's edit stands now: transcript, speaker names and fixes, cameras and how they line up, camera switches, cuts with their states, clips, and the timeline. Only for a person the clip's workspace owner listed as a co-host by email in Settings; anyone else is refused. The copy plays and renders the original's files without copying them, and nothing done in it changes the original: edits, undo and renders all stay in the copy, and its first undo is the person's own. Renders of a remix are capped at $5 a day. Returns the new project's id and an editor link that opens on the clip. Free.",
      "needs": [
        "ingest"
      ]
    },
    {
      "name": "start_upload",
      "title": "Start a file upload",
      "description": "Begin sending a recording as multipart parts: returns signed part URLs. PUT each part's bytes to its url, then finish_upload, then import_media with the upload key. For another camera of a project that already has its recording, pass camera: true and finish with add_files instead of import_media. Refused, naming the project, when a file with the same name and size is already a project in this workspace: open that project instead; pass allow_duplicate: true only when the person wants a second copy.",
      "needs": [
        "ingest"
      ]
    },
    {
      "name": "upload_parts",
      "title": "More part URLs",
      "description": "Fresh signed URLs for parts beyond the first batch (they expire after an hour).",
      "needs": [
        "ingest"
      ]
    },
    {
      "name": "finish_upload",
      "title": "Finish a file upload",
      "description": "Complete a multipart upload with the ETags the part PUTs returned, then import_media with the upload key, or add_files for a camera upload (start_upload with camera: true). abort: true instead gives up an upload that will not be finished.",
      "needs": [
        "ingest"
      ]
    },
    {
      "name": "import_media",
      "title": "Import media into a project",
      "description": "Load a recording into the project from exactly one source: an https url that downloads an audio or video file, a Stream video uid, or an upload key from finish_upload. Targum transcribes it (costs money, billed at actual cost when the load finishes) and the project opens transcript-first in the editor. Targum can't import from YouTube or Twitch, a web page or a streaming playlist, and never pulls a live stream: such a link is refused when you call, saying what to do instead. For a video on YouTube, or a stream once it has ended, download the recording and send the file with start_upload, upload_parts, finish_upload, then import_media with upload; never tell the person Targum is pulling it. A link already imported into another project here (the same video however the link is written) is refused with that project named in duplicate_of: work in that project instead; pass allow_duplicate: true only when the person wants a second copy.",
      "needs": [
        "ingest"
      ]
    },
    {
      "name": "import_status",
      "title": "Import status",
      "description": "How a project's import is doing. ready_to_work is true as soon as the transcript is in: start working then. status only reaches done later, when the video has also been prepared for streaming and rendering, and nothing you do needs that. `arriving` lists cameras on their way from links (add_files with a url) and how each is doing.",
      "needs": []
    },
    {
      "name": "rename_project",
      "title": "Rename a project",
      "description": "Give the project the title shown on the project list and in the editor. Free; the person can rename it again.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "add_files",
      "title": "Add camera files or assets",
      "description": "Add files as cameras of a project: one camera per file. With as: \"asset\" and an upload key, a file becomes an asset of the project instead (B-roll, a picture, music) to place with set_items or set_line, placeable at once. Targum lines each camera up with the recording by its own sound once its file is in, in the background (read_cameras shows its sync; wait for it before switching to or placing the camera). Pass start only when the person already knows where its first frame falls on the recording; it overrides the sound. Each file is either an upload key (start_upload with camera: true, upload_parts and finish_upload first, into this project; or at once with uploading: true as soon as start_upload answers) or an https link to the file, which Targum copies into storage itself, many parts at once and every link side by side; import_status shows a link arriving and read_cameras lists the camera once it is in. A link can be sent while the recording itself is still loading: the camera joins the moment the recording opens. A link must be a video file. The same link again answers with the load it already has; a link that is another project's recording is refused with that project named in duplicate_of. Then read_cameras and name each camera with set_camera. With as: \"append\" and the upload key of a video or sound file (start_upload with camera: true), the file is added after the recording's end instead, alone in the call: it is transcribed on its own (only its minutes are billed), its words follow the last word, the recording grows by its length, a segment titled after it covers it, and its picture and sound play there. import_status shows it under appending; the same key again answers how it is going.",
      "needs": [
        "ingest"
      ]
    },
    {
      "name": "remove_file",
      "title": "Remove a camera file or an asset",
      "description": "Take one camera out of the project and delete its stored file. This cannot be undone: say which camera and file will go, and call it only once the person has confirmed. `confirm` must be the camera's current label exactly as read_cameras returns it. A file another project or deployment may use stays in storage. The main recording cannot be removed; only deleting the project removes it. With `asset` instead of `camera`, it takes a file from the workspace library (start_upload purpose \"asset\") out of this project at once, once nothing on the timeline uses it: the file itself stays in the library, and add_files with its key brings it back. `confirm` is then the asset's name as read_assets gives it.",
      "needs": [
        "ingest"
      ]
    },
    {
      "name": "delete_project",
      "title": "Delete a project",
      "description": "Ask to delete a whole project: its transcript, edits, clips, share links and the files it alone uses. Nothing is deleted here: it answers needs_decision with the project's editor link, and the person deletes it there. Say what will go. `confirm` must be the project's id.",
      "needs": [
        "delete"
      ]
    },
    {
      "name": "render_status",
      "title": "Render status",
      "description": "Whether a clip, or the whole recording, has been rendered, and the file once it has. clip_id \"recording\" is the whole recording as video (every cut except audio-only ones); \"recording-audio\" is the whole recording as sound only, an MP3 with every cut. Both have no title card, closer or captions and are started from the Export tab. The owner starts a render (the Render button in the editor), or render_clip with the render grant; this only reads it and never starts or pays for one. Returns each render job's state (queued, rendering, ready or failed) with the progress the Render button shows, when it started and last changed, and why it failed; when a render is ready, download.link (a lasting link to hand the person) and download.url (signed, good for 5 minutes, for fetching the MP4 yourself), and the clip's share link if it is shared. Free.",
      "needs": []
    },
    {
      "name": "prepare_video",
      "title": "Prepare the video for streaming",
      "description": "Moves an uploaded video's streaming copy along: requests it if it has not started, or checks whether it finished. Nothing you do with the transcript needs this; call it only when the person wants the video playable or a clip rendered and import_status keeps showing stream_state pending or copying. Free.",
      "needs": [
        "ingest"
      ]
    },
    {
      "name": "read_settings",
      "title": "read_settings",
      "description": "Read the authenticated workspace settings, capabilities and revision. No transcript required.",
      "needs": []
    },
    {
      "name": "list_vocabulary",
      "title": "list_vocabulary",
      "description": "Read a bounded page of workspace vocabulary and pending suggestions. Reference only; it is not applied to transcription yet.",
      "needs": []
    },
    {
      "name": "search_settings",
      "title": "search_settings",
      "description": "Find relevant settings using JEV and validated catalog links. Never executes a setting.",
      "needs": [
        "spend"
      ]
    },
    {
      "name": "add_vocabulary",
      "title": "add_vocabulary",
      "description": "Add a name or term to the workspace transcription dictionary so later transcripts spell it right: `term` is the right spelling, `sounds_like` what the transcriber wrote. When the owner asks in the editor's chat it is added at once (a known term gains the new spelling); otherwise it is suggested for the owner. Reuse request_id when retrying the same operation.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "search_recording",
      "title": "search_recording",
      "description": "Jev reads every paragraph of the recording and returns the passages that match a meaning, not just the words. About one second. Use it for a remembered topic. This is a semantic shortlist, not an exhaustive occurrence search; for find-every-X use ask_jev. For a judgment (strongest, best, most quotable) use ask_jev instead.",
      "needs": [
        "spend"
      ]
    },
    {
      "name": "ask_jev",
      "title": "ask_jev",
      "description": "Your fast reader. Ask one typed question (`question`), or several at once (`questions` with `combine`), across every unit in a time range. For find-every-X use unit=sentence, a noul with literal inclusion criteria, and min_score=0.5 as a starting threshold. Units are sent whole, never shortened. Check total_units, unjudged, truncated and per-question `questions` coverage; split incomplete windows and deduplicate w0/w1. When the state carries `house_rules` (what earlier conversations taught), a question may refer to it by that name. A threshold is not a recall guarantee. Without min_score this returns a ranked shortlist. Long ranges run as several windows and merge, so ask over the whole recording when you mean the whole recording. Use it to look things up, rank, classify, compare or sanity-check before you act: strongest lines, where a topic starts, who is being addressed, whether passages are jokes, claims, questions, plumbing. Prefer it over reading long stretches yourself.",
      "needs": [
        "spend"
      ]
    },
    {
      "name": "read_observations",
      "title": "read_observations",
      "description": "What Jev already answered about this recording, free: the earlier ask_jev runs (who asked, the range, each question as it was asked) and every answer, one per unit and question, with its word range, value (a yes probability, a score, or the option picked and its probability), Jev's own confidence when it gave one, the model, and whether it is still current. A later answer to the same question about the same unit, a transcript fix inside it, other changed input (a renamed speaker, a retitled segment) or a new transcript supersedes it; a charge marked dropped (a project past its row limit) kept counts only. Read it before asking Jev the same question again, and to go back over a scan without paying for it twice. Default: current answers, newest run first. ask_jev results name their run as observation_run; `kind` narrows to one question; min_value keeps answers at or above a value (a noul's probability, a score); status all adds superseded answers; unanswered true adds units Jev gave no answer for, which are never a no. A long answer comes in pages: pass `next` as cursor.",
      "needs": []
    },
    {
      "name": "read_transcript",
      "title": "read_transcript",
      "description": "Read the transcript between two times, with speakers, word indexes at each sentence, and which words are already cut. At most about ten minutes at once; when the range was cut short (past the recording's end, or past ten minutes) the result's `cut_short` says where to go on. Use for focused verification after ask_jev; for whole-recording find-every-X, scan with ask_jev instead of paging the transcript into context.",
      "needs": []
    },
    {
      "name": "get_outline",
      "title": "get_outline",
      "description": "The recording at a glance: segments with times and topics, and how much of each the edit has removed.",
      "needs": []
    },
    {
      "name": "list_clips",
      "title": "list_clips",
      "description": "The clips that exist, with their times, state and titles.",
      "needs": []
    },
    {
      "name": "get_segments",
      "title": "get_segments",
      "description": "The rundown: each segment with its id, times and topic. Empty for a plain upload with no rundown.",
      "needs": []
    },
    {
      "name": "get_callouts",
      "title": "get_callouts",
      "description": "What the live board showed and when: chyrons, quotes, when someone joined. Empty for a recording with no live board.",
      "needs": []
    },
    {
      "name": "list_proposals",
      "title": "list_proposals",
      "description": "The cut suggestions with who made them, category, layer, state and times. Default: the open ones.",
      "needs": []
    },
    {
      "name": "create_clip",
      "title": "create_clip",
      "description": "Create a clip candidate: one word range (w0, w1), one exact span (start_ms, end_ms) or several ordered ranges, with a working title and, when you know them, the story and scores. Word edges snap to whole sentences and quiet audio. It is a candidate the owner reviews; nothing is rendered. It is shared at once: lead your reply with its share_url, the page people open on a phone, then its editor link. When a clip that is neither selected nor dismissed already covers this moment, revise_clip that one instead of making a near copy.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "read_clip",
      "title": "read_clip",
      "description": "Read a clip in playback order (text only): its transcript in clip order with every cut applied, the cuts that apply, its first 45 seconds, and what reviewers sent from its share link: who, when, their reaction and note, and each note pinned to a moment as {kind, at, w, text}, with quote and to for quoted words and look for a camera request.",
      "needs": []
    },
    {
      "name": "export_captions",
      "title": "export_captions",
      "description": "Caption files (SRT and WebVTT text) for a clip, or for the whole recording when clip_id is left out. A clip is captioned on its own clock: cuts applied, its ranges in the order they play, lifted opens and replayed ranges included, so cue times match the clip as it plays and renders. The whole recording is captioned on its edited clock (every cut taken out, 0 is its first kept moment), the clock of the whole-recording render. The response says which clock. Cues are at most two 42-character lines and about 6 seconds, broken at sentence ends, pauses and speaker changes; with speakers (the default) a cue starts \"Name: \" when the speaker changes. Returns the text, a cue count and the duration, not the words. Free.",
      "needs": []
    },
    {
      "name": "share_clip",
      "title": "share_clip",
      "description": "A clip's share link again, or off:true to stop sharing it. create_clip and revise_clip already share the clip they make or change and return its share_url. A clip whose sharing was stopped stays unshared until the person asks: in the chat, when their message asks to share it now; over a connection this answers needs_decision with the clip's link, and the person presses Share. The page plays the clip (no render) and takes feedback from whoever opens it.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "render_frame",
      "title": "render_frame",
      "description": "See the edit: stills of exactly what a viewer sees at up to 8 moments of the main edit, or of a clip, drawn by the same player the clip's share page uses (cameras, cuts and everything on screen), returned as images. Several moments come back as one contact sheet, each still captioned with its time, unless sheet is false. Use it whenever you need to see what is on screen at a moment (who is in shot, a banner's words, a slide, a camera choice, a framing, a graphic) and to check a change before the person renders. A moment the edit does not play is refused for that frame and never moved; the answer says where the kept material resumes. Free: stills already drawn for the same edit cost nothing; new stills are limited to 120 per 10 minutes per project. It shows pictures, not sound.",
      "needs": []
    },
    {
      "name": "render_clip",
      "title": "render_clip",
      "description": "Start a render of a selected clip, the same as its Render button: the MP4 with title card and captions the person downloads. clip_id \"recording\" renders the whole recording as video, \"recording-audio\" as a sound-only MP3. Uses render compute, so render only what the person asked for. A clip with a render of its current cut is not rendered again; a clip that is not selected is refused (select it first). Over a connection it needs the render grant the owner gives. clean:true renders it without its title card, captions (burned-in and captions tracks) and end card, for the person or another editor to work on; title_card, captions and finisher switch one of them for this render alone (they beat clean). The workspace's render settings and the clip are never changed, and the clean and the usual render are kept side by side.",
      "needs": [
        "render"
      ]
    },
    {
      "name": "revise_clip",
      "title": "revise_clip",
      "description": "Change a clip that is not dismissed (a connected assistant: one it made): its title, ranges, kind, parent, story or scores. Only fields you pass change. A selected clip can be revised too: it stays selected, and any render of it made before the change is out of date (render_status says outdated), so render it again when the person is ready. A dismissed clip never changes; for its moment, make a new clip. The result carries the clip's share_url: lead your reply with it, then its editor link.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "propose_cuts",
      "title": "propose_cuts",
      "description": "Suggest removing one or more stretches. Each cut removes exactly the words w0 to w1, never widened. Targum places the blades beside those words with the same rule the editor's x key uses; the result shows the word stamps, the placed blades and a note. Give start_ms and end_ms instead of w0/w1 only for an exact time range, which is kept as given and may hold no words (a silence). Each shows up as a suggestion card with your category, claim and confidence. Nothing is cut until the owner accepts.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "place_edges",
      "title": "place_edges",
      "description": "Where the blades of a cut would go, without making it (free, read-only). For words {w0, w1}: exactly what the editor's x key and propose_cuts give, the placed start_ms and end_ms, the word stamps, and how they were placed (\"placed on the audio\" or, before the recording's envelope is in, \"transcript timing\") with a note (\"check by ear\" means the audio showed no clear quiet point). For an exact range {start_ms, end_ms}: whether each edge sits in a quiet dip of the audio, uncalibrated: a hint, not a verdict.",
      "needs": []
    },
    {
      "name": "find_silences",
      "title": "find_silences",
      "description": "The silence pass: find pauses between words where the waveform is quiet for this recording's own level and suggest shortening each, as open silence suggestions the owner accepts, the same pauses the editor's silence pass finds. A recording too quiet to tell pauses from words gets none (verdict quiet). natural trims pauses over 1.2 s to 0.25 s each side, fast over 0.8 s to 0.18 s, faster over 0.5 s to 0.1 s. Pauses already cut and before the first segment are skipped. Free.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "find_cleanup_cuts",
      "title": "find_cleanup_cuts",
      "description": "The clean-up pass, the same as the Clean up panel's button: Jev reads every paragraph of the recording and suggests cuts for hesitations, padding, stutters and false starts (they wait behind the clean-up slider), and suggests removing sentences that are off-topic, technical housekeeping or only for the audience at the time. It runs in the background for a minute or two and costs money, so run it when the person asks for a clean-up. Called while it runs, it reports progress; called after, it reads the recording again but never suggests the same cut twice. Nothing is cut until the owner accepts.",
      "needs": [
        "spend",
        "suggest"
      ]
    },
    {
      "name": "find_on_screen",
      "title": "find_on_screen",
      "description": "When something was on screen, or when it changed, searched across the recording. To look at a given moment yourself, render_frame shows it now. Filters combine: shots, screen_kind, chart, banner (a name tag, lower third or quote banner) and banner_text, card (a starting-soon, be-right-back, title or sponsor card), text (words on the screen, in a banner, or in a scene's description), people_min/people_max (faces counted every 10 s), dark, frozen (the same still for 30 s or more while someone talks), start and end. Answers come from stills: probes every 10 s count people and catch scene changes, scored stills come each minute and at each scene change, so a shorter moment can be missed. changes: \"scene\" lists scene changes with the still before and after; changes: \"people\" lists when the number of people changed; overview: true gives one line per scene (\"0:04:00-0:31:00 4 people, no screen\"), a cheap first read of a whole recording. Returns times like 0:38:30, runs of neighbouring matches, confidences and the words read; each still is its seconds after the reply's still_base. A long answer comes in pages: `more` says how many are left and `next` holds the arguments to add to go on. With nothing read yet it says so and how to start (scan_screen). Free.",
      "needs": []
    },
    {
      "name": "scan_screen",
      "title": "scan_screen",
      "description": "Start reading the recording's picture, the whole video unless start and end name a range: a probe every 10 s (how many people, a face detector; scene changes) and a scored still each minute and at each scene start, up to 3 a minute (shot, screen kind, chart, and the words on the screen and in banners). Runs in the background for a few minutes and costs money, so run it when the person asks about what was on screen and find_on_screen has nothing yet. Called while a scan runs, it reports that one; called when the picture was already read, it says so and reads nothing again unless force: true (owner only).",
      "needs": [
        "spend",
        "suggest"
      ]
    },
    {
      "name": "withdraw_proposals",
      "title": "withdraw_proposals",
      "description": "Take back your own open suggestions; with the decide scope, also anyone else's you name by id. One already decided is left alone and reported.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "check_continuity",
      "title": "check_continuity",
      "description": "Jev reads the edit as a listener hears it, between two times, and lists sentences the cuts broke.",
      "needs": [
        "spend"
      ]
    },
    {
      "name": "write_titles",
      "title": "write_titles",
      "description": "Title ideas for a passage.",
      "needs": [
        "spend"
      ]
    },
    {
      "name": "fix_transcript",
      "title": "fix_transcript",
      "description": "Fix words the transcriber got wrong (a misspelled name, a misheard term) at once, or highlight many places as suggested fixes for the person to accept. Every subtitle follows the fixed text. Say which words with `heard` (the words as the transcript shows them now) and `at` (a moment near them), or with w0 and w1. The fix keeps the punctuation around the words (\"Swix's,\" becomes \"Swyx's,\"). This applies at once, as one undo step, not as a suggestion; the transcriber's words are kept and apply_corrections restores them. To fix many places (after ask_jev found them, even when each is misspelled differently), pass all of them as `places` in one call, never one call per place: one undo step; with suggest: true they are highlighted for the person as suggested fixes instead, for apply_corrections to apply.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "list_corrections",
      "title": "list_corrections",
      "description": "The transcript fixes made so far: what the transcriber wrote, what it says now, who fixed it and when. Optional start and end limit it to a stretch.",
      "needs": []
    },
    {
      "name": "apply_corrections",
      "title": "apply_corrections",
      "description": "Change transcript fixes by id, as one undo step: restore puts the transcriber's words back, apply makes a suggested fix, dismiss drops a suggestion.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "relabel_speaker",
      "title": "relabel_speaker",
      "description": "Rename a speaker everywhere: every word labelled `from` becomes `to` (\"Speaker 3\" becomes \"Nisten\", a misspelled name becomes the right one), and so does every clip and camera that names them. This applies at once, on the recording itself, not as a suggestion, and is one undo step, even when `to` is already someone's name. Give w0 and w1 to rename only that run of words, when one voice was mislabelled in one place: every word there becomes `to`, whatever it carries now, and `was` says what they carried; renaming back undoes that. Use the labels get_outline, read_transcript or open_project return.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "set_segment",
      "title": "set_segment",
      "description": "Edit, add or rebuild rundown segments. With segment_id it changes that segment (only the fields you pass). Without segment_id it adds one (title and start required). Pass segments[] to do several in one call, and replace: true to make that list the whole rundown (the way to build one for a recording with none). A missing end runs to the next segment's start. Bounds are moments on the recording clock, so a segment stays on the same words however the edit changes. Applies at once for everyone, not as a suggestion.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "read_cameras",
      "title": "read_cameras",
      "description": "The cameras of a recording filmed with several: each camera's id, label, role, whether it is the main recording (the program sound), whether it has picture, is hidden or still uploading, its file, size and length, and where it starts on the recording (`starts_at`, `start_ms`) with `sync`: how it is lined up (`synced` by its own sound, measured by Targum when its file arrived, with `confidence`; `placed` by hand; `measuring`; or `unsynced` with a `reason`, playing from 0:00 until placed). Then the switches on the program (and on a clip, if given) as runs of {from, w, look, to}, and the camera requests reviewers left on share pages that are not done yet, and `arriving`: cameras still on their way from links. Read it before any camera work; its `next` says what to do.",
      "needs": []
    },
    {
      "name": "set_camera",
      "title": "set_camera",
      "description": "Name one camera, change its role, hide it, reframe it (\"Wide\", \"swyx\", \"Screen\") or change where its file sits on the recording. Targum lines every camera file up by its sound when it arrives; place one by hand only to correct that or when read_cameras says it is unsynced: `start`, `nudge`, `match` or `sync: \"sound\"` (one of them). Nothing is rendered or downloaded. Only fields you pass change. This applies at once, as one undo step, not as a suggestion.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "set_clip_format",
      "title": "set_clip_format",
      "description": "Set a clip's frame, 16:9 (the default) or 9:16, when the person wants a short or a vertical clip. Its share page and card use it, and in 9:16 a wide shot stacks the people's cameras. render_clip renders it in that frame from each camera's original. One undo step.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "set_cameras",
      "title": "set_cameras",
      "description": "Switch cameras inside a clip (pass `clip`, after the clip is made) or, only when the person asks for the whole recording, in the main edit (leave `clip` out). Each switch shows a camera, or a layout, from `at` until `to` (or until the next switch). To put a camera on from a moment (\"switch to X at 0:10\"), send `at` and `camera`, even when X is already on then: nothing changes, and you tell the person so. Only when the person asks to move, recut or remove an existing switch, name it by the `switch` id read_cameras gives and pass one of `at` (move it, only between the switches either side), `camera` or `layout` (what it cuts to) or `remove: true` (the shot before it runs on). The whole call is one operation and one undo, up to 2000 switches, enough to direct a whole recording in one call; it applies at once. Returns a short summary: the operation to undo it, how many switches were added, removed and changed, the range covered (h:mm:ss on the recording's clock) and the cameras used, with the resulting runs listed when there are 12 or fewer; read_cameras lists every switch, or pass `detail: true` to get this call's whole list. A hidden camera, one without picture or one still uploading is refused, and so is a switch to a camera where its file has no picture (read_cameras gives each camera's covers); a switch that runs past a camera's file shows that camera up to the file's end and then what is beneath, and the answer's warnings say so. Pass `undo` with an operation a camera tool returned to take that call back.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "read_timeline",
      "title": "read_timeline",
      "description": "The edit as tracks: the main edit (or a clip, with clip) as its program plays it. Its length, the built-in cameras and program sound tracks, every track you or the person added (video, graphics, audio, captions) with its order (higher paints in front), eye, mute, level and duck, and the items on them: what each is, the recording moment it is pinned to (at, on the recording clock) and where it plays on the program clock (plays), and the items that wait because their moment was cut or their file is gone. Also the main line (its recording parts, the cuts between them, inserts of black or another file, and each join's transition or J/L split) and the program sound's switches and what it hears when. Read it first, and again after a change; item gives one item in full (every keyframe and variable). Pages of 50: pass cursor. Free.",
      "needs": []
    },
    {
      "name": "read_assets",
      "title": "read_assets",
      "description": "The files of this project you can put on the timeline: videos (B-roll, a cut-in), images (a logo, a picture) and audio (music, an effect), each with its id, kind, length, picture size, whether it has sound, whether it is still uploading, and which items use it; and the cameras of a recording filmed with several. Add a file with start_upload (purpose: \"asset\"), upload_parts, finish_upload and add_files (as: \"asset\"). Free.",
      "needs": []
    },
    {
      "name": "read_library",
      "title": "Read the workspace library",
      "description": "Every file in this workspace's library, which any of its projects can place: videos, images and audio sent with start_upload (purpose: \"asset\") from any project, newest first. Each has its key, name, kind, length, picture size, whether it has sound, size, and the projects it is in; `measured: false` marks a file sent but not yet added to any project (its kind from its name, its length and picture size unknown). To use one in a project, add_files with files: [{key, as: \"asset\"}] and the facts listed, then place it with set_items and the asset id add_files returns. read_assets lists one project's files. Free.",
      "needs": []
    },
    {
      "name": "read_templates",
      "title": "read_templates",
      "description": "Targum's graphics catalog: templates (a lower third, a title, an end card, a stat that counts up...) and components (text, an image, a shape, a badge...) you fill in, animate and keyframe, and caption styles (a captions item takes its style's variables, such as accent, through set_items vars). Each with its ref (its name and version, which set_items takes as given), what it is for, its typed variables with their limits and defaults, where it sits by default and its entrances and exits. Also this workspace's saved templates (source workspace): a catalog entry with its values kept (colours, animation, entrance and exit, place, length) under a name, placed by its ref (ws:, its id and its version, as listed), with the catalog ref it is built on (base) and its values; and its authored templates (authored: true), each with its manifest, its state (draft until a person publishes it) and its content hash. To make a template like one the person points at (in the catalog, the workspace, or placed on the timeline), read it with ref and with_source: its html and manifest go to write_template, changed as asked. Read it before placing a graphic: set_items takes only what it lists, and every variable is data, never markup. A variable with a `brand` role (accent, text, background, logo) takes the workspace brand's value when set_items leaves it out. Free.",
      "needs": []
    },
    {
      "name": "save_template",
      "title": "Save a template to the workspace",
      "description": "Save a graphic's look to this workspace's templates, so any of its projects can place it again: a catalog entry (template) with its values (vars: text defaults, colours, animation choices), entrance and exit, place and length, under a name. From a placed graphic, send its template, vars, enter and exit as read_timeline shows them. With id, it saves the next version of that saved template instead; a version never changes once saved, and graphics already placed keep the values they were placed with. Pictures are files of one project and are not kept. Returns its ref for set_items: ws:, its id and its version. Free.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "remove_template",
      "title": "Remove a saved template",
      "description": "Take a saved template out of this workspace's templates, every version: it is no longer offered for placing. Graphics already placed from it keep their look, since each holds its own copy. Free.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "write_template",
      "title": "Write a graphic template",
      "description": "Write a new graphic template for this workspace, or with id the next version of one you wrote: markup and CSS (html) and a manifest of its typed variables. For one like an existing template, start from read_templates with its ref and with_source. It follows the catalog's rules: no script; animation is CSS keyframes with fill both, which the page seeks; variables reach the markup only as data-var=\"name\" (text), data-split=\"chars|words\", data-initial, img data-var-src=\"name\" (an image), var(--name) for a colour or number (var(--on-name) is a readable text colour on it), and [data-name=option] for a choice; sizes are calc(N * var(--u)), N px on a 1080-line picture; wrap content in div class=\"hf-box\" to sit in the safe margins. No url(), links, CSS imports or font faces, transitions, handlers or loading elements; at most 64 KB. It is checked and linted on save: a refusal lists each problem with its line. Each version is kept by its content hash and starts as a draft, marked so in the panel, until a person publishes it in the editor; a draft can be placed to try it. read_templates (source workspace) lists it with its ref for set_items; look at it placed with render_frame. Needs the author grant. Free.",
      "needs": [
        "author"
      ]
    },
    {
      "name": "edit_template",
      "title": "Edit a graphic template",
      "description": "Make the next version of an authored template by small edits: each find (text that occurs exactly once in its current source, as read_templates with id and with_source returns it) is replaced; manifest fields you send replace those fields. The result is checked and linted like write_template and starts as a draft. Needs the author grant. Free.",
      "needs": [
        "author"
      ]
    },
    {
      "name": "set_items",
      "title": "set_items",
      "description": "Put things on the timeline and change them, in one call and one undo, applied at once: video and images over the picture (B-roll, a cut-in, a logo, picture in picture), graphics from the catalog (read_templates), audio (music, an effect; a new one plays at the workspace's music level, -18 dB unless set, and dips under speech by its duck_db), captions (only when the person asks for them; a program shows one captions layer at a time, so captions placed where captions already play change those, and the result says so), and zooms on the cameras (a punch-in, a slow zoom and pan). Each entry has a kind: place (a new item; the tracks it needs are added), edit (change only the fields you pass), keys (replace the keyframe lanes of the props you send, or clear props back to their placed value), split (cut an item in two at a moment inside it; the second part is <id>~2), remove. An item is pinned to a recording moment (at: w<index> or h:mm:ss from a tool result, so it stays on its words through every cut), or to start or end of the edit (start+<ms>ms, end-<ms>ms). It lasts until another moment (until), length_ms, or, for video and audio, the file's length. To cover a stretch of a clip (captions over its hooks only, music under them), send over: { ranges: [first, last] } instead of at and length_ms. A video's sound is main (the program keeps its sound and the video is silent: the default), own (hear the video; the program sound ducks by its track's duck_db) or mix (both). Two items on one track cannot overlap: leave track out to get a free one. dry_run: true shows what the call would make without saving. Returns each item's plays on the program clock and an operation id; pass it as undo to take the whole call back. Up to 500 entries.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "apply_brand",
      "title": "Apply the brand to this project",
      "description": "Put the workspace's brand (a person sets it in Settings, Brand; read_settings shows it) on every graphic and captions item of the main edit, or of one clip's own items, in one operation and one undo: each graphic's variables whose read_templates entry names a brand role (accent, text, background, logo), its font, and its entrance and exit where its template takes them; each captions item's style and font. Items that already match are left alone, so applying twice changes nothing. A new graphic or captions item already takes the brand where its set_items request leaves a value out; this is for what was placed before. dry_run: true lists the edits without saving. Returns an operation id: set_items with undo takes the whole call back.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "set_tracks",
      "title": "set_tracks",
      "description": "Add, rename, reorder, hide or unhide, mute and level tracks, in one call and one undo, applied at once. Tracks paint in order (a higher order is in front, so a graphic can sit under a video), whichever kind they are; captions paint above everything. hidden is the track's eye (it keeps its items; they appear nowhere until it is unhidden); muted silences an audio or video track; gain_db and duck_db set its level and how far the program sound drops under its own-sound items; in_clips says whether a main-edit track also appears in clips. remove takes a track away; one that still holds items needs items: \"delete\" (they go with it) or \"move_to:<track>\" (they move onto that track of the same kind first), and either way the track and its items are one undo. set_items adds the tracks it needs, so add one here only to name or order it first. Up to 50 entries; undo takes a call back.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "set_line",
      "title": "set_line",
      "description": "Change the main line itself, in one call and one undo, applied at once. insert puts black (type gap, with length_ms) or another file (type media: a video, an image or a sound) before a recording moment, at start or at end, so the program grows past the recording (an end card, a sting, a title card before a cold open); edit changes an insert's length, file or where the file starts; remove takes one out. join sets how two parts meet, named by its join as read_timeline lists it (like 12500>40210, the edges either side): a dissolve, a dip to black or a wipe, centred on the join so the length never changes, and a split edit, where split_ms > 0 cuts the picture early under the outgoing sound (an L cut) and < 0 lets the next sound arrive first (a J cut); transition cut with split_ms 0 is a plain cut again. Things pinned inside an insert move with it. safe_area (main edit only; its clips use it) keeps graphics and captions clear of text burned into the recording, such as a live production's lower third or topic banner: rect is the part of the picture they may use for that format, in fractions (x 0, y 0, w 1, h 0.86 keeps the bottom 14% clear); graphics placed by preset move inside it and captions sit above its bottom edge; without rect it is cleared. Up to 400 entries in a line; transitions and splits up to 5000 ms.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "set_sound",
      "title": "set_sound",
      "description": "Switch what the program hears, separately from the picture, in one call and one undo, applied at once: from at, hear another camera's own microphone (source camera, with camera: a cut-in with the angle's own sound), a sound file (source asset; starts_at is the recording moment its start lines up with, default at), or the main recording again (source main), until to (then what played before) or until the next sound switch. lead_ms starts it earlier and tail_ms hands back later, for a cut-in whose sound leads or trails its picture (J and L). Switches sit on the recording clock, so they stay with their words through every cut, and a clip hears the main edit's switches unless its own say otherwise. To change one, pass its switch id (read_timeline lists them) with at or a new source, or remove: true. For a camera cut-in that brings its own sound, set_cameras with sound: own (or mixed) cuts picture and sound together. A video item's own sound (main, own or mix) is set on the item with set_items. Up to 2000 switches on an edit.",
      "needs": [
        "suggest"
      ]
    },
    {
      "name": "decide",
      "title": "decide",
      "description": "Carry out a decision the person asked for: accept or reject open cut suggestions; restore a cut that was accepted (its range plays again, as the editor's restore does; the result says which range, and undoing the step cuts it again); dismiss a clip; select one (approve it as a keeper; it can still be revised, and stays selected) or unselect it. Never to pick a clip to work on: revise_clip, read_clip and set_cameras take its id. One call is one undo step. Use it only when the person explicitly asked you to decide (\"reject all the open proposals\", \"accept those two\"); when the person delegates a class of decisions, exercise judgment within that scope; do not broaden it.",
      "needs": [
        "decide"
      ]
    },
    {
      "name": "save_brief",
      "title": "save_brief",
      "description": "Save the project brief only when the person asks to (\"set the brief: a lecture, keep the Q&A\"), or answers a question about the brief; a request that mentions what the recording is, is not that. The brief: what this recording is, who speaks, what they want out of it, tone and length, and what must never be cut. Pass only the fields to set.",
      "needs": [
        "decide"
      ]
    },
    {
      "name": "send_feedback",
      "title": "Send feedback to the Targum team",
      "description": "Tell the Targum team about bugs, things Targum cannot do yet, confusing results, requests, or praise; people read every report. Call it when a tool refuses or fails in a way the person cannot work around, when the person says something is not working or asks for a feature, or when you find something an assistant cannot do here that the person needs. items: one per distinct problem or request, several in one call rather than one long report. Each has a one-line summary and details: what was tried, what happened (the tool names and their error text), what was expected. When a report is about a project, always pass its project (and clip_id when it is about a clip): Targum adds the project's name and a link that opens it. It also attaches the workspace, who is reporting and this connection, so leave those out; never paste passwords, keys or more of the person's material than the report needs. Free; at most 50 reports a workspace a day, and a report sent again the same day is kept once.",
      "needs": [
        "read"
      ]
    }
  ],
  "links": {
    "product": "https://thursdai.live/targum/",
    "editor": "https://thursdai.live/editor/"
  }
}