skillferry
Your agent workflow, portable across tools and machines.
skillferry turns one versioned, Git-friendly workspace — skills, global instructions, and non-secret MCP connection templates — into the native configurations of Codex, Claude Code, and DeepSeek Harness, on macOS, Windows, and Linux. It never copies credentials or runtime state, and it tells you honestly, per asset, how portable that asset is.
Sync capabilities, not credentials. · Write skills once. Run them across agents. · Your agent capabilities should not be locked inside one client.
Table of contents
- 30-second demo
- Before / after
- Quick start
- Compatibility matrix
- Security boundary
- Workspace layout
- Not a dotfiles / symlink / GUI tool
- Adapter development
- Migrating from codex-profile-sync
- Documentation map
- Roadmap
- License
30-second demo
$ skillferry import --from codex --output ~/workspaces/demo # 1. two skills + one MCP server
$ export GITHUB_PERSONAL_ACCESS_TOKEN=... # 2. token lives on this machine only
$ skillferry plan --workspace ~/workspaces/demo # 3. grades for all three agents
SKILL release-checklist
codex native
claude native
dsh native
MCP github
codex translated secret resolved from local env
claude translated secret resolved from local env
dsh translated inserted as dsh-mcp-client entries in the profile cordis.patch.yml
$ skillferry apply --workspace ~/workspaces/demo # 4. one workspace, three agents
$ skillferry doctor --workspace ~/workspaces/demo # 5. zero drift
$ skillferry export --shareable ~/workspaces/public # proof: no secrets, ever
Exported 15 file(s). No secret references were expanded.
The five-beat flow — import, secret references, per-target grades, apply,
secret-free export — is rehearsed in CI by the test suite (see
tests/test_plan_apply.py, tests/test_importers.py,
tests/test_export_audit.py) and was accepted natively on macOS in
docs/acceptance/macos-native.md.
Before / after
| Before | After |
|---|---|
| Re-author the same skills, rules, and MCP configs per tool, per machine | One workspace.toml + assets, git pull, skillferry apply |
| Tokens copied into configs that end up in Git | secret:env/NAME references; each machine supplies real values locally |
| "Sync succeeded" with no idea what was lost in translation | plan prints native / translated / degraded / manual / unsupported per asset with loss notes |
| Sync tools silently overwrite hand edits | Per-path hash ledger: local modifications become conflicts (exit 3), never silent overwrites |
Why this matters to real users: cross-machine skill/config loss is one of the most-requested fixes in the official trackers (claude-code #36693, #69231, codex #26691), and the MCP client-configuration split is an open standardization pain point (SEP-2633, MCP IG #2761).
Quick start
$ pipx install skillferry
$ skillferry init my-workspace && cd my-workspace
# add skills/**, edit instructions/global.md and mcp/servers.toml
$ skillferry plan # read every grade and conflict first
$ skillferry apply # backs up, writes only owned paths
$ skillferry doctor # exit 0 = in sync
plan and apply are dry-run-safe by design: plan never writes, and
apply refuses to run when any conflict exists. Exit codes: 0 in sync,
1 error, 2 safe drift, 3 conflict needs a human decision
(--resolve <id>=adopt|overwrite|keep-local).
Compatibility matrix
Grades are produced by each adapter from an evidence-backed capability table
(docs/AGENT_MATRIX.md); nothing is labeled native
without a verified loading path.
| Asset | Codex | Claude Code | DeepSeek Harness |
|---|---|---|---|
| Skills (SKILL.md dirs) | native — ~/.agents/skills/ |
native — ~/.claude/skills/ (docs) |
native — ~/.agents/skills/ |
| Global rules | native — marker blocks in ~/.codex/AGENTS.md |
translated — marker blocks in ~/.claude/CLAUDE.md |
native — marker blocks in $DSH_HOME/AGENTS.md |
| MCP (stdio) | translated — [mcp_servers.<name>] in ~/.codex/config.toml; secrets resolved from local env |
translated — user-level ~/.claude.json mcpServers (docs) |
translated — dsh-mcp-client entries in the profile cordis.patch.yml |
| MCP (http/sse) | manual (per-target instructions printed) |
manual |
manual |
| Extensions/plugins | manual — declared expected state, never auto-installed |
manual |
manual |
What the grades mean
plan grades are a promise about loading: native loads in the target's
own format with nothing lost; translated works after a transformation the
notes name; degraded works with known limits or unverified behavior;
manual prints instructions instead of writing; unsupported does not
apply. The full contract — merge order, conflicts, and exit codes — is in
docs/PORTABILITY_CONTRACT.md.
Security boundary
The security model is architecture, not documentation. See docs/THREAT_MODEL.md; machine-verifiable highlights:
- The workspace schema rejects literal secrets: MCP
envvalues must besecret:env/NAMEorsecret:file/PATHreferences (src/skillferry/workspace.py, negative tests intests/test_workspace.py). export --shareablescans every copied file and refuses to export on any credential-shaped content; it never expands a reference (src/skillferry/secrets.py,tests/test_export_audit.py).- Backups are raw (0600, local-only, for exact rollback) plus redacted
copies for human inspection (
src/skillferry/io_ops.py,test_backups_redact_secrets). - JSON reports and logs contain references, never resolved values
(
test_env_secret_lands_only_in_local_config). [protect]declares what a workspace may never manage (auth, sessions, sqlite, caches, embedded servers); mis-declarations fail at schema level.scripts/audit_public_tree.pyfails CI when the public tree contains credential patterns, machine paths, or runtime filenames.
Workspace layout
# workspace.toml — target-neutral by construction
schema_version = 1
[skills] directory = "skills"
default_targets = ["codex", "claude", "dsh"]
[instructions] common = "instructions/global.md" # marker | copy | include
[mcp] registry = "mcp/servers.toml" # env: secret refs only
[extensions] manifest = "extensions/manifest.toml"
[overlays] platform_dir / target_dir / host_dir # base < target < platform < host < local
[protect] paths = [] # never-manage declarations
A complete runnable example ships in
examples/starter-workspace (validated in CI),
together with two seed skills: setup-skillferry and release-checklist.
Merge order is base < target < platform < host < local override; lists
replace wholesale and dicts deep-merge, every value's origin is visible to
plan, and conflicts are never silent
(docs/PORTABILITY_CONTRACT.md).
Not a dotfiles / symlink / GUI tool
skillferry is deliberately a headless CLI. It is not a full-dotfiles synchronizer (it manages only declared, structured assets), it never creates symlinks or Windows junction/reparse points (the schema rejects them), it ships no GUI, it does not switch API providers, sync sessions/history, or "losslessly convert any plugin". The honest comparison with the existing landscape, including what we can and cannot claim about competitors, is in docs/COMPARISON.md.
Adapter development
Adding a target is bounded: implement adapters/base.py's interface (where
each asset lands, the capability-backed grades, and the MCP rendering) and
register it in adapters/registry.py. See
docs/AGENT_MATRIX.md for the evidence bar each grade
must meet.
Migrating from codex-profile-sync
skillferry migrate --from codex-profile-sync <bundle> --output <dir> converts
the legacy bundle's skills and MCP declarations into a draft workspace
(credential values become secret:env/... references; the bundle is never
modified). Details in docs/MIGRATION.md.
Documentation map
The docs/ tree is indexed by docs/README.md. For your role, start with:
| Role | Start with |
|---|---|
| Everyone | docs/PORTABILITY_CONTRACT.md — grades, merge order, conflicts, exit codes |
| Security review | docs/THREAT_MODEL.md + SECURITY.md |
| Contributors | CONTRIBUTING.md + docs/AGENT_MATRIX.md |
| Comparing alternatives | docs/COMPARISON.md |
| Legacy migration | docs/MIGRATION.md |
| Evidence records | docs/acceptance/macos-native.md · docs/acceptance/windows-native.md |
Chinese translations: README.zh-CN.md is the entry point, core documents live in docs/zh-CN/. Release history: CHANGELOG.md.
Roadmap
- A (this release): the portable core — skills/rules/MCP rendering, grades, ownership ledger, import/export/migrate, CI on 3 OS × Python 3.11–3.13.
- B: Gemini CLI adapter (first v1.x target),
lockfile/provenance records. - C: team layer (
scope/teamoverlays), SSH/remote targets. - D: reference implementations as the SKILL.md/mcp.json standards converge.
License
Apache-2.0. See LICENSE.
Metadata
Release files for skillferry 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| skillferry-0.1.0.tar.gz | 97.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| skillferry-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 165.2 kB
Release files / skillferry-0.1.0.tar.gz
| Download URL | skillferry-0.1.0.tar.gz |
|---|---|
| Size | 97.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9013fbb8e60577dc78ad2545de00cd72da26cedb200b8d1e95eff06adc2913f6
|
|
BLAKE2b-256 checksum How to use checksums |
4b3fb283c6746245a6cd53e871b8d3bd837616ab67f426529fd71fc6d855a542
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.
Transparency logRelease files / skillferry-0.1.0-py3-none-any.whl
| Download URL | skillferry-0.1.0-py3-none-any.whl |
|---|---|
| Size | 67.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3c960615f7422df14c5908bf93ca4ca5d3b32f8777613953d8868f961897807b
|
|
BLAKE2b-256 checksum How to use checksums |
eb4ab5aee4acc10e4b649f1890e0cb3e8e4fb428a745ac5c4393d3c4a2b987af
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.
Transparency log