IntentiAI

Docs

IntentiAI is one command-line tool with two jobs. intentiai audits a repository for patterns that run up an AI bill. intentiai check reviews what a coding agent just changed, before you push.

Install

Nothing to install. Run it with npx from the root of any repository:

npx intentiai

It needs Node 20 or later. Python 3 is optional: with it, Python files are read with a real parser; without it, they are read line by line and a few rules see less. No API key, account or network access is needed to scan.

Cost audit

npx intentiai [path]

It finds every call to a model provider (through the official SDKs, LangChain, LiteLLM, the Vercel AI SDK, Spring AI, LangChain4j, LangChainGo, or plain HTTP to a provider endpoint) and checks it against the rules below. How deep it goes depends on the language:

LanguageWhat runs
TypeScript, JavaScript, PythonEvery call site and all 21 rules, with a real parser.
Go, Java, Ruby, PHPEvery call site, and the 8 rules that need no deeper analysis: missing caps, oversized models, no budget guard, unprotected endpoints, scheduled jobs, vision calls in loops, batchable work, committed keys. Measured at 96 to 100% of call sites found on 37 real apps.
Everything elseCounted and named as not scanned, so a quiet result is never mistaken for a clean one.

It prints a short summary, uploads the findings, and prints a private link to the full report. The upload is findings only: rule, file, line, summary, fix and the model names it saw. Your source code is never sent. See Privacy for the exact fields.

Every dollar figure is an estimate with its assumptions stated next to it: the model it assumed, the calls per month, the token counts. When the model cannot be read from the code, the report says which model it assumed instead of guessing silently.

Cost audit flags

--localAudit and print locally. Nothing is uploaded and no link is printed.
--jsonPrint the full audit as JSON instead of the summary, for scripts and CI.

What the audit looks for

Fourteen of the 21 rules cite the published study or incident behind them, linked from the finding in the report.

no-budget-guardNo dollar or token cap anywhere on the path to a paid call.
guard-conditional-on-envA spending or abuse guard that only exists when certain env vars are set.
no-max-tokensA call with no output cap on a model where long answers are expensive.
model-oversizedA frontier model doing a short, simple job where a cheaper sibling is likely enough.
agent-loop-unboundedAn agent or tool loop with no iteration limit.
retry-stormRetries on a paid call with no cap, no backoff, or both.
orphaned-async-jobA billable job polled with no deadline and no way to cancel it.
full-history-resendThe whole conversation re-sent on every turn, so cost grows with its square.
recurring-job-llmA scheduled job that calls a model whether or not anyone is using the app.
vision-in-loop-uncappedImage or vision calls inside a loop with no limit on how many.
reasoning-budget-in-loopA high reasoning budget on a call that runs many times.
auxiliary-call-multiplicationExtra model calls (moderation, titles, summaries) multiplying every request.
cache-storage-leakProvider-side caches created and never deleted, billed by the hour.
cache-write-churnPrompt caching on text that changes every call, so you pay to write and never read.
result-cache-candidateThe same deterministic call paid for again on every duplicate request.
sync-batch-candidateBulk work sent one call at a time where a batch API costs half.
sticky-fallback-modelA fallback to a pricier model that never switches back.
unvalidated-input-to-paid-callRequest fields reaching a paid call with no validation.
unauthenticated-llm-endpointAn endpoint anyone can call that spends your model budget.
client-side-key-exposureA provider key shipped to the browser.
hardcoded-api-keyA provider key committed in source. The key is masked in every report.

Ship Check

npx intentiai check
npx intentiai check --base main

It reads what changed (uncommitted work against HEAD by default) and runs 21 checks for the mistakes coding agents make after their own tests pass. Findings are ordered by risk, each says what happens to people using your app if it ships, and each names the fix.

It writes a full report to .intentiai/ship-check.html and prints the most serious findings. Nothing leaves your machine unless you add --share.

Ship Check flags

--stagedOnly what is staged for the next commit.
--base <ref>Compare against a branch or commit instead of HEAD, for example the branch you will open a PR into.
--jsonPrint findings as JSON.
--no-reportSkip writing the HTML report.
--out <path>Write the HTML report somewhere else.
--openOpen the HTML report in your browser when the check finishes.
--agent [name]Also review with your own installed coding agent: claude, codex, gemini, or auto. See below.
--model <m>The model the agent pass uses.
--task "…"What you asked the agent to do. Its claims are checked against the change.
--shareUpload this result and print a link to it. Off by default, decided per run.

What Ship Check looks for

test-integrityTests deleted, skipped, narrowed with .only, stripped of assertions, loosened in place, or propped up with a sleep; coverage gates lowered.
migration-safetySchema changes that lock or rewrite a table, or drop something the running app still reads.
destructive-opsRecursive deletes, dropped databases, truncates, unfiltered bulk deletes, force pushes.
auth-surfaceA new endpoint with no visible auth, or a webhook that does not check the sender's signature.
removed-guardA validation, permission or rate-limit call deleted without a replacement.
secretsCredentials committed in the change. Masked in every output.
injection-sinkUntrusted data reaching SQL, HTML, a shell, eval or an outbound URL.
workflow-prompt-injectionIssue or PR text interpolated into a CI script or an AI action.
env-driftCode reading an environment variable nothing declares.
dependency-riskAn import with no matching installed package, the offline sign of a hallucinated dependency.
dependency-bumpA dependency moved across a breaking version boundary.
breaking-exportA public function or export removed or re-signed while other code still calls it.
ops-deltasSchedules run more often, retries added without backoff, timeouts raised, CI concurrency that does nothing.
io-in-loopA database, HTTP or model call made once per loop iteration.
unawaited-asyncAn async call whose result, and whose failure, is dropped.
resource-leakA file, socket, cursor or interval opened and never released.
swallowed-errorsAn empty catch, except or rescue; an error assigned to _ in Go.
suppressed-diagnosticsType or lint errors silenced without a stated reason.
unfinished-workTODOs, stubs and placeholder values left in the change.
debug-leftoversDebugger statements and stray debug prints in application code.
scope-creepCI, infrastructure or generated files touched, or a change too large to review.

Your own agent

npx intentiai check --agent claude --task "add Stripe webhooks"

With --agent, IntentiAI hands the change and its findings to the coding agent you already have installed and signed in (Claude Code, Codex or Gemini CLI) in read-only mode. It runs on your plan, and the report shows what the run cost.

The agent is allowed to do five things, and only these:

  • summarize the change and each file in plain English;
  • compare what it was asked to do (your --task) against what the code actually does;
  • confirm a finding, or rule one out with a stated reason; ruled-out findings stay visible in the report;
  • list what to check before and after you deploy;
  • report up to five defects of its own, each with a file, a line and the exact line quoted. One is kept only if that line exists in a changed file within three lines of where the agent says, and it does not repeat a deterministic finding. They appear in their own “Found by your agent” section, each marked “checked that the quoted line exists, not that the problem is real.”

This is what catches the mistakes no pattern can: a limit applied to the wrong kind of account, a header replaced instead of merged. It cannot change the severity of a deterministic finding, its own findings are never marked critical, and they never count toward the exit code. If it fails or times out, you get the deterministic result unchanged. The change it reads goes to that agent’s provider under your own account’s terms, not to IntentiAI.

Run it automatically

A check you have to remember to run is a check that gets skipped. Three ways to make it happen on its own:

When Claude Code finishes a task

npx intentiai init claude

This adds a Stop hook to .claude/settings.json in your project (add --user for every project). When Claude Code says it is done, Ship Check reviews the change, including commits it made but has not pushed. If there are critical or high findings, they go back to Claude with their fixes, and it gets one round to fix them or explain why each is intended before it stops. It never loops, and if the check itself fails, Claude stops normally. To undo it, remove the intentiai entry under hooks.Stop in that file.

When Codex finishes a task

npx intentiai init codex

Codex has no hook that can stop it from finishing, so this adds a short section to AGENTS.md asking it to run the check and address critical findings. It is an instruction Codex reads, not something enforced.

Before every push

npx intentiai install-hook

Installs a git pre-push hook that checks everything you are about to push against the branch you push to. A critical finding stops the push; git push --no-verify skips it once. It will not replace a hook you already have unless you add --force.

Connect your computer

npx intentiai login

Without an account, every upload prints a private link you open to keep the report. Connect the computer once and reports go straight to your account instead: login shows a short code and opens a page where you confirm it. npx intentiai whoami shows which account a computer uses, npx intentiai logout disconnects it, and your Account page lists every connected computer with a button to revoke it.

Exit codes and CI

  • intentiai check exits 1 when there is at least one critical finding, 0 otherwise, and 2 on a usage error, so it can gate a pre-push hook or a CI job.
  • intentiai (the cost audit) exits 0 after a successful scan whatever it finds; use --json and your own threshold if you want it to gate.
# in CI, on a pull request
npx intentiai check --base origin/main --no-report

Troubleshooting

The claim link says it has expired

Unclaimed cost reports are deleted after seven days, and shared Ship Checks after two. Run the command again for a fresh link.

The sign-in email link does not work

Open it in the same browser you requested it from; the link is tied to that browser. Each link works once.

“Not scanned: N Kotlin files”

The audit reads TypeScript, JavaScript, Python, Go, Java, Ruby and PHP. Other languages are listed so you know what was not checked. Kotlin, C# and Rust are next: they are measured already but do not yet find enough of the calls to ship.

“This change is too large to review as one change”

The diff is over 64 MB. Point --base at a nearer commit, or check the change in parts.

Something else

Open an issue on GitHub with the command you ran and what it printed.

Docs: cost audit and Ship Check commands and flags | IntentiAI