Skip to content

Releases: dha-aa/ae-motion

2.24.0

Choose a tag to compare

@dha-aa dha-aa released this 23 Oct 07:00
a7583b1

Added

  • The installers (scripts/install.sh, scripts/install.ps1) register ae-motion with Claude Desktop and Claude Code themselves (scripts/register.ts), so there is no command left to copy. Claude Desktop gets an absolute node path (it starts with a minimal PATH that misses Homebrew and nvm); Claude Code gets the server at user scope, so it works in every project instead of only the folder the old printed command was run in. Other servers, app settings and an env you added are kept; an entry that is already right is left alone (the panel's Update button re-runs the installer); a config file that isn't valid JSON is never overwritten. AE_MCP_REGISTER=0 skips it.

  • Install with an agent: paste "Install the After Effects MCP server from https://github.com/dha-aa/ae-motion. Follow its INSTALL.md." into Claude Code (or any agent that can run commands) and it clones, installs and registers the server, then lists the two After Effects settings only you can change. INSTALL.md holds the agent's steps; the README's Installation section offers both ways.

  • The installers stop at once with a clear message when Node.js is missing or older than 22.18, instead of failing partway through the build.

  • node scripts/check.ts --ae says what is still missing after an install: it checks the server starts, reads Allow Scripts to Write Files and Access Network from After Effects' own prefs file (read only) and asks the panel for the project, and names the step for each part that fails. The installers run the server part after building, so a build that does not start fails the install instead of the first tool call. INSTALL.md ends with it instead of looking for bridge.json, which a crashed After Effects can leave behind.

  • Install with an agent installs a missing Node.js or git for you, after asking: Homebrew, or Apple's own installers, on macOS, and winget on Windows. It checks After Effects is installed too. The README's Requirements say how to check and install each one by hand.

  • AGENTS.md points AI agents other than Claude Code (Codex, Cursor and others) to INSTALL.md for installing and to CLAUDE.md and CONTRIBUTING.md for changes. CONTRIBUTING.md now says which doc gets what (README for people, INSTALL.md for agents, docs/setup.md for everything else), and a test keeps the docs' links and sections working and every setting documented.

Fixed

  • AE_MCP_FFMPEG (where ffmpeg is, for render checks and deliver) and AE_MCP_UPDATE_URL were read by the server but not documented; both are in the Configuration table now.
  • Installing by following INSTALL.md or the README put you on main, and the panel's Update button, which installs the newest release, then moved you back to that older release (dropping changes not released yet, such as the Claude Desktop / Claude Code registration). Both now install with node scripts/update.ts, which checks out the newest release and runs the installer for your OS, so installing and updating agree.
  • The installer's Claude Code: line and INSTALL.md say how to load the server in a running Claude Code session (/mcp, ae-motion, Reconnect) instead of only "start a new session".

Changed

  • The After Effects quirks (about 40 behaviours found in live testing) are in one place, host/CLAUDE.md, instead of two lists that had drifted apart: CLAUDE.md and docs/development.md each held facts the other lacked. Claude Code now loads them only when working in host/, so the CLAUDE.md read at the start of every session is about a third smaller (26 KB to 17 KB).
  • The README is rewritten in plain words for people who just want to use ae-motion: what it does, how it works, what you need, how to install it with Claude or by hand, and the two steps in After Effects. The details (what the installer changes, other MCP clients, configuration, security, troubleshooting, updating and uninstalling) moved, unchanged, to docs/setup.md; the tool list and example prompts are in docs/tools.md.
  • The server instructions are rewritten to fit in the 4,096 characters Claude Code shows (5,599 before, 4,083 now). The last rules (editing footage, framing, text over video, sound, counting, before finishing, run_jsx) used to be cut off, so Claude only saw them after the motion-guide prompt was run; now every rule reaches the model in every session. Same rules and numbers in fewer words; about 380 tokens less per session, and Claude Code's motion-guide is about 570 tokens (was about 1,090) since nothing is left over for it. A test fails if the instructions grow past the cut.
  • The README ends with every tool, grouped by area with an example of what to ask for, and how to contribute (bug reports, CONTRIBUTING.md, AGENTS.md). A test keeps the tool table equal to the tools the server offers.

2.23.0

Choose a tag to compare

@dha-aa dha-aa released this 21 Oct 17:34
2dfa539

Changed

  • The motion-guide prompt no longer repeats what Claude Code already shows from the server instructions. Claude Code cuts the instructions at 4,096 characters, so the conventions and the first design rules (format, copy, type, layout, timing, holds, polish) were in the model's context twice. The rules past the cut (editing footage, footage framing, text over video, sound, counting, before finishing, and the run_jsx rule) stay in the guide. Claude Code's guide is about 1,090 tokens instead of 1,680. Other clients, which may not show the server instructions to the model, get the whole guide as before.
  • Tool definitions use shorter forms that mean the same in JSON Schema: plain-type anyOf members become one type list ("type": ["integer", "null"]), no "type" beside a string const, no empty additionalProperties. That is about 100 tokens less, on every request in clients that send the definitions with each message; descriptions are unchanged and zod checks every value as before.
  • The server is built on the MCP TypeScript SDK v2 (@modelcontextprotocol/server 2.3) instead of v1 (@modelcontextprotocol/sdk, which now gets only bug and security fixes). Clients see the same tool list, instructions, prompt and results as before. Bad-argument errors are now explained from the schema's own issues instead of the SDK's wording, so they keep their BAD_ARGS format and "did you mean" hints whatever the SDK says.

Fixed

  • Calling a tool that does not exist returns a NOT_FOUND error with the closest tool name as a hint, in the usual {error: {code, message, hint}} format (it was the SDK's raw text).

2.22.0

Choose a tag to compare

@dha-aa dha-aa released this 16 Oct 14:00
6f6fa24

Changed

  • Clients that send every tool definition with every message (Claude Desktop, most others) are shown the core tools only: about 11k tokens of definitions per message instead of 18k. The other 32 tools are named in the server instructions, and a batch step that uses one shows its group first (the result lists loaded_groups); load_tools still works. Claude Code is shown every tool, as before, because it loads definitions only when a tool is used. AE_MCP_TOOLSETS still chooses the groups (all for everything); every tool is registered either way.
  • batch returns results: "auto" by default: each step's result whole up to 600 characters (ids, timing, values read back), larger ones cut to ids and names with a note (results: "all" keeps the old behaviour). Batch results were 43% of the result tokens in a 3-minute video build, mostly keyframe lists nobody re-read.
  • render_status includes the aerender log tail only when a job fails or logged errors; while running, every poll repeated the same ten progress lines.
  • find_fonts groups its result as {family: {style: PostScript name}} (plus listed when limit cut it): the same information in about 40% of the size.
  • Tool definitions: an enum of strings no longer repeats "type": "string" (about 1k characters less on every request; zod still checks every value).

2.21.0

Choose a tag to compare

@dha-aa dha-aa released this 16 Oct 13:57
3a63d93

Added

  • batch named steps: give a step as: "title" and refer to it as "$title.id" instead of counting steps, the most common reference mistake in long builds. A "$word" that is not a declared name stays literal text, so "$TSLA" in a caption still works; a repeated name, or a name used before its step, is reported before anything runs.
  • batch defaults: {tool: args}: shared arguments merged under every step of that tool (nested objects merge, the step's own values win). Repeated layers such as captions send their comp_id and style once instead of in every step, which cut a 48-caption build to about a third of its size.
  • add_layer fit: "cover" | "contain" scales footage, precomps and solids to fill the comp frame or fit inside it (pixel aspect included) and returns the scale used, instead of working out a percentage per clip.
  • add_layer source_in and stretch: place a clip by the source time it shows at in ({in: 1, source_in: 9.3}) and its speed, with no start-time maths. Hand-computed start times put the wrong part of a clip on screen twice while building a 3-minute edit.

Verified

  • Live in After Effects 26.3: fit cover / contain scales, source_in with stretch, named steps, defaults and a literal $word in batch; both are now part of the live tests (27/27 pass).

2.20.1

Choose a tag to compare

@dha-aa dha-aa released this 12 Oct 09:09
8a1be83

Fixed

  • preview_frame images show the comp's background in its own colour. After Effects writes the background as transparent pixels, which clients drew white, so light text on a dark comp looked invisible or washed out and a model could "fix" a design that was fine. The returned image is now opaque and matches the comp exactly (the edges were already blended).
  • set_layer reads back every field it sets: adjustment, guide, effects, audio, quality, sampling, collapse, time_remap, frame_blending, auto_orient, separate_dimensions, preserve_transparency, solid_color and solid_size were left out of its result.
  • import_footage as: sequence refuses a file whose name has no frame number. After Effects took every image in that folder as one sequence named after the folder.
  • A layered PSD or Illustrator comp import says its duration comes from After Effects' still-footage preference (it was 102.9 s), and its <name> Layers folder moves into folder with the comp.
  • About 50 errors now say what to do next (a missing file names the allowed folders, a move starting before 0 s says to start later, stagger on a property with no keys says to animate it first, and so on).

Verified

  • Blend modes and adjustment layers, from preview pixels in After Effects 26.3, now part of the live tests.

2.20.0

Choose a tag to compare

@dha-aa dha-aa released this 12 Oct 08:54
ab7b5c4

Added

  • set_text ranges style part of a text in the same call (After Effects 24.3+): a word in the accent colour, a bold name, one outlined line. Each range is match (every occurrence of a string) or start / end character indexes, with font, size, color, stroke, faux styles, caps, tracking, scale or baseline shift. This used to take a text animator built through several add_property calls. Every range is checked against the text before anything changes.
  • get_text lists the parts styled differently from the first character (ranges, only the fields that differ), so a model sees part styling before it changes the text.
  • import_footage imports several files at once (paths), a layered PSD or Illustrator file as a comp of its layers (as: comp / comp_cropped), and sets the footage's interpretation as it imports: fps (image sequences come in at 30 fps whatever they were rendered at, so a 24 fps render played too fast), loop and alpha. folder files the imports in a project folder (made if missing). Every file is checked before any is imported.
  • set_item, a new tool: rename a project item, set its comment or label, move it into a folder or back to the top level, change a footage item's fps / loop / alpha, or swap its file (or image sequence) for every layer that uses it.
  • Footage in get_project shows its fps, and items inside a folder show folder_id.
  • save_project clean: true removes footage no comp uses before saving (imports never placed, sources left behind by replace_source), and says how many (removed_footage).
  • A wrong argument name now says which one was meant: Unrecognized key: "stagger" (did you mean stagger -> stagger_seconds?). The suggestion is a known synonym (the timing tools name the same idea stagger, stagger_seconds and offset_seconds) or a near spelling, so a model fixes the call on the first retry. It costs nothing in the tool definitions.
  • find_sound_cues events: the model says what moments mean (importance 0-1, a label, optionally the sound) and the tool keeps the timing: the nearest motion cue takes the importance and keeps its frame-exact time; an event with no motion becomes its own cue; importance 0 keeps a moment quiet. The meaning comes from the model and the timing from the rules, which a music and sound-effects planner needs.
  • duck_music dips: stretches of near-silence, e.g. 0.35 s before a reveal (measured live: -100 dB through the pause, then the impact). A dips-only call keeps the ducks as they are.
  • set_layer audio_fade (in / out seconds) and sequence_layers audio_crossfade: equal-power fades, so one music cue crossfades into the next without a dip in level (measured live: within 0.4 dB through a 2 s crossfade).

Changed

  • stagger and shift_layers say which one moves keys and which moves whole layers, and point to sequence_layers.
  • duck_music ducks by -6 dB by default (was -10): the usual range under narration is 4-8 dB.
  • find_sound_cues ranks cuts low on their own, so a hit on every cut is no longer the default; story events raise the cuts that matter.
  • Volume keys can be set under the ducking expression (set_keyframes refused them, and its hint said to clear the expression, which removed the ducking). Springs are still refused there, since they would replace it.

Fixed

  • set_text with new text now says when it removed part styling (ranges_cleared: true): After Effects gives every character the first one's style when the text changes. Passing the same text no longer reassigns it, so part styling survives.
  • find_sound_cues cues a scale pop when the layer arrives (97% of the way), not at its last key: with a spring or snappy ease the last key is where it only settles, up to 15 frames after the hit. An entrance that pops and fades in is now one cue instead of two competing ones. Found by building a 12-second documentary reveal and checking where the impact belongs.
  • The after-render check no longer calls a dark title card with a line of text a black picture (and no longer suggests a GPU failure for it): a frame now counts as black only when 99.9% of it is dark.

2.18.0

Choose a tag to compare

@dha-aa dha-aa released this 11 Oct 15:42
9391ece

Added

  • set_property takes layer_ids: the same value on many layers in one call (13 coins, 10 ingots), every layer checked before any changes.
  • save_project snapshot: true (with an optional note) keeps a numbered copy in snapshots/ next to the project, so going back to an earlier version is open_project on that copy instead of rebuilding it from memory.
  • render_start start / end (seconds) render part of a comp, and draft: true uses the Draft Settings template: a quick moving preview of a few seconds, where preview_frame only shows stills.
  • preview_frame names the scene each frame shows in an edit (scene, or scenes for a contact sheet): the top precomp playing at that time.
  • add_layer_style accepts the Layer Style panel's labels where the match name differs: size (blur), spread / choke, angle, altitude, blend_mode, range, technique.

Fixed

  • render_start always passes the comp's frame range to aerender, and a finished file shorter than that fails the job. A render once stopped at 54 of 2,422 frames, exited 0 and was reported as done with a clean check.
  • A new text layer no longer inherits the last text's character settings (After Effects takes the Character panel's current ones): add_layer starts text from tracking 0, no faux styles or caps, auto leading, 100% scale, before any text_style.
  • set_track_matte and add_layer_style warn when a 3D layer has layer styles: After Effects then ignores its track matte and draws it in stacking order instead of by depth (verified live; even a style switched off does it).
  • review_motion checks text against the title-safe margin on its last frame too, not only mid-way: camera pushes carried titles out of frame by the end, where the check never looked.
  • batch: a "$N.path" reference inside an array (e.g. layer_ids: ["$1.id", "$2.id"]) was rejected by the pre-check ("expected number, received string") although it resolves to a number when the step runs. Zod reports array positions as numbers and the comparison only matched strings.

2.17.0

Choose a tag to compare

@dha-aa dha-aa released this 11 Oct 05:34
5830c82

Added

  • animate moves for holds: push (a slow scale-up, default 4%) and drift (a slow float), from where a layer's animation lands to its out point, keeping the landing's ease (a spring still lands exactly). In review, frozen holds after the build were the most common flaw.
  • Design rules for the model in the server instructions and motion-guide, as a senior motion designer and video editor would work: sizes relative to the comp's short side so they fit landscape, vertical (9:16 social) and square; the safe areas social apps cover; copy kept exactly as given; timing (move within 0.2 s, finish the build by 40%), keeping holds alive, polish (soft-edged glows, depth, one accent colour); and for footage: cutting on action or the beat, shot lengths, hooks, trimming dead air, b-roll over jump cuts, framing and reframing for vertical, text over video and captions, sound levels and delivery loudness.
  • review_motion checks: a late first move (after 0.3 s); changes too small to see no longer count as motion, so a wobbling layer still shows as a hold; text crossing the 5% title-safe margin, or in vertical comps the top 10% and bottom 20% that social apps cover; small text judged against 3% of the comp's short side (was 2.2% of its height).

Changed

  • preview_frame is 5-7 times faster: about 0.1 s per frame instead of 0.6 s, 0.2 s for a six-frame sheet instead of about 3 s. It returns as soon as the PNG is complete (its IEND chunk) instead of polling the size in 150 ms steps, and renders at the coarsest resolution that still covers the returned image instead of always at full resolution.
  • get_project lists each comp's layers (unless the project has over 300), and set_keyframes returns the keys as set, so a model needs fewer calls; the server instructions ask it to make independent calls together and not to re-read what a result already shows.

Fixed

  • get_project works on big projects: it used to stop at 500 items and, past roughly 300 items with real file names, went over the size limit and failed with no way to ask for less. It now takes name (substring) and type filters and pages with limit (default 200) / offset, reporting matched and next_offset like get_comp (the truncated field is gone). The 300-layer limit for listing each comp's layers now counts the comps on the returned page, so paging also brings layers back on big projects.
  • list_markers pages with limit (default 100) / offset and returns next_offset, instead of stopping at 500 markers.
  • set_playhead and set_3d_view are no longer marked destructive: they only change the viewer.
  • The update instructions get_project and check_for_updates give for updating by hand said git pull, which fails in the state the panel's Update button leaves the repo in (a release tag, not a branch). They now say node scripts/update.ts, which checks out the newest release and runs the installer.
  • set_light's point_of_interest was described as where a camera looks.
  • Errors that left the model guessing now say what to do: an unknown blend_mode lists the valid names, an unknown render job explains that jobs are forgotten when the MCP server restarts, a marker property points to the marker tools (not run_jsx), and "not keyframable", "does not support expressions", a missing preset and failed menu commands (text_to_shapes, add_layer_style) have hints.
  • The ae://project and ae://selection resources return compact JSON, and a failed read is now a resources/read error (with the code and hint) instead of the error body returned as if it were the resource.

Removed

  • The evaluations (evals/): the question and build-task runs through headless Claude Code. The live tests (test/live/run.ts) stay.
  • The hard limit on the size of the tool definitions (npm test prints the size instead).

2.16.0

Choose a tag to compare

@dha-aa dha-aa released this 10 Oct 20:14
22af85a

Changed

  • Back to the 2.13.0 code: everything from 2.14.0 and 2.15.0 is undone (the compact schemas, run_jsx hidden when disabled, the core-toolset default and its reversal, the six extra build evaluations, the split review.ts / sound.ts host files, the constant-time token check, and the removed tool-list budget). Reopen the panel after updating. The undone work is kept in the git history and on the backup-speed-quality branch.

2.15.0

Choose a tag to compare

@dha-aa dha-aa released this 10 Oct 19:40
828c45f

Changed

  • All tools are loaded by default again (AE_MCP_TOOLSETS=core is still there to opt in). With core as the default (2.14.0) the evals kept their scores on about 40% fewer input tokens, but cost only 2-8% less, because most of the input is cached and cached tokens are cheap, and ran 12-20% slower; and the model rebuilt camera moves, alignment and 3D settings from keyframes instead of loading camera_move, align_layers and set_3d. The smaller schemas and the hidden run_jsx from 2.14.0 stay: they cut 5-7% of the tokens with no such side effect.
  • No hard limit on the size of the tool definitions any more (npm test prints it).