{
    "archive_path": "archive/1790460241.086398",
    "base_url": "github.com/reladraw/reladraw",
    "basename": "reladraw",
    "bookmarked_date": "2026-09-26 22:04",
    "canonical": {
        "archive_org_path": "https://web.archive.org/web/github.com/reladraw/reladraw",
        "dom_path": "output.html",
        "favicon_path": "favicon.ico",
        "git_path": "git/",
        "google_favicon_path": "https://www.google.com/s2/favicons?domain=github.com",
        "headers_path": "headers.json",
        "htmltotext_path": "htmltotext.txt",
        "index_path": "index.html",
        "media_path": "media/",
        "mercury_path": "mercury/content.html",
        "pdf_path": "output.pdf",
        "readability_path": "readability/content.html",
        "screenshot_path": "screenshot.png",
        "singlefile_path": "singlefile.html",
        "warc_path": "warc/",
        "wget_path": "github.com/reladraw/reladraw.html"
    },
    "domain": "github.com",
    "extension": "",
    "hash": "DMZHR074DRPV550TR2PH",
    "history": {
        "archive_org": [],
        "dom": [],
        "favicon": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "120",
                    "--output",
                    "favicon.ico",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://www.google.com/s2/favicons?domain=github.com"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-09-26T22:05:13.874012+00:00",
                "index_texts": null,
                "output": "favicon.ico",
                "pwd": "/data/archive/1790460241.086398",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-26T22:05:13.350700+00:00",
                "status": "succeeded"
            }
        ],
        "git": [],
        "headers": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--head",
                    "--max-time",
                    "120",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://github.com/reladraw/reladraw"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-09-26T22:05:14.213067+00:00",
                "index_texts": null,
                "output": "headers.json",
                "pwd": "/data/archive/1790460241.086398",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-26T22:05:13.881730+00:00",
                "status": "succeeded"
            }
        ],
        "htmltotext": [],
        "media": [],
        "mercury": [
            {
                "cmd": [
                    "/app/node_modules/@postlight/parser/cli.js",
                    "https://github.com/reladraw/reladraw"
                ],
                "cmd_version": "1.0.0",
                "end_ts": "2026-09-26T22:05:26.635338+00:00",
                "index_texts": null,
                "output": "mercury",
                "pwd": "/data/archive/1790460241.086398",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-26T22:05:22.107596+00:00",
                "status": "succeeded"
            }
        ],
        "pdf": [],
        "readability": [
            {
                "cmd": [
                    "/app/node_modules/readability-extractor/readability-extractor",
                    "/tmp/tmpj0e6123h",
                    "https://github.com/reladraw/reladraw"
                ],
                "cmd_version": "0.0.11",
                "end_ts": "2026-09-26T22:05:22.098566+00:00",
                "index_texts": [
                    "reladraw\nA text language for diagrams where you say where things go.\nTry it in your browser \u2192 \u2014 edit the source on the left, watch the layout re-solve on the right. Nothing to install.\nA diagram drawn by hand in draw.io:\n\nAnd the same diagram written down in reladraw and rendered from the text \u2014 examples/arch.reladraw, 44 statements, no coordinates anywhere in it:\n\nEvery distance in the second picture was worked out from statements like above-left of cluster.hub and between cluster.desktop1 and cluster.laptop1. Nothing chose the arrangement; the file states it.\nThe gap\nMermaid, Graphviz and D2 have you declare entities and connections, and then place everything for you. That is a superpower, and for most diagrams it is the right one. It stops being the right one as soon as you have a particular picture in mind and care where things go. Say you are actively building your understanding of a system by diagramming it, and you want some module over to the right with its connections placed just so: the auto-layout languages have no way to say it.\nOn the other end of the spectrum are the absolute-positioning tools \u2014 draw.io, Excalidraw, Figma. They give you total control of placement, at the cost of making every edit to a complex diagram slow hand-work. And it is slow for a human but expensive for an agent, which has to work the picture out from the coordinates before it can decide which ones to change.\n\nreladraw aims at the middle. Every position is stated relative to something else, and nothing in the file is a coordinate:\nnode app \"Web app\"\nnode app.ui  \"Interface\"\nnode app.api \"API\"  below app.ui\n\nnode store \"Database\"  right of app  level with app\n\nedge app.api -> store  \"queries\"  from: right  to: left\n\nNothing is nested, so no line depends on another line's position or indentation.\nThe draft is in SYNTAX.md, with a worked example in examples/.\nWhy an agent needs this\nThe common case is not drawing a diagram, it is changing one. Ask for the auth service to move left and a queue to go behind it. With pixel coordinates, an agent has to rebuild the picture from the numbers before it can work out which numbers to change. With auto-layout there is nothing to read at all, because the arrangement was never written down \u2014 it can only reword the source and re-render. With stated placement the arrangement is in the file as sentences, and changing the picture is changing the sentence that says where the thing goes.\nWriting has the same shape. An agent emitting Mermaid is guessing at a layout that an algorithm settles later, and its only way to find out is to render and look \u2014 a round trip that comes back as a picture rather than as a list of what is wrong.\nIntent is confirmable, outcomes are not, and the difference is worth being precise about. An agent can re-read its own file and see that the database is under the API and all four machines hang off the sync hub. It cannot see that two clusters anchored to different things now overlap, that a text overflowed its node, or that an edge crosses four others \u2014 those are resolved from the statements rather than stated, so they need the diagnostics in the scope section below.\nUsing it with an agent\nreladraw is too new to be in any model's training data, so an agent has to be told the language before it can write it. This repository ships an agent skill that does exactly that \u2014 the syntax, when to reach for the language, and what re-reading its own source can and cannot confirm.\nnpx skills add reladraw/reladraw -g\n\nThat installs it for whichever agent you use \u2014 Claude Code, Codex, Cursor, Copilot and others \u2014 each into its own skills directory. Drop the -g to install it into the current project instead.\nTo install it for one agent rather than all of them, name it with -a:\nnpx skills add reladraw/reladraw -g -a claude-code\n\nRe-run whichever command you used after a release that changes the syntax. The skill is a copy taken at install time, not a live link, so nothing refreshes it on its own.\nIt is plain Markdown with the syntax reference beside it, so it is worth reading whatever you use, and copying the directory by hand works just as well.\nStatus\nVersion 0.5.0. Early, but it runs: a parser, resolver and SVG renderer in TypeScript with no runtime dependencies, and a command-line tool that takes a text file and writes a standalone SVG. The comparison at the top of this page is that pipeline run on examples/arch.reladraw. What is still visibly off there is typography, not placement.\nnpm install -g reladraw\nreladraw diagram.reladraw -o diagram.svg\n\nOr from a clone, which also gets you the examples:\nnpm install && npm run build\nnode dist/cli.js examples/arch.reladraw -o out.svg\n\nNot built yet, roughly in the order they are missed:\n\nThe diagnostics report. The scope section below says what it is for. Today the tool either renders or fails; it will not tell you what is wrong with a picture it drew successfully.\nEdge routing around nodes. An edge can be told which side of a node to leave and arrive on, and which gap to run down on the way. An edge that says none of that is a straight line between two centers, and it will cut through whatever stands in the way.\nMore pictures. Icons and shapes are closed sets drawn from path data inside the tool, so a diagram wanting one that is not there has nowhere to go.\n\nThe language is not stable. Expect the syntax to change.\nHow it works\nA gap is a minimum distance, never an exact one. Say two things sit side by side, then say a third goes between them, and the first two are pushed apart by exactly what the third needs; delete the third and they close back up. That is the step an author otherwise does by hand \u2014 shove things apart to make room, then drag everything back so the diagram is not full of holes \u2014 and no number goes stale when a text grows.\nSo the resolver solves a system rather than walking a chain. Each axis is a set of minimum distances, and the tightest arrangement satisfying all of them is found by longest paths: one answer, no search, no arrangement ever tried and rejected. The engine works out distances; which side of what a thing sits on came from the file.\nThat is also what makes non-overlap affordable, so it holds for every pair of nodes without anyone writing it down. On its own \"these two must not overlap\" is a choice among four directions, which is the search this design refuses \u2014 but the file has usually settled it already: if your arrangement lets one node travel away from another and offers no way back, that is the only separation it permits. Where the file orders a pair on neither axis, the tool names them rather than guessing; where it orders them on both, the tie breaks toward the axis of least overlap, which is the smallest movement and the one place the tool decides something nobody wrote.\nNothing is nudged. Each round derives the separations the file already implied, adds them as ordinary minimum distances, and solves the whole thing again from scratch \u2014 repairing a solved layout in place is the thing being avoided.\nScope for a first version\n\nParser (done)\nDeterministic resolver: minimum distances in, tightest arrangement out (done)\nStatic SVG renderer (done)\nA command-line tool: text file in, SVG out (done)\nA placement grammar that can say what a real diagram needs: several placements on one node, one thing between two others, exact side-to-side alignment (done)\nNodes that do not overlap by default, with the separation direction derived from the stated arrangement (done)\nMinimal node-avoiding edge routing\nMachine-readable diagnostics from the solved geometry\n\nDiagnostics are a real output rather than a debugging aid. What they cannot do is stand in for the grammar: a check catches only what the language genuinely leaves open, and \"these must not overlap\" rules arrangements out without naming one, so it can never place anything. Everything the source cannot tell you is computable once the geometry is solved, with no image involved: overlapping nodes, crossed edges, text exceeding its container, anything off-canvas, large dead regions. So the tool reports hub overlaps laptop1 and edge auth->db crosses 4 edges, and the fix is written in the same vocabulary as the source. An agent working this way reads a report about a text file it wrote and edits that text file \u2014 no rendering, no vision model, no pixel arithmetic.\nA diagnostic never repairs a solved layout in place. That is the line the design holds: a checker allowed to nudge nodes is a layout algorithm with a bad search strategy, fixing one overlap into the next with no view of the whole. Deriving a constraint the file already implied and solving the whole system again is a different thing, and is how non-overlap works. What is left over \u2014 anything the source genuinely does not settle \u2014 is reported, naming the statement that was broken, and the author edits the source. Open, and it decides how far this goes: may a diagnostic describe a fix in words, or only name the symptom? Describing one means the tool has an opinion about layout, which is the auto-layout instinct coming back in through the side door.\nThree design problems decide how much machinery this needs, and the first outranks the other two:\nSaying enough. The benchmark contains arrangements the grammar cannot express at all, which is why some nodes land in the wrong place no matter how the file is written. So the work is adding statements, not restricting them. Expressiveness is not the danger; the engine choosing an arrangement is.\nWhat the engine is allowed to decide. Auto-layout is refused, because a picture chosen by an algorithm is not predictable from its source, and that predictability is the entire point. Working out coordinates from an arrangement the author stated is a different thing and is simply the job. The test between them: the engine's freedom may affect distances and never relationships. If a default can change which side of something a node sits on, the language was short a statement and the tool should say so rather than guess.\nOverlap and edge routing. Relative placement with default spacing collides as soon as two clusters grow toward each other. Stating placement and then routing edges afterward with no influence on them reproduces the exact failure this is meant to avoid, so minimal node-avoiding orthogonal routing belongs in the first version. Routing and diagnostics are complements, not substitutes: routing fixes what it can, and the diagnostics report what it could not.\nPrior art\nFour things sit near this, and each answers a different part of the problem.\nArchify. Built for agents to write: an agent emits typed JSON, a validator checks it against a schema and lints the layout, and it compiles deterministically to a good-looking, self-contained HTML file, with stepped playback and nodes pinned to git-verified source lines. Its positioning is grid or free coordinates, though \u2014 auto-arrangement on one side, absolute pixels on the other \u2014 and a JSON template says nothing about where the picture will end up, so the loop is still emit, render, look, tweak.\nPIC and pikchr. A text diagram format with no layout engine, where placement is stated and deterministic. But it is turtle graphics \u2014 a movable cursor that drops shapes and steps along \u2014 so a diagram is a sequence of pen movements rather than a set of stated relationships between named things. There is no group that reflows when a member is added.\nGraphviz rank and cluster. Constraints on an auto-layout engine rather than a replacement for one, so output stays emergent and unpredictable from the source.\nStructurizr. Has real manual layout, but is bound to the C4 model, which makes it a modeling notation with a renderer attached rather than a general placement language.\nLicense\nApache-2.0. This is a reusable primitive where adoption is the value, so restricting commercial use would defeat the purpose. See LICENSE.\nThe license covers the code, not the name: it grants no rights to use \"reladraw\", the project logo, or the project's other marks. Forks are welcome and should carry a different name. See NOTICE.\nContributing\nIssues are wanted \u2014 especially a diagram you tried to write and could not. Pull requests are read but not merged yet, for a reason explained in CONTRIBUTING.md."
                ],
                "output": "readability",
                "pwd": "/data/archive/1790460241.086398",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-26T22:05:19.939453+00:00",
                "status": "succeeded"
            }
        ],
        "screenshot": [],
        "singlefile": [],
        "title": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "120",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://github.com/reladraw/reladraw"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-09-26T22:05:19.933047+00:00",
                "index_texts": null,
                "output": "GitHub - reladraw/reladraw \u00b7 GitHub",
                "pwd": "/data/archive/1790460241.086398",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-26T22:05:19.864457+00:00",
                "status": "succeeded"
            }
        ],
        "wget": [
            {
                "cmd": [
                    "wget",
                    "--no-verbose",
                    "--adjust-extension",
                    "--convert-links",
                    "--force-directories",
                    "--span-hosts",
                    "--no-parent",
                    "-e",
                    "robots=off",
                    "--reject=js,mjs,woff,woff2,ttf,otf,eot,mp4,m4v,mov,webm,ogv,mkv,avi,flv",
                    "--timeout=120",
                    "--restrict-file-names=windows",
                    "--page-requisites",
                    "--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) wget/GNU Wget 1.21.3",
                    "--compression=auto",
                    "--timestamping",
                    "https://github.com/reladraw/reladraw"
                ],
                "cmd_version": "GNU Wget 1.21.3",
                "end_ts": "2026-09-26T22:05:19.856335+00:00",
                "index_texts": null,
                "output": "github.com/reladraw/reladraw.html",
                "pwd": "/data/archive/1790460241.086398",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-26T22:05:14.221550+00:00",
                "status": "succeeded"
            }
        ]
    },
    "icons": null,
    "is_archived": true,
    "is_static": false,
    "latest": {
        "archive_org": null,
        "dom": null,
        "favicon": "favicon.ico",
        "git": null,
        "media": null,
        "pdf": null,
        "screenshot": null,
        "singlefile": null,
        "title": "GitHub - reladraw/reladraw \u00b7 GitHub",
        "warc": null,
        "wget": "github.com/reladraw/reladraw.html"
    },
    "link_dir": "/data/archive/1790460241.086398",
    "newest_archive_date": "2026-09-26T22:05:22.107596+00:00",
    "num_failures": 0,
    "num_outputs": 6,
    "oldest_archive_date": "2026-09-26T22:05:13.350700+00:00",
    "path": "/reladraw/reladraw",
    "schema": "Link",
    "scheme": "https",
    "snapshot_id": "04e21404-bcb1-4bf8-bbcd-22cc05201cd2",
    "sources": [
        "/data/sources/1790460241-import.txt"
    ],
    "tags": null,
    "tags_str": "",
    "timestamp": "1790460241.086398",
    "title": "GitHub - reladraw/reladraw \u00b7 GitHub",
    "updated": "2026-09-26T22:05:13.350216+00:00",
    "updated_date": "2026-09-26 22:05",
    "url": "https://github.com/reladraw/reladraw"
}