Metadata-Version: 2.4
Name: klayout-klink
Version: 0.2.2
Summary: AI-native control plane for KLayout — thin RPC bridge + modular external workers
Author: klink developers
License: Apache-2.0
Project-URL: Homepage, https://github.com/klinkdev2026/klayout-klink
Project-URL: Repository, https://github.com/klinkdev2026/klayout-klink
Project-URL: Issues, https://github.com/klinkdev2026/klayout-klink/issues
Keywords: klayout,eda,gds,rpc,ipc
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: klink-boxmaze-rs<0.3,>=0.2
Requires-Dist: klink-trackmaze-rs<0.3,>=0.2
Provides-Extra: photonics
Requires-Dist: gdsfactory<10,>=9.0; extra == "photonics"
Dynamic: license-file

# KLayout-klink

<p align="right">
  <a href="./README.md">English</a> | <a href="./README.zh-CN.md">中文</a>
</p>

klink is an AI-native control plane for [KLayout](https://www.klayout.de/).
It turns a running KLayout GUI into a scriptable layout kernel that can be
controlled from external Python processes, MCP clients, and AI agents.

📖 **Documentation site** (English; 中文 at the site root):
<https://klinkdev2026.github.io/klayout-klink/en/>

**Step-by-step illustrated tutorials** — each one is a real run of a demo,
drawn stage by stage in KLayout, with a screenshot and runnable code per step:

- [Hall bar](https://klinkdev2026.github.io/klayout-klink/en/tutorial-hallbar.html) — geometry-first basics
- [EBL wraparound](https://klinkdev2026.github.io/klayout-klink/en/tutorial-ebl-wraparound.html) — writefield constraints
- [Neural-electrode array](https://klinkdev2026.github.io/klayout-klink/en/tutorial-neural-electrode.html) — parametric arrays + batch RPCs
- [gdsfactory MZI](https://klinkdev2026.github.io/klayout-klink/en/tutorial-gf-mzi.html) — the gdsfactory bridge + drag-to-reroute
- [Custom device → P&R → LVS](https://klinkdev2026.github.io/klayout-klink/en/tutorial-fit-device.html) — fit your own device into a digital place-and-route flow
- [Probe-card padframe](https://klinkdev2026.github.io/klayout-klink/en/tutorial-padframe.html) — pad ring + power net, two card modes
- [Passive-device templates](https://klinkdev2026.github.io/klayout-klink/en/tutorial-passives.html) — IDC / spiral / SAW / BAW

The project is split into three layers:

- `klink`: the external Python client, MCP bridge, routing/domain logic, and
  agent-facing workflows.
- `klink_plugin`: a thin KLayout-side RPC plugin that exposes selected `pya`
  and GUI operations.
- `examples_klink/public`, `tests/public`, and `docs/public`: examples,
  validation, and release documentation.

The core Python package pulls in no third-party runtime libraries — its only
declared dependencies are klink's own two Rust acceleration kernels, shipped as
prebuilt wheels. Virtual environments, caches, build outputs, and local test
artifacts are intentionally not part of a clean release.

## What It Does

- Controls KLayout over local TCP RPC, with batch methods sized for generated
  layouts (thousands of shapes/instances/PCells per call).
- Reads layout, cell, layer, shape, view, selection, and method metadata.
- Creates and edits shapes, text, cells, instances, PCells, Ports, and Anchors.
- Routes: tapered/steiner/damped/channel backends over Port/Anchor markers,
  plus a detailed-router → live LVS flow for custom-device circuits.
- Exposes KLayout operations as MCP tools through `klink-mcp`, navigable with
  `klink.find_tools`; runs controlled `pya` snippets as the escape hatch.
- Remembers what you SEND: selections sent from the KLayout toolbar become
  durable ids an agent can resolve ("this area", "the one I just sent").
- Drives many KLayout sessions from one bridge and moves geometry between
  them with a dry-run-then-commit transfer.
- Records a working session — manual edits and RPC edits — into a replayable
  Python script (plus a standalone `pya` variant).
- Supports gdsfactory-oriented workflows, including Port markers, component
  placement, routing, and klive-compatible `c.show()` display.
- Keeps the KLayout plugin thin while heavier logic runs in external Python.

## What's New

### 0.2.2 — PCell fitter: learn it exactly or refuse

The exemplar fitter now handles COUNT-VARYING geometry (contact arrays,
finger repeats) as a new `klink_fitted_device_pcell_v3` table: counts,
pitch and positions are fitted as exact integer laws, verified at every
exemplar, and anything the model cannot express exactly and uniquely is
REFUSED with an instructive message naming the box family — never a
silently-wrong PCell. Fit tables record their sampled envelope, the
byte-exact differential harness lives in
`klink.domains.structdevice.pcell_diff`, and two one-call routes ship:
`tcell_workflows.py fit` (L-Edit T-Cell → verified KLayout PCell) and
the KLayout-native demo `fit_repeat_device.py` (drawn exemplars →
verified PCell). Details in the [CHANGELOG](./CHANGELOG.md).

### 0.2.1 — L-Edit bridge hardening

Design-targeting safety from blind-test findings: `new_design`/`open_design`
now activate the created design and fail loudly if they cannot (previously
later writes could silently land in whatever design was active), every
file-bound command echoes `result.file`, and an optional `expect_file`
parameter refuses writes to any other design. The template gains
`tcell_template.cpp`, a byte-exact-verified starting point for T-Cell
generator code written back through the bridge. Details in the
[CHANGELOG](./CHANGELOG.md).

### 0.2.0 — L-Edit bridge

klink now drives a running Tanner L-Edit
through a file-exchange RPC bridge: one source-loaded UPI macro (zero
compile, no sockets), full white-box readout (selections, whole cells with
property trees, ports, labels, the design's entire DRC rule table), and
T-Cells in **both directions** — read generator code, instance
programmatically with parameters, and write generated code back as a
native parametric T-Cell. Acceptance is byte-exact: a ported cell counts
only when every box matches L-Edit's own generated geometry. See
`example_template/ledit_bridge/` after `klink init`, MCP domain
`bridge_ledit`, and the [website guide](https://klinkdev2026.github.io/klayout-klink/en/ledit-bridge.html).

![Load ledit_bridge.cpp in L-Edit: Tools > Macro > Load Macro, then the Tools menu gains klink Bridge Start/Stop/Status](https://raw.githubusercontent.com/klinkdev2026/klayout-klink/main/docs/public/assets/ledit_bridge_load.png)

*Connecting L-Edit to your agent: load the macro source once — the
bridge starts polling immediately (Tools menu: klink Bridge Start/Stop/Status).*

Earlier releases: see the [CHANGELOG](./CHANGELOG.md).

## Repository Layout

```text
klink/                  Python client, MCP bridge, and core logic
klink_plugin/           KLayout salt plugin
examples_klink/public/  Public, open-box-runnable example gallery
tests/public/           Public test suite (no KLayout required)
docs/public/            Release documentation
rust/                   Rust acceleration crates (klink_boxmaze, klink_trackmaze)
pyproject.toml          Python packaging configuration
README.md               English README
README.zh-CN.md         Chinese README
CLAUDE.md               Claude Code operating rules and project context
LICENSE                 Apache-2.0 license
THIRD_PARTY_NOTICES.md  Third-party notices
```

## Requirements

- **KLayout** — the layout editor klink controls; for everything live this is
  the core prerequisite. Install the standard desktop build from
  <https://www.klayout.de/build.html>. klink is developed and tested against
  KLayout 0.30.x; any recent official desktop build (whose macro environment
  provides the `pya` Qt bindings) should work. Purely offline workflows (the
  public test suite and the offline demos) run without it.
- Python 3.10 or newer (the bundled Rust kernels ship abi3 stable-ABI wheels,
  covering CPython 3.10 and newer).
- Optional: Claude Code or another MCP client.
- Optional: gdsfactory, the `klayout` Python package, NumPy/OpenCV, or detector
  dependencies depending on the workflow.

## Install Python Package

For normal use, install the published package from PyPI:

```powershell
python -m pip install klayout-klink
```

`pip install klayout-klink` installs klink **and its two Rust acceleration
kernels** (`klink-boxmaze-rs` + `klink-trackmaze-rs`) — klink's own code, shipped
as pre-built abi3 wheels for Linux / macOS / Windows on CPython 3.10+. You get the
fast path automatically; nothing else to do.

> **On a platform with no pre-built kernel wheel** (an unusual OS / arch /
> Python), pip falls back to building the kernel from source, which needs a
> Rust toolchain (rustup). If you don't have one — or want the lightest possible
> install — use `pip install klayout-klink --no-deps` for the **pure-Python core
> only**: everything still works (the kernel has a pure-Python fallback), just
> slower on large place-and-route jobs.

**Third-party** scientific libraries (klayout, gdsfactory, numpy, …) are **not**
bundled — install the ones a feature needs yourself, into the same interpreter:

```powershell
python -m pip install klayout                          # offline DB / LVS extraction
python -m pip install gdsfactory                       # silicon-photonics routing
python -m pip install numpy opencv-python-headless     # nanodevice flake
python -m pip install scipy scikit-learn scikit-image  # flake detectors
```

When a feature needs a library that is missing, klink returns an error naming
the exact `pip install` command — you do not have to know these in advance.

### From source (development only)

Use an editable install (`-e`) only when you are working on klink itself — it
points the package at your working tree so source edits take effect immediately.
Normal users do not need this.

Windows PowerShell:

```powershell
git clone <repo-url> klink
cd klink
py -3.11 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -U pip
python -m pip install -e .
```

Linux / macOS:

```bash
git clone <repo-url> klink
cd klink
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -e .
```

## Start a project

`pip install` gives you the `klink` CLI. Scaffold a project into a **new empty
folder** with `klink init`:

```powershell
klink init mychip     # creates ./mychip (pdk.py, example_template/, recipes/, agent rules, MCP config)
cd mychip
```

`klink init` refuses a non-empty folder, so point it at a fresh name. Then open
the folder with your agent (Claude Code / Codex) and describe what you are
building — it fills in `pdk.py` + `custom_devices/` from the matching recipe. The
scaffolded `example_template/` holds copy-and-adapt starter demos, grouped into
`nanodevice/`, `photonics/`, `passives/`, and `digital/`; run one with
`python example_template/<category>/<name>.py`. The `digital/` family does live
P&R + LVS, so it needs a running KLayout session (`--port`).

When you upgrade klink later, refresh those bundled starters **without touching
your own work** (`pdk.py`, `custom_devices/`, `.klink/`, `out/`, `specs/` are
never changed):

```powershell
python -m pip install -U klayout-klink
klink update mychip   # or run `klink update` from inside the project folder
```

## Install KLayout Plugin

Prerequisite: KLayout itself must be installed first — get the desktop build
for your OS from <https://www.klayout.de/build.html>.

`klink_plugin` is a KLayout salt package. The plugin ships **inside the pip
package**, so after `pip install klayout-klink` one command installs it — no
repository clone needed:

```bash
klink plugin install      # copies the bundled plugin into KLayout's salt/
klink plugin status       # shows installed vs bundled plugin versions
```

The salt directory is auto-detected per OS (`%USERPROFILE%\KLayout\salt` on
Windows, `~/.klayout/salt` elsewhere, honouring `KLAYOUT_HOME`); pass
`--salt-dir` to override. Re-run `klink plugin install` after upgrading the
pip package so the plugin stays in lockstep with the client.

Once installed, KLayout autoruns `pymacros/klink.lym` and starts:

- klink RPC on `127.0.0.1:8765`. If the port is busy, it tries the next ports up
  to `8799`.
- a klive-compatible server on `127.0.0.1:8082` for gdsfactory-style `c.show()`
  workflows.

From a repository checkout you can instead copy the folder by hand — Windows:

```powershell
cd path\to\klink
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\KLayout\salt" | Out-Null
Copy-Item -Path ".\klink_plugin" -Destination "$env:USERPROFILE\KLayout\salt\" -Recurse -Force
```

Linux / macOS:

```bash
cd /path/to/klink
mkdir -p ~/.klayout/salt
cp -R klink_plugin ~/.klayout/salt/
```

Either way the plugin ends up at `<KLayout salt dir>/klink_plugin/` (the folder
that contains `grain.xml`).

Restart KLayout after installing the plugin. Each KLayout window runs its own
klink session: it binds the first free port in `8765`–`8799` and registers as
session `klayout-<port>`, so with several windows open there is one listener
per window (`8765`, `8766`, …). A successful startup prints:

```text
[klink.server] listening on 127.0.0.1:8765
```

When upgrading, close KLayout, run `klink plugin install` again (it replaces
the old copy — from a checkout, remove the old `salt/klink_plugin` and re-copy
instead), then restart KLayout.

## Smoke Test

Start KLayout with the plugin loaded, then connect directly from Python:

```python
from klink import KLinkClient

with KLinkClient() as c:
    print(c.ping(nonce=42))
    print(c.layout_info(verbosity="summary"))
```

If KLayout is listening on a non-default port:

```python
from klink import KLinkClient

with KLinkClient(port=8766) as c:
    print(c.ping())
```

For a first end-to-end result with no external geometry, run one of the public
demos (see [`docs/public/demos.md`](docs/public/demos.md)):

```bash
python -m examples_klink.public.demos.nanodevice.ebl_wraparound      # fully offline
```

## Claude Code / MCP

After installing the Python package, `klink-mcp` is available as a command-line
entry point.

Install the agent skills and project memory files:

```powershell
cd path\to\klink
klink-mcp --setup .
```

This installs or updates:

```text
.claude/skills/klayout/SKILL.md
.claude/skills/klayout-gdsfactory/SKILL.md
CLAUDE.md
```

Register the MCP server with Claude Code:

```powershell
claude mcp add klayout -- python -m klink.mcp --profile read,write,verify,escape --session-id project-klink
```

Common profiles:

| Profile | Purpose |
| --- | --- |
| `read` | Read-only exploration: layout, cell, layer, shape, view, and selection queries. |
| `write` | Editing tools: create cells, layers, shapes, instances, PCells, and undo records. |
| `verify` | DRC / LVS verification tools. |
| `escape` | Escape-hatch tools such as `exec.python`. |
| `all` | Expose everything. |

Profiles can be combined:

```powershell
python -m klink.mcp --profile read,write,verify,escape
```

Optional libraries must be installed into the same Python environment that
runs `klink.mcp`. For example, if gdsfactory tools report missing dependencies,
install gdsfactory into that same environment:

```powershell
python -m pip install gdsfactory
```

Use the MCP `klink.status` tool to inspect the active interpreter, detected
capabilities, and KLayout connection state.

## Tests

The public test suite is pure-Python and does not require KLayout:

```powershell
python -m pytest -q tests/public
```

Integration tests (routing, LVS, recorder) need a live KLayout with the
`klink_plugin` loaded and are exercised in the development repository.

## Troubleshooting

### Connecting from Python fails

Check that:

- KLayout is running.
- `klink_plugin` is installed in the KLayout salt directory
  (`klink plugin status` tells you).
- KLayout was restarted after plugin installation.
- Port `8765` is available, or use the actual session port such as `8766`.
- Firewall or security software is not blocking localhost TCP.

### MCP tools exist but return KLayout connection errors

The MCP server is running, but KLayout is not reachable. Start KLayout with the
plugin loaded, then call `klink.reconnect` or restart the MCP client. Use
`klink.status` to inspect the last connection error.

### gdsfactory or detector tools report missing dependencies

Install the missing library in the same environment used by the script or MCP
server (the error names the exact one):

```powershell
python -m pip install gdsfactory
python -m pip install scipy scikit-learn scikit-image
```

### PowerShell blocks `.venv` activation

Allow script execution for the current PowerShell process:

```powershell
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\.venv\Scripts\Activate.ps1
```

## Further Reading

- [`docs/public/getting-started.md`](docs/public/getting-started.md): install, configure, and first result.
- [`docs/public/architecture.md`](docs/public/architecture.md): the three tiers and the control path.
- [`docs/public/demos.md`](docs/public/demos.md): the demos and what each requires.
- [`docs/public/control-plane.md`](docs/public/control-plane.md): the typed RPC surface, the MCP tool catalogue, batch authoring.
- [`docs/public/interactive-workflows.md`](docs/public/interactive-workflows.md): SEND selection memory, multi-session transfer, the recorder.
- [`docs/public/api-stability.md`](docs/public/api-stability.md): what counts as public API and the 0.x compatibility policy.
- [`docs/public/drc-lvs.md`](docs/public/drc-lvs.md): writing and running DRC/LVS, including the profile-derived deck (`profile.drc_script()`).
- [`docs/public/drc-lvs-agent-handout.md`](docs/public/drc-lvs-agent-handout.md): paste-to-agent recipe that teaches an agent to author KLayout DRC/LVS.
- [`docs/public/plugin-packages.md`](docs/public/plugin-packages.md): extend klink from your own pip package (`klink.plugins` entry points).
- [`docs/public/25d-view.md`](docs/public/25d-view.md): the native 2.5d (3D stack) view driven from your StackSpec + z table.
- [`CLAUDE.md`](CLAUDE.md): Claude Code operating rules and project context.
- [`klink/mcp/README.md`](klink/mcp/README.md): MCP bridge details.

## Contributing

Contributions are welcome. A few project-specific rules keep klink coherent:

- **Process purity.** `klink/` is pure mechanism and holds zero process data
  (no hardcoded layers, devices, DRC numbers, ports, or PDK instances). Process
  facts live in an example or user `pdk.py` and are passed explicitly into the
  APIs. Do not add process constants to `klink/`.
- **One intention = one call.** New agent-facing tools use one call per user
  intention, errors that instruct (carry a `next_action`), validate-before-mutate,
  and state persisted on disk.
- **Tests must pass.** Run the public suite before sending a change:
  `python -m pytest -q tests/public`. Routing/LVS changes count as done only on
  a live KLayout LVS `match=True`.
- **Byte-frozen router.** `klink/routing/backends/flexdr/` and the crate under
  `rust/` are byte-parity baselines — the Rust kernel is a speed-only port of
  the pure-Python reference. Do not alter them casually.
- **Preflight.** `python -m klink.doctor` checks your interpreter, the plugin
  connection, and the client/plugin version handshake.

Open an issue or a pull request describing the change and how you verified it.
Contributions are accepted under the project's Apache-2.0 license.

Want to contribute a PR, discuss a larger change, or co-develop a feature?
Reach the maintainers at **klinkdev2026@163.com** (or open a GitHub issue).

## Acknowledgements

klink builds on and borrows from excellent open-source work:

- **[KLayout](https://www.klayout.de/)** — the layout editor and `pya`/`db` APIs
  klink drives and embeds into.
- **[OpenROAD](https://github.com/The-OpenROAD-Project/OpenROAD)** (BSD-3-Clause)
  — klink's routing engine contains faithful ports and concept adaptations of
  OpenROAD's detailed router `drt` (FlexDR / FlexPA / FlexGC) and global
  router `grt` (FastRoute).
- **[gdsfactory](https://github.com/gdsfactory/gdsfactory)** — the photonic
  component and `route_bundle` backend behind the silicon-photonics workflows.
- **[klive](https://github.com/gdsfactory/klive)** (MIT) — the display protocol
  that klink's plugin reimplements on port 8082 so gdsfactory-style
  `Component.show()` works unchanged.
- **[KlayoutClaw](https://github.com/caidish/KlayoutClaw)** (MIT) — nanodevice
  flake-detection priors and morphological mask helpers.
- **[Klayout-Router](https://github.com/Legendrexial/Klayout-Router)** (MIT) —
  the EBL auto-patching idea behind the writefield patch generator.

Formal third-party copyright and license texts are in
[`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md).

## License

Apache-2.0. See `LICENSE`. Third-party components retain their own licenses; see
`THIRD_PARTY_NOTICES.md`.
