claude-handoff
MAmattpocock/skills288k10,178 new stars in the last 7 days
Unified batch and async-job orchestration
The POST /skills/batch endpoint, query → preview → execute bulk edits, execution reports and async jobs. Parameters come from the schema, never from a skill's name; execution and dryRun rules: root SKILL.md.
An HTTP endpoint, not a skill: never send skills_batch to POST /skill/<name>. It runs up to 50 ordinary skill calls in order inside one main-thread job, each through the full single-skill pipeline (validation, permission gate, its own Undo group, audit): one round trip and one main-thread wake-up instead of N, the biggest saving once there are 3+ writes.
POST /skills/batch
{
"steps": [
{"skill": "gameobject_create", "args": {"name": "Cube", "primitiveType": "Cube"}},
{"skill": "component_add", "args": {"instanceId": {"$ref": "$0.instanceId"}, "componentType": "Rigidbody"}}
],
"continueOnError": false
}
| Body field | Default | Meaning |
|---|---|---|
steps | required | {skill, args} objects, in order. More than 50 → 400 SEMANTIC_INVALID; split the call. |
continueOnError | false | false = stop at the first failure; true = record it and keep going. |
params | none | Values for {"$param":"name"} or {"$param":"name","default":X} nodes in args; static, resolved before $ref; a missing slot without default fails that step. |
$ref: an args object whose only key is $ref, {"$ref":"$N.path"}, is replaced by the value at path (e.g. instanceId, results[0].path; bare $N = the whole result) in the result of earlier successful step N (0-based). Only structured args are scanned, never strings. A ref that cannot resolve (forward, failed step, no match) fails its step with SEMANTIC_INVALID. Refer to created objects through $ref (instanceId, or entityId on Unity 6000.4+) rather than by name: a same-named existing object may win a name lookup.?mode=dryRun (the batch dryRun gate) validates every step, executes nothing and never halts; a step may name an object an earlier step would create (a warning notes the skipped live checks) and $ref args get a structural check only (refsValidated). ?mode=transactional is all-or-nothing with Undo rollback, rejected up front (400) for an unknown skill, a step that may trigger a domain reload, or continueOnError:true. ?diff=1 adds a net sceneDiff; ?wire=v2 slims dryRun step payloads; expectInstance / expectProject work as on /skill. ?mode=plan is not supported. mode / dryRun may sit in the body instead: each key resolves query-first and a blank value counts as absent. Any key outside these (body: steps, params, continueOnError, mode, dryRun) is 400 UNKNOWN_PARAM.Reading the response. HTTP 200 whenever the batch ran; only a rejected request (bad body, >50 steps, unknown mode or key) is 4xx.
{"status":"partial","mode":"execute","dryRun":false,"executed":2,"failed":1,
"results":[{"index":0,"skill":"...","status":"success","result":{...}},
{"index":1,"skill":"...","status":"error","error":{"errorCode":"...","error":"..."}},
{"index":2,"skill":"...","status":"skipped"}]}
status: completed (nothing failed), partial, or rolled_back (transactional: executed steps become rolled_back, asset-writing ones flagged rollbackReliability:"partial"). mode / dryRun echo what actually ran; every entry carries index and skill.success steps are applied; the failed step's Undo-recorded changes are reverted; skipped steps never ran. Resend only the fixed failed step and the skipped ones, never the successful ones.continueOnError notwithstanding: a MODE_RESTRICTED / CONFIRMATION_REQUIRED step halts the batch and returns its full payload (grant token included); complete the grant, then resubmit the remaining steps.Not the same as
batch_execute.batch_execute(confirmToken)commits one previewed bulk operation (one verb over N objects).POST /skills/batchcomposes N different skills over any targets and takes no token; it never skips the preview/confirm gate — abatch_executestep still needs its ownconfirmToken.
Jobs. When a skill or step returns a jobId (async execution, tests, compiles), wait with GET /jobs/{id}?wait=<s> (up to 120 s; answers once the job is terminal, with resultData; waitTimedOut:true = GET it again; a 503 during a domain reload = repeat the same URL) or poll GET /jobs/{id}. Both stay out of the main-thread skill queue and are far smaller than job_status; job_wait blocks the main thread (max 2 s).
queryJson (filters ANDed: name substring, namePattern regex, path / parentPath exact, entityId, instanceId, tag, layer, componentType, sceneName, active, isStatic, prefabSource, includeInactive (false), limit (500)); batch_query_* shows what matches.batch_preview_* or a fixer (batch_fix_missing_scripts, batch_standardize_naming, batch_set_render_layer, batch_replace_material, batch_cleanup_temp_objects). Previews are read-only and return {confirmToken, kind, summary, riskLevel, targetCount, executableCount, skipCount, sampleChanges: [{targetPath, action, before, after}], skipReasons}.batch_execute(confirmToken). The token is single-use and expires after an hour: preview again. Large runs return a jobId; the report (batch_report_get) lists failures, and batch_retry_failed(reportId) reruns only those.Under the guide surface profile previews still work but carry surfaceExclusion; batch_execute then returns SURFACE_EXCLUDED without consuming the token.
All but four of the 22 skills are read-only SemiAuto (query, preview, fixers, validation, reports, job status/progress/logs/list) and run directly under Approval; the 4 FullAuto ones (batch_execute, job_wait, job_cancel, batch_retry_failed) answer MODE_RESTRICTED there first and need a grant. Auto/Bypass run all; none is NeverInSemi → operating mode.
batch_query_gameobjects, batch_query_components, batch_query_assets (type/folder/name regex/label).batch_preview_rename (prefix/suffix/replace/regex_replace), batch_preview_set_property, batch_preview_replace_material, plus the fixers above; batch_validate_scene_objects only reports (missing scripts/references, duplicate names, empty objects).batch_execute, batch_retry_failed, batch_report_get, batch_report_list.job_status, job_progress, job_logs, job_list, job_wait, job_cancel.Per-skill tables and result shapes: reference/<skill_name>.md — rarely needed, the schema notes the parameters.
DO NOT (common hallucinations):
batch_execute cannot run without a confirmToken from a preview or fixer callbatch_run does not exist → use batch_execute(confirmToken)job_poll / job_result do not exist → use GET /jobs/{id} (or job_status) for state; job_status's resultHint names the skill that returns a large resultbatch_delete / batch_move do not exist → use asset_* skills for asset-level operationsElsewhere: asset bulk move/copy/delete → asset_*; workflow session undo → workflow_*.
There is no Batch category: GET /skills/schema?category=Workflow holds 16 of these skills (query, preview, execute, reports, jobs) and ?category=Validation the 5 fixers plus batch_validate_scene_objects; or use ?names=a,b.
MAmattpocock/skills288k10,178 new stars in the last 7 days
AFaffaan-m/ECC278k4,046 new stars in the last 7 days
AFaffaan-m/ECC278k4,046 new stars in the last 7 days
AFaffaan-m/ECC278k4,046 new stars in the last 7 days
DIDietrichGebert/ponytail162k5,405 new stars in the last 7 days
DIDietrichGebert/ponytail162k5,405 new stars in the last 7 days