ZIFFER home

The scanner: run it

Who this is for: the engineer who wants to know what the AI agents in their code, and on their machine, can do before anything is installed.

Who this is for: the engineer who wants to know what the AI agents in their code, and on their machine, can do before anything is installed.

What you end up with: a report of every tool a model can call, which of them cannot be undone, and a draft policy for ZIFFER, the agent authorization service, written from what was found. Nothing is sent anywhere, and you do not need an account.

Read what the scan reads and does not before you trust a clean result. The scan reads source files and configuration. It reads no running system, so a tool your application only builds at run time can be missing from the report, and a check the scan did not find is not proof that nobody is asked.

This page describes @ziffer-io/scan version 0.3.0. The command it installs is ziffer-scan.


1. What the scan is for

It finds the tools a model can call: the ones your own code gives a model, and the ones the AI tools installed on your machine can reach. It then shows what ZIFFER would do with each call, using ZIFFER's own decision engine, which runs on your machine inside the package.


2. What you need

  • Node.js 22 or later.
  • Python 3.9 or later, only if your project has Python files. The scan reads Python with your machine's own Python, found on your PATH as python3 or python. Without it, the Python files are not read: the report says how many Python files were present and not read, and it does not claim it found no tools in them.
  • For a TypeScript or JavaScript project, run it after installing your dependencies. The scan follows types, and imports it cannot resolve make the grade provisional. What the scan reads says more.

3. Run it

From your project folder:

npx @ziffer-io/scan

It first says what it will read. It reads your code, then lists every tool server your AI tools are configured to start, and asks before starting any of them:

1 tool server will be started to list their tools:
  mail  node mail-server.mjs  (Claude Code)

Answer y to start them. Any other answer stops the run by name, and nothing is started. This is output from an example project with one invented server, mail.

To see every option:

npx @ziffer-io/scan --help

4. Three ways to run it

The default: your code, then your installed AI tools. One draft policy covers both. It also replays eight injected instructions against that draft, to show what each would do with and without ZIFFER. Run from your home folder or from /, the code half is skipped with one line saying so: pass --cwd or run from your project folder.

--code: your code only. It starts no tool server and reads no home folder. It ends with the one place to put the ZIFFER call in your code and the code to paste there. There is no replay, because the injected instructions are aimed at an installed AI tool and none was read. Run from your home folder or from /, it refuses by name.

npx @ziffer-io/scan --code --report

--ci <policy-dir>: a pull request in your policy repository. It reads no code. It starts the tool servers configured in that repository, without asking, and grades each tool against the draft policy in <policy-dir>, read unsigned because a pull request carries a draft. It prints one line per tool and exits 1 if any tool is refused, with the line to add to the policy.

npx @ziffer-io/scan --ci policy

In an example repository with one mail server, the first and last lines were:

UNSIGNED: the policy was read without checking a signature, because a pull request carries a draft; this checks what the rules decide, not that the bundle verifies.
2 tools graded: 1 allowed, 1 held for approval, 0 refused; 0 not checked. Exit 0.

A server that cannot start in the job is printed as not checked, and does not fail the run.

There is also ziffer-scan replay: the eight injected instructions against the test policy shipped in the package, and nothing else.


5. Every option

OptionWhat it does
--codeYour code only. Starts no tool server. Cannot be combined with replay, --no-code, --ci, --home, --yes, --timeout or --no-replay.
--no-codeYour installed AI tools only. The code is not read.
--cwd <dir>The folder whose code is read, and the project whose AI tool configuration is read. Default: the current folder.
--fullAfter the one-screen summary, the complete report and the replay case by case.
--jsonOne JSON document on standard output instead of the screen. Progress and questions go to standard error.
--yesStart the tool servers found without asking. Use it only when you have read the list another way.
--out <dir>Where the draft policy folder is written. Default ./ziffer-scan/ziffer-policy. Everything else goes beside it.
--no-replayWrite the draft policy, skip the replay.
--timeout <s>Seconds each tool server has to start and list its tools. Default 60. A server fetched by npx or uvx can need longer the first time.
--home <dir>Read the AI tool configuration under this home folder instead of yours.
--platform <p>darwin, linux or win32. Default: this machine's.
--colorColour even when standard output is not a terminal.
--no-colorNo colour. Setting the NO_COLOR environment variable does the same.
--reportAlso write the HTML report, the JSON file and the review archive. See section 6.
--ci <policy-dir>The pull-request check in section 4. Implies --yes. Cannot be combined with replay, --out, --report, --home, --full, --no-replay or --no-code.
--helpThe option list. -h does the same.
--versionThe version of the package.

An option the scan does not know is refused by name, with the option list after it.


6. What it writes, and where

Everything goes in one folder, ./ziffer-scan/, in the folder you ran it from. --out moves the policy folder, and everything else is written beside it.

FileWhen
ziffer-policy/Every run except --ci and replay. The draft policy.
ziffer-tools.jsonWhen your code was read. The ZIFFER call you paste reads the tool names from it: ship it with your application, or point ZIFFER_TOOLS_FILE at it.
ziffer-scan.jsonWhen your code was read, or with --report. The same document --json prints.
ziffer-replay-own.jsonWhen the replay ran. One replay case the scan wrote from one of your own tools.
ziffer-scan-report.htmlWith --report. The report to open and forward.
ziffer-review.tar.gzWith --report. The report, the JSON file and the policy folder in one archive, for the review.

It never overwrites. If a file it would write is already there, it refuses by name and writes nothing: move the old folder, or pass another --out. Run inside a git repository, it tells you to add the folder to .gitignore or to write it elsewhere. The first lines after the report's header say what was written and that it is yours to delete.

--ci writes nothing. Credentials are shown as [redacted] on the screen, in the report and in the JSON, and paths under your home folder start with ~ in the files.


7. What it starts, and what it never does

It sends nothing anywhere. The scan, the draft policy, the grading and the replay make no network request. npx itself downloads the package the first time, like any other package.

It starts the tool servers your AI tools are configured to start, and only after you say yes. Before it starts anything it prints each server and the command it will run, and waits for y. With --yes it does not ask. With no terminal to ask on and no --yes, it refuses and starts nothing. At most four servers start at once. The only thing it asks a server is its list of tools: it never calls a tool. A server is given the environment its own configuration declares plus a few basic variables such as PATH and HOME, not the rest of yours. The servers are your own programs and do whatever they do when your AI tools start them, which can include reaching the network. A remote server, one that is turned off, or one whose command is not installed is not started, and the report says why.

Reading your code starts no tool server, which is why --code starts none. To read Python it runs your machine's own Python on the scan's reader, which ships in the package. It looks for that Python whenever it reads your code, even in a project with no Python files.

It runs no AI model and does not change your source files. The only files it writes are the ones in section 6.


8. Exit codes

CodeMeaning
0The run finished. Under --ci: and no tool was refused.
1Under --ci: at least one tool was refused. Otherwise: an error the scan does not name, printed as one line.
2The run was refused, by name, on one line of standard error. For example a wrong option, no terminal to ask on, a folder that already holds a policy, or --code run from a home folder.

A refusal looks like this:

UnknownArgument: --verbose

9. The scan from your AI assistant

The same scan runs from the ZIFFER MCP server, the tool server your AI coding assistant can call. First, add the ZIFFER MCP server to your assistant.

Then ask your assistant, in your own words, to scan the project. It calls the server's scan tool, which runs this package:

  • The first call reads your code and returns what it found. It starts no tool server.
  • Installed tool servers are listed first and started only after you agree. If your AI tools are configured to start tool servers, the first call lists them, with credentials shown as [redacted], and starts none of them. The tool's instructions tell your assistant to show you that list and to call again, to start them, only once you agree.
  • The files go into a new folder under your system's temporary folder, never into your project, unless your assistant names another folder. By default that includes the HTML report and the review archive.
  • You can ask why one tool got its result. Your assistant calls explain_scan_finding with the tool's name, and gets back the engine's decision for it, the entry in the draft policy it came from, and how to change it. It answers about the last scan in that session.

ZIFFER has no AI agent of its own. The server runs the scan and returns its results, and no model is asked anything. The explanation you read, and any change made to your code, come from your own AI assistant.

Two things are not offered from your assistant: the pull-request check (--ci) and the replay on its own (ziffer-scan replay). Run those from the command line.

Next: how to read what the scan wrote.

On this page