{"slug": "show-hn-zipzi-open-source-live2d-editor-alternative-with-ai-assisted-editing", "title": "Show HN: Zipzi – Open-source Live2D Editor alternative with AI-assisted editing", "summary": "Zipzi released an alpha of Zipzi 2D, an open-source alternative to Live2D Cubism Editor built in Rust and GPUI, that pairs a visual desktop editor with a Python API so an AI coding agent and a human can inspect and edit the same model with shared undo history. The editor, named from the Cantonese word for origami, ships with an MIT-licensed SDK, supports macOS and Windows, and is explicitly labeled early development with no stable release, meaning APIs and file formats may change. Zipzi positions the tool for commercial use and says an image-capable agent can, for example, export one wireframe-highlighted image per mesh plus a JSON naming worksheet to rename every mesh in a model.", "body_md": "**An open-source 2D modeling and animation tool for creating alongside AI.**\n\nYou shape the artwork. Your AI agent helps with the modeling work. Zipzi connects a visual desktop editor with a Python API, so you and your agent can inspect and edit the same model, share undo history, and build on each other’s changes.\n\nZipzi 2D is an open-source alternative to Live2D Cubism Editor, built with Rust\nand GPUI. Its name comes from Cantonese 摺紙 (*zip3 zi2*), meaning “origami”.\n\n[**Download Alpha**](https://github.com/getzipzi/zipzi-2d/releases) · [Python SDK](https://github.com/getzipzi/zipzi-2d/blob/main/crates/zipzi-python/README.md) · [Report an issue](https://github.com/getzipzi/zipzi-2d/issues) · [Contribute](#contributing)\n\n**Early development:** There is no stable release yet. APIs and file formats\nmay change. The editor supports macOS and Windows.\n\n- **Open source and commercial friendly** — Create, refine, and use your models\ncommercially with an open-source editor and an MIT-licensed SDK.\n- **Native and high performance** — Built with Rust and GPUI for low memory\nusage and responsive editing, even with complex models and dense meshes.\n- **Agent-ready** — Create from scratch, collaborate with AI, or import an\nexisting model for further refinement.\n\n## zipzi-2d-demo.mp4\n\nDescribe what you want to your AI coding agent. It uses the Python SDK to inspect models, view rendered images and make edits you can review and undo in the editor. You and your agent work on the same document, with shared undo history.\n\nBring your own Python-capable agent and point it to the\n[SDK guide](https://github.com/getzipzi/zipzi-2d/blob/main/crates/zipzi-python/client/python/zipzi/docs/guide.md).\n\n**You describe the task; your AI agent writes and runs the code.** The examples\nbelow were generated by an AI coding agent and tested against a running Editor.\nThey show how the agent works through the Python SDK—you do not need to write\nthese scripts yourself. Your role is to explain what you want and review the\nresults in the editor.\n\nAsk your agent: **“Look at every mesh and give it a meaningful name.”**\n\nInstall the [Python client](https://github.com/getzipzi/zipzi-2d/blob/main/crates/zipzi-python/README.md#installation)\n(CPython 3.14), start a compatible Editor with GPU observation support, and open\none model. An image-capable coding agent can run the following two steps.\n\n**1. The agent observes every mesh.** Its generated script exports one image per mesh, with its\nwireframe highlighted over the textured model, plus a JSON naming worksheet.\n`observe` supplies visual evidence; the agent supplies the semantic interpretation.\n\n``` python\nimport json\nfrom pathlib import Path\nfrom uuid import uuid4\n\nimport zipzi\nfrom zipzi import inspection, observation, spatial\n\noutput = Path(\"mesh-review-\" + uuid4().hex[:8]).resolve()\noutput.mkdir()\n\nwith zipzi.connect() as runtime:\n    sessions = runtime.sessions.list()\n    if len(sessions) != 1:\n        raise RuntimeError(\"Open exactly one model for this example.\")\n    session = runtime.sessions.attach(sessions[0].id)\n\n    # Follow every page: a single list() call may not contain all meshes.\n    meshes, cursor, source = [], None, None\n    while True:\n        page = session.meshes.list(cursor=cursor)\n        if source is None:\n            source = page.source\n        if page.source != source:\n            raise RuntimeError(\"Model changed; restart the inspection.\")\n        meshes.extend(page.items)\n        cursor = page.next_cursor\n        if cursor is None:\n            break\n\n    rows = []\n    for index, mesh in enumerate(meshes):\n        # Use this mesh's bounds to frame it, including hidden geometry.\n        # {} evaluates default parameter values, not the editor's current pose.\n        query = spatial.Bounds(\n            targets=(spatial.MeshTarget(value=mesh.id),), include_hidden=True,\n        )\n        bounds = session.modeling.spatial(\n            ({},), (query,), expected=source,\n        ).wait().value.frames[0].results[0].value.model_bounds\n        row = dict(id=mesh.id, old_name=mesh.name, new_name=mesh.name, image=None)\n        if bounds is not None:\n            x0, y0, x1, y1 = bounds\n            margin = max(x1 - x0, y1 - y0, 1.0) * 0.15\n            view = observation.View(\n                width=768, height=768,\n                roi=(x0 - margin, y0 - margin, x1 + margin, y1 + margin),\n                topology=observation.Overlay(\n                    targets=(observation.MeshTarget(value=mesh.id),),\n                    wireframe=True, include_hidden=True,\n                ),\n            )\n            # Freeze all observations to the inventory's source. If the model\n            # changes, the SDK refuses stale reads; rerun instead of mixing them.\n            images = session.modeling.observe(({},), view, expected=source).wait()\n            report = inspection.save(images, output / f\"mesh-{index:04d}\")\n            row[\"image\"] = str(report.images[0])\n        rows.append(row)\n\n    # SessionId is a typed handle: store its fields for the second script.\n    worksheet = output / \"names.json\"\n    worksheet.write_text(json.dumps(\n        dict(session_id=dict(runtime=session.id.runtime, serial=session.id.serial),\n             meshes=rows), indent=2, ensure_ascii=False,\n    ), encoding=\"utf-8\")\n    print(worksheet)\n```\n\nHave the agent **open each exported PNG**, identify the highlighted mesh in\ncontext, and edit only `new_name` in `names.json`. Keep IDs and `old_name` intact.\nThe overlay selects diagnostic geometry, not isolated artwork: surrounding\ntextures remain visible, and hidden or occluded artwork may still be ambiguous.\nKeep the original name for uncertain or image-less entries, or inspect additional\nposes before naming them.\n\n**2. The agent applies the semantic names together.** After you review the\nproposed names, the agent writes and runs the following script with the path to\n`names.json`. You do not need to copy the code or run a terminal command. Keep\nthe same model open and unchanged between inspection and application.\n\n``` python\nimport json\nimport sys\nfrom pathlib import Path\n\nimport zipzi\n\nreview = json.loads(Path(sys.argv[1]).read_text(encoding=\"utf-8\"))\nrows = review[\"meshes\"]\nif len({row[\"id\"] for row in rows}) != len(rows):\n    raise ValueError(\"Duplicate mesh IDs in the worksheet.\")\nif any(not isinstance(row[\"new_name\"], str) or not row[\"new_name\"].strip()\n       for row in rows):\n    raise ValueError(\"Every mesh needs a nonempty name.\")\n\nwith zipzi.connect() as runtime:\n    # Rebuild the typed handle; a restarted Editor requires a new inspection.\n    session = runtime.sessions.attach(zipzi.SessionId(**review[\"session_id\"]))\n    # All renames commit together as one undo step. A missing mesh or changed\n    # original name aborts the edit instead of leaving a partly renamed model.\n    with session.edit(\"AI: semantic mesh names\") as edit:\n        for row in rows:\n            current = edit.meshes.get(row[\"id\"]).value\n            if current.name != row[\"old_name\"]:\n                raise RuntimeError(\"Mesh changed; inspect the model again.\")\n            if row[\"new_name\"] != row[\"old_name\"]:\n                edit.meshes.rename(\n                    row[\"id\"], row[\"new_name\"], expected_name=row[\"old_name\"],\n                )\n    print(\"Review the names in the editor. Undo to revert, or save to keep them.\")\n```\n\nNo project save happens automatically. The name check detects renamed or removed\nmeshes, not every possible geometry or texture change; repeat the inspection if\nthe model has changed. For more workflows, see the\n[capability guide](https://github.com/getzipzi/zipzi-2d/blob/main/crates/zipzi-python/CAPABILITIES.md).\n\nWork with meshes, parameters, deformers and BlendShapes, then bring them together in the animation workspace. Generate mesh geometry or refine it by hand. Mesh Edit lets you work on the posed model or switch to the source image, while resampling stored shapes as the geometry changes.\n\nPython scripts can also run independently with a local Runtime for automation\noutside the editor. Explore the [Python SDK](https://github.com/getzipzi/zipzi-2d/blob/main/crates/zipzi-python/README.md)\nfor modeling, animation authoring, previews and inspection.\n\n- **Use the editor:** Download an Alpha build from[GitHub Releases](https://github.com/getzipzi/zipzi-2d/releases) . Check the\nrelease notes for the available platform builds and requirements.\n- **Automate with Python:** Follow the[installation and connection guide](https://github.com/getzipzi/zipzi-2d/blob/main/crates/zipzi-python/README.md) .\nThe SDK currently requires CPython 3.14.\n- **Build your own tools:** Explore the[Rust SDK](https://github.com/getzipzi/zipzi-2d/blob/main/crates/zipzi-sdk/README.md) for programmatic authoring.\n\n| Area | What you can work with | \n|---|---|\n| Modeling | Meshes, parameters, keyforms, parts, deformers, BlendShapes and Glue | \n| Animation | Motion, expression, physics and pose authoring; animation previews | \n| Project I/O | PSD import and Cubism-related formats, including Model3/MOC3, projects and runtime sidecars; support and loss rules vary by format and direction | \n| Automation | Python sessions, batch edits, shared undo/redo, project operations and model inspection | \n| Platforms | macOS and Windows | \n\nSee the [SDK capability guide](https://github.com/getzipzi/zipzi-2d/blob/main/crates/zipzi-python/CAPABILITIES.md) for details.\nGPU inspection requires a compatible host and usable GPU. Format support does\nnot imply lossless round trips for every model.\n\nTry an Alpha build and [tell us what gets in your way](https://github.com/getzipzi/zipzi-2d/issues).\nFor bug reports, include the build version, platform and steps to reproduce;\nshare model assets only when you have permission to do so.\n\nFor code contributions, start with the [repository map](https://github.com/getzipzi/zipzi-2d/blob/main/MONOREPO.md),\n[editor guide](https://github.com/getzipzi/zipzi-2d/blob/main/crates/zipzi-editor/README.md) or\n[Python SDK guide](https://github.com/getzipzi/zipzi-2d/blob/main/crates/zipzi-python/README.md). The\n[documentation index](https://github.com/getzipzi/zipzi-2d/blob/main/docs/README.md) covers deeper references.\nDevelopment commands and focused test selection are below.\n\nUse Rust 1.95 or newer, uv 0.10.7 or newer, and CPython 3.14.\nThe macOS Editor requires Xcode Command Line Tools and a Metal-capable GPU.\nThe [Windows Editor](https://github.com/getzipzi/zipzi-2d/blob/main/crates/zipzi-editor/README.md) requires\nMSVC, the Windows SDK and a usable GPU.\nRun these commands from the repository root:\n\n```\nuv sync --locked\npython3 tools/workspace/cargo_domain.py --check\n\n# Focused SDK development\ncargo test --locked -p zipzi-sdk --test integration physics_editing::\n\n# Native Editor (macOS)\ncargo run --locked -p zipzi-editor\n./tools/test-editor.sh fast timeline::\n\n# Repository tooling tests; no native application build\nuv run --locked python tools/test_tools.py\n```\n\nFor the Python SDK, `./tools/test-sdk.sh python` refreshes its native adapter\nand runs Local/Connected behavior and static types. `python-connected` installs\nthe pure wheel and validates real subprocess host discovery and session binding;\nadd `--editor-host /absolute/path/to/zipzi-editor` for the current desktop host.\nRoot `pyproject.toml` and `uv.lock` manage development tools.\n\n## Focused test commands and coverage\n\nChoose the smallest gate covering the change, then broaden when needed. Run\ncommands from the repository root; inspect available modes with\n`./tools/test-sdk.sh --help`, `./tools/test-editor.sh --help` or\n`uv run --locked python tools/test_tools.py --help`.\n\n| Changed area | Starting command | \n|---|---|\n| One Rust crate/module | `cargo test --locked -p <crate> --lib <filter>` ; add its integration target when relevant | \n| Runtime ownership/jobs/events | `./tools/test-sdk.sh runtime` | \n| Local protocol / installed Python client | `./tools/test-sdk.sh python-connected` | \n| SDK authoring behavior | `./tools/test-sdk.sh fast <filter>` | \n| Editor adaptive mesh generation | `./tools/test-editor.sh fast adaptive_mesh::` ;`./tools/test-editor.sh fast mesh_generation::` | \n| SDK alpha mesh generation | `./tools/test-sdk.sh mesh` | \n| wgpu backend / local GPU parity | `cargo test --locked -p zipzi-render-wgpu --tests` ;[host selection](https://github.com/getzipzi/zipzi-2d/blob/main/crates/zipzi-render-wgpu/README.md#application-routes-on-macos) | \n| Editor coordination | `./tools/test-editor.sh fast <filter>` | \n| Editor UI (macOS/Metal) | `./tools/test-editor.sh ui <filter>` | \n| Runtime Python SDK ( `zipzi-python` ), Local/Connected and types | `./tools/test-sdk.sh python` ([scope](https://github.com/getzipzi/zipzi-2d/blob/main/crates/zipzi-python/README.md) ) | \n| Shared authoring contract / isolated Python generation | `cargo test --locked -p zipzi-contract` ;`uv run --locked python tools/test_tools.py -p test_python_codegen.py` | \n| Runtime GPU observation / inspection (usable GPU required) | `./tools/test-sdk.sh python --observation` | \n| Python complete-call recovery, Edit state and Job timeout | `./tools/test-sdk.sh python --recovery` (optional`P3ARecovery.test_name` ) | \n| Python collection pages, Session detach/close and offline catalog | `./tools/test-sdk.sh python --discovery` | \n| Installed new client, host discovery and session binding | `./tools/test-sdk.sh python-connected` (optional`--editor-host /absolute/path/to/zipzi-editor` ) | \n| Repository tools | `uv run --locked python tools/test_tools.py -p test_<tool>.py` | \n\nFilters and filenames are placeholders; omit them to run the selected gate.\nFor a crate's integration targets, inspect its README and `tests/`, or list cases\nwith `cargo test --locked -p <crate> --test <target> -- --list`.\nEditor shell gates clear `ZIPZI_DEV_SESSION_DIR`; clear it explicitly when\nrunning Editor Cargo tests directly.\n\n[Full coverage, prerequisites and CI](https://github.com/getzipzi/zipzi-2d/blob/main/tools/README.md#test-coverage) define\nregression, stress, native acceptance and packaged-wheel gates. Both domain\nscripts default to expensive **full** runs when no mode is supplied.\nPlain `cargo test` selects only `zipzi-core`, `zipzi-project` and `zipzi-sdk`.\nTooling tests belong in `tools/tests/`, crate tests stay with their crate, and\nshared data belongs in [`fixtures/`](https://github.com/getzipzi/zipzi-2d/blob/main/fixtures/README.md).\n\nAll owned crates share the root Cargo workspace and lockfile. Local models belong\nin `models/local/`; see the [model inventory](https://github.com/getzipzi/zipzi-2d/blob/main/models/README.md). Source archives,\nPython wheels and macOS app bundles have separate\n[distribution checks](https://github.com/getzipzi/zipzi-2d/blob/main/tools/README.md#local-distribution-artifacts).\n\nSDK components use [MIT](https://github.com/getzipzi/zipzi-2d/blob/main/LICENSE-MIT); Editor components use\n[GPL-3.0-only](https://github.com/getzipzi/zipzi-2d/blob/main/LICENSE-GPL-3.0). [LICENSING](https://github.com/getzipzi/zipzi-2d/blob/main/LICENSING.md) identifies scopes and shared-file origins;\n[third-party notices](https://github.com/getzipzi/zipzi-2d/blob/main/THIRD_PARTY_NOTICES.md) retain dependency and benchmark exceptions.\n\nLive2D, Cubism, the Live2D Cubism SDK, Cubism Core, Cubism Native Framework, and associated sample data are owned by or licensed through Live2D Inc. and/or their respective rightsholders. This project is independent and is not affiliated with, authorized by, endorsed by, or sponsored by Live2D Inc. The names “Live2D” and “Cubism” describe interoperability only.\n\nThis repository does not distribute the proprietary Cubism Core binary, a\nCubism SDK package, or Live2D sample model assets. Users who obtain, build,\nlink, publish, or distribute software using Live2D materials are responsible\nfor complying with all applicable terms, including the\n[Live2D Proprietary Software License Agreement](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_en.html),\n[Live2D Open Software License Agreement](https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html),\nand any applicable [sample data terms](https://www.live2d.com/eula/live2d-sample-model-terms_en.html).\nThe MIT License for this repository grants no rights to third-party software,\nmodels, artwork, trademarks, or other materials.", "url": "https://wpnews.pro/news/show-hn-zipzi-open-source-live2d-editor-alternative-with-ai-assisted-editing", "canonical_source": "https://github.com/getzipzi/zipzi-2d", "published_at": "2026-11-13 02:54:37+00:00", "updated_at": "2026-11-13 03:21:38.084320+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "artificial-intelligence"], "entities": ["Zipzi", "Zipzi 2D", "Live2D Cubism Editor", "Rust", "GPUI", "Python"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-zipzi-open-source-live2d-editor-alternative-with-ai-assisted-editing", "markdown": "https://wpnews.pro/news/show-hn-zipzi-open-source-live2d-editor-alternative-with-ai-assisted-editing.md", "text": "https://wpnews.pro/news/show-hn-zipzi-open-source-live2d-editor-alternative-with-ai-assisted-editing.txt", "jsonld": "https://wpnews.pro/news/show-hn-zipzi-open-source-live2d-editor-alternative-with-ai-assisted-editing.jsonld"}}