-
Notifications
You must be signed in to change notification settings - Fork 0
Ports
Taking the theme into an editor, terminal, native toolkit or any application with its own theme format. For port authors and for anyone deciding whether a target is supported.
Current state: no native ports are published. The capability explorer publishes an empty catalogue, and an empty catalogue means exactly that — no application support, not "support is implied". The owner's historical gedit scheme, IntelliJ scheme, tmux colours and browser-extension colours are catalogued in references/catalogue.json as evidence of where the palette came from. They are not supported downloads.
Contents: What a port is · Must reproduce · Fallbacks · Mapping vocabulary · Statuses · Anatomy · Starting one · Terminals
A port themes only what the host documents as customisable. Editor colouring, application chrome, terminal colours and plugin surfaces are separate scopes: a file that changes one does not get to claim the others.
A port never patches binaries, injects unsupported hacks, overwrites a user's whole settings file, or touches keybindings, credentials or unrelated preferences. It installs under a unique name beside the host's defaults, and it documents how to roll back.
- The surface ladder: canvas, default, raised, overlay, input.
- The text ladder: default, bright, prose, muted, subtle, disabled.
- Focus as a ring distinct from selection as a fill, with the ring recoloured on fills.
- Selection, inactive selection and hover as three distinguishable fills.
- The status hues with their glyphs, where the host renders glyphs.
- Zero radii and 1px borders where the host allows geometry; otherwise a recorded deviation.
- The monospace family by name, honouring the user's size.
Every required role must end up in exactly one of four buckets: mapped, explicitly inherited from the host, marked unsupported with an explanation, or intentionally out of scope. Nothing is left unaccounted for — and a coverage percentage means nothing without its denominator.
Answers for the cases that come up first, from spec/portability.md:
| The host… | Do this |
|---|---|
| has no dashed outlines (many native toolkits) | solid 1px ring in focus.ring; record the deviation |
| has no separate inactive selection | use the selection fill everywhere; record it |
| has no read-only styling hook | treat as default text with a dotted bottom edge if borders are available, otherwise as default |
| has no pattern fills for charts | keep the glyph or label channel; never colour alone |
| is a sixteen-colour terminal |
heritage-ansi for fidelity, or the extended slots once approved; document bold-as-bright and whether 256/24-bit colours bypass the slots |
| has fixed radii | document it; do not fight the toolkit |
| forbids removing its own focus indicator | keep the host's indicator; never draw two |
The explorer and exports/port-capabilities.json distinguish five states, and they are not interchangeable:
| Label | Means |
|---|---|
| Mapped | The role has a named destination in the target |
| Inherited | The target keeps its own value or behaviour, deliberately |
| Unsupported | The target cannot provide this within the recorded scope |
| Out of scope | Deliberately left outside this port |
| Not implemented | Not built |
A legacy unmapped role keeps its stated reason rather than being assigned a guessed classification. mapping.json must list every role in the declared profile exactly once, across mappings and unmapped.
| Status | Means |
|---|---|
experimental |
Artifacts exist and checks pass; real-target verification is incomplete |
verified |
Imported into the recorded target, with matching evidence and a current token digest |
deprecated |
Kept, with a reason |
verified is expensive on purpose. A parse success is a structural pass, not verification. A list of mappings is not verification. An experimental label is not verification. To mark a record verified, all of this must hold at once: the evidence subject digest still matches, the manifest declares verified, the target and tested versions include the recorded version, the recorded platform is a declared target, and every recorded check actually passed. Changing targets, mappings, capabilities or artifact bytes invalidates the evidence; a stale artifact token digest hides the resolved values it claimed.
If the catalogue has no verified port for your target, that is an honest gap. Treat it as one.
A port is created under ports/<slug>/ only when implementation work begins, from templates/port/:
| File | Contents |
|---|---|
port.json |
The manifest: target, versions, status, declared surfaces |
mapping.json |
Theme role → native keys, plus every unmapped role with a reason (schema version 1) |
capabilities.json |
Optional detail: integration kind, a full theme revision, surface states and reasons, each role's mapping state and surface, rollback instructions |
src/ |
Generator inputs |
dist/ |
The committed importable files |
evidence/ |
Real captures — application version, OS, date — and the optional import-evidence protocol |
Each classification in capabilities.json must agree with mapping.json and belong to a supported surface; inherited, unsupported, out-of-scope and not-implemented roles must stay unmapped. Without that file the older mapping contract still applies, but the explorer will report unclassified unmapped roles and missing pins.
The generator writes exports/port-capabilities.json, which is digest-covered and included in task kits. Consumers fetch it at their own pinned revision. Full rules: ports/README.md.
- Read
spec/portability.mdandports/README.md. - Copy
templates/port/toports/<slug>/and work throughCHECKLIST.md. - Inspect the target first. Write down which surfaces it can express before you map anything.
- Map roles to native keys using resolved token values only. Never invent an approximation for something the host cannot do — that is an
unsupportedentry. - Account for every role in the declared profile.
- Ship as
experimental. Only a real import with matching evidence earnsverified. - Document installation, scope and rollback for a user who wants to undo it.
For web frameworks rather than native applications, the equivalent work is in Web integration.
Where a target cannot be redistributed, the bounded private-parity harness runs entirely outside this repository against an operator-supplied config:
npm run parity:private -- --config /private/location/parity.jsonWithout a target it prints a not run prerequisite record — public validation, builds and browser tests never require a private target. The harness validates installed versions against the target package and lock, copies only explicitly selected inputs into a new private directory, and captures native references and real framework controls with recorded environment, input hashes, property differences and screenshots. It never starts the target's backend or runs its package scripts. Private sources, configuration and results stay out of Git and off the public site — including when verification fails. A completed diagnostic may report differences; it does not certify an application port.
A sixteen-colour terminal is the one target where the heritage-ansi profile earns its keep: it holds the historical slots exactly, including the assignments that fail the contrast floor. Use it for fidelity to the original workstation, and be explicit that you are doing so. It is not an approved profile for a new interface, and values that fail are flagged $deprecated rather than presented as ordinary passes.
Document bold-as-bright behaviour and whether the application's 256-colour or 24-bit output bypasses the slots entirely — otherwise the port claims a fidelity it does not have.
Next: Verification · Concepts · Contributing
Wiki home · Agent workflow · Portal · Vue demo · v1.1.0 release
This handbook explains consumption of v1.1.0. The pinned repository's tokens, specification, implementation contracts and evidence remain authoritative. The live site may advance; keep your application's pin explicit. Preserve the material's license notices.