Skip to content

Commit 206fcbf

Browse files
ArchieIndianclaude
andauthored
Add skill-portability-checker: validate OS/binary dependencies in scripts (#23)
Detects OS_SPECIFIC_CALL, MISSING_BINARY, BREW_ONLY, PYTHON_IMPORT, and HARDCODED_PATH issues in companion scripts. Cross-checks against os_filter: frontmatter field. No external dependencies. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 292f707 commit 206fcbf

2 files changed

Lines changed: 461 additions & 0 deletions

File tree

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
---
2+
name: skill-portability-checker
3+
version: "1.0"
4+
category: core
5+
description: Validates that a skill's companion scripts declare their OS and binary dependencies correctly, and checks whether those dependencies are actually present on the current machine.
6+
---
7+
8+
# Skill Portability Checker
9+
10+
## What it does
11+
12+
Skills with companion scripts (`.py`, `.sh`) can silently fail on machines where their dependencies aren't installed. A skill written on macOS may call `brew`, `pbcopy`, or use `/usr/local/bin` paths that don't exist on Linux. A Python script may `import pandas` on a system without it.
13+
14+
Skill Portability Checker:
15+
1. Scans companion scripts for OS-specific patterns and external binary calls
16+
2. Checks whether those binaries are present on the current system (`PATH` lookup + `which`)
17+
3. Cross-checks against the skill's declared `os_filter:` frontmatter field (if any)
18+
4. Reports portability issues before the skill fails at runtime
19+
20+
## Frontmatter field checked
21+
22+
```yaml
23+
---
24+
name: my-skill
25+
os_filter: [macos] # optional: ["macos", "linux", "windows"]
26+
---
27+
```
28+
29+
If `os_filter:` is absent the skill is treated as cross-platform. The checker then warns if OS-specific calls are detected without a corresponding `os_filter:`.
30+
31+
## Checks performed
32+
33+
| Check | Description |
34+
|---|---|
35+
| OS_SPECIFIC_CALL | Script calls macOS/Linux/Windows-only binary without `os_filter:` |
36+
| MISSING_BINARY | Required binary not found on current system PATH |
37+
| BREW_ONLY | Script uses `brew` (macOS-only) but `os_filter:` includes non-macOS |
38+
| PYTHON_IMPORT | Script imports a non-stdlib module; checks if importable |
39+
| HARDCODED_PATH | Absolute path that doesn't exist on this machine (`/usr/local`, `C:\`) |
40+
41+
## How to use
42+
43+
```bash
44+
python3 check.py --check # Full portability scan
45+
python3 check.py --check --skill my-skill # Single skill
46+
python3 check.py --fix-hints my-skill # Print fix suggestions
47+
python3 check.py --format json
48+
```
49+
50+
## Procedure
51+
52+
**Step 1 — Run the scan**
53+
54+
```bash
55+
python3 check.py --check
56+
```
57+
58+
**Step 2 — Triage FAILs first**
59+
60+
- **MISSING_BINARY**: The script calls a binary that isn't installed. Either install it or add a graceful fallback in the script.
61+
- **OS_SPECIFIC_CALL without os_filter**: Add `os_filter: [macos]` (or whichever OS applies) to the frontmatter so users on other platforms know the skill won't work.
62+
63+
**Step 3 — Review WARNs**
64+
65+
- **PYTHON_IMPORT**: Install the missing module or add a `try/except ImportError` with a graceful degradation path (like `HAS_MODULE = False`).
66+
- **HARDCODED_PATH**: Replace with `Path.home()` or environment-variable-based paths.
67+
68+
**Step 4 — Add os_filter when needed**
69+
70+
If a skill genuinely only works on one OS, declare it:
71+
72+
```yaml
73+
os_filter: [macos]
74+
```
75+
76+
This prevents the skill from being shown as broken on other platforms — it simply won't be loaded there.
77+
78+
## Output example
79+
80+
```
81+
Skill Portability Report — linux (Python 3.11)
82+
────────────────────────────────────────────────
83+
32 skills checked | 1 FAIL | 2 WARN
84+
85+
FAIL obsidian-sync: MISSING_BINARY
86+
sync.py calls `osascript` — not found on this system
87+
Fix: add os_filter: [macos] to frontmatter (osascript is macOS-only)
88+
89+
WARN morning-briefing: PYTHON_IMPORT
90+
run.py imports `pync` — not importable on this system
91+
Fix: wrap in try/except ImportError and degrade gracefully
92+
```

0 commit comments

Comments
 (0)