skillporter 2.0.0__py3-none-any.whl
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.
- skillporter/__init__.py +16 -0
- skillporter/__main__.py +4 -0
- skillporter/atomic.py +55 -0
- skillporter/cli.py +1288 -0
- skillporter/diagnose.py +303 -0
- skillporter/formats.py +168 -0
- skillporter/frontmatter.py +242 -0
- skillporter/harnesses.py +934 -0
- skillporter/install.py +413 -0
- skillporter/manifest.py +325 -0
- skillporter/mcp_server.py +267 -0
- skillporter/py.typed +0 -0
- skillporter/registry.py +301 -0
- skillporter/security.py +350 -0
- skillporter/sources.py +361 -0
- skillporter/state.py +261 -0
- skillporter/ui.py +49 -0
- skillporter-2.0.0.dist-info/METADATA +258 -0
- skillporter-2.0.0.dist-info/RECORD +23 -0
- skillporter-2.0.0.dist-info/WHEEL +5 -0
- skillporter-2.0.0.dist-info/entry_points.txt +2 -0
- skillporter-2.0.0.dist-info/licenses/LICENSE +21 -0
- skillporter-2.0.0.dist-info/top_level.txt +1 -0
skillporter/__init__.py
ADDED
|
@@ -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__"]
|
skillporter/__main__.py
ADDED
skillporter/atomic.py
ADDED
|
@@ -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
|