Conversation
Adds `codea screen-size [preset]` over the setScreenSize/getScreenSize MCP tools, so a project can be screenshotted at different sizes and orientations without editing it. Modelled on `idle-timer`/`paused` rather than `runtime`: the presets apply to the viewer, not to a project, so there is no project argument. The five preset ids are validated client-side, which rejects a typo without a round trip, and the display name is mapped locally since the device returns the bare id. The device half is not implemented yet, so this errors against current Codea builds until it ships. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014kJYH24sqV9xNvhVb86bMZ
The Air Code server only runs for Pro subscribers, so every `codea` command already requires Pro and a non-Pro user cannot reach `screen-size` to be told about it. Singling this command out as Pro-gated, and promising an error instead of a paywall, described a path that cannot happen. Replaces it with the two failures that are reachable — no project running, and a non-viewer host such as the standalone Runner — and notes that WIDTH/HEIGHT change with the preset, confirmed on device across all five presets. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014kJYH24sqV9xNvhVb86bMZ
Records the history back to 0.1.0 from the tags, and configures cargo-release to move the Unreleased section and its compare links to the new version on bump. Distribution is by cargo-dist from the pushed tag, so publishing to crates.io stays off. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TqPb55Kii6dZHot2PPGMFq
release.toml duplicated publish, allow-branch and pre-release-commit-message from [package.metadata.release] in Cargo.toml, and cargo-release 1.1.6 gives the Cargo.toml section precedence: with tag-name set in both, a dry run tags from Cargo.toml. The values matched, so nothing behaved differently, but editing release.toml — the obvious place to look — would have silently done nothing for those three keys. Removes the Cargo.toml section so release.toml is the only source, and notes in the file why that section must stay gone. Verified by dry run: the tag is v0.1.7 from release.toml, publish = false is honoured (no packaging or upload step, unlike publish = true), and allow-branch still refuses a topic branch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014kJYH24sqV9xNvhVb86bMZ
getScreenSize now returns {"preset": id} plus width and height once the viewer
has laid out, rather than the bare preset id, so a future custom size with an
arbitrary width and height needs no second change to the wire format. Changing
it now costs nothing because neither half has shipped.
The dimensions are the viewer's live bounds, not the preset's nominal size, so
under match-display they follow the window and reading the size is a query
rather than a stored setting; the docs say so. They are omitted rather than
null before first layout, so a lone width or height, or neither, prints the
preset alone. setScreenSize is unchanged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014kJYH24sqV9xNvhVb86bMZ
The reported size demonstrably comes from laid-out bounds rather than a table of preset sizes: ResizableRenderer.Preset.width is 0 for tv, square and matchWindow, yet tv reports 1920 x 1080, and the five presets cross-check to the pixel against WIDTH/HEIGHT read inside Lua. That part stands. Following the window under match-display does not: it is a sound inference from the renderer tracking view bounds, but resizing the window needs Stage Manager or split view and hands on the device, so it has not been observed. The absent-dimensions branch has never fired either — polling after a run returns "no project running" until the size is already there. Both now read as expected rather than tested, and the changelog states only what shipped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014kJYH24sqV9xNvhVb86bMZ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue
Agents driving Codea through
codeacould screenshot a project only at whateversize the viewer happened to be. Checking a layout at another size or orientation
meant changing the viewer by hand on the device, which is exactly what the CLI
exists to avoid.
Fix
Adds
codea screen-size [preset]over thesetScreenSize/getScreenSizeMCPtools, accepting the five viewer preset ids verbatim:
Shaped after
idle-timer/pausedrather thanruntime: the presets apply tothe viewer, not to a project, so there is no project argument. Preset ids are
validated client-side, so a typo fails with the valid list and no round trip,
and the id → display name mapping lives in the CLI so the reported id stays the
contract.
Reading the size is a live query, not a stored setting.
getScreenSizereturns
{"preset": id}pluswidthandheightonce the viewer has laidout, and those are its laid-out bounds rather than the preset's nominal size.
Under
match-displayit should therefore follow the window, though that is anexpectation rather than something observed — see Tests. Dimensions are omitted
rather than null before first layout, so the command prints the preset alone in
that case.
No
--jsonflag: this CLI has none anywhere, and adding one here would havemade
screen-sizethe odd command out.Depends on
Do not merge before the app half ships, or a released
codeaadvertises acommand no shipped Codea answers. The MCP tools exist only in
codea PR #440,
so until that merges and reaches a build, this command fails with an
unknown-tool MCP error for everyone.
Tests
cargo fmtclean, no new clippy warnings, 13 unit tests pass — the parser iscovered for dimensions present, omitted, half-present and fractional, and for a
bare id or a missing preset now being an error.
Verified on an iPad Pro (iPad14,5, iOS 26.7) against a local build of #440,
re-run after the read contract changed to JSON. All five presets, read back
through the parser:
match-displayiphone-portraitiphone-landscapetvsquareThese agree to the pixel with
WIDTH/HEIGHTread inside Lua in an earlierrun — two independent sources. That the size comes from laid-out bounds rather
than a preset table is also proven directly:
ResizableRenderer.Preset.widthis 0 for
tv,squareandmatchWindow, yettvreports 1920 × 1080.Both reachable failures print their message and exit 1: no project running, and
an unknown preset, the latter rejected client-side with no round trip.
Two branches are deliberately untested because neither can be reached here.
The non-Pro path is unreachable by design — the Air Code server only starts for
Pro subscribers, so a non-Pro user cannot reach any MCP tool at all. The
absent-dimensions path has never been seen to fire: polling after
codea runreturns "no project is running" until the size is already present. Both are
kept anyway, since reporting a wrong or zero size would be worse than handling
a case that may occur on a slower device. Likewise,
match-displayfollowingthe window is expected from the renderer tracking view bounds but was not
observed — the two levers available remotely,
viewer.mode = FULLSCREENandsliding the output pane, both overlay the viewer rather than inset it, and a
real resize needs Stage Manager or split view.
Also folds in a changelog and
cargo releaseconfiguration, and removes the[package.metadata.release]section fromCargo.tomlsorelease.tomlis theonly home for that config: cargo-release 1.1.6 gives the
Cargo.tomlsectionprecedence, so editing the duplicated keys in
release.tomlsilently didnothing. Verified by dry run that the tag, the changelog replacements,
publish = falseandallow-branchall behave fromrelease.tomlalone.🤖 Generated with Claude Code
https://claude.ai/code/session_014kJYH24sqV9xNvhVb86bMZ