agent-xplat
Find the OS assumptions that break AI-agent workflows.
Development preview: 1.0.2 changes are unreleased; install and pin this PR commit using CI adoption. The current published version remains 1.0.1. Read the ten-repository study before enabling required checks.
Why agent-xplat
AI-agent workflows combine Markdown instructions, shell commands, Python, Node, package managers, and external tools. A workflow that is valid in Linux Bash can still fail in Windows PowerShell, Windows CMD, Git Bash, WSL, or macOS zsh.
agent-xplat is a deterministic cross-OS portability checker for AI-agent workflows, Agent Skills, agent configuration, and related scripts. It reports the OS × Shell × Runtime assumptions behind a failure—not just the operating system.
Skill validators check structure, and general linters check style. agent-xplat checks whether those otherwise-valid workflows can survive the environments where agents actually run. It is deliberately not a security scanner, Agent Skill schema validator, benchmark, general linter, or repository health tool.
The current verification path exercises real GitHub-hosted Windows, macOS, and Linux runners. Static analysis covers the full eight-target matrix; static findings use STATIC = INFERRED, while only a real runner or controlled local runtime check produces RUNTIME = VERIFIED evidence.
Quick Start
Install the published package from PyPI and scan the current repository:
python -m pip install agent-xplat
agent-xplat scan .
For an isolated CLI installation:
pipx install agent-xplat
agent-xplat scan .
The scan produces a deterministic, target-specific compatibility matrix:
Agent Workflow Portability
===========================
Compatibility Matrix
---------------------
Environment Score Status Findings
Windows / PowerShell 43/100 BLOCKED 3
Windows / CMD 3/100 BLOCKED 5
Windows / Git Bash 78/100 PARTIAL 2
Windows / WSL 78/100 PARTIAL 2
macOS / zsh 58/100 PARTIAL 3
macOS / bash 58/100 PARTIAL 3
Linux / bash 58/100 PARTIAL 3
Linux / zsh 58/100 PARTIAL 3
6 portability issues found (0 ignored)
Findings
The scores are deterministic and explainable. The included output is a mixed-platform fixture example, not a claim about every repository.
📦 Installation
Python 3.10 or newer is required. The package is published on PyPI as a wheel and source distribution. Use python -m pip install agent-xplat in an active virtual environment, or pipx install agent-xplat for an isolated CLI installation. The runtime package includes the small Tree-sitter parser bindings needed for JavaScript/JSX/TypeScript/TSX AST analysis; pytest is only a development extra. pipx install . remains a convenient isolated CLI installation when working from a source checkout.
From a source checkout:
python -m pip install .
agent-xplat scan .
For development:
python -m pip install -e ".[dev]"
python -m pytest -q
The module invocation is always available as a fallback:
python -m agent_xplat scan . --format json
🔍 Supported environments
The internal model is OS × Shell × Runtime:
| Target | OS | Shell | Runtime context |
|---|---|---|---|
windows-powershell |
Windows | PowerShell | native |
windows-cmd |
Windows | CMD | native |
windows-git-bash |
Windows | Bash | Git Bash |
windows-wsl |
Windows | Bash | WSL |
macos-zsh |
macOS | zsh | native |
macos-bash |
macOS | Bash | native |
linux-bash |
Linux | Bash | native |
linux-zsh |
Linux | zsh | native |
📋 What is scanned
The default bounded discovery includes SKILL.md, AGENTS.md, CLAUDE.md, GEMINI.md, README.md, .github/**, .cursor/**, .claude/**, .codex/**, scripts/**, package manifests/lockfiles, Python metadata, Docker/Make files, and common shell, Python, JavaScript, JSX, TypeScript, TSX, and batch extensions (.js, .mjs, .cjs, .jsx, .ts, .mts, .cts, .tsx). .git, node_modules, vendor, dist, build, caches, binary files, and oversized files are excluded.
✨ Examples
Included fixtures exercise portable, OS-specific, shell-specific, Python, Node, mixed, and agent-instruction workflows:
agent-xplat scan tests/fixtures/mixed
agent-xplat scan tests/fixtures/python --format json
agent-xplat scan tests/fixtures/node --format sarif --output agent-xplat.sarif
agent-xplat scan tests/fixtures/node-ast --format json
The fixture metadata in tests/fixtures/*/expected.json records expected rules, affected targets, severity, and confidence. It is test data, not a claim about a third-party tool's standard.
🧩 Rules, severity, and confidence
The current registry contains 49 modular rules with stable AX-* identifiers. They cover paths, shell commands and environment syntax, quoting, Python, Node package scripts and Node/JS/TS AST facts, filesystems, package managers, external tools, runtime assumptions, and agent configuration. JavaScript-family source is parsed structurally with Tree-sitter; dynamic strings and behavior still remain static inferences. See docs/RULES.md.
Severity is one of BLOCKER, ERROR, WARNING, or INFO. Confidence is one of HIGH, MEDIUM, or LOW. A low-confidence assumption is reported as such and does not become a blocker merely because it is inconvenient.
📊 Scan and reports
agent-xplat scan .
agent-xplat scan . --format json --output agent-xplat.json
agent-xplat scan . --format sarif --output agent-xplat.sarif
agent-xplat report .
JSON is versioned (schema_version: 1.0) for agent and CI consumption and contains targets, scores, findings, baseline, contract, verification, and summary. SARIF output is version 2.1.0 and includes file, line, column, rule, level, message, and help. The Markdown report contains the executive summary, matrix, blocking issues, warnings, assumptions, contract violations, affected files, suggested fixes, evidence, ignored findings, and baseline status.
🛠️ Safe fixes
agent-xplat fix . --dry-run
agent-xplat fix .
Only deterministic, high-confidence, behavior-preserving fixes are eligible. v1.0.1 automatically normalizes CRLF shebang files to LF. Shell rewrites, path rewrites, environment syntax conversions, and dependency migrations remain suggestions because their equivalence cannot be proven from static text alone. Dry-run prints a unified patch and does not modify files.
🧪 Runtime verification
agent-xplat test .
scan performs no target-code execution. test is explicit and bounded: it may run an allowlisted project test command with a timeout and records the actual host target, command, exit code, and output tail. A missing command is INFERRED, not VERIFIED. Runtime evidence from one host does not prove all matrix rows.
⚙️ GitHub Actions and SARIF
agent-xplat init-ci
The generated consumer workflow installs only the scanner, performs a static scan on Ubuntu, compares PRs with their base commit, and publishes Job Summary plus JSON/SARIF/Markdown artifacts with contents: read. It does not install or execute the scanned project. The separate project development workflow retains real Windows/macOS/Linux tests. See CI adoption for preview installation, baselines, policy and evidence boundaries.
🧭 Baseline and diff mode
agent-xplat baseline
agent-xplat scan . --baseline-only
agent-xplat scan . --diff master
agent-xplat scan . --diff HEAD~1 --format markdown
Baselines distinguish existing, new, and resolved fingerprints. --baseline-only gates on new findings. Diff mode compares before/after scores and issue fingerprints from a Git reference without executing the reference tree.
📐 Compatibility contract
.agent-xplat.yml accepts declared support and requirements:
supported:
- windows-powershell
- windows-git-bash
- windows-wsl
- macos-zsh
- linux-bash
unsupported:
- windows-cmd
requirements:
python: ">=3.11"
node: ">=22"
minimum_score: 85
fail_on:
- BLOCKER
- ERROR
The optional agent-xplat: wrapper is also accepted. Declared support is compared to detected assumptions and reported as VIOLATION; unsupported targets are not treated as contract failures.
🧾 Configuration and ignoring rules
agent-xplat init
The schema supports targets, exclude, ignore, minimum_score, fail_on, supported, unsupported, requirements, max_file_size, and verification. Global suppression uses ignore. A line-level marker is explicit and auditable:
# agent-xplat-ignore AX-SHELL-001
chmod +x scripts/render.sh
Ignored findings remain in machine-readable output with ignored: true, and the summary reports their count. Unknown keys, targets, severities, rule IDs, and invalid values fail with exit code 2. Unused line-level suppression markers are reported as suppression diagnostics instead of being silently accepted.
🤖 Agent-native usage and exit codes
agent-xplat scan . --format json
Agents should consume summary, per-target scores, findings, and contract.violations rather than parsing terminal decoration. The CLI commands are scan, test, fix, report, explain, doctor, baseline, init, init-ci, and badge; the root command also supports --version.
| Code | Meaning |
|---|---|
| 0 | No configured portability gate failure |
| 1 | Portability violation, contract violation, or new diff regression |
| 2 | Invalid configuration, input, Git reference, or command arguments |
| 3 | Unexpected internal tool error |
🩺 Badge and doctor
agent-xplat badge
agent-xplat doctor
The default badge says Static Checked and Inference only. A Cross-OS Verified badge must be backed by a verification artifact that records verified Windows, macOS, and Linux evidence; the badge label is never implied by a static scan. doctor only reports local availability of Git, Node, Python, Docker, PowerShell, Git Bash, WSL, Bash, and zsh. It does not inspect repository health.
🛡️ Security model
Default commands are offline, read-only with respect to the target source, non-executing, non-telemetric, and do not upload data. test is the only command that may execute a selected allowlisted project test command, and it has no shell operators, a bounded timeout, and a clear runtime evidence record. There is no AI API, SaaS backend, credential upload, or hidden network path.
🏗️ Architecture
See docs/ARCHITECTURE.md. The core flow is:
Config -> bounded discovery -> structured/text parsers -> rule registry
-> target-specific findings -> suppression -> score/contract
-> terminal / JSON / SARIF / Markdown / baseline / diff
⚠️ Limitations and roadmap
Static analysis cannot prove every shell version, installed tool, filesystem policy, native binary, dynamic command string, or runtime behavior. JavaScript-family source now has structured AST coverage for the supported suffixes, but dynamic evaluation, generated code, unsupported syntax recovery, and actual subprocess behavior remain runtime concerns. The release workflow is generated and documented, but hosted runner evidence must come from the user's GitHub repository. Future work may add more runtime adapters and independently reviewed rules without changing the public finding contract.
📦 Release and verification
The current release is v1.0.1. The package is published to PyPI as a wheel and source distribution, and the GitHub Release v1.0.1 is the release record.
The release path uses GitHub Actions Trusted Publishing: an OIDC-based publication flow that avoids long-lived PyPI tokens. The repository's verification record documents local checks, hosted Windows/macOS/Linux evidence, package readback, and the boundary between inferred static findings and verified runtime results. Release changes are summarized in CHANGELOG.md.
🤝 Contributing
Read CONTRIBUTING.md, add a positive and negative fixture for every rule change, run python -m pytest -q, and preserve deterministic output. Do not add telemetry, network calls, secrets, or machine-specific paths.
📄 License
MIT. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agent_xplat-1.0.2.tar.gz.
File metadata
- Download URL: agent_xplat-1.0.2.tar.gz
- Upload date:
- Size: 77.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a4fe21a1f8dfd22dd57686e07128a601f591f1cf0d3eeb014ad90921ce40f58
|
|
| MD5 |
31ec78112cb7a17471bf3d18279e426a
|
|
| BLAKE2b-256 |
b1c490ff5905f40970c6d87aa6d2d30eeac7817507cb901f631bab3a8d378b68
|
Provenance
The following attestation bundles were made for agent_xplat-1.0.2.tar.gz:
Publisher:
publish-pypi.yml on kwhi6693-web/agent-xplat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agent_xplat-1.0.2.tar.gz -
Subject digest:
6a4fe21a1f8dfd22dd57686e07128a601f591f1cf0d3eeb014ad90921ce40f58 - Sigstore transparency entry: 2733775976
- Sigstore integration time:
-
Permalink:
kwhi6693-web/agent-xplat@2270038a01bf2c5785fb6f43b462a2a81ed5b15f -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/kwhi6693-web
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@2270038a01bf2c5785fb6f43b462a2a81ed5b15f -
Trigger Event:
release
-
Statement type:
File details
Details for the file agent_xplat-1.0.2-py3-none-any.whl.
File metadata
- Download URL: agent_xplat-1.0.2-py3-none-any.whl
- Upload date:
- Size: 75.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c63fc3a085bd6ca9c9566d27b54ee2fedd946e8c9007492e3ed169efc9c5b311
|
|
| MD5 |
7301bd8b39a8a7744398e8a87cec3595
|
|
| BLAKE2b-256 |
276e1defbd8fee5de28df902598756fd0236f73aa3d64bb7ca19d4b06b1d6c6c
|
Provenance
The following attestation bundles were made for agent_xplat-1.0.2-py3-none-any.whl:
Publisher:
publish-pypi.yml on kwhi6693-web/agent-xplat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agent_xplat-1.0.2-py3-none-any.whl -
Subject digest:
c63fc3a085bd6ca9c9566d27b54ee2fedd946e8c9007492e3ed169efc9c5b311 - Sigstore transparency entry: 2733775982
- Sigstore integration time:
-
Permalink:
kwhi6693-web/agent-xplat@2270038a01bf2c5785fb6f43b462a2a81ed5b15f -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/kwhi6693-web
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@2270038a01bf2c5785fb6f43b462a2a81ed5b15f -
Trigger Event:
release
-
Statement type: