From klayoutclaw
Places bonding pads and routes nanodevice contacts to pads in KLayout layouts with multi-window EBL support, variable line widths per window, and boundary connection patches.
npx claudepluginhub caidish/klayoutclaw --plugin klayoutclawThis skill uses the workspace's default tool permissions.
Route nanodevice contacts to bonding pads, with multi-window EBL write field support (different line widths per window, boundary connection patches).
Orchestrates end-to-end nanodevice design in KLayout from user query through flake detection, material analysis, geometry creation, routing, evaluation, and GDS export. Device-agnostic.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
Share bugs, ideas, or general feedback.
Route nanodevice contacts to bonding pads, with multi-window EBL write field support (different line widths per window, boundary connection patches).
numpy, scipy, scikit-image (in conda env instrMCPdev)python scripts/place_pads.py --field 2000 --pad-size 80 --pads-per-edge 12 [--layer 2/0] [--margin 60]
--field — EBL write field size in um (default: 2000)--pad-size — Bonding pad side length in um (default: 80)--pads-per-edge — Number of pads per edge (default: 12)--layer — Output layer as layer/datatype (default: 2/0)--margin — Pad center inset from field edge in um (default: 60)Example — 48 pads (12 per edge) around a 2mm field:
python scripts/place_pads.py --field 2000 --pad-size 80 --pads-per-edge 12
Routes device contacts to bonding pads in two passes with different line widths, placing connection patches at the window boundary.
python scripts/route_multiwindow.py \
--pin-contacts 100/0 \
--pin-pads 101/0 \
--inner-window 800 \
--outer-window 2000 \
--inner-width 0.5 \
--outer-width 1.0 \
--inner-layer 3/0 \
--outer-layer 4/0 \
--patch-layer 5/0 \
--patch-size 1.0 \
--obstacle-layers 1/0
--pin-contacts — Layer with pin markers at device contacts (default: 100/0)--pin-pads — Layer with pin markers at bonding pads (default: 101/0)--inner-window — Inner EBL window size in um (default: 800)--outer-window — Outer EBL window size in um (default: 2000)--inner-width — Route line width for inner window in um (default: 0.5)--outer-width — Route line width for outer window in um (default: 1.0)--inner-layer — Output layer for inner routes (default: 3/0)--outer-layer — Output layer for outer routes (default: 4/0)--patch-layer — Output layer for boundary patches (default: 5/0)--patch-size — Boundary patch size in um (default: 1.0)--obstacle-layers — Comma-separated obstacle layers (default: 1/0)The script:
python scripts/clear_routes.py 3/0 4/0 5/0
Clears all shapes from the listed layers. Useful for re-routing without losing device geometry.
place_pads.py (also places pin markers on 101/0)route_multiwindow.py to connect everythingclear_routes.pyNote: These layers are task-specific examples. Always use the layer assignments from the task instruction, which may differ (benchmarks frequently use 20/0 for mesa, 22/0 for topgate, etc.).
| Layer | Purpose | EBL Pass |
|---|---|---|
| 1/0 | Mesa (graphene etch) | Pass 1 |
| 2/0 | Bonding pads | Pass 3 (coarse) |
| 3/0 | Fine routes (<inner window) | Pass 2 (fine) |
| 4/0 | Coarse routes (inner→outer) | Pass 3 (coarse) |
| 5/0 | Boundary patches | Pass 2 or 3 |
| 100/0 | Pin markers: contacts | (removed after routing) |
| 101/0 | Pin markers: pads | (removed after routing) |
All layer parameters use the "L/D" string format (layer/datatype), not arrays or separate integers. Examples: "1/0", "3/0", "100/0".
This applies to all CLI flags (--layer, --inner-layer, --outer-layer, --patch-layer, --obstacle-layers, --pin-contacts, --pin-pads) and to the auto_route MCP tool parameters (pin_layer_a, pin_layer_b, obstacle_layers, output_layer).
path_safe_distance, or manually adjust problem routes via execute_scriptThe auto_route MCP tool runs a subprocess on the host machine (KLayout runs on the host, not inside the container). By default it activates conda env instrMCPdev via ~/miniforge3/etc/profile.d/conda.sh. This fails if the host uses a different conda distribution (e.g., anaconda3).
Workaround: Pass the python_path parameter to bypass conda activation entirely. To discover the correct path, use execute_script (which also runs on the host):
import glob, os
candidates = glob.glob(os.path.expanduser("~/anaconda3/envs/instrMCPdev/bin/python3")) + \
glob.glob(os.path.expanduser("~/miniforge3/envs/instrMCPdev/bin/python3"))
result = candidates[0] if candidates else "instrMCPdev env not found"
Then pass the discovered path as python_path in your auto_route call.
When auto_route fails for individual pin pairs (reports "No path found"), create manual L-shaped routes via execute_script:
top_cell = _layout.top_cell()
li_route = _layout.layer(3, 0) # or your route layer
# Create an L-shaped path from contact to pad
x1, y1 = 766.0, 811.4 # contact center (um)
x2, y2 = 928.0, 1825.0 # pad center (um)
mid_x = x2 # route goes horizontal then vertical
width = 1.0 # path width in um
path = pya.DPath([
pya.DPoint(x1, y1),
pya.DPoint(mid_x, y1), # horizontal segment
pya.DPoint(mid_x, y2), # vertical segment to pad
], width / _layout.dbu)
top_cell.shapes(li_route).insert(path)
Use this for any pairs that auto_route couldn't connect. Check the auto_route result for failed_pairs to identify which contacts need manual routing.