Changelog
What changed in each release of the Clipwright client packages and API.
The four client packages — @clipwright/core, @clipwright/sdk,
@clipwright/cli and @clipwright/mcp-server — are released together and always
share one version, so each section below covers all four. The format follows
Keep a Changelog. The HTTP API reports its
contract version in the X-Clipwright-Contract response header and in the
contract_version field of a quote. Entries marked Breaking: require a change
on the client side. Entries marked Server-side changed the API itself: every
client version sees them from the day the API was deployed, not from the package
release they are listed under.
Entries marked Dashboard: changed the web app (the dashboard or a public page of the site) and no package. This file is also the public changelog at /changelog, so they are listed here: a customer reading it should not miss what appeared in the product. Like Server-side entries, they are live from the day the web app was deployed, not from the package release they are listed under.
[Unreleased]
Changed
- Breaking:
failedis no longer always final. A run whose paid vendor job we still hold can be reopened: it goes back toqueuedand may reachsucceeded. Every reopening is named inwarnings[], and one run is reopened at most three times. An agent that stops polling the moment it readsfailedwill miss a video that was paid for and delivered. - Server-side A run that lost the video while the vendor was still working on it no longer says its paid job "was retained for recovery" when this run's terms cannot support recovery. Reading the terms fails soft: when they cannot be read at all, the run promises nothing either way.
- Server-side A recovered delivery is written to the ledger under its own
reason,
run_recovered_delivery, because the vendor spend was already counted on the day the run first failed.
Operations
- Migration 0036 adds
recovery_attemptandrecovery_reopened_attoruns, and both are read on the main render path. Apply the migration before deploying any service: an early deploy fails everymake_ugcrun, not one feature. Order forward is migration, api, worker, web; backwards it is worker and api first, then drop the columns.
[0.18.0] - 2026-09-21
Long-form clips can now show a face for a fifth of their length instead of nearly all of it, which is what the face-second meter was priced for.
Added
cover_wordson an insert says how many spoken words it covers, counted from the first word of its anchor. The share of words left uncovered decides the share of the clip that shows a face, and it does not move with the speed the voice reads at. Word length still varies: at a 560-word script, asking for 19% delivered 16 to 22 in nine hundred and ninety-seven simulated runs out of a thousand, measured on this profile's voice. A shorter script scatters wider.- A quote for a narrated clip carries
estimatedFaceWordShare: the share of the clip that will show a face, known before anything is synthesised.
Changed
- Up to 49 inserts per clip, not two, and at most six appearances of the actor between them. Both are counted from the word indexes you send, so an input asking for more is refused before anything is paid for.
- Server-side An insert now ends where its first uncovered word begins rather than where its last covered word ends, so the pause between two words belongs to the insert. Inserts whose coverage meets are adjacent frame for frame and no longer leave a fragment of actor footage between them.
- Server-side The credit hold for a narrated clip reserves the words you leave uncovered instead of the whole narration. On a clip that covers four fifths of its script the hold falls from 2170 credits to 630. Billing is unchanged: it has always used the face intervals actually delivered.
[0.17.0] - 2026-09-16
Everything here came out of the second dry run by a tester who had not seen the product before.
Added
- The MCP server reports money.
make_ugccarriescredits_reservedandget_runcarriescredits_charged, in every state, so an agent no longer has to callget_accountbefore and after and subtract. The field names come from the run schema, so REST and MCP cannot drift apart. (clipwright#209) - Server-side: in
GET /v1/voices, each entry ofmodelscarriesvendor_verifies_voices— whether the vendor's library listing marks any voice as verified for that model. It isfalseforeleven_v3(measured: none of 303 live catalog voices), so an emptyverified_modelson that model says nothing about the voice. (clipwright#208) - Server-side: a voice whose gender differs from the actor's is named in
warnings, in the quote and in the run. The combination still runs as asked — voicing a man with a female voice is sometimes deliberate — but it is no longer silent. (clipwright#210) - Server-side: an
imagesmaller than the output on its short side gets a warning that the source is upscaled, with both sizes and the size to send instead. The default actor is silent: its size is a property of our own image, stated once in the docs. (clipwright#211)
Fixed
- Server-side: a request body that is not valid JSON answers 400
malformed_body, not 500. A 500 says the failure is ours, so an agent retries bytes that will never parse; the new message says both what to fix and that a retry fails the same way. (clipwright#212) - Server-side: a source we cannot use — private or loopback host, http,
unreachable, redirecting, over 10 MB, or not PNG/JPEG/WebP — is refused with
400
unusable_sourcebefore any charge, in the quote and in the run alike. It used to be priced: a loopback url answered 200 and an estimate, while the tool description promised a refusal. (clipwright#213) - Server-side: refusals on
script,voice,voice_idandimageare written in the product's words instead of the schema library's, and the description ofscriptno longer names a field the API rejects. (clipwright#212) - Dashboard: the root of the cabinet host sends a signed-in visitor to their dashboard instead of showing the landing page with a "Sign in" button. (clipwright#214)
- Dashboard: every tile on
/videosprints itsrun_idand links to the support form with it. The id used to live only in the preview image's alt text, so tiles without a preview had none at all. (clipwright#215) - Dashboard: the REST example on
/quickstartruns unchanged in any shell: one line, no backslash continuations and no shell substitution. (clipwright#211)
[0.16.0] - 2026-09-16
Added
- Server-side: a new skill,
create_actor, builds a personal actor for the account from a description of a fictional adult: a 9:16 portrait with exactly one face, plus the other requested formats edited from it.POST /v1/skills/create_actor/quoteand/runtake the description,gender,approximate_age,name,qualityandaspect_ratios; the run reportscreated_actorwhen it succeeds, and the returnedactor_idgoes tomake_ugcin the same field a catalog actor does.GET /v1/actorslists the account's own actors after the catalog, andDELETE /v1/actors/{id}takes one out of the choice. The skill appears inGET /v1/public/skillsonly while generation is switched on; until then quote and run answer 503actor_generation_disabledand no run is created. (clipwright#120) - Server-side: runs have a new state,
generating, which onlycreate_actorenters. The set of terminal states is unchanged:succeededandfailed, and nothing else. (clipwright#120) - Personal actors reached the clients. The SDK gained
quoteActor,createActoranddeleteActor; the CLI gainedquote-actor,create-actoranddelete-actor; the MCP server gainedquote_actor,create_actoranddelete_actor, sotools/listnow returns ten tools instead of seven. The idempotency key of an actor run is built from the actor's own schema: two different descriptions are two different keys, and a repeated call with the same description returns the run already paid for. (clipwright#120) - Dashboard:
/actorsshows the account's personal actors next to the catalog and deletes one on confirmation. A deleted actor stops being offered at once; its images are removed by a daily cleanup. (clipwright#120)
Changed
- Server-side: a request with
personand generation switched on gets a warning that points atcreate_actorinstead of only saying the field is not honored. (clipwright#120) - Server-side:
create_actoris charged per published image, not per second: the portrait and each extra format cost what the quote showed, a partial result charges only what was published and names the rest inwarnings, and a failed run costs nothing at all. Refused descriptions and unusable portraits are free. (clipwright#120)
[0.15.0] - 2026-09-14
Changed
- Server-side: in
GET /v1/voices, a catalog voice carriespreview_urlandpreview_expires_atonce its sample is recorded: a short clip of that voice oneleven_v3, in the voice's own language. The link is signed by us and expires like a preset's. A voice without a recorded sample for its current model and sample text still has neither field, and the list never links to the vendor. The sample texts outside English and Russian are machine translations that no native speaker has checked. (clipwright#164) - Server-side: without
voiceorvoice_id, the voice follows the actor's gender: a woman fromactor_idspeakssarah, a man speaksgeorge. The default actor still speaksgeorge, and an explicit voice always wins. (clipwright#183) - Server-side: a request with
imageand no voice gets a warning that the malegeorgevoice is used, namingvoiceandactor_genderas the fix.GET /v1/runs/{id}derives it from the stored input, so runs started before this change show it too. A request withactor_gendernext tovoiceorvoice_idgets a warning that the hint changed nothing. (clipwright#183) - Server-side: the contract version moved to
2026-09-14. (clipwright#183) - Dashboard:
/actorssays that an actor without a chosen voice speaks the default voice of their gender. (clipwright#183)
Added
-
actor_gender(femaleormale) in themake_ugcinput: next toimageit picks the default voice of that gender. It is refused withactor_idand withoutimage, and the remote fetch killswitch turns it off together withimage. The REST API accepts it from the day the API is deployed; the MCP tool schema, the SDK types and the CLI flag--actor-genderarrive with this release. (clipwright#183) -
Dashboard:
/actorsshows the actor library as a gallery: every published portrait with itsactor_idto copy, next to gender, approximate age, description and version. A person can pick a face without callingGET /v1/actorsfirst. (clipwright#148) -
Dashboard:
/videoslists the finished videos of the account. Each one is a still frame taken from the delivered file, with the length of the clip and the day it finished, and a tile with a frame plays the video. Runs that are still going or that failed stay on the Balance page. (clipwright#138) -
Dashboard:
/changelogrenders this file as a public page, so the release notes are readable without installing a package. (clipwright#102)
[0.14.0] - 2026-09-13
Changed
- Breaking: Server-side:
GET /v1/voiceslists the catalog voices after the five presets, by language and then by rank; a voice retired from the catalog is not listed. Every entry gainskind(presetorcatalog) andsupported_models, the contract models that know the voice's language. A catalog voice also carriesverified_modelsand whichever oflocale,accent,gender,ageanduse_casethe catalog has. The response gainsmodels: each contract model with itschar_limitandlanguages. Only a preset carriespreview_url; a catalog voice has no sample yet. Clients 0.11.0 and 0.12.0 cannot read this response and fail inlistVoices(),list_voicesandclipwright voices: upgrade to 0.13.0 or later. The contract version moved to2026-09-13.2. (clipwright#164) - Server-side:
GET /v1/voicestakes the filterslanguage,gender,age,use_caseandmodel.modelkeeps the voices whose language the model knows. A voice without a label matches no value of that filter. An unknown value gets 400invalid_requestthat names the allowed values, and an unknown query key gets 400unknown_field; neither returns an empty list. (clipwright#164) listVoices()takes the same filters as an object, MCPlist_voicesas arguments, andclipwright voicesas--language,--gender,--age,--use-caseand--model.clipwright voicesprints age and use case next to language and gender, and cuts a description longer than 100 characters. (clipwright#164)
Added
@clipwright/coreexportsvoicesQuery,voicesQueryShape,VoicesQueryandVOICES_QUERY_FIELDS.unknownFieldstakes an optional list of accepted keys, andUnknownFieldHit.suggestionis typedstring. The subpath@clipwright/core/voice-listingexportslistVoices,serverVoicesQueryandserverVoicesQueryFor. (clipwright#164)
[0.13.0] - 2026-09-13
Changed
listVoices(), MCPlist_voicesandclipwright voicesaccept a voice name outside the five presets, agenderother thanfemaleormale, a voice withoutlanguage, and the new optional fieldskind,locale,accent,age,use_case,supported_modelsandverified_models, plus a top-levelmodelslist. Unknown keys are dropped, as before. Until now the first such voice made all three fail. (clipwright#164)- A voice name the client does not know goes to the API, which decides.
clipwright make --voicechecks only the form of the name: letters, digits,_and-, up to 64 characters. The SDK and MCPmake_ugcno longer refuse such a name before sending it. Intools/list,voiceis a string with a pattern instead of an enum of preset names. The API itself is unchanged: a name that is not a preset still gets 400invalid_requestwith the same message, before any charge. (clipwright#164) - In
VoiceCatalogEntry,nameandgenderare typedstring, andlanguageis optional. InMakeUgcInputArgs,voiceis typedstring. (clipwright#164) - Server-side: quote and run accept a voice from the catalog by its name, as
well as a preset. A catalog voice speaks
eleven_v3unlesstts_modelnames another model, and its script limit follows that model: 5,001 characters withouttts_modelget 400 before any charge, as with a preset. A name that is neither a preset nor a catalog voice gets 400invalid_requestthat says the voice is unknown; a voice retired from the catalog gets 400 that says it was retired. Both point tolist_voices. The language of a voice limits nothing: any catalog voice speaks any language. A run already stored with a voice that was later retired still reads, with its warnings. (clipwright#164)
Added
@clipwright/coreexportsVOICE_NAME_PATTERN,isVoicePresetName,serverUgcInputWithandvoiceModelEntry. The subpath@clipwright/core/voice-admissionexportsserverUgcInput, which checks a voice name against the catalog, andcatalogVoiceRefusal. The catalog stays out of the main entry point. (clipwright#164)
[0.12.0] - 2026-09-13
Changed
- Breaking: Server-side: quote and run refuse a key that is not part of
the contract with 400
unknown_field, before any charge. Such keys were dropped silently before, so a misspelled field fell back to its default:aspectRatio: "16:9"rendered 9:16 without a warning.fieldsnames each unknown key, and the message suggests the matching field (aspect_ratio). Fix the key name. The contract version moved to2026-09-13. (clipwright#166) - Server-side: the duration estimate for a Cyrillic script uses 2.3 words a
second instead of 2.6, measured on
eleven_v3. A Russian script now quotes and reserves about 13% more credits, closer to what the run is charged. Other scripts keep 2.6. (clipwright#164) - A stress mark (U+0301) at the start of a word is no longer counted as its first letter, so a capital right after the mark stays a capital. A capital vowel later in the same word still marks stress. (clipwright#164)
- Each package ships this changelog as
CHANGELOG.md. (clipwright#102)
Added
- Quote returns
tts_model, the speech model the run will use. (clipwright#164) @clipwright/coreexportsunknownFields,unknownFieldError,unknownFieldBodyandACCEPTED_UGC_FIELDS, andunknown_fieldis part ofAPI_ERROR_CODES. (clipwright#166)
Fixed
- Server-side: a body with an empty key name gets 400
unknown_fieldinstead of 500internal_error. (clipwright#167)
[0.11.0] - 2026-09-13
Removed
- Breaking:
eleven_multilingual_v2is no longer a validtts_model. Quote and run refuse it with 400 before any charge. Passeleven_v3,eleven_flash_v2_5oreleven_turbo_v2_5, or omit the field. Runs stored with the old value still read. (clipwright#145)
Changed
- Breaking: every voice preset and a raw
voice_idnow speak oneleven_v3. Before, four of five presets and a rawvoice_idusedeleven_multilingual_v2, with a 10,000-character script ceiling. The default ceiling is now 5,000 characters. A script of 5,001–10,000 characters that passed before is refused; send it withtts_model: "eleven_flash_v2_5"or"eleven_turbo_v2_5"(10,000 each). The refusal names these models when the script fits them. The voices sound different, and the samples fromlist_voiceswere re-recorded. (clipwright#145) - Breaking: on
eleven_v3, a single capital vowel after the first letter of a Cyrillic word marks stress:потОмis sent asпото́м(lowercase vowel plus U+0301). A script that used such a capital for another reason is now spoken differently; write that word in lowercase. A capital at the start of a word, a word in capitals, and a word with a second capital stay as written. Stress marks count toward the character limit. (clipwright#145) - The contract version moved from
2026-08to2026-09. (clipwright#145)
Added
tts_modelacceptseleven_flash_v2_5andeleven_turbo_v2_5, 10,000 characters each. (clipwright#145)- Server-side: quote and run return a warning when a script with stress marks or in Cyrillic goes to a 2.5 model. The default path stays silent. (clipwright#145)
@clipwright/coreexports the stress helpers (STRESS_MARK,stressMarksFromCapitals,speechTextFor) and the run preflight schema (runPreflight,parseRunPreflight). (clipwright#145, clipwright#146)
Fixed
- Server-side: for a body with
image, the 202 response of a run and the quote now return the samewarnings[]. Warnings that depend on a network probe no longer disappear when a run fails. (clipwright#146)
[0.10.0] - 2026-09-11
Added
- MCP tool
get_account, SDKgetAccount()and CLIclipwright account. All three readGET /v1/account(balance, debt, holds, grants) and spend nothing. (clipwright#135) - Server-side: quote adds a warning when a run with the same input would be
refused with
account_not_admitted,debt_outstandingorinsufficient_credits. The warning carries the same numbers as the refusal. (clipwright#134) @clipwright/coreexportsAPI_ENDPOINTS,QUICKSTART_ENDPOINTS,endpointLabelandNODE_MIN_MAJOR(the Node.js major the clients require). (clipwright#135, clipwright#129)
Fixed
- Server-side: the
errorof a failed run inGET /v1/runs/{id}no longer contains stack frames or internal file paths. (clipwright#133) - Server-side: when our wait for the avatar vendor times out, the run is charged nothing, and its warning says what happened. (clipwright#150)
[0.9.0] - 2026-09-09
Added
- Each voice in
GET /v1/voices,list_voicesandlistVoices()carriespreview_urlandpreview_expires_at: a signed link to a sample recorded with that voice and its model. The link is valid for one hour. A voice without a sample has neither field. A 0.8.0 client drops both fields. (clipwright#147) - CLI
clipwright voicesprints the sample link on its own line. (clipwright#147)
[0.8.0] - 2026-09-09
Added
- Actor library:
GET /v1/actors, MCP toollist_actors, SDKlistActors()and CLIclipwright actors. Each actor has a stableactor_id, a name, a gender, an approximate age, a version and verified image variants. (clipwright#120) actor_idinput on quote and run, and CLI--actor-idonmakeandquote. Do not combine it withimageorperson. (clipwright#120)- Quote and run responses carry
actor: the selectedactor_id,versionandgender;{gender}for the default actor;nullwhen you pass your ownimage. (clipwright#64, clipwright#120)
[0.7.0] - 2026-09-09
Removed
- Breaking:
daily_remaining_creditsis gone fromGET /v1/accountand from theaccountschema in@clipwright/core. The per-account daily spend cap it reported was removed. A client that read the field now getsundefined; readbalance_credits, anddebt_creditsfor a block. The contract version was not moved for this change: it stayed2026-08until 0.11.0, so the header gave no signal. (clipwright#139) - Breaking:
@clipwright/coreno longer exportsMAX_SCRIPT_WORDSorSCRIPT_SECONDS_BASIS. Code that imports them fails; useTTS_MODEL_CHAR_CAPorMAX_SCRIPT_CHARS. (clipwright#128) - Server-side: the refusal
daily_cap_exceededis no longer produced. Runs refused before keep it in their history. (clipwright#139) - Server-side: the refusal
global_cap_exceededis no longer produced. The service-wide daily spend cap became an internal alert. (clipwright#141)
Changed
- The 180-word script ceiling is replaced by a character limit per speech model:
eleven_v35,000,eleven_multilingual_v210,000. Length is counted as JavaScript.length, spaces and audio tags included; an emoji may count as two. Longer scripts than before are accepted. The refusal text changed fromscript is ~N words; ceiling is 180 wordstoscript has N characters; <model> allows at most N characters; update code that matches on it. (clipwright#128) - Breaking: Server-side: quote and run refuse a script whose text contains
U+FFFD with 400
script_encoding_lost, before any charge. Such a script was accepted before and billed for about a second of speech. The bytes were lost before the request left the client: send the script as valid UTF-8. (clipwright#131) - Server-side: a run whose speech is impossibly short for its script fails with
speech_too_short_for_scriptand is charged nothing, instead of succeeding. Retrying rarely helps. (clipwright#131) - Server-side: a new sign-up gets an admitted account with zero credits, so it
is no longer refused with
account_not_admitteduntil the owner admits it. (clipwright#112)
[0.6.0] - 2026-09-06
Added
@clipwright/cliinstalls a second binary,clipwright-cli, next toclipwright. An unrelated npm package also ships aclipwrightbinary; the second name avoids that collision.core,sdkandmcp-serverhave no changes in this release and moved to keep one version. (clipwright#105)
[0.5.0] - 2026-09-06
Added
POST /v1/uploadstakes a local PNG or JPEG of up to 10 MB and returnsupload_id,url,media_type,bytes,width,heightandexpires_at. Pass the httpsurlasimage. The url is valid for 24 hours and the object is kept for 7 days. An account may upload 20 images a day. New refusal codes:invalid_image,unsupported_media_type,upload_cap_exceeded. (clipwright#99)- MCP tool
upload_image, SDKuploadImage(), CLIclipwright upload <path>, and--image,--image-file,--aspect-ratio,--resolutionon CLImakeandquote. (clipwright#99) tts_modelinput (eleven_v3oreleven_multilingual_v2) and CLI--tts-model. Without it the preset's model is used. Each voice in the catalog names itsmodel. A script over the model's character limit (v3 5,000, v2 10,000) is refused before any charge, in addition to the 180-word ceiling. (clipwright#101)- MCP
tools/listdescribesimage,aspect_ratio,resolution,voiceandvoice_id; the descriptions were empty before. (clipwright#99)
Changed
- Server-side: the
owner_ru_clonepreset speaks oneleven_v3. All presets usedeleven_multilingual_v2before. (clipwright#101)
[0.4.0] - 2026-08-28
Changed
- Breaking: the default API address in the SDK, CLI and MCP server moved to
https://api.clipwright.io. The old addresshttps://api-production-7e69.up.railway.appstill answers, so older clients keep working. If your network allowlists hosts, addapi.clipwright.io, or pin the old address withCLIPWRIGHT_API_URLor the SDKbaseUrloption. (US-613)
[0.3.0] - 2026-08-28
Removed
- Breaking:
@clipwright/coreno longer exportsMAX_SCRIPT_SECONDS. Code that imports it fails;SCRIPT_SECONDS_BASISholds the value (and was removed in turn in 0.7.0).
Changed
- Breaking: the CLI and the MCP server refuse a
CLIPWRIGHT_API_URLthat is nothttps. Loopback addresses may stayhttp. Point the variable at an https address. (clipwright#85) - Breaking: every URL field of the input is limited to 2,048 characters
(
MAX_URL_LENGTH). A longer URL is refused with 400. Pass a URL of at most 2,048 characters, for example by hosting the file at a shorter address. (clipwright#85) - Breaking: SDK requests now have deadlines.
requestTimeoutMs(per client, default 30 s) bounds every request, andmaxWaitMs(permakeUgccall, default 10 min) bounds the whole call, including the request in flight. A call that used to hang now rejects. A start request cut off mid-flight throwsClipwrightResponseErrorwithmayHaveTakenEffect: true: check the run before retrying with a new idempotency key. RaiserequestTimeoutMsbehind a slow proxy. - Breaking: Server-side: a run from an account not admitted to the beta is
refused with 403
account_not_admittedbefore any charge. Topping up does not lift it. The clients parse this refusal from 0.3.0 on. (US-620) - The voice catalog is in English, and the SDK validates the
GET /v1/voicesresponse. Each voice hasname,language,genderanddescription. (clipwright#85) - The MCP server checks the shape of
run_idinget_run. (clipwright#85) - Server-side: the video link in a finished run is signed for 7 days instead of
- (clipwright#22)
- Server-side: a failed run is charged only if the vendor accepted the work that produces the clip. A run that paid only for speech is charged nothing. (clipwright#46)
- Server-side: credits bought while an account has debt pay the debt first; only the rest reaches the balance. (US-611)
Fixed
- Server-side: 401 and validation refusals use the declared error body.
Validation errors return
invalid_requestand list each problem asfield: reason, up to 12. Before, clients reported these bodies as "not a Clipwright error object". (US-616) - Server-side: the 202 response of a run carries its
warnings[]; it always returned an empty list before. (clipwright#64)
[0.2.0] - 2026-07-29
Added
@clipwright/cliis published for the first time, under MIT. Commands:quote,make,runs <id>,voices.maketakes--script,--person,--captions,--voice,--voice-idand--retry. (US-622)- Server-side:
GET /v1/accountreturnsaccount_id,balance_credits,debt_credits,holds_credits,daily_remaining_creditsandgrants. (US-602) @clipwright/coreexports the refusal schemas and the retry policy:parseApiFailure,isRetryableFailure,retryDelayMs,agentFailureReport,apiError, the 402 and 429 bodies, the rate-limit header names,accountandcreditGrant. (US-622)- Server-side: a service-wide daily spend cap; a run past it is refused with
global_cap_exceeded. (US-603)
Changed
- Breaking: Server-side: a run reserves credits before rendering. Without
enough balance the API answers 402
insufficient_credits; with unpaid debt, 402debt_outstanding, whatever the balance. Buy credits to lift either. (US-602) - Breaking: Server-side: rate limits per account: 60 requests a minute for
starting runs, 300 for quote, voices, run status and account. Over the limit
the API answers 429
rate_limitedwithRetry-AfterandX-RateLimit-*headers; wait and repeat the same call. At most 3 renders run at once per account; a fourth queues and still returns 202. (US-605) - Breaking: the SDK throws
ClipwrightApiErrororClipwrightResponseError(both extendError) instead of a plainError, and reads the status before the body. Code that parsed the message text should read the error's status and code instead.makeUgcnow waits out 429 and 5xx while polling; money refusals and other 4xx still throw at once.attemptmust be a positive safe integer and is checked before any request. (US-622) - Breaking: MCP tools return a refusal as a JSON report inside the text block,
with
isError: true, instead of one sentence. Agents should branch on itsretryablefield, not on prose. (US-622) - The MCP server starts when
~/.clipwrightis read-only; onlymake_ugcrefuses, naming the variable that fixes it. (US-622) SKILL.mdinside@clipwright/mcp-serveris in English. (US-622)- Server-side: idempotency keys are scoped to the account, so two accounts can use the same key. (US-604)
[0.1.0] - 2026-07-26
Added
- First publication of
@clipwright/core,@clipwright/sdkand@clipwright/mcp-serverunder MIT.@clipwright/cliwas not published. - API: quote (
POST /v1/skills/make_ugc/quote), run (POST /v1/skills/make_ugc/run,Idempotency-Keyrequired), run status (GET /v1/runs/{id}), voice catalog (GET /v1/voices). Requests carry acw_*bearer token. (US-205, US-516, US-550) - MCP tools
quote_ugc,make_ugc,get_run,list_voices.make_ugcreturns arun_idat once, and the agent pollsget_run. (US-206, US-512, US-516) - SDK
ClipwrightClientwithquoteUgc,startUgc,makeUgc,getRunandlistVoices. The idempotency key comes from the input andCLIPWRIGHT_CLIENT_ID;attemptstarts a deliberate new run. (US-201, US-202) - Input:
script(up to 180 words),voice,voice_id,image,aspect_ratio(default 9:16, 16:9 supported),resolution,captions,disclosure_overlay. Parameters that are not honoured come back inwarnings[];webhook_urlis refused with 400. (US-533, US-535, US-539) - Quote returns
credits_estimate,duration_estimate_sec,warnings,contract_version,sourceandresolved_aspect_ratio. A source whose aspect ratio differs from the request by more than 15% is refused before any charge; up to 15% it is snapped with a warning. (US-525) - Credits: 30 per second of video, reserved at start and charged on the measured
duration. Server-side: a per-account daily spend cap refuses runs with
daily_cap_exceeded. (US-538, US-537) - Contract version
2026-08inX-Clipwright-Contractandcontract_version. (US-533)