Metadata-Version: 2.4
Name: codefig
Version: 0.18.0
Summary: Research-paper figures from code: compose layout primitives, get venue-width, lint-checked PDF/SVG/PNG. AI-friendly (llms.txt).
Author: Justin
License: MIT
Project-URL: Homepage, https://github.com/justinhk001/codefig
Project-URL: Documentation, https://github.com/justinhk001/codefig/tree/main/docs
Project-URL: Repository, https://github.com/justinhk001/codefig
Project-URL: Issues, https://github.com/justinhk001/codefig/issues
Project-URL: Changelog, https://github.com/justinhk001/codefig/blob/main/CHANGELOG.md
Keywords: research figures,scientific figures,diagrams,paper,LaTeX,architecture diagram,academic,publication,svg,pdf,layout,visualization,LLM,AI,llms.txt
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Visualization
Classifier: Topic :: Multimedia :: Graphics
Classifier: Topic :: Text Processing :: Markup :: LaTeX
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cairosvg>=2.7
Requires-Dist: pillow>=10
Requires-Dist: kiwisolver>=1.4
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Dynamic: license-file

<div align="center">
<h1>codefig</h1>

**Paper figures as code: no coordinates, real column widths, a linter for figures.**

Compose architecture, memory, pipeline and attention diagrams in Python.
Design at print size, inspect the result, and keep the source alongside your paper.

![PyPI](https://img.shields.io/pypi/v/codefig)
![Python](https://img.shields.io/pypi/pyversions/codefig)
![MIT](https://img.shields.io/badge/license-MIT-blue)
![CI](https://github.com/justinhk001/codefig/actions/workflows/ci.yml/badge.svg)

[Quickstart](#quickstart) · [Gallery](#gallery) · [Why](#why-codefig) · [Docs](#documentation) · [AI](#ai-first-authoring)

[English](https://github.com/justinhk001/codefig/blob/main/README.md) | [简体中文](https://github.com/justinhk001/codefig/blob/main/README.zh-CN.md)

<img src="https://raw.githubusercontent.com/justinhk001/codefig/main/docs/assets/flagship.png" width="90%" alt="Original LLM serving architecture, overlap schedule and illustrative tradeoff">

</div>

## Flagship example

An original disaggregated LLM serving design with nested GPU/CPU groups, an overlap timeline, and illustrative throughput–latency curves. [Read the source](https://github.com/justinhk001/codefig/blob/main/examples/flagship_llm_serving.py).


<a id="why-codefig"></a>

## Why codefig

Drawing a paper figure often means nudging boxes in draw.io or PowerPoint,
then discovering that LaTeX scaling made the labels 4 pt tall.
TikZ makes the source reviewable, but detailed placement can still take time.
Colours drift between panels; every reviewer comment can trigger another redraw.

codefig makes the composition explicit and checks the exported result:

- **Layout instead of coordinates:** describe rows, columns, groups and relationships.
- **Real venue widths:** choose the final column or text width before drawing.
- **Publication defaults:** shared typography, stroke roles and semantic categories.
- **Figure lint:** catch small text, collisions, missing keys and export problems.
- **Reviewable Python:** version the structure, labels and data with your manuscript.

### An honest comparison

✅ natural strength · ⚠️ possible with setup or tradeoffs · ❌ not the intended workflow.
This is a workflow comparison, not a benchmark of every extension.

| Capability | codefig | matplotlib | TikZ | draw.io | Mermaid | Graphviz |
|---|---|---|---|---|---|---|
| No manual coordinates | ✅ | ⚠️ | ⚠️ | ⚠️ | ✅ | ✅ |
| Diffable code/text source | ✅ | ✅ | ✅ | ⚠️ XML | ✅ | ✅ |
| Layout at real venue width | ✅ presets | ⚠️ figsize | ✅ TeX | ⚠️ | ⚠️ | ⚠️ |
| Built-in paper figure lint | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Publication theme | ✅ | ⚠️ styles | ✅ control | ⚠️ | ⚠️ | ⚠️ |
| CVD-safe palette workflow | ✅ | ✅ palettes | ⚠️ | ⚠️ | ⚠️ | ⚠️ |
| Rich data plotting | ⚠️ embedded charts | ✅ | ✅ PGFPlots | ❌ | ⚠️ | ❌ |
| Freehand editing | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| Huge auto-laid graphs | ❌ | ❌ | ⚠️ | ⚠️ | ⚠️ | ✅ |
| Gentle learning curve | ⚠️ Python | ⚠️ Python | ❌ | ✅ | ✅ | ⚠️ DOT |
| Ecosystem maturity | ⚠️ pre-1.0 | ✅ | ✅ | ✅ | ✅ | ✅ |
| Ultimate typography/control | ⚠️ | ⚠️ | ✅ | ⚠️ | ⚠️ | ⚠️ |

### When NOT to use codefig

- Use matplotlib for exploratory analysis, scientific axes and specialised plots.
- Use draw.io for direct mouse editing and unconstrained visual sketches.
- Use Graphviz for large automatically laid-out dependency graphs.
- Use TikZ when precise TeX typography and unrestricted control dominate.
- Use Mermaid when a short Markdown diagram is the whole requirement.

<a id="quickstart"></a>

## Quickstart

```sh
pip install codefig
```

Three boxes, two semantic categories, two edges, and an automatic legend.

```python
from codefig import Figure, Box, Row, Col, Diagram, Edge, Legend

fig = Figure(venue="icml", width="column", panel_caption="none")
enc = Box("Encoder", category="model")
kv = Box("KV cache", category="memory")
dec = Box("Decoder", category="model")
body = Col([Col([enc, kv, dec], gap=18), Legend(direction="row")], gap=10)
with fig.panel("a") as p:
    p += Diagram(body, [Edge(enc.port("bottom"), kv.port("top")),
                       Edge(kv.port("bottom"), dec.port("top"))])
alt = "Encoder writes a KV cache read by the decoder."
print(fig.lint(alt=alt))
fig.save("quickstart.png", alt=alt)
fig.save("quickstart.pdf", alt=alt)
```

```text
codefig lint (icml, 234 pt): 0 error(s), 0 warning(s), 0 info
```

![Quickstart](https://raw.githubusercontent.com/justinhk001/codefig/main/docs/assets/quickstart.png)

The example uses a vertical composition to fit a column without shrinking labels.
Change the labels and categories first; let the containers handle placement.
`Legend()` collects the categories automatically.

Include the PDF at its native width:

```tex
\includegraphics{quickstart.pdf}
```

Do not add a width here: the PDF is already designed at the exact column width.
Keeping that size preserves the intended 6–8 pt theme typography.
If the composition grows too wide, reflow it and re-lint rather than scaling it down.

<a id="gallery"></a>

## Gallery

Original demonstrations and cookbook recipes; click an image for runnable source.

<table>
<tr>
<td><a href="examples/survey_round1_demo.py"><img src="https://raw.githubusercontent.com/justinhk001/codefig/main/docs/assets/survey1.png" width="280" alt="Memory and serving"><br><b>Memory and serving</b></a><br>Tables, attention matrices and routed pools.</td>
<td><a href="examples/survey_round3_demo.py"><img src="https://raw.githubusercontent.com/justinhk001/codefig/main/docs/assets/survey3.png" width="280" alt="Schedules and operators"><br><b>Schedules and operators</b></a><br>Timelines, pipeline bubbles and code blocks.</td>
<td><a href="docs/cookbook/03_serving_cluster.py"><img src="https://raw.githubusercontent.com/justinhk001/codefig/main/docs/cookbook/03_serving_cluster.png" width="280" alt="Serving cluster"><br><b>Serving cluster</b></a><br>Groups and branching connections.</td>
</tr>
<tr>
<td><a href="docs/cookbook/12_solids_pyramid.py"><img src="https://raw.githubusercontent.com/justinhk001/codefig/main/docs/cookbook/12_solids_pyramid.png" width="280" alt="Solids and pyramid"><br><b>Solids and pyramid</b></a><br>Cuboids, slabs and hierarchy.</td>
<td><a href="docs/cookbook/15_chart_features.py"><img src="https://raw.githubusercontent.com/justinhk001/codefig/main/docs/cookbook/15_chart_features.png" width="280" alt="Embedded charts"><br><b>Embedded charts</b></a><br>Themed data inside a diagram.</td>
<td><a href="docs/cookbook/21_block_sparse.py"><img src="https://raw.githubusercontent.com/justinhk001/codefig/main/docs/cookbook/21_block_sparse.png" width="280" alt="Block-sparse matrix"><br><b>Block-sparse matrix</b></a><br>Unequal tracks and split lines.</td>
</tr>
<tr>
<td><a href="docs/cookbook/22_migration_timeline.py"><img src="https://raw.githubusercontent.com/justinhk001/codefig/main/docs/cookbook/22_migration_timeline.png" width="280" alt="Migration timeline"><br><b>Migration timeline</b></a><br>Tasks and migration spans.</td>
<td><a href="docs/cookbook/13_charts_wrapflow.py"><img src="https://raw.githubusercontent.com/justinhk001/codefig/main/docs/cookbook/13_charts_wrapflow.png" width="280" alt="Wrapped flow"><br><b>Wrapped flow</b></a><br>Charts beside a folded chain.</td>
<td><a href="docs/cookbook/04_kv_cache.py"><img src="https://raw.githubusercontent.com/justinhk001/codefig/main/docs/cookbook/04_kv_cache.png" width="280" alt="KV cache"><br><b>KV cache</b></a><br>Structured cache blocks and ports.</td>
</tr>
</table>

[Browse all 31 recipes](https://github.com/justinhk001/codefig/blob/main/docs/cookbook/contact_sheet.png) · [Cookbook index](https://github.com/justinhk001/codefig/blob/main/docs/cookbook/README.md)

<a id="features"></a>

## Features

### Layout primitives

| Category | Public primitives |
|---|---|
| Composition | `Row`, `Col`, `Grid`, `Group`, `Stack` |
| Nodes | `Box`, `Text`, `Circle`, `Diamond`, `Triangle`, `Polygon` |
| Structured data | `Matrix`, `TokenStrip`, `Table`, `DotGrid` |
| Repetition | `Stacked`, `Repeat`, `Series` |
| Spatial structure | `Region`, `Cuboid`, `SlabStack`, `Pyramid` |
| Sequences | `WrapFlow`, `Tree`, `Timeline`, `Lanes` |
| Annotation | `Brace`, `Callout`, `Badge`, `Step`, `Dim`, `CodeBlock` |
| Connections and keys | `Diagram`, `Edge`, `Guide`, `Fork`, `Join`, `Legend` |

Compose small containers, then combine them into panels.
Use `Region` for overlapping membership rather than forcing everything into nested groups.
`WrapFlow` folds a long chain; `Matrix` expresses cell structure directly.
See [layout concepts](https://github.com/justinhk001/codefig/blob/main/docs/concepts/layout.md) for composition rules.

### Constraints

- `same_x`, `same_y`: share an alignment axis.
- `same_width`, `same_height`: equalise dimensions.
- `align_columns`, `align_rows`: share tracks across matrices and token strips.
- `above`, `below`, `left_of`, `right_of`: express relative placement.
- `place`, `distribute`, `align`: place and space related elements.

Use constraints for relationships across containers, not as a coordinate substitute.
Read [constraints](https://github.com/justinhk001/codefig/blob/main/docs/concepts/constraints.md) before combining many relations.

### Edges & routing

- Attach edges to visible nodes with `node.port("right")` and other side ports.
- Sliding ports and edge alignment can straighten small offsets.
- Fan-in trunks share a route; `Edge(trunk=False)` opts out.
- `Fork` and `Join` express explicit branching and merging.
- `Edge(via=...)` passes through an operator.
- `Guide` draws a helper line without pretending to be a data arrow.
- `Diagram.zoom` connects an overview to a magnified detail.

Dense crossings still need visual inspection.
Changing the ordering or leaving a routing channel often helps more than adding bends.

### Charts

| Primitive | Intended use |
|---|---|
| `BarChart` | A compact bar comparison |
| `GroupedBarChart` | Multiple series, horizontal bars or baseline comparisons |
| `StackedBarChart` | Composition of totals |
| `LineChart` | Trends, including error bands |
| `Sparkline` | A small trend embedded beside a label |

These are themed codefig primitives, not matplotlib wrappers.
They share the figure's typography and visual language.
Use log scales for values spanning decades and error bars or bands for uncertainty.
For a specialised scientific plot, use a plotting library instead.

### Themes & venues

The paper theme documents 6/7/8 pt annotation/label/title roles,
0.6/0.75/1.2 pt box/arrow/emphasis strokes, and a CVD-safe categorical palette.
Use `category=` and `Legend()` for meaning; reserve accents for emphasis.
The classic theme supports older scripts and a larger screen-oriented appearance.

Preset dimensions below come from `venues.py`; they are template presets, not a
promise that every year's author kit will remain unchanged. Check your submission template.

| Venue | Column width (pt) | Text width (pt) |
|---|---:|---:|
| `neurips` | — (single column) | 396 |
| `iclr` | — (single column) | 396 |
| `icml` | 234 | 486 |
| `mlsys` | 234 | 486 |
| `vldb` | 239.76 | 504 |
| `sigmod` | 239.76 | 504 |
| `osdi` | 240.12 | 504 |
| `sosp` | 239.76 | 504 |

Aliases include `acm` for SIGMOD and `usenix`, `nsdi`, `fast`, `atc` for OSDI.
For NeurIPS and ICLR, use `width="text"`; `width="column"` requires a two-column preset.
See [themes and venues](https://github.com/justinhk001/codefig/blob/main/docs/concepts/themes-and-venues.md).

### Lint

38 rules inspect the figure at its final width. Examples:

| Rule | What it catches |
|---|---|
| `CF-TXT-001` | Text too small at final width |
| `CF-TXT-007` | Label overflow or insufficient padding |
| `CF-TXT-010` | Drawn text covered or struck through |
| `CF-COL-004` | Semantic categories without a key |
| `CF-ARR-003` | Edges attached to invisible containers |
| `CF-REG-001` | A region covering a non-member |
| `CF-LAY-004` | Aspect ratio outside the slot's suggested range |
| `CF-EXP-001` | Width mismatch or excessive shrink |

`save()` refuses export on lint errors under the default venue lint policy.
It writes a `<name>.lint_preview.png` with findings outlined so you can inspect the problem.
Warnings and info findings still deserve attention; lint cannot judge the scientific story.
See the complete [rule reference](https://github.com/justinhk001/codefig/blob/main/docs/lint-rules.md).

### Export

- PDF: vector output with embedded TrueType subsets; no Type 3 fonts.
- SVG: text remains text, with alt text in the document title.
- PNG: 300 dpi by default for physical figures; configure `dpi=` as needed.
- `alt=` writes a companion `.alt.txt` file.
- `layout_report()` returns fitting diagnostics for debugging layout.

Keep Python as the authoritative source, and regenerate every format from it.

<a id="lint-in-action"></a>

## Lint in action

Six stages in one row, one colour each, squeezed into a 234 pt ICML column. Lint tells you exactly what is wrong, by how much, and what to do:

```python
from codefig import Figure, Box, Row, Col, Legend

fig = Figure(venue="icml", width="column", panel_caption="none")
stages = ["Tokenize", "Embed", "Encode", "Attend", "Decode", "Sample"]
with fig.panel("a") as panel:
    panel += Col([Row([Box(s, category=s) for s in stages]), Legend(direction="row")])
print(fig.lint(alt="A six-stage pipeline squeezed into one column."))
```

```text
codefig lint (icml, 234 pt): 0 error(s), 2 warning(s), 2 info
  WARN  CF-EXP-001 content is 250 pt wide but the slot is 234 pt: everything shrinks ×0.94 (fonts 5.6–7.5 pt) — use width='text', cols=, or fewer/shorter boxes; …
        fix: Figure(venue=..., width='column'|'text') and \includegraphics at scale 1; see docs/cookbook/30_compact_column.py
  WARN  CF-TXT-001 6 text run(s) below 6 pt at final size (smallest 5.61 pt) [text:'Attend', text:'Decode', text:'Embed' …]
        fix: use the theme size roles (6/7/8 pt); widen the figure (width='text') or shorten labels
  INFO  CF-COL-001 5 categorical hue families [#4DB1F2, #FCD188, #8FCCA7 …]
  INFO  CF-LAY-004 aspect 6.63 outside 1.1–2.5 for a column-width figure
```

The fix is structural, not cosmetic: two rows, and categories that mean something (at most 4). Warnings are gone, fonts stay at the theme's 6/7/8 pt roles:

```python
from codefig import Figure, Box, Row, Col, Legend

fig = Figure(venue="icml", width="column", panel_caption="none")
kind = {"Tokenize": "data", "Embed": "model", "Encode": "model",
        "Attend": "attention", "Decode": "model", "Sample": "data"}
boxes = [Box(s, category=c) for s, c in kind.items()]
with fig.panel("a") as panel:
    panel += Col([Row(boxes[:3]), Row(boxes[3:]), Legend(direction="row")])
print(fig.lint(alt="A six-stage pipeline in two rows."))
```

```text
codefig lint (icml, 234 pt): 0 error(s), 0 warning(s), 1 info
  INFO  CF-LAY-004 aspect 3.37 outside 1.1–2.5 for a column-width figure
```

<a id="ai-first-authoring"></a>

## AI-first authoring

LLMs can describe rows, groups and connections without guessing spatial coordinates.
Lint findings carry rule identifiers and suggested fixes, giving an author a concrete repair loop.
This reduces placement guesswork; it does not remove the need to inspect the rendered PNG.

The quick card is ~12.9 KB; the full reference is ~276.0 KB (decimal KB).
Choose the short card first, then retrieve relevant sections of the full reference.

| File | Role |
|---|---|
| [llms.txt](https://github.com/justinhk001/codefig/blob/main/llms.txt) | Small entry point and authoring rules |
| [llms-full.txt](https://github.com/justinhk001/codefig/blob/main/llms-full.txt) | Consolidated reference |
| [AGENTS.md](https://github.com/justinhk001/codefig/blob/main/AGENTS.md) | Authoring and development workflow |
| [CLAUDE.md](https://github.com/justinhk001/codefig/blob/main/CLAUDE.md) | Assistant entry point |
| [API](https://github.com/justinhk001/codefig/blob/main/docs/api.md) | Real constructors and arguments |
| [Cookbook](https://github.com/justinhk001/codefig/blob/main/docs/cookbook/README.md) | Copy a working composition |

Paste this into Claude Code, Cursor or Codex:

```text
Create an original codefig diagram for the system I describe.
1. Read llms.txt and AGENTS.md. Confirm the intended venue and column/text width.
2. Open the cookbook index and choose the nearest working recipe.
3. Use documented primitives and semantic categories with Legend().
   Do not guess constructor arguments or introduce absolute coordinates.
4. Keep labels short. Compose Row/Col/Grid before adding cross-container constraints.
5. Print fig.lint(alt=ALT). Apply each finding's suggested fix.
   Repeat until there are 0 errors and 0 warnings; inspect info findings too.
6. If save refuses, inspect the generated lint_preview.png before guessing.
7. Render and VIEW the PNG at print width. Check the story, routes and labels.
8. Export PDF, SVG and PNG with descriptive alt text. Keep the Python source.
9. Include the PDF in LaTeX at native size, with no width override.
```

For a chat AI: “Read the attached llms.txt; use llms-full.txt as reference and help me build a lint-clean codefig figure.”

<a id="evaluation"></a>

## Measured AI usability

Fresh AI authors received only public docs and reproduced six published systems/ML figures.
An independent scorer applied a 100-point rubric:

- **A: outcome, 60 points:** structural fidelity 30, visual quality 15, lint 10, code 5.
- **B: process friction, 40 points:** authoring friction and repair process.

| Target | Figure | 0.15 independent | 0.16 independent |
|---|---|---:|---:|
| t1 | ServerlessLLM | 80 | 64.6 |
| t2 | Lero | 81 | 82.5 |
| t3 | MegaBlocks | 89 | 87.5 |
| t4 | Llumnix | 89 | 91.0 |
| t5 | Gated Attention | 81 | 72.0 |
| t6 | RETRO | 74 | 72.5 |
| Mean | | 82.3 | 78.4 |

The 0.15 independent median was 81.0.
The 0.16 mean regressed by 3.9 points, concentrated in column-width targets t1/t5.
The other four independent deltas were within ±2 points.
This is six targets with one author sample each; scorer models differed,
so calibration may explain part of the difference.
A successful process exit does not imply a lint-clean or structurally faithful figure.

### What the findings changed

- Drawn-text collisions motivated `CF-TXT-010`.
- Refused exports without a diagnostic image motivated `lint_preview.png`.
- Missing magnification and helper lines motivated `Diagram.zoom` and `Guide`.
- Width guesswork motivated diagnostics naming the widest layout chain.
- The retest exposed compact-recipe discoverability and `widths=` confusion.

Column fitting and compact-before-shrink behaviour remain priorities.
These results are a feedback loop, not a claim of autonomous publication quality.
The target paper figures are not redistributed; this README includes no eval images.

<a id="install"></a>

## Install

```sh
pip install codefig
# From a source checkout:
pip install -e .
# Development dependencies:
pip install -e ".[dev]"
```

| Platform | System Cairo setup |
|---|---|
| Linux / Debian / Ubuntu | `sudo apt install libcairo2` |
| macOS / Homebrew | `brew install cairo` |
| Windows | Install Cairo via conda-forge (`conda install -c conda-forge cairo`) or a GTK runtime; make its DLLs discoverable |

CairoSVG requires the system Cairo library in addition to Python packages.
Use a virtual environment to isolate the Python dependencies.

<a id="faq"></a>

## FAQ

### Is this a matplotlib replacement?

No. It focuses on composed paper diagrams and compact embedded charts.
Keep matplotlib for rich scientific plotting and exploratory analysis.

### Can I edit the SVG?

Yes, in an SVG editor. Text remains text, but external edits are not imported
back into Python. Keep the source if you want reproducible regeneration.

### What about fonts?

The paper theme uses a sans stack and 6/7/8 pt roles.
PDF export embeds TrueType subsets. Inspect the result on your actual machine;
font availability can affect metrics. The lint reference describes PDF font checks.

### Does it work in Jupyter?

You can run the Python API and display a saved PNG or SVG using notebook tools.
There are no `_repr_svg_` or `_repr_png_` hooks for automatic rich display.

### Can I use the output in Overleaf?

Export PDF locally, upload it, and use `\includegraphics{quickstart.pdf}`.
Keep the native size so the designed print typography is preserved.

### Is the API stable?

This is pre-1.0 software. Pin the version for a paper and keep the generating script.
Review changes before upgrading a manuscript's build environment.

<a id="documentation"></a>

## Documentation

| Read | Purpose |
|---|---|
| [Getting started](https://github.com/justinhk001/codefig/blob/main/docs/getting-started.md) | First figure and lint loop |
| [Layout](https://github.com/justinhk001/codefig/blob/main/docs/concepts/layout.md) | Composition primitives |
| [Constraints](https://github.com/justinhk001/codefig/blob/main/docs/concepts/constraints.md) | Relationships across containers |
| [Themes and venues](https://github.com/justinhk001/codefig/blob/main/docs/concepts/themes-and-venues.md) | Print typography and width presets |
| [Fit a column](https://github.com/justinhk001/codefig/blob/main/docs/guides/fit-a-column.md) | Diagnose width pressure |
| [Cookbook](https://github.com/justinhk001/codefig/blob/main/docs/cookbook/README.md) | 31 runnable recipes |
| [API](https://github.com/justinhk001/codefig/blob/main/docs/api.md) | Public constructor reference |
| [Lint rules](https://github.com/justinhk001/codefig/blob/main/docs/lint-rules.md) | All 38 rules and suggested fixes |
| [Feature tour](https://github.com/justinhk001/codefig/blob/main/docs/feature-tour.md) | Broader examples and capabilities |

<a id="roadmap"></a>

## Roadmap

Plans, not promises; priorities follow observed authoring friction.

- [ ] Compact or reflow before shrinking below readable type sizes.
- [ ] Make compact-column recipes easier to discover.
- [ ] Clarify width budgets and spare-space semantics of `widths=`.
- [ ] Improve dense routes, annotation placement and diagnostics.
- [ ] Continue fresh-author evaluations and report regressions honestly.

<a id="contributing"></a>

## Contributing

Start with [CONTRIBUTING.md](https://github.com/justinhk001/codefig/blob/main/CONTRIBUTING.md).
A useful bug report includes a minimal script, version, venue and lint output.
For new recipes, include descriptive alt text and inspect the rendered PNG.
Only submit diagrams and assets you have the right to redistribute.

```sh
python -m pytest -q -W error
python tools/gen_api_docs.py
```

[Code of conduct](https://github.com/justinhk001/codefig/blob/main/CODE_OF_CONDUCT.md) · [Security](https://github.com/justinhk001/codefig/blob/main/SECURITY.md)

If codefig helps your paper, star the repository or share an original figure and its source.

<a id="citation"></a>

## Citation

```bibtex
@software{codefig2026,
  author = {justinhk001},
  title = {codefig},
  year = {2026},
  url = {https://github.com/justinhk001/codefig}
}
```

<a id="license"></a>

## License & acknowledgements

[MIT](https://github.com/justinhk001/codefig/blob/main/LICENSE). Copyright (c) 2026 Justin.

Thanks to Tabler Icons (MIT), kiwisolver (Cassowary constraint solving),
and CairoSVG (vector/raster export).
