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.
Both scripts are worth a minute before you run them: install.ps1, install.sh.
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.
--host, --scope, and one of --skill, --module or
--all. A missing one is named.
$ 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
OpenCode reads Claude Code’s directory. A skill deployed for one answers for both, so at global scope they hold the same variant. The last column says which hosts share a directory.
Every command takes --plan or --apply.
A host’s directories change. Each row carries the artifact it was read from and the date it was read. A row without them 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 |
Reading the hosts themselves corrected two rows: Antigravity’s roots were both wrong, and OpenCode reads two 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.
$ 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.