{"_id":"@biolytics.ai/diascope","_rev":"3-3e5437ed116dd5cfaac2cd89b7826188","name":"@biolytics.ai/diascope","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@biolytics.ai/diascope","version":"0.1.0","_id":"@biolytics.ai/diascope@0.1.0","maintainers":[{"name":"hugolytics","email":"hugo.evers@biolytics.ai"}],"homepage":"https://diascope.biolytics.ai","bugs":{"url":"https://github.com/Biolytics-AI/DiaScope/issues"},"bin":{"diascope":"dist/cli/index.js"},"dist":{"shasum":"e1ae5a08e247fff2cd820975f4ef9bf444bf0f58","tarball":"https://registry.npmjs.org/@biolytics.ai/diascope/-/diascope-0.1.0.tgz","fileCount":61,"integrity":"sha512-ZtknWKt6F+cSMJYiIDJd+Lmdm+adW7LcKPWpoZL9stc/01kDPoU0vMUE3FssDGEoL94zTu6iQqeOiRelI/0FSw==","signatures":[{"sig":"MEYCIQCwkvAx9JSCODKl93YB22XDALjgkl5B1mVipoRJur01TAIhANprka7PmCeWIlltTcngTaetjTggEmpJVnWhxDsyU/OG","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@biolytics.ai%2fdiascope@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":182766},"main":"./dist/viewer/index.js","type":"module","types":"./dist/viewer/index.d.ts","exports":{".":{"types":"./dist/viewer/index.d.ts","import":"./dist/viewer/index.js"},"./story":{"types":"./dist/story/index.d.ts","import":"./dist/story/index.js"}},"gitHead":"a8a9112307604ae617702a0b4317c624f7ac0617","scripts":{"test":"vitest run","build":"tsc && node esbuild.mjs","docs:dev":"npm --prefix docs-site run dev","build:tsc":"tsc","docs:build":"npm run build && npm run docs:prepare-assets && npm --prefix docs-site run build","test:watch":"vitest","docs:prepare-assets":"mkdir -p docs-site/public/examples/vllm && cp examples/vLLM/deployment.d2 docs-site/public/examples/vllm/deployment.d2 && cp examples/vLLM/deployment.story.yaml docs-site/public/examples/vllm/deployment.story.yaml && cp examples/vLLM/README.md docs-site/public/examples/vllm/README.md && node dist/cli/index.js build examples/vLLM/deployment.d2 examples/vLLM/deployment.story.yaml -o docs-site/public/examples/vllm/deployment.html && cp docs-site/public/examples/vllm/deployment.html examples/vLLM/deployment.html"},"_npmUser":{"name":"hugolytics","email":"hugo.evers@biolytics.ai"},"repository":{"url":"git+https://github.com/Biolytics-AI/DiaScope.git","type":"git"},"_npmVersion":"11.11.0","description":"Turn D2 diagrams into narrated interactive stories","directories":{},"_nodeVersion":"25.8.1","dependencies":{"js-yaml":"^4.1.0","commander":"^12.0.0","svg-pan-zoom":"^3.6.1"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.5.0","esbuild":"^0.21.0","typescript":"^5.4.0","@types/node":"^20.0.0","@types/js-yaml":"^4.0.9"},"_npmOperationalInternal":{"tmp":"tmp/diascope_0.1.0_1773311692052_0.5892582754305142","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@biolytics.ai/diascope","version":"0.1.1","_id":"@biolytics.ai/diascope@0.1.1","maintainers":[{"name":"hugolytics","email":"hugo.evers@biolytics.ai"}],"homepage":"https://diascope.biolytics.ai","bugs":{"url":"https://github.com/Biolytics-AI/DiaScope/issues"},"bin":{"diascope":"dist/cli/index.js"},"dist":{"shasum":"6586683f4bc91e3eb06448f2ab4edadeb9220c26","tarball":"https://registry.npmjs.org/@biolytics.ai/diascope/-/diascope-0.1.1.tgz","fileCount":61,"integrity":"sha512-mO1Z1cS1AMHm+pvpo7Z92k0j+MAwXabUNKPCLalOzt2If6C/WWST4y8+Hu6nvaxo8FEaaj3vuouY6xHbblV3zw==","signatures":[{"sig":"MEYCIQDuyZC/nAq08q+bEJ58CQ5CB/6pX6+104wEa6gNQ0V75AIhAOcGGQWDQVP/k2/z+A4HcTaLS3Up2S7FKeJARu8OwVEe","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@biolytics.ai%2fdiascope@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":183423},"main":"./dist/viewer/index.js","type":"module","types":"./dist/viewer/index.d.ts","exports":{".":{"types":"./dist/viewer/index.d.ts","import":"./dist/viewer/index.js"},"./story":{"types":"./dist/story/index.d.ts","import":"./dist/story/index.js"}},"gitHead":"4d80860a157e84fe484cb4e448dd87bd607518e5","scripts":{"test":"vitest run","build":"tsc && node esbuild.mjs","docs:dev":"npm --prefix docs-site run dev","build:tsc":"tsc","docs:build":"npm run build && npm run docs:prepare-assets && npm --prefix docs-site run build","test:watch":"vitest","docs:prepare-assets":"mkdir -p docs-site/public/examples/vllm && cp examples/vLLM/deployment.d2 docs-site/public/examples/vllm/deployment.d2 && cp examples/vLLM/deployment.story.yaml docs-site/public/examples/vllm/deployment.story.yaml && cp examples/vLLM/README.md docs-site/public/examples/vllm/README.md && node dist/cli/index.js build examples/vLLM/deployment.d2 examples/vLLM/deployment.story.yaml -o docs-site/public/examples/vllm/deployment.html && cp docs-site/public/examples/vllm/deployment.html examples/vLLM/deployment.html"},"_npmUser":{"name":"hugolytics","email":"hugo.evers@biolytics.ai"},"repository":{"url":"git+https://github.com/Biolytics-AI/DiaScope.git","type":"git"},"_npmVersion":"11.11.0","description":"Turn D2 diagrams into narrated interactive stories","directories":{},"_nodeVersion":"25.8.1","dependencies":{"js-yaml":"^4.1.0","commander":"^12.0.0","svg-pan-zoom":"^3.6.1"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.5.0","esbuild":"^0.21.0","typescript":"^5.4.0","@types/node":"^20.0.0","@types/js-yaml":"^4.0.9"},"_npmOperationalInternal":{"tmp":"tmp/diascope_0.1.1_1773313302476_0.35979419551336655","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@biolytics.ai/diascope","version":"0.1.2","description":"Turn D2 diagrams into narrated interactive stories","homepage":"https://diascope.biolytics.ai","repository":{"type":"git","url":"git+https://github.com/Biolytics-AI/DiaScope.git"},"bugs":{"url":"https://github.com/Biolytics-AI/DiaScope/issues"},"type":"module","main":"./dist/viewer/index.js","types":"./dist/viewer/index.d.ts","exports":{".":{"import":"./dist/viewer/index.js","types":"./dist/viewer/index.d.ts"},"./story":{"import":"./dist/story/index.js","types":"./dist/story/index.d.ts"}},"bin":{"diascope":"dist/cli/index.js"},"scripts":{"build":"tsc && node esbuild.mjs","build:tsc":"tsc","docs:prepare-assets":"mkdir -p docs-site/public/examples/vllm && cp examples/vLLM/deployment.d2 docs-site/public/examples/vllm/deployment.d2 && cp examples/vLLM/deployment.story.yaml docs-site/public/examples/vllm/deployment.story.yaml && cp examples/vLLM/README.md docs-site/public/examples/vllm/README.md && node dist/cli/index.js build examples/vLLM/deployment.d2 examples/vLLM/deployment.story.yaml -o docs-site/public/examples/vllm/deployment.html && cp docs-site/public/examples/vllm/deployment.html examples/vLLM/deployment.html","docs:dev":"npm --prefix docs-site run dev","docs:build":"npm run build && npm run docs:prepare-assets && npm --prefix docs-site run build","test":"vitest run","test:watch":"vitest"},"dependencies":{"commander":"^12.0.0","js-yaml":"^4.1.0","svg-pan-zoom":"^3.6.1"},"devDependencies":{"@types/js-yaml":"^4.0.9","@types/node":"^20.0.0","esbuild":"^0.21.0","typescript":"^5.4.0","vitest":"^1.5.0"},"gitHead":"1fdb0f3c4f68cd285b562b14a97a9bc5e360fe0c","_id":"@biolytics.ai/diascope@0.1.2","_nodeVersion":"25.8.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-1SH9htcYcpfZV3ync+nE5udMRiHtoziDVo53NoEj1flAl7nYDYaLp7vT0L9IllmIDSXeEiS0rejl3+63LD1fLg==","shasum":"1243d6fd44ac5bd31f6dd4fda5a0735a2d1833be","tarball":"https://registry.npmjs.org/@biolytics.ai/diascope/-/diascope-0.1.2.tgz","fileCount":61,"unpackedSize":197519,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@biolytics.ai%2fdiascope@0.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCuGQ4ADZDmEvE7bHKonarRnrB1vv5l2DZH/D69b5M0vAIhAMLluBF8ANfClTh9Ns5SiqSISpO83MRLkcQHh/6rct9r"}]},"_npmUser":{"name":"hugolytics","email":"hugo.evers@biolytics.ai"},"directories":{},"maintainers":[{"name":"hugolytics","email":"hugo.evers@biolytics.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/diascope_0.1.2_1773317428800_0.4720380164588647"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-12T10:34:51.985Z","modified":"2026-03-12T12:10:29.361Z","0.1.0":"2026-03-12T10:34:52.215Z","0.1.1":"2026-03-12T11:01:42.622Z","0.1.2":"2026-03-12T12:10:29.049Z"},"bugs":{"url":"https://github.com/Biolytics-AI/DiaScope/issues"},"homepage":"https://diascope.biolytics.ai","repository":{"type":"git","url":"git+https://github.com/Biolytics-AI/DiaScope.git"},"description":"Turn D2 diagrams into narrated interactive stories","maintainers":[{"name":"hugolytics","email":"hugo.evers@biolytics.ai"}],"readme":"# DiaScope\n\n[![Package CI](https://github.com/Biolytics-AI/DiaScope/actions/workflows/ci.yml/badge.svg)](https://github.com/Biolytics-AI/DiaScope/actions/workflows/ci.yml)\n[![Docs](https://github.com/Biolytics-AI/DiaScope/actions/workflows/docs.yml/badge.svg)](https://github.com/Biolytics-AI/DiaScope/actions/workflows/docs.yml)\n[![npm version](https://img.shields.io/npm/v/%40biolytics.ai%2Fdiascope)](https://www.npmjs.com/package/@biolytics.ai/diascope)\n[![Docs Site](https://img.shields.io/badge/docs-diascope.biolytics.ai-06E1EC)](https://diascope.biolytics.ai)\n[![Node](https://img.shields.io/badge/node-%3E%3D22-002451)](https://nodejs.org/)\n\nTurn any codebase, system, or flow into a narrated interactive diagram story — a self-contained `.html` file your audience can step through with arrow keys.\n\nYou author a [D2](https://d2lang.com) diagram and a YAML narration sidecar. DiaScope renders the diagram, wires up the step-by-step navigation, and writes one file you can open in a browser or share anywhere.\n\nDocs: `https://diascope.biolytics.ai`\n\n**Or:** install the `narrate` skill and let an agent do it for you.\n\n---\n\n## How it looks\n\nEach story is a full-screen page: diagram on the left, narration panel on the right. Each step highlights the relevant nodes, pans/zooms to them, and shows the title + body text. Click a node for detail. Press `→` to advance.\n\n## Interactive features\n\n- Step-by-step narration with active node highlighting\n- Automatic pan and zoom to the current step\n- `Focus` mode to isolate active nodes and edges\n- `Fit` plus manual zoom controls\n- Keyboard navigation with arrow keys\n- Clickable node detail panels\n- Edge hover tooltips\n\nSee the live example and feature docs at `https://diascope.biolytics.ai`.\n\n---\n\n## Requirements\n\n* Node.js 18+\n* [`d2`](https://d2lang.com/tour/install) on your PATH\n\n---\n\n## Install\n\n```bash\nnpm install -g @biolytics.ai/diascope\n```\n\n---\n\n## Human-driven workflow\n\n**1. Write your D2 diagram** — and optionally annotate it with `# @step` markers:\n\n```d2\n# @step step-01\nClient -> Server: POST /api/data\n\n# @step step-02\nServer -> Database: SELECT ...\n\n# @step step-03\nDatabase -> Server: result row\nServer -> Client: 200 OK\n```\n\n`# @step` comments are invisible to the D2 renderer. They tell `diascope init` which nodes belong to which narrative beat.\n\n**2. Scaffold the narration:**\n\n```bash\ndiascope init auth-flow.d2\n# → writes auth-flow.story.yaml\n```\n\n**3. Fill in the narration** — edit `auth-flow.story.yaml`:\n\n```yaml\nmeta:\n  title: \"Auth Flow\"\n  d2_source: auth-flow.d2\n\nsteps:\n  - id: step-01\n    tag: \"01\"\n    title: \"Client sends authenticated request\"\n    body: |\n      The client attaches a short-lived JWT in the Authorization header.\n      Tokens expire after 15 minutes — refresh before expiry or the\n      request is rejected at the next step.\n    nodes:\n      - Client\n      - Server\n\n  - id: step-02\n    tag: \"02\"\n    title: \"Server queries the database\"\n    nodes:\n      - Server\n      - Database\n```\n\n**4. Build:**\n\n```bash\ndiascope build auth-flow.d2 auth-flow.story.yaml -o auth-flow.html\nopen auth-flow.html\n```\n\n---\n\n## Agent-driven workflow\n\nInstall the `narrate` skill into your coding agent. Then just point it at code:\n\n> \"Narrate the payment flow in `src/payments/`\"\n> \"Create a diagram story explaining how the sync engine works\"\n> \"Help me explain the request lifecycle to a new developer\"\n\nThe agent reads your code, writes the D2 diagram and `.story.yaml`, runs `diascope build`, and hands you the `.html`.\n\n### Install for Claude Code\n\n```bash\ngit clone https://github.com/Biolytics-AI/DiaScope.git ~/.claude/diascope\nmkdir -p ~/.agents/skills\nln -s ~/.claude/diascope/skills ~/.agents/skills/diascope\n```\n\nRestart Claude Code. Full instructions: [.claude/INSTALL.md](.claude/INSTALL.md)\n\n### Install for Codex\n\nTell Codex:\n\n```text\nFetch and follow instructions from https://raw.githubusercontent.com/Biolytics-AI/DiaScope/main/.codex/INSTALL.md\n```\n\nFull instructions: [.codex/INSTALL.md](.codex/INSTALL.md)\n\n---\n\n## Story format reference\n\nThe `.story.yaml` file is the source of truth for all narration. The `.d2` file is **never modified** by DiaScope tooling.\n\nFull reference: [docs/story-format.md](docs/story-format.md)\n\n### Linking steps to nodes\n\n`nodes:` values must match D2 node names **exactly** (case-sensitive):\n\n| D2 source       | `nodes:` value  |\n|-----------------|-----------------|\n| `Client`        | `Client`        |\n| `System.Client` | `System.Client` |\n| `\"My Service\"`  | `My Service`    |\n\n`diascope build` warns you if any referenced node ID isn't found in the rendered SVG.\n\n### Detail panels and edge tooltips\n\n```yaml\ndetail_panels:\n  Server: |\n    <p>Handles auth and routing. Rate limited: 1000 req/s.</p>\n\nedge_tooltips:\n  \"POST /api/data\": \"Authenticated with Bearer token\"\n```\n\n---\n\n## CLI reference\n\n```text\ndiascope build <diagram.d2> <story.yaml> [options]\n\n  -o, --out <file>          Output HTML (default: <story>.html)\n  --viewer-bundle <path>    Custom path/URL for viewer JS bundle\n\ndiascope init <diagram.d2> [options]\n\n  -o, --out <file>          Output story file (default: <diagram>.story.yaml)\n```\n\n---\n\n## Examples\n\nWorking examples live in [`examples/`](examples/). The current vLLM example includes:\n\n- `examples/vLLM/deployment.d2`\n- `examples/vLLM/deployment.story.yaml`\n- `examples/vLLM/README.md`\n\nYou can also browse the same example in the docs at `https://diascope.biolytics.ai/examples/vllm-deployment/`.\n\n---\n\n## JS library\n\nEmbed in a framework or custom shell:\n\n```js\nimport { DiaScopeViewer } from \"@biolytics.ai/diascope\";\nimport { parseStoryFile, storyToViewerOptions } from \"@biolytics.ai/diascope/story\";\n\nconst story = parseStoryFile(yamlString);\nconst viewer = new DiaScopeViewer({\n  ...storyToViewerOptions(story),\n  autoBindControls: true,\n});\nviewer.init();\n```\n\nThe viewer expects `svg-pan-zoom` on `window.svgPanZoom` (or via `options.svgPanZoom`). See [templates/story.html](templates/story.html) for a complete working shell.\n\n---\n\n## Release process\n\nDiaScope releases are published from GitHub, not from local machines.\n\n1. Open a PR into `main`.\n2. Merge only after `build-and-test` and `build-docs` pass.\n3. Create and push a version tag like `v0.1.0`.\n4. GitHub Actions publishes `@biolytics.ai/diascope` to npm and creates the matching GitHub Release.\n\nLocal `npm publish` should only be used for dry-runs and debugging.\n\n---\n\n## LLM patching guide\n\nWhen asking an LLM to update a `.story.yaml`:\n\n* Add steps by appending to `steps[]` with a new unique `id`\n* Node IDs come from the `.d2` file — never invent them\n* `body` supports inline HTML; use `|` block scalar for multi-line\n* Preserve existing `id` values — they match `# @step` annotations in the `.d2`\n* Run `diascope build` after edits to validate and regenerate\n","readmeFilename":"README.md"}