---
name: kaleidoscope-floor-plans
description: Convert floor plans into Kaleidoscope Plan drawing files. Use when the user shares a floor plan image, sketch, PDF or written room description and wants an editable drawing (.kalar file) for the Kaleidoscope Plan app on iPhone, iPad or Mac - e.g. "turn this floor plan into a Kaleidoscope Plan file", "make me a .kalar of this plan", "convert this estate-agent plan so I can edit it".
license: See LICENSE.txt (free to use and share; provided as-is)
---

# Kaleidoscope Floor Plans

You turn a floor plan - an image, a PDF page, a hand sketch, or a written description - into a **`.kalar` drawing file** that opens directly in [Kaleidoscope Plan](https://kaleidoscopeplan.app) (iPhone / iPad / Mac). A `.kalar` is plain, human-readable JSON: one building, its floors, their rooms, and each room's walls, doors, windows and openings. Everything you write stays fully editable in the app - walls keep real layer build-ups, doors keep their swing, rooms keep their names.

Format documentation: https://kaleidoscopeplan.app/docs/file-formats

## What to ask the user for

1. **The plan** - image, PDF, sketch, or a description ("a 5 × 4 m studio with the door on the south wall…").
2. **One real dimension**, if the plan has no printed dimensions or scale bar. Any known measurement works (a wall length, a room width). If the user has none, assume a standard interior door leaf is **0.838 m** wide, scale everything from a door, and *tell the user you did that*.

## The contract (read carefully)

- **Units are meters.** Coordinates are 2-D points `{"x": …, "z": …}`: **x grows to the right, z grows downward** as you look at the plan. There is no y in the floor plane.
- **Walls are centre-lines** between `startPoint` and `endPoint`. Thickness comes from the wall's layer `stack` (omit it for a standard 100 mm partition).
- **Each room's walls form one closed loop.** Consecutive walls must share endpoint coordinates **exactly - copy the same numbers** (the app tolerates ≤ 1 cm, but exact is correct). The room's `boundary.polygon` lists the loop's corner points in order with `"closed": true`, and `area` (shoelace formula) and `perimeter` (sum of edge lengths) must match it.
- `metadata.schemaVersion` is `"1.0.0"`. The file is UTF-8 JSON, extension `.kalar`.
- **Every `id` in the file is unique.** Use `"<kind>-<UUID>"` (e.g. `"wall-53F618F9-…"`). All numbers finite - never NaN/Infinity.
- Empty collections are **present as `[]`, never omitted**: every room needs `walls`, `openings`, `windows`, `doors`, `fixturesAndFittings` keys even when empty.

## Workflow

1. **Read the plan.** Identify wall centre-lines and thicknesses, doors (with swing direction), windows, archways / pass-throughs (= openings), and room name labels. Prefer axis-aligned walls when the plan is orthogonal - snap near-horizontal/vertical lines straight.
2. **Establish scale** from a printed dimension, scale bar, or known element; state what you used and convert everything to meters (round to 5 mm is plenty).
3. **Build rooms one at a time.** Each enclosed space on the plan = one room object with its own closed wall loop:
   - A wall **shared by two rooms** appears once in *each* room at the same centre-line, and both copies carry the same `linkGroupId`, set to the **first copy's own `id`** (that copy is "canonical"). The app then treats the pair as one physical wall.
   - A **free-standing partition** inside a room (a stub that doesn't help close the loop) gets `"isFreeWall": true` and is exempt from the loop rule.
   - **Exterior walls** deserve a real build-up - give them a `stack` (outside → inside). Common UK build-ups are in `reference/kalar-schema.md`; brick / cavity / block / plaster (266 mm) is a safe default for masonry exteriors. Interior partitions: omit `stack` (defaults to a 100 mm stud partition).
4. **Attach doors, windows and openings** to their wall: `parentWallId` must reference a wall **in the same room object** (for a linked pair, attach to the canonical wall and put the element in that wall's room). `startPoint`/`endPoint` sit **on the wall's centre-line, strictly inside its span**. Typical sizes: door width 0.76–0.95 m, height 1.98 m, `heightFromFloor` 0; window sill (`heightFromFloor`) 0.9 m, height 1.2 m. An archway with no door leaf = an **opening**.
   - **Door swing:** `hingeSide` `"left"` = hinge at the door's `startPoint` end, `"right"` = at its `endPoint` end. `openingDirection` `"inward"` = the leaf swings to the room-interior side of the wall. Match the arc drawn on the plan; if it's not drawn, use `left`/`inward` - the user can flip either with one tap in the app.
5. **Name the rooms** from the plan's labels (`"name": "Kitchen"`). Unlabelled rooms: use a sensible name, not an empty string.
6. **Self-check** against the checklist below, fix anything that fails, then save as **`<Building name>.kalar`** and hand the file to the user with the opening instructions.

## Validation checklist (run it every time)

- [ ] Valid JSON; `schemaVersion` `"1.0.0"`; at least one floor with at least one room.
- [ ] Every room: walls form one closed loop (shared endpoints exact); `boundary.polygon` = the loop corners in order, `closed: true`; `area`/`perimeter` computed from that polygon.
- [ ] Every door/window/opening: `parentWallId` exists in the **same room**, both points on the parent's centre-line, inside the span, not overlapping another element on that wall.
- [ ] Linked walls: both copies coincident, same `linkGroupId`, exactly one copy's `id` equals the group id.
- [ ] All ids unique file-wide. All numbers finite, in meters.
- [ ] Enums exact: `confidence` `high|medium|low` · `hingeSide` `left|right` · `openingDirection` `inward|outward` · door `type` `singleSwing|doubleSwing|sliding|pocket` · window `type` `fixed|casement|sash|awning|sliding`.
- [ ] No omitted collections; no extra commentary inside the JSON.

## Complete working example

A real, openable studio flat - 5 × 4 m, front door on the south wall, two windows. Use it as your template; the full pretty-printed version is `examples/studio.kalar`.

<!-- kalar-template:begin -->
```json
{
  "metadata": {
    "schemaVersion": "1.0.0",
    "exportId": "export-F93B0737-063C-56E8-A76B-22780921C5F3",
    "createdAt": "2026-06-12T09:00:00.000Z",
    "device": { "model": "", "osVersion": "", "roomPlanVersion": "" },
    "scanDuration": 0,
    "units": "meters",
    "coordinateSystem": { "type": "right-handed", "origin": "", "axes": {} },
    "confidence": "high"
  },
  "building": {
    "id": "building-F93B0737-063C-56E8-A76B-22780921C5F3",
    "name": "Studio Flat",
    "floors": [
      {
        "id": "floor-F93B0737-063C-56E8-A76B-22780921C5F3",
        "name": "Ground Floor",
        "level": 0,
        "elevation": 0,
        "rooms": [
          {
            "id": "room-F93B0737-063C-56E8-A76B-22780921C5F3",
            "name": "Studio",
            "ceilingHeight": 2.4,
            "area": 20.0,
            "perimeter": 18.0,
            "boundary": {
              "closed": true,
              "polygon": [
                { "x": 0, "z": 0 }, { "x": 5, "z": 0 },
                { "x": 5, "z": 4 }, { "x": 0, "z": 4 }
              ]
            },
            "walls": [
              { "id": "wall-53F618F9-F991-509A-9231-EF4922F9D652", "category": "wall",
                "startPoint": { "x": 0, "z": 0 }, "endPoint": { "x": 5, "z": 0 },
                "confidence": "high", "completedEdges": [] },
              { "id": "wall-6EB946CB-BE10-5BF1-876C-9979C3B840F6", "category": "wall",
                "startPoint": { "x": 5, "z": 0 }, "endPoint": { "x": 5, "z": 4 },
                "confidence": "high", "completedEdges": [] },
              { "id": "wall-7A126CE9-F54A-5C7C-8608-D759C008D40C", "category": "wall",
                "startPoint": { "x": 5, "z": 4 }, "endPoint": { "x": 0, "z": 4 },
                "confidence": "high", "completedEdges": [] },
              { "id": "wall-990C3B1C-268E-597C-888A-33A9AB6D30F0", "category": "wall",
                "startPoint": { "x": 0, "z": 4 }, "endPoint": { "x": 0, "z": 0 },
                "confidence": "high", "completedEdges": [] }
            ],
            "doors": [
              { "id": "door-50586B1F-2DE4-5D7D-B731-34390A1E1113",
                "parentWallId": "wall-7A126CE9-F54A-5C7C-8608-D759C008D40C",
                "startPoint": { "x": 4.3, "z": 4 }, "endPoint": { "x": 3.4, "z": 4 },
                "heightFromFloor": 0, "height": 1.98,
                "hingeSide": "left", "openingDirection": "inward",
                "isOpen": false, "confidence": "high", "type": "singleSwing" }
            ],
            "windows": [
              { "id": "window-D41FBFA5-1492-5A08-B12D-C4AA4F2190BE",
                "parentWallId": "wall-53F618F9-F991-509A-9231-EF4922F9D652",
                "startPoint": { "x": 1.2, "z": 0 }, "endPoint": { "x": 2.8, "z": 0 },
                "heightFromFloor": 0.9, "height": 1.2,
                "confidence": "high", "type": "casement" },
              { "id": "window-3529670E-06F0-50BB-93F9-1B4097C62A19",
                "parentWallId": "wall-6EB946CB-BE10-5BF1-876C-9979C3B840F6",
                "startPoint": { "x": 5, "z": 1.5 }, "endPoint": { "x": 5, "z": 2.7 },
                "heightFromFloor": 0.9, "height": 1.2,
                "confidence": "high", "type": "fixed" }
            ],
            "openings": [],
            "fixturesAndFittings": []
          }
        ]
      }
    ]
  }
}
```
<!-- kalar-template:end -->

For a multi-room plan with linked shared walls, custom exterior build-ups and an archway opening, read `examples/one-bed-flat.kalar` (4 rooms).

## Opening the file

Tell the user:

- **iPhone / iPad** - save the `.kalar` to the Files app (or AirDrop it), then tap it: it opens in Kaleidoscope Plan. Or in the app: **Drawings → Import**.
- **Mac** - double-click the file, or drag it onto the app.

Everything is live geometry: they can move walls, retype doors and windows, edit layer build-ups, place furniture, run the 3-D view and the measurement/area tools on what you produced.

## Scope and honesty

- **Straight walls only** - the format stores straight centre-line segments. Approximate a gentle curve with 2–4 short segments and say so.
- **Don't place furniture, fixtures, lights or radiators** unless the user insists - the format supports them, but placing them from the app's catalogue is faster and more accurate. Your job is the structure: walls, doors, windows, openings, rooms.
- **Multi-storey:** one entry in `floors` per storey (`level` 0, 1, 2…), each with its own rooms.
- Your output is a **draft for editing, not a survey**. Always tell the user to check key dimensions in the app before relying on them.
- If the plan is unreadable or ambiguous, ask - don't invent geometry silently. List any assumption you made.

## Bundled reference

- `reference/kalar-schema.md` - full field-by-field schema: every struct, every enum raw value, wall layer types, common build-ups, link-group rules.
- `examples/studio.kalar` · `examples/one-bed-flat.kalar` - verified files that open in the app as-is.

---

*This skill is an independent integration published by Maritime Master Limited, the maker of Kaleidoscope Plan (https://kaleidoscopeplan.app). It is not created, endorsed or supported by Anthropic. Claude is a trademark of Anthropic, PBC. Floor plans you share in a conversation are processed by your AI provider under its own terms.*
