The layer that lets an AI coding host execute capabilities it was never trained on.
A command line, and the two Dart packages underneath it — skillwire 0.2.0 and datajack 0.1.0 on pub.dev. Use the CLI, or mount the same module in your own.
irm https://skillwire.ccisne.dev/install.ps1 | iex
curl -fsSL https://skillwire.ccisne.dev/install.sh | bash
Both fetch the latest release, unpack it into %LOCALAPPDATA%\skillwire or ~/.skillwire, add it to your PATH and create the
sw alias. There is no macOS build yet.
Read them before you run them — install.ps1, install.sh. Piping a script from the internet into a shell is worth that minute, here as anywhere.
Then, from anywhere:
$ skillwire skill list --host claude --scope global --all
A skill is standardised: a directory holding a SKILL.md, the same everywhere. A subagent is not. Every host wants a different path
and a different file format, and hooks are worse — in some hosts they have no destination at all.
The skillwire package absorbs the difference. A capability is defined once, and the package resolves where it must land and in what shape for each host it is asked about.
There is no implicit host, no implicit scope and no implicit “everything”. Each omission is answered by naming what is missing, not by choosing on the reader’s behalf.
$ skillwire skill list
Error: --host is required and has no default (R12.2). [missing_parameter]
$ skillwire skill list --host claude --scope global
Error: --skill, --module or --all is required and has no default (R12.2). [missing_parameter]
$ skillwire skill list --host claude --scope global --all
name version module kind host scope status also visible from
-------- ------- ------ ----- ------ ------ ------ -----------------
kritik 1.0.0 core skill claude global keep opencode
legion 1.0.0 core skill claude global keep opencode
research 1.0.0 core skill claude global keep opencode
The last column is the part no host will tell you. OpenCode reads Claude Code’s directory, so a skill deployed for one is answering for both — and the two cannot hold different variants of it at global scope.
Nothing is written without being described first, and the description is not a flag you may forget:
$ skillwire skill deploy --host claude --scope global --all
Error: Choose --plan or --apply.
--plan show what would change; nothing is touched
--apply show it, ask for approval, then do it
A host’s directories change, and a table that cannot say when it was last checked is a guess wearing a table’s clothes. Each row below carries the artifact it was read from and the date. A row without one does not resolve — it throws.
| Host | Global | Repository | Read from | On |
|---|---|---|---|---|
| Claude Code | ~/.claude/skills |
.claude/skills |
Anthropic documentation | 2026-08-26 |
| Codex | $CODEX_HOME/skills |
.agents/skills |
codex.exe 0.146.0, and OpenAI documentation | 2026-08-26 |
| Antigravity | ~/.gemini/config/skills |
.agents/skills |
Antigravity’s own bundled skill, agy-customizations | 2026-08-26 |
| OpenCode | ~/.config/opencode/skills |
.opencode/skills |
opencode.exe 1.17.10, brace glob {skill,skills} | 2026-08-26 |
| GitHub Copilot | ~/.copilot/skills |
.github/skills |
GitHub documentation | 2026-08-23 |
Two of these were wrong when they were first written down, and reading the hosts themselves is what found it: Antigravity’s roots were both incorrect, and OpenCode turned out to read both spellings of its own directory.
Rule 4 is the one that is mechanically enforced. Reconciliation is a pure function of what was observed, what is desired and what the ledger recorded, and a test greps the package to prove no file under it imports
dart:io — because that is the layer where a bug destroys work somebody else did.
The skillwire package is the domain and depends on no CLI framework. datajack
is the command-line surface over it: five routes, their parameters, and their exit codes. Adding it gives your CLI a
skill module that ships your skills, not somebody else’s.
$ dart pub add datajack
import 'package:datajack/datajack.dart';
import 'package:modular_cli_sdk/modular_cli_sdk.dart';
import 'package:skillwire/skillwire.dart';
final ws = Workspace.detect();
ModularCli().module(
'skill',
(m) => buildSkillModule(
m,
// Written into every ledger row this CLI creates, and the reason
// another consumer can tell your artifacts from its own.
consumer: 'my_cli',
workspace: ws,
catalogue: Catalogue.read(
ws.assetsRoot,
validator: SkillValidator(reservedNames: ws.matrix.reservedNames),
),
),
);
All three consumers — the reference CLI, macss and inquiry — mount this same module against one ledger per machine, which is what lets each of them refuse to touch what another one deployed.