Resize logo

Resize

Organization
imgly
resize

Use when resizing or reformatting a CoDesign / CE.SDK design to a new size or aspect ratio (ig-post ↔ ig-square ↔ ig-story ↔ widescreen, or a custom W×H); when building the size/format editions of a design from an existing design or from a brief; or when a reformatted edition has a dead void / letterboxed empty band, drifted or broken margins, off-canvas or clipped elements, mis-scaled decoration, or a stretched / squished layout. Also for animated / video designs: timed blocks, animations, captions, and audio carried into each edition.

Overview

Publisherimgly
Repositorycodesign
Skill nameresize
Stars
43
Forks
1
Bundled files
1
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 1 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by imgly on GitHub. Read the source before you install it.

Installation

Install the Resize AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/imgly/codesign/tree/main/plugins/codesign/skills/resize
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/imgly/codesign.git /tmp/codesign
mkdir -p .claude/skills
cp -r /tmp/codesign/plugins/codesign/skills/resize .claude/skills/resize
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Resize in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Resize on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Resize is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

resize

Point this skill at the current design and one or more target formats, and it produces or repairs the size/format editions by re-composing each for its new aspect. It operates on the design in the current session, and each produced format is saved as its own .imgly file. Single home for the resize workflow, the re-composition technique, and the reformat no-goes.

The one mechanic to understand before anything else. A session holds one design, so N formats are produced in sequence, not in parallel, and the saved source file is what you return to between them (handbook §1):

export({ format: 'imgly' })                     → SOURCE_URI   (save the source FIRST)
per format:
  import({ source: { uri: SOURCE_URI } })       → a copy of the source is the session
  edit(…)  re-compose for the new canvas
  preview()                                     → check it
  export({ format: 'imgly' })                   → this format's own file

Save the source before you touch it. Re-importing is what makes every format a re-composition of the source rather than of the previous format — and it is why "never resize a resize" is a mechanical rule here, not just advice.

Builds on two things it does not restate: handbook §6.3 Hierarchy + §6.4 Composition & grid (margins as % of the shortest dimension, the spacing ladder, balanced whitespace / no dead void, nothing off-canvas) and §6.1.2 type-scale bands; and the handbook's engine mechanics (the text.font declaration, auto-reshape, loadResources). For the same-aspect, translate-the-strings case, use the localize skill instead.

Scoring: reformatting is judged with the judge skill — every applicable axis ≥ 8. A dead void, a stretched element, a broken margin, or anything off-canvas fails composition.

Reference files (load on demand)

This SKILL.md holds the always-needed spine: inputs, the localize-vs-resize distinction, core principle, workflow, the re-composition routine, the no-goes, and the resize composition checklist (end of this file). Per-format data lives in the formats skill — exact W×H, aspect, and platform safe zones, one file per format: ../formats/SKILL.md for the index, ../formats/<id>.md for the format(s) you're building.

Building several editions of one design, or re-applying a fix to editions you already built: the master → editions workflow, editions.md. For an animated or video design, read Video and animated designs below as well.

Localize vs resize — snap vs re-compose

Format is the outer distinction: a different format is a different layout; a different language is the same layout with different strings.

  • localize — same canvas: change words + the script's font, then snap every block back to the reference geometry. Any geometry deviation is drift.
  • resize — new canvas: the geometry must change. You re-derive the layout from the design system on the new canvas. Here "drift" is not "moved from the reference" — it's re-composition that loses the design's identity or leaves the canvas unbalanced.

Never confuse the two: don't snap a resize (that reproduces the source's proportions on the wrong canvas → a dead void), and don't re-compose a localization (that's how localized sets drift).

Inputs — what to resize, and into what

Two inputs, resolved before any work by the intake contract — derive, ask once, echo, invent nothing: ../handbook/intake.md. R = required, no default; A = ask if underived; D = defaultable.

ParameterKindChips / valuesDefault
target formatsRInstagram post · Instagram story · LinkedIn · Widescreen · A4 print · Custom W×H · Othernone
source designderived—the design in the current session

1. The source — the design in the current session. Save it first (export({ format: 'imgly' })) and hold onto the uri: every target format is re-composed from that file — never resize a resize (don't chain; re-import the source between formats). If the user asks to resize a design saved earlier, its uri IS the source uri: open it to preview and capture it, skip the first save, then import a copy of it per format. If the request is a brief (no design exists yet), build the native base first at the brief's canvas per handbook §6, preview and sanity-check it, then save it and treat that file as the source.

2. The formats — named formats (ig-post, ig-square, ig-story, widescreen, and the rest of the formats skill's index) or a custom W×H. Resolve each named format's exact size, aspect, and safe zones from the formats skill (../formats/<id>.md).

If the format set is not stated, ask — Which sizes do you need? — with the chips above; a format set has no sensible default, so never pick one for the user. Then echo the resolved set ("1 design → 3 formats") before building.

Core principle — re-compose for the aspect, preserve the system

A new format is a new layout. Re-lay it out for the new canvas while holding the design system constant:

  • Invariant (carry to every format): palette + the single accent; type-scale bands (headline / body / caption as % of page height, §6.1.2); margin ratio (§6.4: 8–12% of the shortest side); spacing scale (§6.4 ladder); hierarchy order (§6.3); the group hierarchy (carry the source's grouping — re-group each cluster after re-composition, don't ship a flattened tree); the region of interest of every image/video fill (the subject stays framed — see the ROI section below); each decoration's role (a ghost quote stays a ghost quote); the element inventory (every content cluster on the source has a counterpart on the new canvas — see below); and the appearance of every block (fill/gradient, effect/blur stack, opacity, corner radius, stroke, shadow, and font weight — carried in by re-importing the source, not re-created by eye).
  • Element inventory — nothing silently dropped. A reformat re-composes; a tight format tempts you to drop elements, and the result reads "way too simplistic / missing elements from the original." Before finishing, count: every text cluster, image, chip, icon, and decoration on the source must have a counterpart on the new canvas. An element may be omitted only deliberately (it genuinely can't earn its place on a smaller canvas) — never by oversight, and the omission is a judgment you can name. Re-composing from an impression of the source instead of its actual block list is how elements vanish.
  • Variable (re-derive per canvas): absolute positions, absolute sizes, wrap width, line count, and how the content group is distributed vertically.

Never stretch or squish the whole design to force-fit (that distorts type and shapes — resize by re-flow, not by scaling the canvas contents). Never leave a lopsided void (§6.4).

Workflow

  1. Save the source and keep its uri — export({ format: 'imgly' }). Everything below re-imports it, once per format.
  2. Read the source's design system (palette, accent, type bands, margin %, spacing rhythm, hierarchy) and capture its layout as fractions of the source canvas (positions/sizes as % of source W/H — see routine). Do this once, on the source; the JSON it returns is what you carry from format to format.
  3. Re-import the source for this target format (import({ source: { uri: SOURCE_URI } })); capture the region of interest of every image/video fill first (ROI section below); set the page to the new W×H and resize the full-bleed background to cover it; then restore each fill's ROI so the same region of the image stays framed — never let a Cover fill silently re-center the subject on the new aspect.
  4. Re-derive from the new canvas: margins = 8–12% of the new shortest dimension; type sizes from the new page height within their bands (§6.1.2); gaps from the spacing scale (§6.4).
  5. Proportional re-flow to fill, then balance. Place blocks by their captured fractions × the new canvas (this fills a taller/wider canvas instead of letterboxing it), then center or distribute the content group within the platform safe band — no top-anchored void. (Safe-zone bounds and per-format guidance: the formats skill, <id>.md.)
  6. Scale decoration proportionally to the canvas (a ghost glyph sized as % of page height grows on a taller format, shrinks on a shorter one) — keep its role and framing.
  7. Re-wrap & re-fit: text re-wraps at the new column width; check overflow / clipping / off-canvas; adjust size within its band only.
  8. Let the size/font write carry the rich text. A text.fontSize / text.font / text.lineHeight write reshapes on its own and preserves every per-character style range — color, weight, style, case, decoration (handbook §6.1.3). A resize keeps the same string, so there is nothing to capture and replay. What still flattens the accent is a whole-block styling write: getProps(id, ['text.color']).text.color reads run 0 only, and writing it back as text: { color } collapses the whole block to run 0's formatting. Don't re-apply whole-block styling in a resize; if you must, pass the runs from getProps(id, ['text.ranges']) back as text: { ranges: [...] } in the same setProps — every run, not just the accent.
  9. loadResources → preview this format (dead void / crop / tofu only show in the render), then save it: export({ format: 'imgly' }). That file is the format's edition — until you save, it exists nowhere the user can reach, and the next import will replace it. Collect the returned uris and report them all at the end. Give each build's edit a note naming the format (e.g. "ig-story 1080×1920"). Then go back to step 2 for the next format. For a video design, preview each format at several times — see Video and animated designs below.

Proportional re-composition routine

The resize analog of localize's snap-to-reference — but a first pass, not the finish. It fills the new canvas proportionally (killing the letterbox void); you then clamp margins/bands/safe-zones and judge the balance in preview. Resize is judgment-driven; there is no single deterministic answer.

Capture the source as fractions (run on the source page):

js
const [page] = await engine.design.findByType('page');
const pg = await engine.design.getProps(page, ['width', 'height']);
const PW = pg.width,
  PH = pg.height;
const out = [];
async function walk(id) {
  const p = await engine.design.getProps(id, [
    'type',
    'width',
    'height',
    'position'
  ]);
  const r = {
    type: p.type, // the SHORT name: 'text', 'graphic', 'page'
    fx: p.position.x / PW,
    fy: p.position.y / PH,
    fw: p.width / PW,
    fh: p.height / PH
  };
  if (p.type === 'text') {
    const t = (await engine.design.getProps(id, ['text'])).text;
    r.s = t.string;
    // the size read carries its unit ('32px', always pixels) — parse for math
    r.ffs = parseFloat(t.fontSize) / PH; // fraction of page height
    r.lh = t.lineHeight;
    r.ls = t.letterSpacing;
    r.align = t.horizontalAlignment;
  }
  if (id !== page) out.push(r);
  for (const c of await engine.design.getChildren(id)) await walk(c);
}
await walk(page);
return { type: 'text', text: JSON.stringify({ PW, PH, blocks: out }, null, 1) };

Apply to the re-imported source at the new size (first pass, then clamp):

js
const NW = 1080,
  NH = 1920; // target format
const SAFE_TOP = 250,
  SAFE_BOT = 320; // ig-story/reel UI chrome (authoritative per-format values: formats skill, <id>.md); 0 for post/square/widescreen
const [page] = await engine.design.findByType('page');
await engine.design.setProps(page, { width: NW, height: NH });

// full-bleed background → cover the new page (don't reposition it proportionally)
let bg;
for (const id of await engine.design.getChildren(page)) {
  const p = await engine.design.getProps(id, ['type', 'width']);
  if (p.type === 'graphic' && p.width >= NW * 0.9) {
    bg = id;
    break;
  }
}
if (bg !== undefined) {
  const roi = await captureFill(bg); // BEFORE the aspect change — ROI section
  await engine.design.setProps(bg, {
    position: { x: 0, y: 0 },
    width: NW,
    height: NH
  });
  await reapplyFill(bg, roi); // keep the same image region framed on the new aspect
}
// ...and captureFill/reapplyFill around EVERY other image/video-fill block you resize.

// content blocks → position/size by captured fractions (fill), then you clamp + balance below
// for each captured fraction f matched to its block id:
//   await engine.design.setProps(id, { position: { x: f.fx*NW, y: f.fy*NH } }); // fills the taller canvas
//   if (f.fw) await engine.design.setProps(id, { width: f.fw*NW }); // a logo: set height by the same factor
//   if (f.ffs) await engine.design.setProps(id, { text: { fontSize: clampToBand(f.ffs*NH) + 'pt' } });
//              // the unit is required; the write auto-reshapes, ranges preserved
//
// THEN, not optional:
//   • margins: ensure left/right within 8–12% of min(NW,NH); re-center centered blocks on NW.
//   • safe band: shift the whole content group so nothing vital sits above SAFE_TOP or below NH-SAFE_BOT.
//   • balance: if proportional spread looks airy/crowded, distribute the group evenly or center it —
//     preview and adjust. Scale decoration with the canvas; keep type within §6.1.2 bands.
return {
  type: 'text',
  text: 'first pass placed — now clamp margins/safe-zone/balance and preview'
};

Platform safe zones and per-format notes are in the formats skill — read <id>.md for each target format.

Preserve the region of interest (image / video / pattern fills)

Re-flowing positions is only half the job. A block backed by an image or video fill shows a window onto its source, and that window is recomputed when the block's frame aspect changes: a Cover fill re-centers, a Crop fill exposes gaps. Left alone, the resize crops the subject out of frame — the face, product, logo, or focal point that made the asset worth using. That is a composition and craft failure, and it only shows in preview.

The ROI is defined by (all on the block, via the api skill): contentFill.mode (Crop | Cover | Contain); for the auto modes, contentFill.horizontalAlignment + contentFill.verticalAlignment (Left|Center|Right, Top|Center|Bottom) — this is the focal side a Cover fill keeps; and for Crop, crop.scaleRatio + crop.translationX/Y (translation in % of the crop frame) + crop.rotation, which pin an explicit window.

Capture before the resize, re-apply after — around every fill-bearing block, not just the background:

js
async function captureFill(id) {
  // image/video/pixel fills only
  const caps = await engine.design.getCapabilities(id);
  if (!caps.includes('contentFillMode')) return null;
  const cf = (await engine.design.getProps(id, ['contentFill'])).contentFill;
  const cap = {
    mode: cf.mode,
    hAlign: cf.horizontalAlignment,
    vAlign: cf.verticalAlignment
  };
  if (cap.mode === 'Crop') {
    const c = (await engine.design.getProps(id, ['crop'])).crop;
    cap.crop = {
      sr: c.scaleRatio,
      tx: c.translationX,
      ty: c.translationY,
      rot: c.rotation
    };
  }
  return cap;
}

async function reapplyFill(id, cap) {
  if (!cap) return;
  await engine.design.setProps(id, {
    contentFill: {
      mode: cap.mode,
      horizontalAlignment: cap.hAlign, // ROI focus for Cover/Contain
      verticalAlignment: cap.vAlign
    }
  });
  if (cap.mode === 'Crop' && cap.crop) {
    const c = cap.crop;
    await engine.design.setProps(id, {
      crop: { rotation: c.rot, translationX: c.tx, translationY: c.ty }
    });
    await engine.design.adjustCropToFillFrame(id, c.sr); // refill gaps, keep scale ≥ source
  }
}

Order matters: captureFill before you write the block's width/height, reapplyFill after. setProps(id, { crop: null }) forces the mode back to Cover, so never call it in a resize path. Default to keeping the ROI centered; when the brief or the asset's metadata names a focal point, bias alignment (Cover) or translation (Crop) toward it. preview each format and confirm the subject is still framed — the render is the only place ROI drift shows.

Crop invariants — the three properties every photo-in-a-frame must hold (checked in preview; they fail independently of ROI focus, and a shape frame — circle/rounded card — makes them easy to miss). A logo or other mark is the exception: it is shown whole, never cropped — keep its frame at the logo's own aspect (scale width and height by the same factor) or its Contain mode, and leave the space around it empty (handbook design rules, "A logo is shown whole").

  1. Full coverage, zero gap. The fill covers its frame completely — no sliver of empty frame at any edge (the "gap at the top of the circle" defect). If the aspect change exposed a gap, adjustCropToFillFrame (Crop) or the Cover mode refills it; never leave the frame partly unfilled.
  2. Uniform scale — no stretch. The image scales the same on both axes; a hand-set non-uniform crop distorts the subject. Scale is one ratio, not two. (Contain never stretches: it scales uniformly and leaves the rest of the frame empty — which is why it suits a logo and breaks invariant 1 for a photo.)
  3. Subject inside the window. After 1–2, the focal point is still within the visible crop, not pushed out by the refill. This is the ROI check above — do it last, after coverage is guaranteed.

Re-group after re-composition. Resize moves and resizes loose blocks; before you finish, restore the source's group hierarchy on the new canvas (handbook §4 "Group blocks & hierarchy") so each format ships the same grouped, nested structure — not a flattened tree.

Video and animated designs

Applies when the page has a playback.duration, blocks carry playback.timeOffset / playback.duration, animations, an audio block, or a captionTrack. A resize re-composes the frame; the timeline is invariant.

  • Fork, move, resize — never recreate a timed block. A page resize keeps every block's timeOffset, duration, animations, audio and video trims; a re-created block loses all of them. Walk the whole tree, not just the page's children: timed blocks can sit under tracks and captions under a captionTrack (the capture walk above already recurses).
  • Re-aim every entrance for the new layout. slide / pan direction is the direction of travel in radians, y pointing down: 0 enters from the left moving right, π/2 from the top moving down, π from the right, 3π/2 from the bottom moving up. A slide that entered from the photo's side on 16:9 crosses the photo once 9:16 stacks text under it — aim it along the new reading axis. Patch in place with the same type, which keeps the animation's duration: setProps(id, { animations: { in: { type: 'slide', slide: { direction: (3 * Math.PI) / 2 } } } }) (a different type replaces the animation and resets its duration); duration: s in the same spec sets it.
  • Scaling entrances overdraw. zoom / grow scale around the block's centre, so a full-height photo spills over its neighbours during the entrance — check the first frames after every re-layout.
  • Vertical safe zones hold for the whole timeline. Story / reel / TikTok / Shorts UI covers the top and bottom bands (and the right edge on TikTok / Shorts) — ../formats/ig-story.md, ../formats/tiktok.md, ../formats/yt-shorts.md. Captions and CTAs belong inside the safe band, and so does every block's position mid-entrance.
  • Captions carry their own frame, per caption. Writing the first caption's position or size does not reach the others — set position, width, height, caption/fontSize on every caption, with caption/automaticFontSizeEnabled off (otherwise the text grows past its frame and over the layout). Keep the frame's bottom at or above H − bottom safe band.
  • A fill's region of interest moves over time. Capture / re-apply the ROI as above, then check it at the start, middle and end of every video clip and of every ken_burns / pan move — a crop that frames the subject at 0 s can cut it at 3 s.
  • Preview at several times, per edition. One frame of a video proves nothing about the rest: preview({ time }) at the first frame, mid-entrance of each timed block, each hold, each caption change and the last second. Then export({ format: 'mp4', blockId: page }) for the real motion.

No-goes / red flags

  • Dead void / letterboxing — the headline failure: content clustered on one side of a taller/wider canvas, an empty band elsewhere. Fill or balance the group; respect safe zones.
  • Design drift — re-composition that loses the design's identity: margins wander, the type scale or hierarchy shifts, the accent is misused, or decoration loses its role. Re-compose within the system, don't redesign.
  • Stretch / squish — scaling the canvas contents non-proportionally to force-fit. Never distort type or shapes; re-flow instead.
  • Broken margin rhythm — margins not re-derived from the new shortest dimension, or asymmetric.
  • Off-canvas / clipping / overflow — elements pushed past the new edges; decoration over-cropped; text overflowing the new column.
  • Decoration mis-scale — a ghost glyph or accent kept at the source's absolute size instead of scaling with the canvas.
  • ROI drift — a resized image/video fill re-centered and cropped the subject out of frame (face, product, logo, focal point). Capture and re-apply the fill's region of interest.
  • Missing elements — the reformat re-composed from an impression and silently dropped source content ("too simplistic / elements missing from the original"). Inventory every source cluster against the new canvas; omit only deliberately, never by oversight.
  • Appearance drift — a block's fill/gradient/effect/corner-radius/overlay differs from the source, or an overlay was added/removed the source didn't have (a cover that "became darker"). Appearance is inherited by re-importing the saved source; don't re-create or restyle it by eye.
  • Crop broken — a fill leaves a gap inside its frame, or was stretched non-uniformly. See the three crop invariants (coverage, uniform scale, subject-in-window).
  • Flattened hierarchy — the resize dropped the source's group blocks and shipped a flat list of siblings. Re-group each cluster (nested where nested) on the new canvas.
  • Ignoring platform safe zones — vital content under story/reel UI chrome.
  • Timeline drift (video) — a timed block re-created instead of moved, an entrance still aimed across the old layout, or a caption left in the platform's UI band.
  • tofu / overflow at new wrap widths — a new measure can push a glyph the font lacks, or wrap to a line count that overflows; only preview catches it.

Before reporting done

Run the resize composition checklist below against each format's render, then close with a judge run per format (the judge skill; composition and hierarchy are the axes reformatting most often breaks). Score honestly — a residual void is a composition fail, say so.

Resize composition checklist

Any "no" on an applicable line drops the axis below 8.

Composition (§6.4)

  • Margins 8–12% of the new shortest dimension; on the shared grid / one alignment
  • Whitespace balanced — no lopsided dead void / letterbox; content occupies or balances the canvas
  • Consistent spacing scale (§6.4 ladder); nothing off-canvas, clipped, or overlapping
  • Primary content within the format's safe band (per its formats file; story/reel: clear of top 269px / bottom 672px)

Hierarchy (§6.3) & identity

  • One dominant element preserved; reading order intact; ≈3 levels
  • Palette + single accent, type-scale bands (§6.1.2), and each decoration's role carried over
  • Decoration scaled proportionally to the canvas (not the source's absolute size)
  • Every image/video fill keeps its region of interest — subject/focal point still framed, nothing important cropped out or newly empty (checked in preview)
  • Source's group hierarchy restored on the new canvas (grouped clusters, nested where nested — not a flat list)
  • Element inventory complete — every source content cluster (text, image, chip, icon, decoration) has a counterpart on the new canvas; any omission is deliberate and nameable, not an oversight
  • Appearance parity — every block's fill/gradient, effect/blur, opacity, corner radius, stroke, shadow, and font weight match the source; no overlay added or removed the source didn't have (checked against the source render)

Craft / baseline

  • No stretch/squish; type re-fit within its band, not distorted
  • Crop invariants hold on every fill-in-frame — full coverage (no gap), uniform scale (no stretch), subject inside the window (checked in preview)
  • Zero tofu / overflow at the new wrap width, checked in preview
  • Native export dimensions (the page's own pixel size)

Video / animated (when the design has a timeline)

  • Every block's timeOffset / duration, animations and audio carried over — moved, not re-created
  • Every entrance re-aimed for the new layout (direction = direction of travel); no block crosses the photo or leaves the safe band mid-entrance
  • Every caption framed and sized on the new canvas, inside the safe band, auto font size off
  • Checked at several times (entrances, holds, caption changes, last second), not one frame

Cross-references

  • formats skill — per-format W×H, aspect, and platform safe zones (one file per format id).
  • handbook §6.3 Hierarchy, §6.4 Composition & grid, §6.1.2 type-scale bands — the general composition criteria this skill operationalizes; §6.1.2's canvas table for type sizing by % of page height; and the handbook's engine mechanics (the text.font declaration, auto-reshape, loadResources, dirty-on-throw).
  • judge — the acceptance gate every produced format must pass.
  • localize — the sibling for translating a design at the same size (snap, don't re-compose).

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Resize AI skill do?

Use when resizing or reformatting a CoDesign / CE.SDK design to a new size or aspect ratio (ig-post ↔ ig-square ↔ ig-story ↔ widescreen, or a custom W×H); when building the size/format editions of a design from an existing design or from a brief; or when a reformatted edition has a dead void / letterboxed empty band, drifted or broken margins, off-canvas or clipped elements, mis-scaled decoration, or a stretched / squished layout. Also for animated / video designs: timed blocks, animations, captions, and audio carried into each edition.

Why use Resize on TypingMind?

Because you install it once and use it with any model. Resize is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Resize in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/imgly/codesign/tree/main/plugins/codesign/skills/resize. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Resize?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Resize?

As many as you like. As long as a model supports skills, you can use Resize with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Resize AI skill free?

Yes. It is published on GitHub by imgly under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇