skillporter 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. skillporter-2.0.0/LICENSE +21 -0
  2. skillporter-2.0.0/PKG-INFO +258 -0
  3. skillporter-2.0.0/README.md +230 -0
  4. skillporter-2.0.0/pyproject.toml +68 -0
  5. skillporter-2.0.0/setup.cfg +4 -0
  6. skillporter-2.0.0/skillporter/__init__.py +16 -0
  7. skillporter-2.0.0/skillporter/__main__.py +4 -0
  8. skillporter-2.0.0/skillporter/atomic.py +55 -0
  9. skillporter-2.0.0/skillporter/cli.py +1288 -0
  10. skillporter-2.0.0/skillporter/diagnose.py +303 -0
  11. skillporter-2.0.0/skillporter/formats.py +168 -0
  12. skillporter-2.0.0/skillporter/frontmatter.py +242 -0
  13. skillporter-2.0.0/skillporter/harnesses.py +934 -0
  14. skillporter-2.0.0/skillporter/install.py +413 -0
  15. skillporter-2.0.0/skillporter/manifest.py +325 -0
  16. skillporter-2.0.0/skillporter/mcp_server.py +267 -0
  17. skillporter-2.0.0/skillporter/py.typed +0 -0
  18. skillporter-2.0.0/skillporter/registry.py +301 -0
  19. skillporter-2.0.0/skillporter/security.py +350 -0
  20. skillporter-2.0.0/skillporter/sources.py +361 -0
  21. skillporter-2.0.0/skillporter/state.py +261 -0
  22. skillporter-2.0.0/skillporter/ui.py +49 -0
  23. skillporter-2.0.0/skillporter.egg-info/PKG-INFO +258 -0
  24. skillporter-2.0.0/skillporter.egg-info/SOURCES.txt +31 -0
  25. skillporter-2.0.0/skillporter.egg-info/dependency_links.txt +1 -0
  26. skillporter-2.0.0/skillporter.egg-info/entry_points.txt +2 -0
  27. skillporter-2.0.0/skillporter.egg-info/requires.txt +4 -0
  28. skillporter-2.0.0/skillporter.egg-info/top_level.txt +1 -0
  29. skillporter-2.0.0/tests/test_archive_security.py +174 -0
  30. skillporter-2.0.0/tests/test_atomic_writes.py +144 -0
  31. skillporter-2.0.0/tests/test_regressions.py +65 -0
  32. skillporter-2.0.0/tests/test_skillporter.py +319 -0
  33. skillporter-2.0.0/tests/test_v2_ecosystem.py +619 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shanmukh Dheekonda
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,258 @@
1
+ Metadata-Version: 2.4
2
+ Name: skillporter
3
+ Version: 2.0.0
4
+ Summary: ONE SKILL. EVERY AGENT. Universal package manager, validator, security scanner, and synchronizer for AI-agent skills across 19+ harnesses.
5
+ Author: Shanmukh Dheekonda
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Shanmukh-l33t/skillporter
8
+ Project-URL: Issues, https://github.com/Shanmukh-l33t/skillporter/issues
9
+ Project-URL: Changelog, https://github.com/Shanmukh-l33t/skillporter/blob/main/CHANGELOG.md
10
+ Keywords: agent-skills,claude-code,codex,cursor,windsurf,github-copilot,gemini-cli,hermes,openclaw,openhands,goose,mcp,developer-tools
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Topic :: Software Development :: Build Tools
19
+ Classifier: Topic :: Software Development :: Quality Assurance
20
+ Classifier: Topic :: Security
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=7; extra == "dev"
26
+ Requires-Dist: ruff>=0.6; extra == "dev"
27
+ Dynamic: license-file
28
+
29
+ # SKILLPORTER
30
+
31
+ ## ONE SKILL. EVERY AGENT.
32
+
33
+ **Install, manage, validate, security-scan, and synchronize AI-agent skills across the entire agent ecosystem.**
34
+
35
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org/)
36
+ [![Harnesses: 19 Verified](https://img.shields.io/badge/harnesses-19%20supported-00b4d8)](docs/harnesses/README.md)
37
+ [![Tests: 60 Passing](https://img.shields.io/badge/tests-60%20passing-brightgreen)](tests/)
38
+ [![Zero Dependencies](https://img.shields.io/badge/dependencies-0-success)](pyproject.toml)
39
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
40
+
41
+ <p align="center">
42
+ <img src="docs/assets/demo.svg" alt="Skillporter Terminal Demonstration" width="860" />
43
+ </p>
44
+
45
+ Every AI coding and autonomous agent harness reads skills from a **different directory**:
46
+
47
+ | Harness | Project Path | Personal / Global Path | Support |
48
+ |---|---|---|---|
49
+ | **Claude Code** | `.claude/skills/` | `~/.claude/skills/` | `NATIVE` |
50
+ | **OpenAI Codex** | `.agents/skills/` | `~/.agents/skills/` | `NATIVE` |
51
+ | **Cursor** | `.agents/skills/`, `.cursor/skills/` (+2 compat) | `~/.agents/skills/`, `~/.cursor/skills/` | `NATIVE` |
52
+ | **GitHub Copilot** | `.github/skills/`, `.agents/skills/` (+1 compat) | `~/.copilot/skills/`, `~/.agents/skills/` | `NATIVE` |
53
+ | **Gemini CLI** | `.agents/skills/`, `.gemini/skills/` | `~/.agents/skills/`, `~/.gemini/skills/` | `NATIVE` |
54
+ | **Google Antigravity** | `.agents/skills/` (+1 compat) | `~/.gemini/config/skills/` | `NATIVE` |
55
+ | **Windsurf** | `.windsurf/skills/` | `~/.codeium/windsurf/skills/` | `NATIVE` |
56
+ | **Cline** | `.cline/skills/`, `.clinerules/skills/` (+2 compat) | `~/.cline/skills/` | `NATIVE` |
57
+ | **Roo Code** | `.roo/skills/`, `.agents/skills/` | `~/.roo/skills/`, `~/.agents/skills/` | `NATIVE` |
58
+ | **OpenCode** | `.opencode/skills/`, `.agents/skills/` (+1 compat) | `~/.config/opencode/skills/` (+2 compat) | `NATIVE` |
59
+ | **Zed** | `.agents/skills/` | `~/.agents/skills/` | `NATIVE` |
60
+ | **Replit Agent** | `.agents/skills/`, `.claude/skills/` | `~/.config/agents/skills/` | `NATIVE` |
61
+ | **JetBrains Junie** | `.junie/skills/`, `.agents/skills/` | `~/.junie/skills/`, `~/.agents/skills/` | `NATIVE` |
62
+ | **Hermes Agent** | `.hermes/skills/` | `$HERMES_HOME/skills/<category>/<name>` | `NATIVE` |
63
+ | **OpenClaw** | `.openclaw/skills/`, `skills/`, `.agents/skills/` | `~/.openclaw/skills/`, `~/.agents/skills/` | `NATIVE` |
64
+ | **OpenHands** | `.agents/skills/`, `.openhands/skills/` | `~/.agents/skills/`, `~/.openhands/skills/` | `NATIVE` |
65
+ | **Goose** | `.agents/skills/`, `.goose/skills/` | `~/.agents/skills/`, `~/.config/goose/skills/` | `NATIVE` |
66
+ | **Continue** | `.continue/skills/` (`.continue/rules/` adapted) | `~/.continue/skills/` | `COMPATIBLE` |
67
+ | **Aider / AiderDesk** | `.aider-desk/skills/` (`CONVENTIONS.md` adapted) | `~/.aider-desk/skills/` | `ADAPTED` |
68
+
69
+ A skill authored for Claude Code in `.claude/skills/` is silently invisible to OpenAI Codex, Gemini CLI, Zed, and Windsurf. Hand-rolled symlinks break in Docker build contexts, `git worktree`, and Windows checkouts — while manual copies silently drift out of sync.
70
+
71
+ **Skillporter solves the entire lifecycle:** one command resolves skills from GitHub or local paths, runs a static security and supply-chain scan, deduplicates shared destinations (`.agents/skills`), tracks ownership and SHA-256 content hashes, detects content drift across copies, and supports deterministic lockfiles (`skillporter.lock`) and transactional rollback.
72
+
73
+ ---
74
+
75
+ ## One-Command Installation & Zero-Install Execution
76
+
77
+ ```bash
78
+ # 1. Run immediately via npx directly from GitHub (zero install)
79
+ npx github:Shanmukh-l33t/skillporter diagnose .
80
+
81
+ # 2. Run immediately via uvx directly from GitHub (zero install)
82
+ uvx --from git+https://github.com/Shanmukh-l33t/skillporter skillporter diagnose .
83
+
84
+ # 3. Install globally via curl (Linux/macOS — bypasses PEP 668 externally-managed-environment)
85
+ curl -fsSL https://raw.githubusercontent.com/Shanmukh-l33t/skillporter/main/install.sh | sh
86
+
87
+ # 4. Install globally via uv tool or pipx directly from GitHub
88
+ uv tool install git+https://github.com/Shanmukh-l33t/skillporter
89
+ pipx install git+https://github.com/Shanmukh-l33t/skillporter
90
+ ```
91
+
92
+ ### Native Agent Integration (MCP Server)
93
+
94
+ Register Skillporter directly inside Claude Code, Codex, Cursor, Windsurf, or Hermes so your agent can diagnose, scan, and synchronize skills on command:
95
+
96
+ ```bash
97
+ claude mcp add skillporter -- uvx --from git+https://github.com/Shanmukh-l33t/skillporter skillporter mcp
98
+ codex mcp add skillporter -- uvx --from git+https://github.com/Shanmukh-l33t/skillporter skillporter mcp
99
+ ```
100
+
101
+ ---
102
+
103
+ ## 60-Second Quick Start
104
+
105
+ ```bash
106
+ # 1. Detect which AI agent harnesses are installed or active in your repo
107
+ skillporter detect .
108
+
109
+ # 2. Install a skill from GitHub across all detected harnesses (validates + security-scans first)
110
+ skillporter add anthropics/skills --skill pdf --harness all
111
+
112
+ # 3. Diagnose reachability, broken symlinks, duplicate loading, and SHA-256 content drift
113
+ skillporter diagnose .
114
+
115
+ # 4. Run a static supply-chain security scan on any skill directory
116
+ skillporter scan .
117
+
118
+ # 5. Initialize skillporter.yaml, synchronize teammates, and pin skillporter.lock
119
+ skillporter init
120
+ skillporter sync
121
+ skillporter lock
122
+ ```
123
+
124
+ ---
125
+
126
+ ## Real-World Evidence: Why Skillporter Exists
127
+
128
+ Built after auditing the exact failure modes reported across upstream agent ecosystems:
129
+
130
+ - **[agentskills/agentskills#15](https://github.com/agentskills/agentskills/issues/15)** (130+ comments) — *"Claude is looking at `.claude/skills/` and GitHub Copilot is looking at `.github/skills/`… create symlinks that match the specific folder of each harness"*
131
+ - **[thn-inc/claude-tweaks#3000](https://github.com/thn-inc/claude-tweaks/issues/3000)** — skill resolution misses `.agents/skills` when the symlink is absent or inside a **git worktree**
132
+ - **[openclaw/openclaw#14593](https://github.com/openclaw/openclaw/issues/14593)** — symlinked skill installs fail inside Docker build contexts
133
+ - **[squne121/loop-protocol](https://github.com/squne121/loop-protocol/issues)** — replacing broken Codex skill symlinks with a fail-closed `.agents/skills` bridge
134
+
135
+ ---
136
+
137
+ ## Key Features
138
+
139
+ ### 1. Universal Source Resolution (`skillporter add`)
140
+ Install skills from:
141
+ - **GitHub shorthand**: `skillporter add owner/repo` or `skillporter add owner/repo/skills/my-skill@v1.2.0`
142
+ - **GitHub tree URLs**: `skillporter add https://github.com/owner/repo/tree/main/skills/my-skill`
143
+ - **Git URLs & commit SHAs**: `skillporter add https://example.com/skills.git --ref ceb64c6`
144
+ - **ZIP & tar.gz archives**: `skillporter add ./bundle.zip` (hardened against Zip-Slip and symlink escapes)
145
+ - **Registry slugs**: `skillporter add registry:anthropics/skills`
146
+ - **Local directories**: `skillporter add ./authoring/my-skill --harness claude-code --harness codex`
147
+
148
+ ### 2. SHA-256 Content-Drift & Duplicate Detection (`skillporter diagnose`)
149
+ Competing tools copy files once and report success forever. Skillporter hashes every file inside every installed skill copy (`SHA-256`).
150
+ - **Drift**: If you edit `.claude/skills/my-skill/SKILL.md` and forget to update `.agents/skills/my-skill/SKILL.md`, `skillporter diagnose` flags `DRIFT` with the exact diverging hashes and exits `1`.
151
+ - **Duplicate loading**: If a skill is installed in both `.agents/skills` and `.cursor/skills`, `diagnose` flags `DUPLICATE` so Cursor does not load the same skill twice.
152
+
153
+ ### 3. Static Security & Supply-Chain Protection (`skillporter scan`)
154
+ Agent skills contain natural-language instructions and executable scripts. Before installing any skill, Skillporter inspects all Markdown and script files for:
155
+ - **Embedded secrets & private keys** (`sec-private-key`, `sec-aws-key`, `sec-github-token`, `sec-api-key`)
156
+ - **Prompt injection & covert overrides** (`sec-prompt-override`, `sec-hidden-unicode`, `sec-html-comment-instruction`)
157
+ - **Dangerous execution patterns** (`sec-curl-pipe-sh`, `sec-reverse-shell`, `sec-credential-harvest`, `sec-dynamic-eval`)
158
+ - **Filesystem escapes** (`sec-symlink-escape`, `sec-path-traversal`, `sec-binary-artifact`)
159
+
160
+ *Transparency note: Static scanning inspects files for known dangerous patterns and structural escapes; it does not guarantee runtime safety.*
161
+
162
+ ### 4. Manifest (`skillporter.yaml`), Lockfile (`skillporter.lock`) & Rollback
163
+ Declare your project's skills in `skillporter.yaml`:
164
+
165
+ ```yaml
166
+ schema_version: 1
167
+ project: acme-platform
168
+ scope: project
169
+ strategy: copy
170
+ security_policy: HIGH
171
+ harnesses:
172
+ - claude-code
173
+ - codex
174
+ - cursor
175
+ - github-copilot
176
+ skills:
177
+ - name: skillporter
178
+ source: Shanmukh-l33t/skillporter/skills/skillporter
179
+ ref: main
180
+ ```
181
+
182
+ Run `skillporter sync` to reconcile the workspace, `skillporter lock` to pin exact git commits and SHA-256 tree hashes in `skillporter.lock`, and `skillporter rollback <skill>` to restore the previous snapshot from `.skillporter/backups/` if an update introduces a regression.
183
+
184
+ ---
185
+
186
+ ## CLI Reference
187
+
188
+ | Command | Description |
189
+ |---|---|
190
+ | `skillporter add <source>` | Resolve, validate, security-scan, and install skills from GitHub, Git, archive, or local path |
191
+ | `skillporter diagnose [path]` | Check reachability, broken symlinks, SHA-256 content drift, duplicates, and spec compliance |
192
+ | `skillporter doctor [path] [--fix]` | Run full workspace health check and optionally auto-repair missing/drifted installs |
193
+ | `skillporter scan [path]` | Run static supply-chain and prompt-injection security assessment |
194
+ | `skillporter validate [path]` | Validate `SKILL.md` frontmatter and body against the [Agent Skills spec](https://agentskills.io/specification) |
195
+ | `skillporter inspect <source>` | Inspect a local or remote skill package (files, scripts, security, adapted previews) before installing |
196
+ | `skillporter detect [path]` | Detect which AI agent harnesses are installed on the machine or active in the project |
197
+ | `skillporter matrix` | Print the 19-harness compatibility and verification matrix (`--json` supported) |
198
+ | `skillporter init [path]` | Generate `skillporter.yaml` from discovered skills and active harnesses |
199
+ | `skillporter sync [path]` | Reconcile workspace skills across target harnesses and update `skillporter.lock` |
200
+ | `skillporter lock [path]` | Write deterministic `skillporter.lock` with SHA-256 content tree hashes |
201
+ | `skillporter list [path]` | List managed and discovered skills with ownership, hashes, and active harnesses |
202
+ | `skillporter update [skill]` | Update tracked skills from their recorded upstream source |
203
+ | `skillporter rollback <skill>` | Restore a skill to its previous backup snapshot in `.skillporter/backups/` |
204
+ | `skillporter install <path>` | Low-level local directory installer (`--strategy copy\|symlink`, `--adapt`, `--force`) |
205
+ | `skillporter remove <skill>` | Remove a skill from target harnesses (`uninstall` alias supported) |
206
+ | `skillporter search [query]` | Search the seed and configured skill registry catalog |
207
+ | `skillporter info <target>` | Show detailed metadata for a harness adapter or registry package |
208
+ | `skillporter pack [path]` | Build an immutable `.tar.gz` release archive and `provenance.json` checksum manifest |
209
+ | `skillporter mcp` | Start the zero-dependency stdio JSON-RPC 2.0 MCP server |
210
+
211
+ ### Exit Codes (CI Contract)
212
+ - `0` — Clean / all checks passed
213
+ - `1` — Findings detected (missing reachability, content drift, broken symlink, spec error, or security policy block)
214
+ - `2` — Usage or runtime error (invalid path, unknown harness, unsafe overwrite refusal)
215
+
216
+ ---
217
+
218
+ ## GitHub Action Integration
219
+
220
+ Validate `SKILL.md` compliance, scan for security risks, and verify harness reachability automatically on every pull request:
221
+
222
+ ```yaml
223
+ name: Skillporter Check
224
+ on: [push, pull_request]
225
+ jobs:
226
+ skills:
227
+ runs-on: ubuntu-latest
228
+ steps:
229
+ - uses: actions/checkout@v4
230
+ - uses: Shanmukh-l33t/skillporter@v2
231
+ with:
232
+ command: validate
233
+ path: .
234
+ run-security-scan: "true"
235
+ ```
236
+
237
+ ---
238
+
239
+ ## Documentation
240
+
241
+ - [Getting Started](docs/getting-started/README.md)
242
+ - [Installation & Distribution (uvx, npx, binaries, MCP)](docs/installation/README.md)
243
+ - [Supported Harnesses & Evidence Directory (19 Harnesses)](docs/harnesses/README.md)
244
+ - [CLI Command Reference](docs/commands/README.md)
245
+ - [Configuration (`skillporter.yaml` & `skillporter.lock`)](docs/configuration/README.md)
246
+ - [Security & Supply-Chain Model](docs/security/README.md)
247
+ - [System Architecture](ARCHITECTURE.md)
248
+ - [Adapter Development SDK](docs/adapters/README.md)
249
+ - [Registry & Immutable Packaging](docs/registry/README.md)
250
+ - [Troubleshooting](docs/troubleshooting/README.md)
251
+ - [Contributing Guide](CONTRIBUTING.md)
252
+ - [Product Roadmap](ROADMAP.md)
253
+
254
+ ---
255
+
256
+ ## License
257
+
258
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,230 @@
1
+ # SKILLPORTER
2
+
3
+ ## ONE SKILL. EVERY AGENT.
4
+
5
+ **Install, manage, validate, security-scan, and synchronize AI-agent skills across the entire agent ecosystem.**
6
+
7
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org/)
8
+ [![Harnesses: 19 Verified](https://img.shields.io/badge/harnesses-19%20supported-00b4d8)](docs/harnesses/README.md)
9
+ [![Tests: 60 Passing](https://img.shields.io/badge/tests-60%20passing-brightgreen)](tests/)
10
+ [![Zero Dependencies](https://img.shields.io/badge/dependencies-0-success)](pyproject.toml)
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
12
+
13
+ <p align="center">
14
+ <img src="docs/assets/demo.svg" alt="Skillporter Terminal Demonstration" width="860" />
15
+ </p>
16
+
17
+ Every AI coding and autonomous agent harness reads skills from a **different directory**:
18
+
19
+ | Harness | Project Path | Personal / Global Path | Support |
20
+ |---|---|---|---|
21
+ | **Claude Code** | `.claude/skills/` | `~/.claude/skills/` | `NATIVE` |
22
+ | **OpenAI Codex** | `.agents/skills/` | `~/.agents/skills/` | `NATIVE` |
23
+ | **Cursor** | `.agents/skills/`, `.cursor/skills/` (+2 compat) | `~/.agents/skills/`, `~/.cursor/skills/` | `NATIVE` |
24
+ | **GitHub Copilot** | `.github/skills/`, `.agents/skills/` (+1 compat) | `~/.copilot/skills/`, `~/.agents/skills/` | `NATIVE` |
25
+ | **Gemini CLI** | `.agents/skills/`, `.gemini/skills/` | `~/.agents/skills/`, `~/.gemini/skills/` | `NATIVE` |
26
+ | **Google Antigravity** | `.agents/skills/` (+1 compat) | `~/.gemini/config/skills/` | `NATIVE` |
27
+ | **Windsurf** | `.windsurf/skills/` | `~/.codeium/windsurf/skills/` | `NATIVE` |
28
+ | **Cline** | `.cline/skills/`, `.clinerules/skills/` (+2 compat) | `~/.cline/skills/` | `NATIVE` |
29
+ | **Roo Code** | `.roo/skills/`, `.agents/skills/` | `~/.roo/skills/`, `~/.agents/skills/` | `NATIVE` |
30
+ | **OpenCode** | `.opencode/skills/`, `.agents/skills/` (+1 compat) | `~/.config/opencode/skills/` (+2 compat) | `NATIVE` |
31
+ | **Zed** | `.agents/skills/` | `~/.agents/skills/` | `NATIVE` |
32
+ | **Replit Agent** | `.agents/skills/`, `.claude/skills/` | `~/.config/agents/skills/` | `NATIVE` |
33
+ | **JetBrains Junie** | `.junie/skills/`, `.agents/skills/` | `~/.junie/skills/`, `~/.agents/skills/` | `NATIVE` |
34
+ | **Hermes Agent** | `.hermes/skills/` | `$HERMES_HOME/skills/<category>/<name>` | `NATIVE` |
35
+ | **OpenClaw** | `.openclaw/skills/`, `skills/`, `.agents/skills/` | `~/.openclaw/skills/`, `~/.agents/skills/` | `NATIVE` |
36
+ | **OpenHands** | `.agents/skills/`, `.openhands/skills/` | `~/.agents/skills/`, `~/.openhands/skills/` | `NATIVE` |
37
+ | **Goose** | `.agents/skills/`, `.goose/skills/` | `~/.agents/skills/`, `~/.config/goose/skills/` | `NATIVE` |
38
+ | **Continue** | `.continue/skills/` (`.continue/rules/` adapted) | `~/.continue/skills/` | `COMPATIBLE` |
39
+ | **Aider / AiderDesk** | `.aider-desk/skills/` (`CONVENTIONS.md` adapted) | `~/.aider-desk/skills/` | `ADAPTED` |
40
+
41
+ A skill authored for Claude Code in `.claude/skills/` is silently invisible to OpenAI Codex, Gemini CLI, Zed, and Windsurf. Hand-rolled symlinks break in Docker build contexts, `git worktree`, and Windows checkouts — while manual copies silently drift out of sync.
42
+
43
+ **Skillporter solves the entire lifecycle:** one command resolves skills from GitHub or local paths, runs a static security and supply-chain scan, deduplicates shared destinations (`.agents/skills`), tracks ownership and SHA-256 content hashes, detects content drift across copies, and supports deterministic lockfiles (`skillporter.lock`) and transactional rollback.
44
+
45
+ ---
46
+
47
+ ## One-Command Installation & Zero-Install Execution
48
+
49
+ ```bash
50
+ # 1. Run immediately via npx directly from GitHub (zero install)
51
+ npx github:Shanmukh-l33t/skillporter diagnose .
52
+
53
+ # 2. Run immediately via uvx directly from GitHub (zero install)
54
+ uvx --from git+https://github.com/Shanmukh-l33t/skillporter skillporter diagnose .
55
+
56
+ # 3. Install globally via curl (Linux/macOS — bypasses PEP 668 externally-managed-environment)
57
+ curl -fsSL https://raw.githubusercontent.com/Shanmukh-l33t/skillporter/main/install.sh | sh
58
+
59
+ # 4. Install globally via uv tool or pipx directly from GitHub
60
+ uv tool install git+https://github.com/Shanmukh-l33t/skillporter
61
+ pipx install git+https://github.com/Shanmukh-l33t/skillporter
62
+ ```
63
+
64
+ ### Native Agent Integration (MCP Server)
65
+
66
+ Register Skillporter directly inside Claude Code, Codex, Cursor, Windsurf, or Hermes so your agent can diagnose, scan, and synchronize skills on command:
67
+
68
+ ```bash
69
+ claude mcp add skillporter -- uvx --from git+https://github.com/Shanmukh-l33t/skillporter skillporter mcp
70
+ codex mcp add skillporter -- uvx --from git+https://github.com/Shanmukh-l33t/skillporter skillporter mcp
71
+ ```
72
+
73
+ ---
74
+
75
+ ## 60-Second Quick Start
76
+
77
+ ```bash
78
+ # 1. Detect which AI agent harnesses are installed or active in your repo
79
+ skillporter detect .
80
+
81
+ # 2. Install a skill from GitHub across all detected harnesses (validates + security-scans first)
82
+ skillporter add anthropics/skills --skill pdf --harness all
83
+
84
+ # 3. Diagnose reachability, broken symlinks, duplicate loading, and SHA-256 content drift
85
+ skillporter diagnose .
86
+
87
+ # 4. Run a static supply-chain security scan on any skill directory
88
+ skillporter scan .
89
+
90
+ # 5. Initialize skillporter.yaml, synchronize teammates, and pin skillporter.lock
91
+ skillporter init
92
+ skillporter sync
93
+ skillporter lock
94
+ ```
95
+
96
+ ---
97
+
98
+ ## Real-World Evidence: Why Skillporter Exists
99
+
100
+ Built after auditing the exact failure modes reported across upstream agent ecosystems:
101
+
102
+ - **[agentskills/agentskills#15](https://github.com/agentskills/agentskills/issues/15)** (130+ comments) — *"Claude is looking at `.claude/skills/` and GitHub Copilot is looking at `.github/skills/`… create symlinks that match the specific folder of each harness"*
103
+ - **[thn-inc/claude-tweaks#3000](https://github.com/thn-inc/claude-tweaks/issues/3000)** — skill resolution misses `.agents/skills` when the symlink is absent or inside a **git worktree**
104
+ - **[openclaw/openclaw#14593](https://github.com/openclaw/openclaw/issues/14593)** — symlinked skill installs fail inside Docker build contexts
105
+ - **[squne121/loop-protocol](https://github.com/squne121/loop-protocol/issues)** — replacing broken Codex skill symlinks with a fail-closed `.agents/skills` bridge
106
+
107
+ ---
108
+
109
+ ## Key Features
110
+
111
+ ### 1. Universal Source Resolution (`skillporter add`)
112
+ Install skills from:
113
+ - **GitHub shorthand**: `skillporter add owner/repo` or `skillporter add owner/repo/skills/my-skill@v1.2.0`
114
+ - **GitHub tree URLs**: `skillporter add https://github.com/owner/repo/tree/main/skills/my-skill`
115
+ - **Git URLs & commit SHAs**: `skillporter add https://example.com/skills.git --ref ceb64c6`
116
+ - **ZIP & tar.gz archives**: `skillporter add ./bundle.zip` (hardened against Zip-Slip and symlink escapes)
117
+ - **Registry slugs**: `skillporter add registry:anthropics/skills`
118
+ - **Local directories**: `skillporter add ./authoring/my-skill --harness claude-code --harness codex`
119
+
120
+ ### 2. SHA-256 Content-Drift & Duplicate Detection (`skillporter diagnose`)
121
+ Competing tools copy files once and report success forever. Skillporter hashes every file inside every installed skill copy (`SHA-256`).
122
+ - **Drift**: If you edit `.claude/skills/my-skill/SKILL.md` and forget to update `.agents/skills/my-skill/SKILL.md`, `skillporter diagnose` flags `DRIFT` with the exact diverging hashes and exits `1`.
123
+ - **Duplicate loading**: If a skill is installed in both `.agents/skills` and `.cursor/skills`, `diagnose` flags `DUPLICATE` so Cursor does not load the same skill twice.
124
+
125
+ ### 3. Static Security & Supply-Chain Protection (`skillporter scan`)
126
+ Agent skills contain natural-language instructions and executable scripts. Before installing any skill, Skillporter inspects all Markdown and script files for:
127
+ - **Embedded secrets & private keys** (`sec-private-key`, `sec-aws-key`, `sec-github-token`, `sec-api-key`)
128
+ - **Prompt injection & covert overrides** (`sec-prompt-override`, `sec-hidden-unicode`, `sec-html-comment-instruction`)
129
+ - **Dangerous execution patterns** (`sec-curl-pipe-sh`, `sec-reverse-shell`, `sec-credential-harvest`, `sec-dynamic-eval`)
130
+ - **Filesystem escapes** (`sec-symlink-escape`, `sec-path-traversal`, `sec-binary-artifact`)
131
+
132
+ *Transparency note: Static scanning inspects files for known dangerous patterns and structural escapes; it does not guarantee runtime safety.*
133
+
134
+ ### 4. Manifest (`skillporter.yaml`), Lockfile (`skillporter.lock`) & Rollback
135
+ Declare your project's skills in `skillporter.yaml`:
136
+
137
+ ```yaml
138
+ schema_version: 1
139
+ project: acme-platform
140
+ scope: project
141
+ strategy: copy
142
+ security_policy: HIGH
143
+ harnesses:
144
+ - claude-code
145
+ - codex
146
+ - cursor
147
+ - github-copilot
148
+ skills:
149
+ - name: skillporter
150
+ source: Shanmukh-l33t/skillporter/skills/skillporter
151
+ ref: main
152
+ ```
153
+
154
+ Run `skillporter sync` to reconcile the workspace, `skillporter lock` to pin exact git commits and SHA-256 tree hashes in `skillporter.lock`, and `skillporter rollback <skill>` to restore the previous snapshot from `.skillporter/backups/` if an update introduces a regression.
155
+
156
+ ---
157
+
158
+ ## CLI Reference
159
+
160
+ | Command | Description |
161
+ |---|---|
162
+ | `skillporter add <source>` | Resolve, validate, security-scan, and install skills from GitHub, Git, archive, or local path |
163
+ | `skillporter diagnose [path]` | Check reachability, broken symlinks, SHA-256 content drift, duplicates, and spec compliance |
164
+ | `skillporter doctor [path] [--fix]` | Run full workspace health check and optionally auto-repair missing/drifted installs |
165
+ | `skillporter scan [path]` | Run static supply-chain and prompt-injection security assessment |
166
+ | `skillporter validate [path]` | Validate `SKILL.md` frontmatter and body against the [Agent Skills spec](https://agentskills.io/specification) |
167
+ | `skillporter inspect <source>` | Inspect a local or remote skill package (files, scripts, security, adapted previews) before installing |
168
+ | `skillporter detect [path]` | Detect which AI agent harnesses are installed on the machine or active in the project |
169
+ | `skillporter matrix` | Print the 19-harness compatibility and verification matrix (`--json` supported) |
170
+ | `skillporter init [path]` | Generate `skillporter.yaml` from discovered skills and active harnesses |
171
+ | `skillporter sync [path]` | Reconcile workspace skills across target harnesses and update `skillporter.lock` |
172
+ | `skillporter lock [path]` | Write deterministic `skillporter.lock` with SHA-256 content tree hashes |
173
+ | `skillporter list [path]` | List managed and discovered skills with ownership, hashes, and active harnesses |
174
+ | `skillporter update [skill]` | Update tracked skills from their recorded upstream source |
175
+ | `skillporter rollback <skill>` | Restore a skill to its previous backup snapshot in `.skillporter/backups/` |
176
+ | `skillporter install <path>` | Low-level local directory installer (`--strategy copy\|symlink`, `--adapt`, `--force`) |
177
+ | `skillporter remove <skill>` | Remove a skill from target harnesses (`uninstall` alias supported) |
178
+ | `skillporter search [query]` | Search the seed and configured skill registry catalog |
179
+ | `skillporter info <target>` | Show detailed metadata for a harness adapter or registry package |
180
+ | `skillporter pack [path]` | Build an immutable `.tar.gz` release archive and `provenance.json` checksum manifest |
181
+ | `skillporter mcp` | Start the zero-dependency stdio JSON-RPC 2.0 MCP server |
182
+
183
+ ### Exit Codes (CI Contract)
184
+ - `0` — Clean / all checks passed
185
+ - `1` — Findings detected (missing reachability, content drift, broken symlink, spec error, or security policy block)
186
+ - `2` — Usage or runtime error (invalid path, unknown harness, unsafe overwrite refusal)
187
+
188
+ ---
189
+
190
+ ## GitHub Action Integration
191
+
192
+ Validate `SKILL.md` compliance, scan for security risks, and verify harness reachability automatically on every pull request:
193
+
194
+ ```yaml
195
+ name: Skillporter Check
196
+ on: [push, pull_request]
197
+ jobs:
198
+ skills:
199
+ runs-on: ubuntu-latest
200
+ steps:
201
+ - uses: actions/checkout@v4
202
+ - uses: Shanmukh-l33t/skillporter@v2
203
+ with:
204
+ command: validate
205
+ path: .
206
+ run-security-scan: "true"
207
+ ```
208
+
209
+ ---
210
+
211
+ ## Documentation
212
+
213
+ - [Getting Started](docs/getting-started/README.md)
214
+ - [Installation & Distribution (uvx, npx, binaries, MCP)](docs/installation/README.md)
215
+ - [Supported Harnesses & Evidence Directory (19 Harnesses)](docs/harnesses/README.md)
216
+ - [CLI Command Reference](docs/commands/README.md)
217
+ - [Configuration (`skillporter.yaml` & `skillporter.lock`)](docs/configuration/README.md)
218
+ - [Security & Supply-Chain Model](docs/security/README.md)
219
+ - [System Architecture](ARCHITECTURE.md)
220
+ - [Adapter Development SDK](docs/adapters/README.md)
221
+ - [Registry & Immutable Packaging](docs/registry/README.md)
222
+ - [Troubleshooting](docs/troubleshooting/README.md)
223
+ - [Contributing Guide](CONTRIBUTING.md)
224
+ - [Product Roadmap](ROADMAP.md)
225
+
226
+ ---
227
+
228
+ ## License
229
+
230
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,68 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "skillporter"
7
+ version = "2.0.0"
8
+ description = "ONE SKILL. EVERY AGENT. Universal package manager, validator, security scanner, and synchronizer for AI-agent skills across 19+ harnesses."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Shanmukh Dheekonda" }]
13
+ keywords = [
14
+ "agent-skills",
15
+ "claude-code",
16
+ "codex",
17
+ "cursor",
18
+ "windsurf",
19
+ "github-copilot",
20
+ "gemini-cli",
21
+ "hermes",
22
+ "openclaw",
23
+ "openhands",
24
+ "goose",
25
+ "mcp",
26
+ "developer-tools",
27
+ ]
28
+ classifiers = [
29
+ "Development Status :: 5 - Production/Stable",
30
+ "Environment :: Console",
31
+ "Intended Audience :: Developers",
32
+ "License :: OSI Approved :: MIT License",
33
+ "Operating System :: OS Independent",
34
+ "Programming Language :: Python :: 3",
35
+ "Programming Language :: Python :: 3 :: Only",
36
+ "Topic :: Software Development :: Build Tools",
37
+ "Topic :: Software Development :: Quality Assurance",
38
+ "Topic :: Security",
39
+ ]
40
+ dependencies = []
41
+
42
+ [project.optional-dependencies]
43
+ dev = ["pytest>=7", "ruff>=0.6"]
44
+
45
+ [project.scripts]
46
+ skillporter = "skillporter.cli:main"
47
+
48
+ [project.urls]
49
+ Homepage = "https://github.com/Shanmukh-l33t/skillporter"
50
+ Issues = "https://github.com/Shanmukh-l33t/skillporter/issues"
51
+ Changelog = "https://github.com/Shanmukh-l33t/skillporter/blob/main/CHANGELOG.md"
52
+
53
+ [tool.setuptools]
54
+ packages = ["skillporter"]
55
+
56
+ [tool.setuptools.package-data]
57
+ skillporter = ["py.typed"]
58
+
59
+ [tool.pytest.ini_options]
60
+ testpaths = ["tests"]
61
+ addopts = "-q"
62
+
63
+ [tool.ruff]
64
+ line-length = 120
65
+ target-version = "py39"
66
+
67
+ [tool.ruff.lint]
68
+ select = ["E", "F", "I", "UP", "B", "SIM"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,16 @@
1
+ """skillporter — Universal package manager and diagnostics engine for AI-agent skills.
2
+
3
+ ONE SKILL. EVERY AGENT.
4
+
5
+ Install, validate, scan, synchronize, and manage Agent Skills across 19+ AI
6
+ coding and autonomous agent harnesses (Claude Code, OpenAI Codex, Cursor,
7
+ GitHub Copilot, Gemini CLI, Google Antigravity, Windsurf, Cline, Roo Code,
8
+ OpenCode, Zed, Replit Agent, JetBrains Junie, Hermes Agent, OpenClaw,
9
+ OpenHands, Goose, Continue, and Aider).
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ __version__ = "2.0.0"
15
+
16
+ __all__ = ["__version__"]
@@ -0,0 +1,4 @@
1
+ from skillporter.cli import main
2
+
3
+ if __name__ == "__main__":
4
+ raise SystemExit(main())
@@ -0,0 +1,55 @@
1
+ """Crash-safe file writes.
2
+
3
+ A plain ``Path.write_text`` truncates the destination and then streams the new
4
+ content. If the process dies (OOM, Ctrl-C, power loss) between those two steps,
5
+ the user is left with a truncated or empty file — for skillporter that means a
6
+ corrupted state file, manifest or lockfile, which is precisely the
7
+ "failed operations must not leave the environment inconsistent" case.
8
+
9
+ ``atomic_write_text`` writes to a sibling temp file in the *same directory*
10
+ (same filesystem, so ``os.replace`` is atomic) and renames it into place.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import contextlib
16
+ import os
17
+ import tempfile
18
+ from pathlib import Path
19
+
20
+
21
+ def atomic_write_text(path: Path, content: str, *, encoding: str = "utf-8") -> None:
22
+ """Write *content* to *path* atomically.
23
+
24
+ The destination is either the previous content or the complete new content —
25
+ never a partial write. File permissions of an existing destination are
26
+ preserved so we do not silently widen them.
27
+ """
28
+ path = Path(path)
29
+ path.parent.mkdir(parents=True, exist_ok=True)
30
+
31
+ existing_mode: int | None = None
32
+ try:
33
+ if path.exists():
34
+ existing_mode = path.stat().st_mode & 0o777
35
+ except OSError:
36
+ existing_mode = None
37
+
38
+ fd, tmp_name = tempfile.mkstemp(
39
+ dir=str(path.parent), prefix=f".{path.name}.", suffix=".tmp"
40
+ )
41
+ tmp = Path(tmp_name)
42
+ try:
43
+ with os.fdopen(fd, "w", encoding=encoding, newline="\n") as fh:
44
+ fh.write(content)
45
+ fh.flush()
46
+ os.fsync(fh.fileno())
47
+ if existing_mode is not None:
48
+ with contextlib.suppress(OSError):
49
+ os.chmod(tmp, existing_mode)
50
+ os.replace(tmp, path)
51
+ except BaseException:
52
+ # Never leave a temp file behind, even on KeyboardInterrupt.
53
+ with contextlib.suppress(OSError):
54
+ tmp.unlink()
55
+ raise