oats-scan
See what the agent skills on your machine tell an AI agent to run.
pip install oats-scan
oats-scan
Thirty seconds. No account, no sign up, no configuration, and nothing leaves your machine.
You already installed these
Agent skills are markdown files that tell an AI what commands to run on your computer. You install them the way people installed browser extensions in 2010: on a recommendation, without reading them.
Your agent reads them. You usually don't.
oats-scan reads them for you. Here is a real run on a working laptop:
Scanning 3 installed skill locations and my-project
4331 files, 1528 command blocks. Classifying ...
What these instruct an agent to do
Destructive command 4 always needs a person
Remote code execution 13 always needs a person
Credential access 2 always needs a person
Shell command 1506
Read 3
19 of 1528 actions, in 3 classes, can never run unattended.
Those are the ones worth your attention.
Nineteen. In plugins from well known vendors, all of them legitimate. One is this line, sitting in an installed skill, waiting for the agent to decide to run it:
curl -fsSL https://downloads.cursor.com/origin/install.sh | sh
Nothing there is an attack. That is the point. You still want to know.
oats-scan --files # which skill each one came from
Install
pip install oats-scan
Python 3.9 or newer. No other dependencies: pip list will show oats-scan
and nothing else.
Platform support. The classifier is compiled, so each platform has its own
wheel and pip downloads only yours.
| Platform | Wheel |
|---|---|
| macOS, Apple Silicon and Intel | universal |
| Linux x86-64 | yes |
| Linux aarch64 | yes |
| Windows x86-64 | yes |
Working from source. This repository holds the Python and the tests; the compiled classifier is not committed, which is why a clone is small and fast. To run against a source checkout, install the package for the binaries and put the checkout ahead of it:
git clone https://github.com/pheo-ai/oats-scan
cd oats-scan
pip install oats-scan
PYTHONPATH=src python3 -m oats_scan --files
Or point OATS_SCAN_BIN_DIR at a directory holding pheo-action-gateway and
oatsctl.
What it looks at
With no arguments it reads the agent skills installed on this machine:
~/.claude, ~/.cursor, ~/.codex, ~/.openclaw, ~/.aider, ~/.windsurf,
~/.gemini, ~/.continue, plus the directory you are standing in.
Give it a path to read somewhere specific:
oats-scan ~/my-project
oats-scan --json # machine readable
oats-scan --strict # exit 1 if anything needs review, for CI
How it decides
Every command is sorted into one of 33 consequence classes, each carrying a
severity from 0 to 100. Classes at or above 75 are the ones that can never
become routine, however well an agent has behaved. Those are what
always needs a person marks.
Some things you can take back:
- Agent writes a bad document, you fix the document
- Agent opens a pull request, you close it
Some you can't:
- Agent deletes a folder, the files are gone
- Agent pushes to production, your customers already saw it
- Agent reads your password file, it has your password now
- Agent runs a script off the internet, whatever it did, it did
The classifier is deterministic. No model, no inference, no network call. It reads the command string and nothing else, so the same command produces the same class today, next year, and on your machine. Any result can be re-derived without re-running anything.
The full list of 33 classes ships with the package as
oats_scan/data/action-classes.json.
What it tells you, and what it leaves to you
oats-scan reports the class of each action. It does not decide whether
that action is acceptable, because that answer is yours.
A startup will let an agent install packages all day. A bank will not let one read a credential file, ever. Both are right. They are different companies with different blast radii. So this gives you the view and leaves the limit to you.
Everything it reports is normal software doing normal things. Installers download and run code, because that is what installers are for. Some of those actions happen to be ones you cannot undo, and those are the ones worth a look.
How it works with your other tools
oats-scan reads actions. Registry scanners read artifacts. The two see
different things and both are worth having.
Scanners are the right tool for harm that never becomes an action: a hardcoded
recipient, an undisclosed scope, an instruction written to talk an agent into
misbehaving. oats-scan is the right tool for what the agent then goes and
does. Run both and you cover both.
Honest limits
These counts are a floor. Only fenced shell content is read. Prose is ignored, because "this skill can delete your notes" is a sentence rather than an action. A block is skipped unless its first command is a recognised one. The real number is what you see here or higher.
Precision is 92%, with a 95% confidence interval of [84.8, 96.5] on a
hand adjudicated sample of 100. The known failure mode is content that looks
like a command inside a heredoc. When that happens the extra line is visible in
--files, so you can see it and judge for yourself.
Unresolved blocks are counted separately. A block the classifier could not read is reported on its own line rather than folded in with the clean ones.
Privacy
Everything runs on your machine. The classifier is a local process listening on 127.0.0.1, started for the length of the scan and shut down afterwards. It writes to a temporary database that is deleted when the scan ends, so a scan never touches state you rely on. No telemetry, no account, no network calls.
Where this comes from
The classifier is the resolver from the Open Agent Trust System, the same one that runs in front of live agents deciding whether an action executes. The measurement study behind the class list covers 66,192 public agent skills, and the classification of all of them is published as pheo-ai/clawhub-consequence-classes.
Once you can see what your agent is told to do, the next question is usually
whether something can hold an action while you look at it. That is
Pheo OATS, which is the gateway this classifier normally
lives in. oats-scan is the view. The gateway is the brake. Start with the
view.
Licence
The Python source in this repository is MIT. The compiled classifier bundled in
the published wheels is proprietary software of Pheo Inc., redistributable as
part of an unmodified oats-scan wheel. See LICENSE.
Release files for oats-scan 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| oats_scan-0.1.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| oats_scan-0.1.0-py3-none-manylinux_2_28_x86_64.whl | Python 3 | none | Linux glibc 2.28+ x86-64 | Details |
| oats_scan-0.1.0-py3-none-manylinux_2_28_aarch64.whl | Python 3 | none | Linux glibc 2.28+ ARM64 | Details |
| oats_scan-0.1.0-py3-none-macosx_10_9_universal2.whl | Python 3 | none | macOS 10.9+ universal2 (ARM64, x86-64) | Details |
Total release size: 39.5 MB
Release files / oats_scan-0.1.0-py3-none-win_amd64.whl
| Download URL | oats_scan-0.1.0-py3-none-win_amd64.whl |
|---|---|
| Size | 7.7 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
75b7d85479db54035c46728740caac21a14bf02aeb4150eeb092ace9dd851845
|
|
BLAKE2b-256 checksum How to use checksums |
143c8f314f51c1cd03cbd8df48e253ca2c68324bde34f603623a54d0b46f15bd
|
| 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 Sep 12, 2026.
Transparency logRelease files / oats_scan-0.1.0-py3-none-manylinux_2_28_x86_64.whl
| Download URL | oats_scan-0.1.0-py3-none-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 8.0 MB |
| Tags | Linux glibc 2.28+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
3c61dabfd0c932a85e3d47c1887f156bee83191270c18b2cdd6fe44f50527905
|
|
BLAKE2b-256 checksum How to use checksums |
ce0d2f56246704711bbe2c089da31d06bd75882aaba967579db5d4a37ff2c8be
|
| 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 Sep 12, 2026.
Transparency logRelease files / oats_scan-0.1.0-py3-none-manylinux_2_28_aarch64.whl
| Download URL | oats_scan-0.1.0-py3-none-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 7.5 MB |
| Tags | Linux glibc 2.28+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
d7dd78f46bca1b8e7bfec0c0541ae952f8f1e3cf484274d402a9582fe526a5da
|
|
BLAKE2b-256 checksum How to use checksums |
e229543a33fe3eb814bb0182a60f560548221ba499915007304c4a44dc063c7c
|
| 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 Sep 12, 2026.
Transparency logRelease files / oats_scan-0.1.0-py3-none-macosx_10_9_universal2.whl
| Download URL | oats_scan-0.1.0-py3-none-macosx_10_9_universal2.whl |
|---|---|
| Size | 16.4 MB |
| Tags | Python 3 macOS 10.9+ universal2 (ARM64, x86-64) |
|
SHA-256 checksum How to use checksums |
7d89c9439234d53946582435631e1aba0f0254aa4cd4d8badc7edeef3ddbe94e
|
|
BLAKE2b-256 checksum How to use checksums |
a24d7c45fdd95be57e6189fcb17a9913fdc5c205ff64b8348a72aa4bb0f826cf
|
| 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 Sep 12, 2026.
Transparency log