Skip to main content

design-graph

Tests Python 3.10+ License: MIT Version

design-graph parses standalone HTML prototypes—including bundled React generated by tools such as Claude Artifacts and Cursor Composer—into a typed Kuzu knowledge graph. It exposes screens, sections, components, props, styles, design tokens, interactions, text and layout through a CLI and an MCP server.

Instead of sending a 50–200k-token HTML bundle to an agent, the agent can request only the component or screen context it needs.

Requirements

  • Python 3.10 or later
  • pip or pipx
  • An MCP-compatible client only if you intend to use design-mcp

Runtime dependencies (beautifulsoup4, kuzu and mcp) are installed automatically.

Install

Install directly from GitHub:

python3 -m pip install git+https://github.com/manorfm/design-graph.git

For an isolated command-line installation:

pipx install git+https://github.com/manorfm/design-graph.git

This installs three commands:

  • design-graph — build, validate, inspect and export graphs
  • design-query — query graphs from the terminal
  • design-mcp — expose graphs to MCP clients over stdio

Verify the installation:

design-graph --version
design-graph --help
design-query --help
design-mcp --help

Upgrade

python3 -m pip install --upgrade git+https://github.com/manorfm/design-graph.git

With pipx:

pipx upgrade design-graph

This package now requires Python 3.10+ (the mcp SDK dependency doesn't support 3.9). If python3/pipx resolve to an older interpreter, the upgrade fails to resolve dependencies — install or point pipx at a 3.10+ interpreter first (e.g. pipx install --python python3.11 ...).

Uninstall

python3 -m pip uninstall design-graph

Or, if installed with pipx:

pipx uninstall design-graph

Uninstalling the package does not delete generated databases. Remove those separately from the configured graph directory if they are no longer needed.

Local clone, installed globally (no venv)

git clone https://github.com/manorfm/design-graph.git
cd design-graph
python3 -m pip install -e .

This installs design-graph, design-query and design-mcp as global commands backed directly by this clone (an editable install just points at src/, it doesn't copy files).

To update, pull and reinstall:

cd design-graph
git pull
python3 -m pip install -e . --no-deps

--no-deps skips reinstalling beautifulsoup4/kuzu and is safe unless pyproject.toml added a new dependency. Reinstalling replaces the old version metadata in place — pip uninstalls the previous editable version automatically, so nothing stale is left behind. git pull alone is not enough to fix --version output, since the version string is baked into package metadata at install time, not read from git at runtime.

Development installation

git clone https://github.com/manorfm/design-graph.git
cd design-graph
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -e '.[dev]'
pytest

Build a graph

design-graph prototype.html

By default the graph is written to:

~/.local/share/design-graph/prototype.db

Each source file gets its own database based on the HTML filename.

design-graph app-v1.html
design-graph admin.html

Build options:

Option Description
--db PATH Write to a custom database path
--name NAME Write to <name>.db under the graph directory
--diff Show changes since the previous build
--force Rebuild even when the HTML hash is unchanged
--verbose Show debug-level pipeline logs
--quiet Suppress output except errors
--json Emit machine-readable build output for CI
--version Print the installed version

Use --db when you want to choose the exact file path. Use --name when you want the CLI to keep the standard graph directory but change the database filename.

Builds are incremental. An unchanged HTML file is skipped unless --force is supplied.

Each database owns an independent state file named <database>.state.json. Builds, diffs and --force therefore affect only their target prototype. When an old shared .graph-state.json exists, it is migrated only if the directory contains a single database.

If two HTML files have the same filename stem, they resolve to the same default database. The CLI warns when that database was previously built from a different source; use --db to keep both.

Use --name when you want the generated database to be named explicitly, for example:

design-graph prototype.html --name "Admin Panel"

This produces Admin Panel.db inside the resolved graph directory.

A build takes an exclusive lock on its target database. A second build started against the same database while one is already running (e.g. a watch script overlapping a manual build) fails fast with a clear error instead of corrupting the database. If a build reports non-zero write_errors in its summary or --json output, the graph may be missing nodes or edges — rerun with --verbose for details.

Additional design-graph commands

Export AI-ready chunks

design-graph chunk prototype.html
design-graph chunk prototype.html --output context.jsonl --max-chars 8000

The default output is <prototype>.jsonl beside the input file. The default maximum chunk size is 12,000 characters.

Inspect graph status

design-graph status
design-graph status --doc "prototype"
design-graph status --db /path/to/prototype.db --verbose

With multiple databases, select one using --doc, --db, DESIGN_GRAPH_DOC, or design-graph db use.

Status separates fully extracted components from unresolved references. Components is the total, while Extracted and Unresolved explain how that total was formed.

Validate graph integrity

design-graph validate
design-graph validate --doc "prototype"
design-graph validate --db /path/to/prototype.db
design-graph validate --json

Validation checks database readability and graph integrity conditions such as orphan components and unused tokens. It exits with status 1 when errors are found.

Generate a Markdown report

design-graph report
design-graph report --doc "prototype"
design-graph report --db /path/to/prototype.db --output report.md
design-graph report --name "Admin" --no-tokens --jsx

Without --output, the report is written to stdout.

List and select databases

design-graph db list
design-graph db list --json
design-graph db current
design-graph db use "app-v1"
design-graph db info "app-v1"
design-graph db remove "old-prototype"
design-graph db remove "old-prototype" --force
design-graph db prune --dry-run
design-graph db prune

db use persists default_doc in the user configuration. Database names are filenames without the .db suffix.

db remove deletes the selected database, its <database>.state.json, and any interrupted build directory owned by it. It asks for confirmation unless --force is supplied. If the removed database was the configured default, only default_doc is cleared; other settings are preserved.

db prune removes per-database state files whose database no longer exists and interrupted build directories older than one hour. Use --dry-run to inspect the plan without deleting anything. Stop MCP or other processes holding the database before removal.

Configure the UI-context skill in a consuming project

design-graph ships a project-agnostic agent skill — a set of instructions that makes an agent working on a frontend project check design-graph for screen/component context before writing UI code, instead of reading the whole prototype HTML. Configure it for one or more AI coding tools with:

cd /path/to/your-frontend-project
design-graph init                          # interactive: pick tools from a menu
design-graph init --tool claude,cursor     # non-interactive: install for specific tools
design-graph init --tool all               # install for every supported tool
design-graph init --force                  # overwrite a copy you edited by hand

Without --tool, the interactive prompt uses a real arrow-key/checkbox menu when questionary is installed (pip install design-graph[interactive] or pipx inject design-graph questionary) and stdin/stdout are a real terminal; otherwise it falls back to a plain numbered text prompt — both work the same from a script or CI as long as --tool is passed, since neither path runs then.

Each tool gets its own native format and location, adapted from a single canonical source so the five copies can't drift out of sync with each other:

Tool File Format
Claude Code .claude/skills/design-graph-ui-context/SKILL.md name/description frontmatter, loaded when relevant to the task
Cursor .cursor/rules/design-graph-ui-context.mdc description/globs/alwaysApply frontmatter, loaded when relevant
Codex CLI AGENTS.md (project root) Plain Markdown, always loaded — appended inside a marked section, never overwrites the rest of the file
Google Antigravity .agents/rules/design-graph-ui-context.md Plain Markdown, always loaded
Kiro .kiro/steering/design-graph-ui-context.md inclusion: always frontmatter, always loaded

design-graph init never silently overwrites a copy you've customized — it refuses with a clear message unless --force is passed. Re-running it with no changes is a no-op.

Run design-graph <command> --help for the complete options of a command.

Graph directory configuration

The graph directory is resolved in this order:

  1. GRAPH_DIR environment variable
  2. graph_dir in the user configuration file
  3. $XDG_DATA_HOME/design-graph, defaulting to ~/.local/share/design-graph

The user configuration file is $XDG_CONFIG_HOME/design-graph/config.json, defaulting to ~/.config/design-graph/config.json:

{
  "graph_dir": "/path/to/graphs",
  "default_doc": "app-v1"
}

GRAPH_DIR affects all three commands and overrides the configuration file.

GRAPH_DIR=/path/to/graphs design-graph prototype.html
GRAPH_DIR=/path/to/graphs design-query screens

Query from the terminal

design-query screens
design-query --doc "app-v1" screens
design-query --db /path/to/app-v1.db screens
design-query tokens
design-query tokens color
design-query search "primary button"
design-query inspect SectionCard
design-query impact SectionCard
design-query screen RestaurantsPage
design-query interactions BtnPrimary
design-query children CardProduct
design-query metrics

--verbose, --doc and --db are accepted before or after the command.

Token filters accepted by design-query tokens are color, spacing, typography, shadow and radius. Without a filter, all categories are returned, including extracted CSS variables.

Every terminal query operates on one selected database. Selection follows this order:

  1. --db PATH
  2. --doc NAME
  3. DESIGN_GRAPH_DOC
  4. default_doc in the user configuration
  5. Automatic selection when exactly one database exists

When multiple databases exist without a selection, the command exits with guidance instead of choosing one silently.

design-query metrics is the one exception: it never touches a .db file, so it works even when no prototype has been built yet — see Call metrics.

Configure the MCP server

The server scans the configured graph directory for every *.db file when it starts. It remains available in degraded mode when no graph exists and returns setup guidance from tool calls.

Cursor

Add the server to the Cursor MCP configuration (user-level ~/.cursor/mcp.json or project-level .cursor/mcp.json):

{
  "mcpServers": {
    "design-graph": {
      "command": "design-mcp"
    }
  }
}

Claude Code

Register the stdio server with the Claude Code CLI:

claude mcp add --scope user design-graph -- design-mcp
claude mcp get design-graph

For project-shared configuration, use --scope project; Claude Code writes a .mcp.json file in the project.

Custom graph directory and default prototype

Environment variables can be passed by the MCP client:

{
  "mcpServers": {
    "design-graph": {
      "command": "design-mcp",
      "env": {
        "GRAPH_DIR": "/path/to/graphs",
        "DESIGN_GRAPH_DOC": "app-v1"
      }
    }
  }
}
  • GRAPH_DIR selects the directory scanned for databases.
  • DESIGN_GRAPH_DOC sets the default active prototype when multiple databases are loaded.

The server detects a rebuilt *.db file on its own (it compares file mtimes before each tool call) and reloads without a restart. Restarting or reconnecting the MCP client is only needed after changing GRAPH_DIR, DESIGN_GRAPH_DOC, or upgrading the package itself — those are read once, at startup.

MCP tools

Tool Purpose Parameters
list_screens List screens across all loaded prototypes
get_screen Return a structural screen overview name, doc?
get_screen_full Return everything needed to reconstruct a screen name, doc?
get_screen_layout Return layout profiles for a screen's components and, for any section styled via CSS classes, one profile per section selector name, doc?
get_section Return visual details for a section screen, section, doc?
list_components List components, optionally filtered by semantic type (capped at 100 by default) comp_type?, limit?, doc?
get_component Return JSX, styles, tokens, text, interactions and children name, doc?
get_component_spec Return a reconstruction-oriented component specification. Falls back to a CSS-class spec (styles + which screens/components use it) when name matches no component — for a shared class like .page-title or .chip that was never factored into a named React component name, doc?
get_component_full Return a component plus every descendant (up to 3 levels via CONTAINS), each with its own styles, tokens, texts, interactions and props name, doc?
get_component_props Return declared component props and defaults name, doc?
get_component_children Return direct child components, in render order name, doc?
get_component_interactions Return hover/focus effects and transitions name, doc?
get_full_jsx Return unsanitized JSX name, doc?
get_full_styles Return a component's or a screen section's complete style list, with no display cap — the get_full_jsx equivalent for styles. For name=, also includes @media-scoped styles in their own section name? (component) or screen? + section?, doc?
get_full_texts Return a component's or a screen section's complete text list, with no display cap — the get_full_styles equivalent for texts name? (component) or screen? + section?, doc?
get_component_data Return the complete, uncapped content of every module-level constant a component's own body references by name (e.g. an icon-name -> SVG-path table indexed as ICONS[name]) — reuse these exact values instead of substituting an equivalent icon/asset name, doc?
get_tokens Return color, spacing, typography, shadow, radius or CSS-variable tokens, or all categories when omitted category?, screen?, doc?
find_token_usage Find components and screens using a token value, doc?
search Search screens, components, tokens, text and shared CSS classes across prototypes query
impact Find screens and sections affected by a component or token name, doc?
get_build_diff Return screens/components added or removed since the previous build, plus a warning when any bundle entry failed to decode and was dropped from that build doc?
validate_component_implementation Compare JSX you wrote against a component's stored spec (children, default-state styles, texts) and report discrepancies name, jsx_source, doc?
set_prototype Set or inspect the active prototype for this MCP connection — resets on a connection restart (e.g. a client /mcp reconnect), even mid-task name?
get_metrics Return usage metrics for this server's own tool calls — see Call metrics doc?, tool?, outcome?, since?, until?, limit?, raw?

get_tokens.category accepts color, spacing, typography, shadow, radius and css_var. Omit category to retrieve every extracted category.

validate_component_implementation is best-effort, not a full re-extraction: it reliably catches missing/extra child components and missing inline styles/texts, but cannot verify styles that came from the prototype's own CSS classes or Tailwind color utilities (e.g. bg-blue-500) — those require the original stylesheet, unavailable for a standalone snippet. Treat a clean report as "no red flags found", not proof of a pixel-perfect match. jsx_source is capped at 20,000 characters.

A response that includes a ⚠ Extração truncada notice means an extraction cap was hit for that component — the spec shown is incomplete for the listed fields. Call get_full_jsx for the raw, uncapped JSX before treating it as the full picture. A style, text or "Dados referenciados" table that ends in a +N mais notice is a display-time cut, not missing data, and always names the call that recovers the rest — get_full_styles for styles, get_full_texts for texts, get_component_data for referenced module-level data. Pass screen to scope the list to tokens that screen's own components actually use.

A component's spec can include a "Dados referenciados" ("Referenced data") section: the literal content of any module-level constant its own body references by name — e.g. an icon-name -> SVG-path table indexed as ICONS[name], or a role-key -> badge metadata table. Reuse those exact values when reimplementing a component instead of substituting a different icon or asset — see get_component_data above.

Prototype selection

When multiple databases are loaded, the server selects a prototype in this order:

  1. doc passed to the current tool call
  2. Prototype selected by set_prototype
  3. DESIGN_GRAPH_DOC
  4. default_doc from the user configuration
  5. Automatic selection when only one prototype is loaded
set_prototype(name="app-v1")
get_component(name="SectionCard")
get_screen_full(name="HomePage", doc="admin")

The doc value is the database filename without .db.

Call metrics

Every call made through the MCP server (dispatch_tool_call) is logged as one JSON line to metrics.jsonl in the XDG data directory — always $XDG_DATA_HOME/design-graph (~/.local/share/design-graph by default), regardless of any GRAPH_DIR/graph_dir override used for .db files (see Graph directory configuration): the log's location doesn't move with the graph directory. Each line records the tool name, the active prototype, an outcome, duration and the call's own arguments. design-query's other commands talk to the graph directly and are not logged — only calls that went through the MCP server are.

Outcome is classified from the tool's own rendered response: error for a raised exception, not_found / ambiguous / no_results from the same phrasing every tool already uses for those cases, ok otherwise. This is a heuristic read on the response text, not a separate contract — a tool that changes its wording could fall through to ok.

Read the log back with the get_metrics MCP tool or design-query metrics — both take the same filters and read the same file:

design-query metrics
design-query metrics --tool search --outcome no_results
design-query metrics --doc "app-v1" --since 24h
design-query metrics --raw --limit 20
Parameter Meaning
doc Filter to calls tagged with this prototype
tool Filter to calls of one tool (e.g. search)
outcome ok, not_found, ambiguous, no_results or error
since / until ISO-8601 timestamp or relative shorthand (24h, 7d, 30m)
limit Max rows shown with raw=true — never affects the aggregate below
raw Return the raw call list instead of the aggregate summary

The default output is an aggregate summary: counts per tool and outcome, an overall not-ok rate, a per-prototype breakdown, and the search queries that most often returned nothing — the fastest way to see where search coverage is actually failing in real usage, not just in a hand-picked example:

## Métricas de uso
(342 chamadas)

| Ferramenta | Total | ok | not_found | ambiguous | no_results | error |
|---|---|---|---|---|---|---|
| search | 128 | 96 | 0 | 6 | 26 | 0 |
| get_component_spec | 74 | 68 | 6 | 0 | 0 | 0 |
| list_components | 30 | 30 | 0 | 0 | 0 | 0 |

**Taxa não-ok:** 14.6%

### Por prototype
| Prototype | Total | Taxa não-ok |
|---|---|---|
| app-v1 | 210 | 12.4% |
| admin | 132 | 18.2% |

### Buscas sem resultado (top)
| Query | Ocorrências |
|---|---|
| botao cinza | 6 |
| modal confirmação | 4 |

Set DESIGN_GRAPH_METRICS_DISABLED=1 to turn logging off entirely.

Extracted capabilities

  • Bundled React/JSX and plain HTML routing
  • Visual-function filtering that excludes non-rendering React/Babel runtime internals
  • Lexical function scanning that handles destructured parameters, strings, templates and comments
  • Semantic screen roles that keep forms, tabs, sections and modals as components unless they are true navigation surfaces
  • Screens, semantic sections and reusable components — a section is detected from a padding/margin-heavy container whether that padding comes from an inline style={{}} or only from a CSS class the container's own stylesheet resolves
  • Typed screen-to-screen and section-to-screen references without synthetic component shells
  • Consolidation of same-named source variants without dropping props, JSX, styles or child references
  • Component hierarchy in sibling render order, occurrence counts, declared props and defaults
  • Default, hover, focus and transition styles, including hover/focus resolved from Tailwind state-variant classes (hover:, focus:)
  • Component and property-level token linkage
  • Color, spacing, typography, shadow, radius and CSS-variable tokens
  • UI text and semantic text types
  • Layout profiles for flex/grid and dimensions, per component and per section selector
  • Tailwind utility and custom CSS class resolution, attributed per selector — a section styled by several classes never has their properties flattened into one bag
  • CSS classes reused across screens without ever becoming a named component (e.g. .page-title) stay discoverable via search and get_component_spec, not just classes belonging to a real component
  • Every top-level return in a component's body is captured (guard clauses / early returns included), not just the first one a naive scan would match
  • Fuzzy component matching and Portuguese/English search aliases
  • Sanitized JSX markers for lists, conditionals and alternatives
  • Extraction-cap truncation surfaced as data on the affected component, not just a build log
  • External/library component references (e.g. icon imports) kept visible instead of silently dropped
  • Whole-subtree reconstruction of a single complex component (itself plus every descendant) in one call
  • Best-effort round-trip validation of agent-written JSX against a component's stored spec
  • Incremental builds, exclusive per-database write locks, graph diffs (persisted for MCP, not just CLI), validation and JSON output for CI
  • AI-ready JSONL chunks and Markdown reports

Graph schema

Schema

Editable source: diagram.excalidraw.

See schema.py for the authoritative node and relationship definitions.

Makefile shortcuts

After installing the package or activating the development environment:

make build PROTO=prototype.html
make diff PROTO=prototype.html
make rebuild PROTO=prototype.html

make start
make stop
make restart
make status
make logs

make screens
make tokens
make search Q='button'
make inspect C='SectionCard'
make impact C='SectionCard'
make screen S='RestaurantsPage'

make list-graphs
make remove-db DOC='old-prototype'
make prune-dbs
make clean-graph DB=/path/to/prototype.db
make clean-all

Developer-oriented targets include install-hooks, version, push and release. Run make help for the complete list.

Repository structure

src/design_graph/
├── cli/          # build, query, status, validation, reports and init
├── core/         # shared models, constants and patterns
├── extraction/   # components, props, screens, sections and chunks
├── graph/        # Kuzu schema, writer, reader and diff
├── mcp/          # stdio server, tool schemas and search
├── parsing/      # source, HTML/JS, CSS classes and token extraction
├── pipeline/     # orchestration, progress and incremental state
├── resources/    # packaged agent skill (see `design-graph init`)
└── paths.py      # GRAPH_DIR, user config and XDG resolution

tests/            # unit and integration tests
docs/             # architecture specs, plans and change records
pyproject.toml    # package metadata and CLI entry points
Makefile          # local workflow shortcuts
schema.svg        # graph schema diagram

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

design_graph-0.34.0.tar.gz (2.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

design_graph-0.34.0-py3-none-any.whl (208.7 kB view details)

Uploaded Python 3

File details

Details for the file design_graph-0.34.0.tar.gz.

File metadata

  • Download URL: design_graph-0.34.0.tar.gz
  • Upload date:
  • Size: 2.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for design_graph-0.34.0.tar.gz
Algorithm Hash digest
SHA256 62e598e715af848ac2b8a8a347df38aa593f67757e840af12fc6dc0567affab2
MD5 51271d8a9b29016028cc10a5c6afa6c6
BLAKE2b-256 501d22b30cdba5b8969414bc164d1358a7a703f2a1314160a99b469d6fc60c94

See more details on using hashes here.

Provenance

The following attestation bundles were made for design_graph-0.34.0.tar.gz:

Publisher: publish.yml on manorfm/design-graph

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file design_graph-0.34.0-py3-none-any.whl.

File metadata

  • Download URL: design_graph-0.34.0-py3-none-any.whl
  • Upload date:
  • Size: 208.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for design_graph-0.34.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f2c4d0b413c73ebe6b99c6c300920d751293ffcc8a0676c86f1d7d5aeef8ff24
MD5 f801bb632fe95685bc96f8c8c4b5b680
BLAKE2b-256 9c524a28e5ab8d35d4e65d2b97e50a4a9109c0423e95ce7585aaba06bc6b4177

See more details on using hashes here.

Provenance

The following attestation bundles were made for design_graph-0.34.0-py3-none-any.whl:

Publisher: publish.yml on manorfm/design-graph

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.34.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page