# Codia Image To Design

> Convert screenshots or images into editable Codia design data. Trigger when the user asks to turn an image, screenshot, poster, UI, or design mockup into structured editable design output.

- Skill: `codia-ai/codia-image-to-design` (Agent Skill)
- Install (CLI): `npx skillmds@latest add codia-ai/codia-image-to-design`
- Raw SKILL.md: https://api.skillmd.com/api/skills/codia-ai/codia-image-to-design/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Design & Media
- Author: codia-ai (https://skillmd.com/u/codia-ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/codia-ai/codia-image-to-design

---


# codia-image-to-design

## Runtime And Auth

Use the local `codia-design` CLI for this feature. Before calling the API, verify that `codia-design` is available. If it is missing and global npm installs are allowed, install it with `npm install -g @codia-ai/codia-design-cli`. Then check `codia-design auth status`; if it is not connected, run `codia-design auth login --platform codex` or bind an API key with `codia-design auth set --api-key api_key_xxx`. Never print API keys or `~/.codia/design-skills/config.json`.

Convert UI screenshots into editable hierarchical design trees (VisualElement trees).

## CLI Command

```bash
# Synchronous direct conversion
codia-design image-to-design --image <PATH|URL> [--out FILE]

# Asynchronous task submit
codia-design image-to-design --image <HTTPS_URL> --async [--callback URL] [--idempotency KEY] [--out task.json]

# Asynchronous task submit and poll
codia-design image-to-design --image <HTTPS_URL> --poll [--timeout 300000] [--out result.json]
```

## Parameters

| Flag | Type | Required | Default | Description |
|---|---|---|---|---|
| `--image` | path \| URL | yes | — | Local PNG/JPG/WebP path, or public HTTPS URL |
| `--async` | boolean | no | false | Create an `image_to_design` task and return `task_id` without waiting |
| `--poll` | boolean | no | false | Create an `image_to_design` task, poll `/v2/open/tasks/:task_id`, and return the completed design tree |
| `--timeout` | milliseconds | no | 300000 | Maximum wait time for `--poll` |
| `--callback` | URL | no | — | Optional task callback URL for async mode |
| `--idempotency` | string | no | — | Sends `Idempotency-Key` for async task creation |
| `--out` | path | no | stdout | Write JSON results to file (recommended for large responses) |

## Sync vs Async Selection

Use synchronous `POST /v2/open/image_to_design` for one image, especially local files and images below 2K on the longest edge. It keeps the result in a single request and supports direct multipart upload for local files.

Use asynchronous `POST /v2/open/tasks` with `operation: "image_to_design"` for multiple images, images at 2K or above, or flows that need callback/idempotency/retry behavior. Submit one task per image. Task mode currently accepts `input.image_url`, so the CLI requires `--image` to be a public HTTPS URL in `--async` or `--poll` mode. For a local large image, upload it to user-owned storage/CDN first and pass that URL, or use synchronous mode if the expected runtime is acceptable.

## Response

Synchronous mode and completed `--poll` mode return the design data. `--poll` also includes task metadata fields such as `task_id`, `operation`, `status`, and `progress`.

```json
{
  "ok": true,
  "data": {
    "configuration": {
      "scalingFactor": 1.0,
      "baseWidth": 375,
      "measurementUnit": "px"
    },
    "visualElement": {
      "elementId": "root_001",
      "elementName": "Body",
      "elementType": "Body",
      "layoutConfig": { "positionMode": "Normal" },
      "styleConfig": {
        "widthSpec":  { "sizing": "FIXED", "value": 375 },
        "heightSpec": { "sizing": "FIXED", "value": 812 }
      },
      "contentData": null,
      "processingMeta": { "detectionScore": 1.0, "surfaceArea": 304500 },
      "childElements": []
    }
  }
}
```

### configuration field

| Field | Type | Description |
|---|---|---|
| `scalingFactor` | number | All values must be multiplied by this factor to get the actual pixels |
| `baseWidth` | number | Canvas base width (375=mobile, 1440=desktop) |
| `measurementUnit` | string | `"px"` or `"pt"` |

### VisualElement node structure

Every node (including the `visualElement` root node and all `childElements`) has the same schema:

| Field | Type | Description |
|---|---|---|
| `elementId` | string | Node ID (regenerated for each call, not stable across calls) |
| `elementName` | string | Human-readable tag name |
| `elementType` | string | Node type, see the table below |
| `layoutConfig` | object | Positioning information |
| `styleConfig` | object | visual style |
| `contentData` | object \| null | Node content (only Text/Image has value) |
| `processingMeta` | object | Detection confidence and area |
| `childElements` | array | child nodes (recursive) |

### elementType value

| elementType | has child nodes | contentData field | description |
|---|---|---|---|
| `Body` | yes | — | Root node, always exists |
| `Layer` | yes | — | Universal container (card, section, etc.) |
| `Group` | yes | — | Pure grouping, no self-visualization |
| `Text` | no | `textValue: string` | Text leaf node |
| `Image` | no | `imageSource: string` | Image (CDN URL) |
| `Vector` | no | `vectorData` | Vector shape |
| `Component` | Varies | `componentReference` | Detected UI component |

### layoutConfig key fields

```
positionMode: "Flex" | "Absolute" | "Normal" | "Relative"
```

- `"Flex"` — Participate in the flex layout of the parent node. The parent node’s `flexAttributes` describe the direction/alignment
- `"Absolute"` — absolute positioning, read `absoluteAttrs.coord.x` / `.y` to get the offset
- `flexAttributes`: `{ flexDirection, alignItems, justifyContent, flexWrap }` (on Flex container)

### styleConfig key fields

| Field | Type | Description |
|---|---|---|
| `widthSpec` / `heightSpec` | `{sizing, value}` | `sizing`: FIXED=exact px / FILL=fill parent / FIT_CONTENT=shrink |
| `textConfig` | object | `fontSize`, `fontFamily`, `fontStyle`, `lineHeight`, `letterSpacing`, `textAlign` |
| `textColor` | `{rgbValues, hexCode}` | Text color |
| `borderConfig` | object | `borderWidth`, `borderStyle`, `borderColor`, `borderRadius: [tl,tr,br,bl]` |
| `backgroundConfig` | object | `type`: `"COLOR"` / `"IMAGE"` / `"LINEAR_GRADIENT"` + respective fields |
| `opacityLevel` | number | 0–255, divided by 255 to get CSS opacity |
| `paddingValues` | array | `[top, right, bottom, left]` |

## Usage Example

```bash
# Synchronous local file, recommended for a single small image
codia-design image-to-design --image ./screenshot.png --out result.json

# Synchronous URL
codia-design image-to-design --image https://example.com/screen.png --out result.json

# Submit an async task for a large image and return task_id
codia-design image-to-design --image https://example.com/large-screen.png --async --out task.json

# Submit and wait for completion
codia-design image-to-design --image https://example.com/large-screen.png --poll --timeout 300000 --out result.json
```

Traverse the tree after reading the results (Node.js):

```js
const { data } = require('./result.json');
const { scalingFactor } = data.configuration;

function walk(node, depth = 0) {
  const pad = '  '.repeat(depth);
  if (node.elementType === 'Text') {
    console.log(pad + '[Text]', node.contentData?.textValue);
  } else if (node.elementType === 'Image') {
    console.log(pad + '[Image]', node.contentData?.imageSource);
  } else {
    console.log(pad + '[' + node.elementType + ']', node.elementName);
  }
  node.childElements?.forEach(c => walk(c, depth + 1));
}
walk(data.visualElement);

//Extract all text nodes
function extractText(node, results = []) {
  if (node.elementType === 'Text') results.push(node.contentData?.textValue);
  node.childElements?.forEach(c => extractText(c, results));
  return results;
}
```

Low confidence node filtering (`processingMeta.detectionScore < 0.5`) is recommended for use in production code.

## Input Limits

The maximum size and file size of input images depend on the plan level:

| Packages | Maximum resolution | Maximum file size |
|---|---|---|
| Free | 1440×1440 | 5 MB |
| Starter | 4096×4096 | 20 MB |
| Pro | 10000×10000 | 50 MB |

## Errors & Billing

| HTTP | Meaning | Fix |
|---|---|---|
| 400 | The image URL is not accessible or the format is not supported | Confirm that the URL is publicly accessible and the format is PNG/JPG/WebP |
| 402 | Insufficient credits | `codia-design credits` Recharge after confirming the balance |
| 429 | Rate limit exceeded | Retry after backing off |
| 500 | Service internal error | Safe to try again |

**Credits**: 13 credits/request. After the command completes, the CLI checks `available_credits` and reminds the user if the remaining balance is below 26 credits (2x estimate); this does not block generation. **Duration**: synchronous mobile screenshots are usually < 10s, desktop intensive pages are longer. Prefer async task mode for large images, 2K+ images, and batches.

