Agent skill

Lini

by monfa-red in monfa-red/lini

A skill your agent uses when asked to create, edit, review, or debug a Lini diagram (a .lini file or its SVG) — architecture/box-and-arrow diagrams, flowcharts, mindmaps, org charts, ER schemas…

MITAuto-check passedDevelopment

Install Lini

skills CLI
$ npx skills add monfa-red/lini --skill lini -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install monfa-red/lini lini --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
lini
GitHub stars
137
Token cost
~11k tokens
SKILL.md length
5,170 words
Files
576 (incl. assets)
Skills in repo
1
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when asked to create, edit, review, or debug a Lini diagram (a .lini file or its SVG) — architecture/box-and-arrow diagrams, flowcharts, mindmaps, org charts, ER schemas…

  • Works in 7 steps: Colour by meaning. One hue per subsystem… → Name regions with |group| + its caption… → Refined over heavy: keep strokes thin… → …
  • Asked to create
  • SKILL.md covers The loop, A complete file, Syntax laws that bite and Cascade, plus 7 more sections
  • Calls cargo

What it does

Lini is an agent skill from monfa-red/lini. Use when asked to create, edit, review, or debug a Lini diagram (a .lini file or its SVG) — architecture/box-and-arrow diagrams, flowcharts, mindmaps, org charts, ER schemas, tables, sequence diagrams, bar/line/area/pie/radar/scatter charts, engineering drawings, floor plans, circuit schematics, or pen-drawn artwork written in the Lini language.

Its SKILL.md is about 11k tokens, which your agent loads only when the skill is triggered. The skill folder holds 580 other files, including assets (for example `.github/ISSUE_TEMPLATE/bug_report.yml`, `.github/ISSUE_TEMPLATE/config.yml` and `.github/ISSUE_TEMPLATE/feature_request.yml`).

It sits in Development, covering Diagrams. It works with Rust. The repository describes itself as: One small language for every figure from plain text — diagrams, charts, sequences, mindmaps, trees, ER schemas, schematics, floor plans and dimensioned technical drawings —…. The licence is MIT.

When your agent uses it

  • Asked to create
  • Debug a Lini diagram (a .lini file
  • Its SVG) — architecture/box-and-arrow diagrams
  • Sequence diagrams

Example prompts

  • “/lini”

Workflow steps

7 steps, taken from the first numbered list in SKILL.md.

  1. Colour by meaning. One hue per subsystem / branch / state, in the
  2. Name regions with |group| + its caption label (`|group#edge| "Edge"
  3. Refined over heavy: keep strokes thin (1.5–2), body text
  4. Let the engines work. Don't hand-place what flow/grid/tree can lay out;
  5. Meaning in line style: solid = sync/primary, --> dashed = return/
  6. Air: root padding: 24–30; group gap 20–28; don't shrink the default
  7. hint: on dense nodes, href: where a diagram lands in a doc, |icon|s for

What it can do on your machine

Read from SKILL.md and the folder at commit 0502d38. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • cargo

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Lini loads about 11k tokens when it runs. Until then it costs about 88 tokens; SKILL.md has 5,170 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~88
When it runs · the whole SKILL.md, loaded when a task matches
~11k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from monfa-red/lini at commit 0502d38, republished under its MIT licence (© monfa-red). 5,170 words, ~10,903 tokens.

Download SKILL.mdSave it as .claude/skills/lini/SKILL.md (or your agent's skills folder). This skill also uses 575 other files; get the full folder from GitHub.
name
lini
description
Use when asked to create, edit, review, or debug a Lini diagram (a .lini file or its SVG) — architecture/box-and-arrow diagrams, flowcharts, mindmaps, org charts, ER schemas, tables, sequence diagrams, bar/line/area/pie/radar/scatter charts, engineering drawings, floor plans, circuit schematics, or pen-drawn artwork written in the Lini language.

Lini — writing beautiful diagrams

Lini compiles plain text to clean, themeable SVG: composable nodes, a CSS-like cascade, compile-time layout. One core drives every diagram family. This file is self-sufficient for real work; SPEC.md (the full language), ROUTING.md (wire geometry), and samples/ (the showroom — one file per feature cluster) go deeper.

The loop

Write → compile → look at the render → refine. Never ship a diagram you haven't seen.

sh
lini d.lini -o d.svg                 # compile; errors are file:line:col with fixes
lini --check --strict d.lini         # full compile, nothing written; warnings fail — the pre-finish gate
lini fmt d.lini                      # canonical formatting in place (--check: exit 1 if it would change)
lini --static d.lini -o s.svg && resvg s.svg d.png   # rasterize, then READ d.png

--static inlines CSS variables and outlines text — required before resvg (it can't resolve var()). Outlining covers the bundled Latin charset; a run with CJK, Arabic, arrows, or emoji stays <text> and warns (O001) — check the PNG for it. --strict / --no-warn bind every form (SVG, --check, --json diagnostics for tooling). Also: --watch (with -o), --format html, --embed-font (browser-only @font-face), --theme NAME|FILE|light/dark. Exit codes: 0 ok · 1 error (or fmt --check would reformat) · 2 I/O · 3 bad CLI. In this repo the binary is target/release/lini (cargo build --release if missing). lini desugar d.lini prints the lowered form when sugar confuses; lini serve opens a live playground.

A complete file

A file is one optional { } stylesheet, then drawn statements in source order. The stylesheet configures and styles; it draws nothing, and must come first.

{                                          // the stylesheet — setup only
  layout: grid;  columns: repeat(2);  gap: 30;   // scene config (root declarations)
  --brand: #ff6600;                        // a themeable colour variable
  w = 120;  scale(n) = (100 * 1.2^n);      // bindings — baked numbers / functions
  |box| { radius: 6; }                     // a rule: style every box
  |-| { stroke: --gray-deep; }             // a rule: style every link
  .hot { stroke: --red-deep; }             // a class definition
  |svc::box| { fill: --teal-wash; stroke: --teal-ink; }  // a define: new type over a base
  |room::group| { gap: 40; } [             // a define with a BODY: intrinsic children + links,
    |box#in| "in"; |box#out| "out"         //   re-materialised per instance; ids local,
    in -> out "flows"                      //   reachable from outside as `garden.out`
  ]
}

|svc#api| "API"                            // instances — the canvas
|cyl#db| "Postgres" { fill: --rose-wash; }
|room#garden|
api -> db "queries" .hot                   // a link with a label and a worn class
users -> api                               // undeclared id → auto-creates |box#users| "users"
garden.out -> api                          // a dot-path into a body

Every drawn statement is a node (|…|), a text leaf ("…"), or a link (bare name + operator). The full node anatomy — only the bars are required, order fixed — is |type#id| "label" .class1.class2 { key: value; } [ children ]; a link takes the same tail on a different head: a -> b "label" .cls { } [ ].

Syntax laws that bite

  • Declarations end with ; and live only inside { }. A value runs to its ;, so it may span lines. (; optional right before }.)
  • A statement ends at a newline or ; — two nodes on one line need the ;: |topic| "A"; |topic| "B". Bare strings are self-delimiting ("a" "b" is two text leaves). A { } or [ ] may span lines freely.
  • Text is always double-quoted; escapes \" \\ \n \t; leading/trailing spaces are trimmed. A bare word is an identifier (keyword, colour name, id). Single quotes are not strings. String-valued properties (title, hint, href, src) need quotes even for one word.
  • The comma law: commas separate repeated list items, spaces separate the components of one item. data: 9, 15, 24 (three values) · data: 10 20, 30 40 (two x-y points) · padding: 5 2 5 5 (one four-part value: N · v h · t r b l) · gap: 8 0 (row col — flow, grid, sequence alike) · translate: 10 -4.
  • Math needs parens — operators appear only inside (…): padding: (8 * 2); width: (w / 2). A call's own parens count, so an operator inside a call's arguments needs no inner group: move(-tail - 1, -y), right(w / 2), pattern: grid(1, 3, 0, pitch). Calls are bare (width: scale(3)), signed numbers are bare (translate: -35 20). Inside a group: + - * / ^, comparisons, a ? b : c, pi/e, 1e-6, locals (r = 40; 2 * r), a top-level , makes a point, and the math library — sqrt exp ln log abs sin cos tan min max clamp floor round pow. Stylesheet bindings (w = 120; wave(a, f) = (u * 320, a * sin(2 * pi * f * u));) read bare anywhere a value goes — stroke-width: w, move(w, 0), pattern: grid(1, 3, 0, pitch).
  • Parametric geometry: a points: value may be one expression in the ambient clock u (0 → 1), sampled samples: times — |line| { points: (u * 320, 24 * sin(2 * pi * 3 * u)); samples: 64 }, or points: wave(18, 2) from a point-valued binding. Charts bind x the same way (below).
  • A class is worn, never glued into bars: |box| .hot — not |box.hot|. The label comes before classes: |box#a| "A" .hot. First class spaced off the head, further ones glued: .hot.loud.
  • --name variables are visual only (colours, font-family). Sizes, gaps, padding, font-size, letter-spacing, line-spacing, text-transform bake at compile time — literals or bindings, never variables.
  • No coordinate property. Layout places nodes; to place absolutely use pin: center; translate: x y (parent-local coordinates, y grows down) — or layout: stack (below) when the whole scene is hand-placed.
  • No text-align — a text's lines align by its container's horizontal packing knob: justify in a row, align in a column or grid — so align in a card, which stacks. Split intents: wrap text in its own |block| { justify: start; }.
  • id.child paths glue (no spaces): kitchen.bowl. a:left forces a link side. Paths resolve exactly in scope — never searched, never auto-created. An anonymous container is scope-transparent: its children belong to the enclosing scope and no path names it.
  • Comments are // … only. Identifiers are [a-zA-Z_][a-zA-Z0-9_-]*, case-sensitive. Ids may not start with lini-.

Cascade

Five tiers, most specific wins, ties → later wins: type defaults/rules |box| { } → descendant rules |table| |box| { } → class rules .hot { } → id rule #hero { } → the instance's own { } block. Links walk the same ladder via |-| (#g |-| { } styles links written in #g); (-) { } is the dimension subtype and beats |-| { } for dimensions only. Values replace wholesale (no per-component merge). Text properties (font-*, color, spacing, transform) plus clearance/routing/format/thickness also inherit down the tree, nearest ancestor wins — set font-size once on the root and everything scales, captions and link labels included.

Box model & placement

  • Center origin; source order = paint order (later on top; layer: N overrides).
  • Auto-size: box = content + padding each side (default 20 on framed boxes, 0 on |block|). Explicit width/height are floors — content never clips. Empty auto box = 2×padding (40×40).
  • max-width: N wraps text to fit (text-wrap: nowrap forbids); the wrapped size is the measured size.
  • pin lifts a child out of flow onto a parent anchor: center, edges (top …), corners (top left …). A pinned child is an overlay — paints above, never grows the parent.
  • translate: x y nudges any node after placement (layout-neutral); rotate: N turns about the bbox centre. Both work on text too.
  • Flow containers: direction: row | column (default row — source order flows the way it reads; a closed shape's and a |topic|'s children are card content and stack instead, so an icon sits over its label), gap (default 36; 12 in card content; gap: row col), align (cross axis) / justify (main axis): start | center | end | stretch | evenly | origin — no-ops without slack (explicit size or fixed tracks). Inside a drawing/floorplan/stack scope a block that must lay out its own content states layout: flow itself (|room::block| { layout: flow; direction: column; align: center }).
  • Grid: columns required — columns: 80, auto, repeat(3), repeat(5, 80); rows optional; children auto-flow, or cell: col row / span: cols rows (span: 2 = 2 1) on any non-text child (bare text can't carry them — wrap it in |block|). Empty "" holds a grid cell. Per-column alignment: align: start, center, end (one entry per track).
  • gap-fill: colour paints the gutters (gap: 1; gap-fill: --stroke = hairline rules — how |table| works).

Node catalogue

Primitives: |block| (frameless base rect), |oval| (equal sides = circle: |oval| { width: 40 }), |hex|, |slant|, |cyl|, |diamond|, |poly| (points:), |line| (points:, marker*:), |path| (raw SVG path:), |image| (src: + width/height; local files embed; fit: auto | contain | cover | stretch), |icon| (a Phosphor icon), |sketch| (draw: pen — see Drawing). Text is not a node type — a bare "…" is a text leaf; wrap it in |block| when it needs an id, border, padding, or pin.

Templates (all overridable; extend with |name::base| { … }):

TypeWhat it is
|box|the default: rounded framed card (radius 8, padding 20)
|rect|sharp-cornered box
|group|dashed light frame for a captioned region
|caption| · |footnote| · |sheet-caption|small muted title pinned above the top-left corner (a group/table label becomes one) · at the bottom centre · inside the top-left corner (a schematic scope's label lowers to it)
|badge|small accent pill pinned over the top-right corner
|row| / |column| / |grid| / |stack|frameless layout wrappers
|icon| / |sign|Phosphor icon: symbol: bell or the label names the glyph — never both (|icon| "user" is the user glyph, unnamed on the page; a captioned icon is a box wrapping one: |box#cdn| "CDN" [ |icon| { symbol: cloud } ]). |sign| is the 64px standalone preset (fit: contain). Icons paint with fill (body) + stroke (line) — color: does nothing. An icon's [ ] text rides on the symbol as a badge and grows the square: |icon| { symbol: bell } [ "3" ]
|table|ruled grid; first row auto-becomes the header band; cells via bare strings
|entity|ER card: label = centred title, rows = "field" "type" (3 columns for a key gutter)
|note|folded-corner callout card (works in every layout)
|topic| / |mindmap|tree structure node / the full mindmap preset
|chart| / |pie| / |sequence| / |drawing| / |floorplan| / |schematic|layout presets (below)

Shape extras: multiple: N (one offset duplicate behind — "several of these"; N is the offset, not a count), shadow: dx dy blur, stroke-style: solid|dashed|dotted (+ drafting center/phantom on shapes, wavy on links only) — one node, one stroke style: dashed interior geometry is its own child — opacity: 0.75. href: "url" makes anything clickable; hint: "…" adds a tooltip/accessible <title>. A standalone arrow is |line| { points: 0 0, 50 0; marker-end: arrow; }.

a -> b                          // 1 link (labels boxes into existence)
a -> b -> c                     // chain: 2 links, every hop marked
a -> b & c                      // fan-out — shares one trunk at a's side
a & b -> c                      // fan-in
|group#g| [ |box#child| "C" ]
a:right -> g.child:left "label" // forced sides, path endpoint, label
client -> |cyl#db|              // capsule endpoint: declare + link in one statement

Operators are [marker][line][marker], glued. Lines: - solid, -- dashed, --- dotted, ~ wavy. End markers: > arrow, < crow, * dot, <> diamond (mirrored at the start: <-, <->, *-*…). ER cardinality (crow's-foot), end-side forms: -+ one · -< many · -o+ zero-or-one · -+< one-or-many · -o< zero-or-many · -++ exactly one (mirror at the start: >o-o<). The same set by name on marker: / marker-start: / marker-end: (overriding the operator, and the only way on a standalone |line|): arrow dot circle diamond one crow exactly-one zero-or-one one-or-many zero-or-many datum none.

  • Style links like nodes: |-| { stroke: #888; stroke-width: 1.5; } for all, a worn class per link (a -> b .loud), the link's own { } to override. stroke* is the wire; color/font-* the labels.
  • Labels: one inline (a -> b "hi"), several or styled ones in [ ]: a -> b { along: 0.3, 0.7; } [ "near a" "near b" ]. Labels slide to dodge; they never move the wire.
  • Scene config, not link paint: clearance: N (min gap wire↔node; 16 in flow, 10 in a schematic, 18 for dimensions) and routing: orthogonal | natural | straight sit on a container's { } and cascade. orthogonal (default) = right-angle runs, rounded corners; natural = smooth direct curves (the mindmap look — free crossings); straight = one trimmed segment. Per-link routing: is an error.
  • A self-loop a -> a exits right, hooks over the top. Bodies are sealed: a link inside [ ] connects that body's own children; cross-container links go at the lowest scope seeing both ends, via dot-paths. Where a link is written is its routing world: a link between two children of one group routes inside that group only if written in its [ ] — written at root it detours around the group's outside. Keep intra-group wires in the group.
  • An unroutable link draws as a dashed slanted stray and is reported — fix by widening gap, shrinking clearance, or re-siding; nodes never move.

Colour & theming

Every colour is a light-dark() pair — dark mode is automatic; never hardcode hex where a variable fits. Role variables (as values, write the short form): --bg, --fill, --stroke, --stroke-dark (full drafting black — pen geometry, walls, dimension linework), --stroke-light (thin support tone — centrelines, extension lines), --accent, --muted, --danger, --warn. fill: --bg on the root paints the backdrop (default is none — transparent).

The palette is the beauty engine. Eleven hues — red rose orange amber lime green teal sky blue purple gray (aliases yellow→amber pink→rose indigo→purple cyan→teal) — each in five job-named tiers that survive the dark flip: --teal-wash (palest — card/section backgrounds) · --teal-soft (pastel fill, charts) · --teal (everyday pastel) · --teal-deep (strong — borders, strokes, wires) · --teal-ink (deepest — text). The coloured-node recipe is wash fill + ink (or deep) stroke + ink text: { fill: --teal-wash; stroke: --teal-ink; color: --teal-ink; }. red is reserved for danger; rose is the decorative pink. Literal colours: #f80, CSS names, rgb(), hsl(280, 55%, 50%), oklch(0.72, 0.16, 25) (the palette's own space).

Gradients (on fill/stroke/gap-fill): gradient(--rose, --sky) auto-135°, linear-gradient(135, --rose, --sky), radial-gradient(…). hatch(45) / hatch(45, 6, --gray-deep) is the section-line fill texture. Declare your own variables in the stylesheet: --brand: #ff6600; then fill: --brand.

Text: bundled Google Sans (default) and Google Sans Code (mono, via font-family: "Google Sans Code"). font-weight: normal | medium | semibold | bold (or 400–700), font-style: italic, text-decoration: underline | line-through, text-shadow: dx dy blur colour, text-transform: uppercase | lowercase | capitalize, letter-spacing / line-spacing (px). Body default 15/medium; captions and link labels derive from the inherited size, so one root font-size: scales everything.

Themes re-skin at render time — no file edits: --theme takes a builtin (light · dark · high-contrast · blueprint, white linework on cyanotype blue — the diazo print, for any diagram), a CSS file of --lini-* overrides, or a light/dark pair. lini theme NAME prints a builtin as CSS to start your own.

Layout engines

layout: on any container (the root included): flow (default) · grid · stack · tree · sequence · chart · pie · drawing · floorplan · schematic. Everything core — cascade, paint, palette, links syntax — works identically inside each.

Tables & entities
|table#basket| { columns: 80, 140, 80; align: start, center, end; } [
  "Fruit" "Quantity" "Notes"       // first row → header band
  "Apple" "12"       "fresh"
  "Mango" "3" { color: --red-ink }  "ripe"   // a styled cell
]

|entity#users| "Users" { columns: auto, auto, auto; } [
  "PK" "id"    "int"
  ""   "email" "varchar"
]
users -o< orders        // crow's-foot relationship, lands on the card edge

Style cells with |table| |cell| { … }, the header with |table| |header| { … }. A cell needing an id (to wire a field) is written as one: |cell#uid| "user_id" (a |block| there loses the cell inset).

Tree & mindmap

Structure is |topic| nesting inside a layout: tree scope — exactly one root topic; non-topic children are a topic's own content (an icon, a badge). direction: column (org chart, default) · row (outline) · bilateral (mindmap split; per-branch side: left|right overrides). Branch wires are generated; style a whole arm with #branchid |-| { }; size a tier with .lini-level-2 { font-size: 12; }.

|mindmap| "Root" [ |topic#ship| "Shipping" [ |topic| "Weekly train" ] … ] is the preset worth reaching for: bilateral + routing: natural + an automatic hue per first-level branch (wash fill, deep stroke and wires, ink text) + depth-ramped sizes + max-width: 160 wrap. Authored cross-links stay neutral: a.x:right --- b.y:right "relates" { along: 0.8; }.

Sequence

layout: sequence reads links as time: participants across the top (declared, or auto-created on first use), messages top-to-bottom in source order. -> call (opens an activation bar) · --> return (closes it) · ~> async · a -> a self-message. A participant's own paint colours its lifeline and bars.

{ layout: sequence; }
|box#user| "Customer" { fill: --rose-wash; stroke: --rose-deep; } [
  |icon| { symbol: user; fill: none; stroke: --rose-deep; }
]
|box#shop| "Storefront" { fill: --sky-wash; stroke: --sky-deep; }
|cyl#db| "Orders" { fill: --orange-wash; stroke: --orange-deep; }

user -> shop "place order"
|loop| "each item" [
  shop -> db "reserve stock"
  db --> shop "in stock"
]
|note| "rate-limited" { place: over shop db; }

Frames: |loop| / |opt| / |alt| (+ |else| separators) hold their messages in [ ] but open no scope — messages always wire the sequence's participants. gap: row col spaces rows/columns. place: modes: over a (one lifeline), over a b (span), left a / right a (beside). A named actor is a box wrapping an icon (above) — a bare |icon#user| "user" spends its label on the symbol name.

Charts & pie

A chart fixes a shared scale from all children, then draws. Default size 360×220 (width/height set the whole box); radial/pie default 280 square.

|chart| "Cycle time (s)" { categories: "15", "30", "50"; } [
  |bars| "1.8 kW" { data: 9, 15, 24; }
  |bars| "2.3 kW" { data: 7, 13, 20; }
]
  • Series: |bars|, |line|, |area| (baseline: 40 floats the fill off axis zero), |dots| (+ per-node |bubble| { at: x y; value: N; }; |slice| { value: N; } in a pie). Label = legend entry (auto-shown at ≥ 2). Data — one of data: / fn:, never both: categorical data: 9, 15, 24 (must match categories: count) · points data: 0 225, 60 221 · dates data: "2026-01-01" 18, … · formula in x sampled over the domain (samples: count): fn: (min(100, x * 2)), a bare call fn: cure(18), or per-band segments fn: (0.1 + u^2), 5, (2 * u) — one per |band|, each in its local clock u (0 → 1). labels: "a", "b", … per-datum text needs explicit data:.
  • Colour is automatic and good: series walk the palette (interleaved hues, red skipped) in the outlined look — soft fill + deep edge. Only override for meaning: fill: --sky-soft, stroke: --teal. Per-datum highlight on bars/ dots: fill: auto, auto, --red, auto.
  • curve: linear (default) | smooth (monotone, never overshoots) | step; marker: dot|circle|diamond puts a mark at every datum; tooltip: none|hover|auto|always.
  • Axes only when you have something to say: |axis#t| "Speed (mm/s)" { side: bottom; range: 0 133; unit: "%"; scale: log|time; step: 50; } (step: month / 2 week on a time axis; ticks: an explicit list). Bind a series with axis: t. range: 50 1 reverses; gridlines: none or a colour. format: decimal 1 | significant 3 | percent 0 | scientific 2 | engineering 1 | fraction 8 | year|month|day|hour|minute on a scope, axis, series, or dimension — inherits; presentation only, never measurement.
  • Annotations in data space: |band| "Hold" { range: 1.5 4; axis: t; fill: --amber; } shades a region; a |mark| is a reference line (at: V), a labelled point (at: x y), or label-only (marker: none) — style its rule like a wire: |mark| "SLO 250 ms" { at: 250; axis: ms; stroke: --amber-deep; stroke-style: dashed; color: --amber-ink; }.
  • direction: row flips bars horizontal; direction: radial makes radar (lines close into polygons); bars: grouped (default) | stacked | overlay combines bar series. |pie| { hole: 0.5 } is a donut.
Stack (one datum)

layout: stack arranges nothing: every child's origin lands on the container's datum and translate: is the only offset. A symmetric primitive's origin is its centre, so shapes stack concentric; a |sketch|'s is its pen origin, so several sketches keep the frame they were drawn in — which flow throws away. Reach for it for artwork (a logo), a hand-placed figure, or a diagram tuned past what an arranger will do.

{ layout: stack; unit: mm; density: 10; padding: 25; cap = 0.9; bowl = 2.5; }
|sketch#n| { draw: move(0, -3.4) arc(3.4, 3.4, 3.4) down(bowl) arc(cap, 180) up(bowl); mirror: y-axis; }
|sketch#dots| { draw: move(11, -9) down(1) arc(cap, -180) up(1) arc(cap, -180) close(); pattern: grid(1, 3, 0, 3); }

|stack| is the node form. Links go to the router, so arrows and labels behave as in a flow. gap/direction/align/justify are ignored (a root block refuses them). Nested boxes are unaffected: a |box| inside a stack still lays out its own content. Units: unit: px (the default) is 1 : 1; unit: mm plus a root density: (px per mm, default 4) draws in millimetres — density: 10 renders a 24 mm mark 240 px wide. layout: drawing is this engine plus drafting — mates, dimensions, generated chrome. Same placement, so |sketch|, mirror: and pattern: work identically in both; only a drawing draws a fused mirror's centreline.

Show full SKILL.md (2,387 more words)Show less
Drawing (engineering)

layout: drawing places every child's origin on a shared datum (no flow); links become dimensions/leaders; measured values are computed from the geometry — never type a number a dimension can read. No auto-create.

{ layout: drawing; }
|rect#plate| { width: 120; height: 70; } [
  |hole#pin| { width: 10; translate: -35 20; pattern: grid(2, 1, 70, 0); }
  |hidden#bore| { draw: move(-20, -35) down(70); }   // dashed interior geometry
]
plate:left (-) plate:right { side: bottom; }   // → 120
plate:left (-) plate.pin { side: top; }        // → 25
plate.pin (o)                                  // → 2× ⌀10
plate.pin.2 <- "THRU"                          // leader to the 2nd pattern copy
  • Anchors are id{.id}[.index][:point]: :center (default), the four sides, the four corners vertical-word-first (:top-right), or an authored :segment/station. Pattern copies index plate.pin.2; mirror: copies are not addressable.
  • Ops: (-) linear (binary, chains share a row: a (-) b (-) c; a side or edge anchor sets the axis, two point anchors — a corner, a hole — read the aligned diagonal, so add project: horizontal | vertical to read one axis and stack it on a side:) · (o) round (unary: ⌀ for round features, R for named arcs) · (<) angle · leaders <- "text" (arrow) / *- "text" (dot on a face) / >- "A" (datum triangle) — or node-first to a placed annotation: b1 -* housing:boss (a |balloon#b1| "1"), plate.pin <- bore (a |note#bore|) · a:left || b:right { gap: 4 } mates part faces (moves geometry, draws nothing; negative gap = inserted) and also seats an annotation on a face (finish || plate:top, gap: along the normal, translate: the lateral slide).
  • The pen (|sketch| { draw: … }, and it works in any layout): calls run left-to-right — move(x, y) starts a subpath, left/right/up/down(n), line(dx, dy), angle(deg, n), curve(c1x, c1y, c2x, c2y, dx, dy), circle(r), fillet(r) / chamfer(c) between two segments, point() (a station: records the current point, draws nothing — beside a fillet it is the sharp corner), close(). A second move() starts a subpath; fill is even-odd, so an inner one reads as a hole. :name glued to any call — close():west, point():m1 included — names that segment/station for dimensioning (body:neck (o) → ⌀); built-in names (:left…) can't be authored; a duplicate errors. Every argument is an expression (bindings read bare).
  • Coordinates bite: the verbs are visual (up goes up), but move/line/ curve take raw y-down numbers — move(0, -14) is 14 above the origin.
  • Two arcs, and they are not interchangeable. arc(dx, dy, r) is the minor arc to a relative point — r > 0 sweeps clockwise, r < 0 counter-clockwise, |r| ≥ half the chord. arc(r, deg) is a tangent arc: it continues the current heading and sweeps deg (positive = clockwise), updating the heading. Every run, line(), curve(), angle() or arc leaves a heading; a bare move() leaves none — so open a tangent chain with a run or the two-point form. Bearings are up = 0, clockwise (90 right, 180 down).
  • mirror: reflects the node's path and its features about an axis through its origin, then unions the copy — y-axis (left↔right), x-axis (top↔bottom), a bearing, or a list applied left to right, each reflecting the union so far (y-axis, x-axis = 4-fold). An open subpath is fused (draw half, get the whole — both ends must sit on the axis) and generates the axis |centerline| in a drawing; a closed one is duplicated (draw one ear, get both). The default auto reflects iff an ancestor does; mirror: none opts a node and its subtree out.
  • pattern: (any layout) — grid(cols, rows, dx, dy) where the seed is copy one, so grid(1, 3, 0, 20) gives three, not four; radial(count, radius) puts count copies on the circle about the node's position and draws the |pitch-circle|.
  • revolve: x-axis makes a turned part (centerline + shoulder lines auto); |hole| punches and centre-marks itself (thread: 1.25 on it draws the ¾ thread arc). Generated chrome (|centerline|, |pitch-circle|, |breakline|, |shoulder|, |projection|, |threadline|) is styled — or removed — by the cascade: |sketch| |centerline| { stroke: none; fill: none } takes its space back too. Each is also free to author by hand: |centerline| { points: 0 -20, 0 20; }.
  • Dims: side: picks the stacking edge, tol: 0.1 / tol: +0.2 -0.05 / tol: h6 appends tolerance, labels follow (pin (o) "H7") or replace (two-ended) the value; a dimension's [ ] carries annotation nodes (plate:top (-) plate:bottom [ |datum| "C" ]). Scale is three settings: scale: 2 is the drafting ratio (a 2:1 view that still measures true), unit: the physical size of one drawing unit (mm default here, also cm/m/in/px), and root density: the pixels per mm (default 4) — the engine's px-per-unit is their product, never authored. Magnitude is scale:'s job: a 5 m beam on A4 is scale: 0.02. density: lives on the root; unit: and scale: on the drawing / stack scope (the root itself when it is one).
  • Sheets: the root stays flow; views are |drawing| children of a |page|: |page| { sheet: a4; align: origin } [ |drawing#side| "Title" { scale: 2 } [ … ] side.a (-) side.b |title-block| { title: "…"; drawing-number: "…"; revision: "A"; sheet-number: "1/1"; date: "…"; author: "…"; } [ |image| { src: "logo.svg"; cell: 3 3; width: 12; height: 12 } ] ] (authored cells seat after the generated fields; dimensions sit in the view or on the page). Multi-view rows share axes with align: origin, and an unmarked - between anchors in different views (side.screw:head - end.od:top) is the projection construction line — the one legal cross-view link.
  • Deep machinery, a line each: thread: neck 1.25 dresses an ISO thread on a revolved profile — a bare leader on that segment composes M8×1.25; break: -40 40 cuts a long part's boring middle (the view compresses, dims still read the unbroken model). A section / detail is a marker plus a view: |plane#a| "A" { at: 40 } or |magnifier#c| "C" { width: 12 } on the source, a sibling |drawing| { of: a } as the view — its title (A-A (1:1), C (3:1)) composes itself. GD&T: |surface-finish| "Ra 1.6", |feature-control| "position" { tol: 0.05; datums: A B; zone: diameter; material: maximum; modifiers: projected 10 } (+ |control| rows for a composite frame; the ISO 1101 characteristic names validate), |datum| — seat on a face with || or carry in a dimension's [ ]; datum letters come from >- leaders (body:seat >- "A").
Floorplan (architectural)

layout: floorplan is the drawing engine in an architect's vocabulary — same datum, scale:/unit:, anchors and dimensions. Build it in four passes: walls → openings → fixtures → dimensions. Sizes you type are drawing units; every built-in size is true physical mm converted through unit:.

{ layout: floorplan; unit: m; scale: 0.02 }     // 1:50 — 80 px per metre

|wall#outer| {                                  // draw: is the CENTRELINE
  draw: move(0, 0) right(7.2):north down(4.8):east
        left(7.2):south close():west;
} [                                             // openings ride the wall's [ ]
  |window|     { on: north; at: 2.7; width: 1.6 }
  |door#entry| "D1" { on: south; at: 1.05; width: 0.95; swing: right }
  // 'south' runs leftward: 'at' counts from its EAST end, and the pen's left
  // is the outside — 'right' is what opens the door into the flat
]
|partition#bathwall| {                          // ends ON the shell, never across an opening
  draw: move(4.9, 0) down(2.3):face right(2.3):side
} [
  |door| { on: side; at: 0.15; width: 0.8 }     // opens into the bathroom
]

|rect#counter| { width: 0.6; height: 1.4; translate: 6.8 3.2;
                 fill: --bg; stroke: --stroke-dark; stroke-width: 1 }
|bed|    { rotate: 90; translate: 1.15 1.05 }   // head to the west wall
|sofa|   { symbol: two; rotate: 90; translate: 0.6 3.4 }
|dining| { symbol: round; translate: 3.3 3.3 }
|appliance| "F" { symbol: fridge; translate: 6.8 2.8 }
|bath| { symbol: shower; translate: 6.6 0.6 }
|bath| { symbol: toilet; rotate: 90; translate: 5.35 0.5 }   // 0° backs WEST
"STUDIO 27 m²" { translate: 2.2 2.2 }           // room names are plain sheet text

// Clear spans, face to face. 'face' runs south, so its 'out' face is the
// living side's and its 'in' face the bathroom's — read them the other way
// round and each dimension eats the partition.
outer:west-in (-) bathwall:face-out { side: top }   // → 4.75 — the living space
bathwall:face-in (-) outer:east-in { side: top }    // → 2.15 — the bathroom
outer:west-in (-) outer:east-in { side: top }       // → 7 — the shell, clear
outer:north-in (-) outer:south-in { side: right }   // → 4.6
  • Walls. |wall| is a |sketch| whose draw: traces the centreline; thickness: (200 mm default, inherits nearest-wins; authored per wall in drawing units — thickness: 0.4 under unit: m) offsets it into the mitred, solid-filled poché outline that takes the paint. |partition| is the 100 mm interior define. fill: --bg; stroke: --stroke-dark is the hollow double-line look, fill: hatch(45) the section convention. Walls bend with arc(); curve() errors. Draw meeting walls as separate nodes — paint order merges them seamlessly.
  • Openings. A |door| / |window| must sit in its wall's [ ], stationed on: a straight named segment, at: the near jamb's distance from that segment's start (mind the draw direction — a left(...) run measures from its east end). They clip the wall and generate their chrome: hinge: start|end × swing: left|right (left of the pen's travel), symbol: single | double | sliding (a slider takes no hinge:/swing:). translate: on one is an error.
  • Fixtures. Place them against something and leave every door its swing: a fixture floating mid-room, a leaf sweeping a tub, or a body crossing a partition is what makes a plan read as noise. rotate: turns a piece to its wall — a toilet and a sink back west unturned, a sofa backs north, a corner sofa seats a north-west corner; add 90° per quarter-turn clockwise. The families: |bed| (queen·king·double·single) · |sofa| (three·two·one·corner·stool — one is the armchair, stool the ⌀350 bar seat) · |dining| (six·four·round — sized by its tabletop, ⌀1000 for round; the pull-back chairs extend the bbox) · |bath| (tub·shower·toilet·sink·double-sink — the last is one unit, two basins) · |appliance| (stove·fridge·washer·dishwasher) · |stairs| (steps: N ≥ 2 required; no symbol:). width/height are floors that stretch the body. Each fills --bg, so furniture masks the floor under it. Label seats: a fixture's hangs below the body — leave air there; an |appliance|'s centres inside it ("F" / "DW" / "W/D"); an opening's sits beside the gap; each turns upright.
  • Everything else is plain geometry: counters, islands, desks and coffee tables are |rect|s; a balcony deck, a north arrow or a scale bar is a |sketch|; room names and areas are sheet text placed with translate: (a two-line name over its area is a |block| { layout: flow; direction: column }). A casework |rect| takes the core radius: for a softened counter — mind that it is sheet-space pixels, not drawing units (at 1:50 and the default density, radius: 4 is 50 mm).
  • Dimensions anchor on the wall's own named runs, which answer three ways: every named run derives its two face anchors — -in (the enclosed side on a closed run, the left of the pen's travel on an open one) and -out — and the bare :segment is the centreline, where a structural drawing measures. Dimension inside faces, always: a room reads its clear span and the overall the shell's clear interior — what a listing plan publishes. Never a centreline, and never a span that runs through a wall: take the face on the room's own side, so the room clears plus the partitions sum to the overall (2.65 + 0.1 + 4.05 = 6.8). Which face that is follows the run's draw direction, so check it — a partition drawn southward has its -out face to the west. A name of your own ending -in/-out on a wall errors. A named edge's extension line springs from the end nearest the dimension line, so it leaves a corner and runs away from the plan. Mind the axis — an edge dimensions across itself, so a horizontal span names the two vertical runs. An id'd opening anchors at its centre, which makes a location chain (outer:west-in (-) outer.entry (-) outer:east-in) — a setting-out drawing's dimension, not a room's, so reach for it only when that is what the sheet is.
  • The print look is a theme, never authoring: render with --theme blueprint for white-on-cyanotype; a plan's default stays black-on-white.
Schematic

layout: schematic seats parts and lets the router draw square, junction-dotted wires onto pins. 3+-pin parts (and anything with cell:) are anchors on tracks; 1–2-pin parts and labels are satellites seated at the pin their wire touches. The sheet is on a grid — gap is the part pitch (column and row, default 100), and it is the one lever when a long value overhangs the column beside it, since no part's ink ever moves another part. A schematic's columns: is the wrap count (one integer, not a track list) and its cell: col row is ordinal — empty tracks collapse. clearance is 10 (past the pin-pitch 20 it errors). No auto-create — unknown bare ids error.

{ layout: schematic; |vcc::label| { symbol: power } [ "5V" ] }
|component#u1| "AMS1117-3.3" [
  |pin#vin| { side: left; number: 3; }
  |space| { span: 2; }                 // empty rail slots — the datasheet's pin-group gap
  |pin#en| "EN/~SHDN" { side: left; number: 4; }   // label = displayed name (id shows when absent)
  |pin#gnd| { side: bottom; number: 1; }
  |pin#vout| { side: right; number: 2; }
]
|J#j1| "3V3 OUT" { pins: 4; rotate: 180; }
|C#c1| "22u"
|label#tach| "TACH"

u1.vin - |vcc|              // the power-flag capsule, defined above
u1.vout - c1 - |gnd|        // a chain PASSES THROUGH a 2-pin part: series circuit
u1.vout - j1.p3 "3V3"       // net name = the wire's label, set beside the trace
j1.p1 -> "NSTDBY"           // one-ended label wire; the marker sets the tag's shape
u1.en - "EN"                // a plain name is a RUN of trace, not a stop
j1.p2 - tach; tach - j1.p4  // two wires to one declared label merge at its point
  • Parts. Discretes with generated pins: |R| |C| |L| |D| |LED| |Q| |Y| |F| |FB| |SW| |BT| |V| |I| |M| |BZ| |TP| (pins p1 p2, or a k, b c e / g d s by symbol: variant — zener, npn, nfet, polarized…); |opamp| (pins out inp inn, power hidden); |J| (pins: N — one left-facing column); |component| + |pin| for anything else; |gnd|, |nc|, |junction| built in. The id is the reference designator (#R5 reads R5); anonymous parts auto-number (display only — give an id to wire it); prefix: "IC" on a define renames the family. |region::group| { layout: schematic } makes a captioned sub-sheet — tile several on a |page| grid.
  • Pose. rotate: is 90°-step: a satellite auto-poses to face its wire, and a forced turn also sets which way its chain grows (|R| { rotate: 270 } off a side pin stands the chain up); mirror: x-axis | y-axis flips a part about its own axis before the turn — on a |J|, rotate: 180 moves pin 1 to the bottom, mirror: y-axis faces it right with pin 1 still on top; a transistor's collector swaps sides. Text stays upright, bar a net name, which reads along a vertical trace.
  • Wires. Writing a polarised pin mid-chain sets orientation (q1.s - d1.k - |gnd|). A 2-pin part between two placed pins is a bridge (u2.en - r5 - u2.vin). Naming a discrete's pin reserves it first, so u6.fb - r16.p1 beside u6.vout - r15 - r16.p1 - |gnd| taps between the resistors. A name on a pin another statement wires rides that wire as its net label. :side on any terminal is an error.
  • Labels. shape: plain (default, no outline) | left | right | both | round; symbol: gnd | earth | chassis | power | nc | antenna (text beside it; symbol + text = power flag, define it once as above). A plain run's width: N lengthens the trace it names, side: picks its flank. The classic look (green wires, yellow bodies, beige sheet) is automatic.

Making it beautiful

The defaults are designed — a plain file already reads well. Beauty is mostly restraint plus a few deliberate moves:

  1. Colour by meaning. One hue per subsystem / branch / state, in the wash + ink recipe. Two or three hues, not seven. Define the pairing once as a define or class and instantiate — never repeat paint per node.
  2. Name regions with |group| + its caption label (|group#edge| "Edge" { gap: 20; } [ … ]). Groups organize; boxes state.
  3. Refined over heavy: keep strokes thin (1.5–2), body text normal/medium; save bold and strong colour for titles, one hero node, a |badge|. One gradient per scene at most (fill: gradient(--sky, --purple); stroke: none; color: white on the hero).
  4. Let the engines work. Don't hand-place what flow/grid/tree can lay out; reach for pin+translate only for free-form canvases (ER graphs) and overlays, stack for artwork. Force :side sparingly — reorder declarations first. Charts: accept the palette walk unless colour has meaning.
  5. Meaning in line style: solid = sync/primary, --> dashed = return/ cache/secondary, ~> wavy = async/event. Encode it as classes (.async { stroke: --amber-deep; }) so the legend lives in one place.
  6. Air: root padding: 24–30; group gap 20–28; don't shrink the default 36 scene gap without reason. max-width on prose-y labels (~160–200).
  7. hint: on dense nodes, href: where a diagram lands in a doc, |icon|s for recognition. Set root fill: --bg only when a backdrop plate is wanted.

When the compiler complains

Errors carry did-you-mean suggestions — read them, they're usually exact. The ones whose fix is not in the message:

SymptomFix
text content takes no '[ ]' / 'pin' needs a box / 'cell' places a grid childwrap the string in |block|
'routing' is a scope's strategyset routing: on the container, not the link
link endpoint not foundpaths never auto-create; declare it or fix the path (the error lists candidates)
impossible (a -> b): no legal route: …a stray — drawn as a slanted dashed line, a warning unless --strict. Widen gap, drop a forced :side, move the link into the group whose children it joins, or lower clearance (a schematic already sits at 10)
no bundled glyph for '你' …--static kept that run as <text>; fine in a browser, boxes in resvg
a tangent arc() right after move()no heading yet — open with a run or arc(dx, dy, r)

Warnings matter too (--check --strict before finishing): near-miss ids (cta vs cat), split label blocks, never-worn classes, strays.

© monfa-red, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 575 other files (assets) in the repository root of monfa-red/lini.

  • SKILL.md
  • .cargo/config.toml
  • .github/ISSUE_TEMPLATE/bug_report.yml
  • .github/ISSUE_TEMPLATE/config.yml
  • .github/ISSUE_TEMPLATE/feature_request.yml
  • .github/pull_request_template.md
  • .github/workflows/ci.yml
  • .gitignore
  • AGENTS.md
  • CLAUDE.md
  • Cargo.lock
  • Cargo.toml
  • LICENSE
  • LICENSES/google-sans
  • LICENSES/google-sans-code
  • LICENSES/phosphor
  • … and 560 more

Open the folder on GitHubat commit 0502d38

Compare with similar skills

Lini next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Lini compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Lini this skillmonfa-red/lini137—~11kAutomated safety check: PassMIT
Deepwiki Rssopaco/deepwiki-rs3.1k—~748Automated safety check: PassMIT
Generating Documentationancoleman/ai-design-components525—~3kAutomated safety check: PassMIT
Mermaid Graph Renderercuriositech/some_claude_skills244—~2.5kAutomated safety check: NotesMIT
Archify Diagramstt-a1i/archify81k—~2.9kAutomated safety check: PassMIT
JSON Canvasheyitsnoah/claudesidian2.6k18 repos~3.5kAutomated safety check: PassMIT

Similar skills

  • Deepwiki Rs

    sopaco/deepwiki-rs

    AI-powered Rust documentation generation engine for comprehensive codebase analysis, C4 architecture diagrams, and automated technical documentation.

    3.1k GitHub stars~748 tokensUpdated 25 days ago
    DevelopmentAuto-check passed
  • Generating Documentation

    ancoleman/ai-design-components

    Generate comprehensive technical documentation including API docs (OpenAPI/Swagger), code documentation (TypeDoc/Sphinx), documentation sites (Docusaurus/MkDocs), Architecture Decision Records…

    525 GitHub stars~3k tokensUpdated 10 mo ago
    DevelopmentAuto-check passed
  • Mermaid Graph Renderer

    curiositech/some_claude_skills

    Renders Mermaid diagrams to SVG, PNG, and PDF in both web and offline contexts.

    244 GitHub stars~2.5k tokensUpdated 1 mo ago
    DevelopmentAuto-check: notes
  • Archify Diagrams

    tt-a1i/archify

    Creates interactive architecture, workflow, sequence, data-flow and lifecycle diagrams as standalone HTML with inline SVG, themes and image or video export.

    81k GitHub stars~2.9k tokensUpdated today
    DevelopmentAuto-check passed
  • JSON Canvas

    heyitsnoah/claudesidian

    Create and edit JSON Canvas files (.canvas) with nodes, edges, groups, and connections.

    2.6k GitHub starsUsed in 18 repos~3.5k tokens
    DevelopmentAuto-check passed
  • Diagram Design

    cathrynlavery/diagram-design

    Creates branded diagrams, from architecture, flowchart and sequence to charts and maps, as self-contained HTML with inline SVG, with import from draw.io, Mermaid and Excalidraw.

    48k GitHub starsUsed in 1 repo~7.6k tokens
    DevelopmentAuto-check passed

Works with

Categories

Questions about Lini

What does Lini do?

A skill your agent uses when asked to create, edit, review, or debug a Lini diagram (a .lini file or its SVG) — architecture/box-and-arrow diagrams, flowcharts, mindmaps, org charts, ER schemas…. Lini is an agent skill from monfa-red/lini.lini file or its SVG) — architecture/box-and-arrow diagrams, flowcharts, mindmaps, org charts, ER schemas, tables, sequence diagrams, bar/line/area/pie/radar/scatter charts, engineering drawings, floor plans, circuit schematics, or pen-drawn artwork written in the Lini language.

When should I use Lini?

Lini fits situations like: asked to create; debug a Lini diagram (a .lini file; its SVG) — architecture/box-and-arrow diagrams; sequence diagrams.

How do I install Lini in Claude Code?

Run `npx skills add monfa-red/lini --skill lini -a claude-code`. Or copy the skill folder (the monfa-red/lini repository) into .claude/skills/lini in your project. Claude Code loads it when a task matches its description.

How do I install Lini in Codex?

Run `npx skills add monfa-red/lini --skill lini -a codex`. Or copy the skill folder (the monfa-red/lini repository) into .agents/skills/lini in your project. Codex loads it when a task matches its description.

Can I use Lini in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add monfa-red/lini --skill lini -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/lini, .gemini/skills/lini, .github/skills/lini and .opencode/skills/lini in your project.

What does Lini need to run?

Going by SKILL.md and its folder, Lini needs the command-line tools its instructions call (cargo).

Does Lini access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Lini safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Lini use?

Lini is published under the MIT licence (from the LICENSE file in the skill folder). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Lini use?

About 11k tokens (SKILL.md is roughly 44k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Lini?

Skills that share tags, products or a category with Lini: Deepwiki Rs (sopaco/deepwiki-rs, 3.1k stars), Generating Documentation (ancoleman/ai-design-components, 525 stars), Mermaid Graph Renderer (curiositech/some_claude_skills, 244 stars) and Archify Diagrams (tt-a1i/archify, 81k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Lini?

monfa-red (a GitHub user) maintains it in monfa-red/lini, which has 137 GitHub stars. The repository was last updated on October 9, 2026.

Source: monfa-red/lini on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.