Skillwire

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.

Install

Windows · PowerShell
irm https://skillwire.ccisne.dev/install.ps1 | iex
Linux · bash
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
the first thing worth running

One capability, five destinations

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.

Every parameter is required

--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
skillwire_cli 0.1.0 — captured 2026-08-27, unedited

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.

Every path says where it came from

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.

HostGlobalRepositoryRead fromOn
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.

Five rules, and no exceptions

  1. Never destroy what the acting consumer did not deploy.
  2. Never act implicitly — no default host, scope, or artifact set.
  3. Never bypass --plan / --apply.
  4. Never let reconciliation touch the filesystem; it is a pure function.
  5. Never present an unverified path as a fact.

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.

Mount it in your own CLI

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
What to add
lib/my_cli.dart
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.