DACIP DACIP

Licensing & the trial

Four paths, one rule each:

You are running on Identity needed Network calls Cost
A public repo none public check only (see below) free forever
A private repo, trial dacip login one allow-check per run free for 1 private repo
A private repo, licensed RSA license file none (renewal only) paid
The GitHub App (PR gating) App installation server-side by nature free tier / Team

Public repos: free forever

Before scan, investigate, diff, baseline, or verify touches a private-path decision, DACIP checks locally whether the repo is public. Three steps:

  1. git remote get-url origin must parse to github.com/<owner>/<repo>.
  2. An unauthenticated GET https://api.github.com/repos/<owner>/<repo> must return 200 with "private": false.
  3. git ls-remote against that URL must list your local HEAD commit among its ref SHAs. This is the anti-spoof step: pointing origin at some unrelated public repo fails, because your commits don't exist there.

All three pass → no login, no ping, no meter. The check itself sends nothing about your code except one commit SHA; the analysis pipeline makes no network calls at all (there is no LLM in it — see /docs/determinism/).

Stale checkouts: ls-remote returns branch and tag tips only. If your HEAD is behind the remote — or ahead with unpushed commits — step 3 fails and the repo is treated as private. Pull (or push) and rerun. Any failure is treated as non-public by design, including DACIP_OFFLINE=1, no remote, or a non-GitHub host.

dacip login

Private repos need a GitHub sign-in. It's the standard device flow:

$ dacip login
To sign in, open https://github.com/login/device and enter code:  ABCD-1234
Signed in as ana. Free trial: 1 private repo.

The OAuth scope is empty on purpose: the token can read your username and nothing else. DACIP never receives repo access, so it cannot read your code even in principle. The GitHub token is exchanged once for a DACIP session token and discarded; the session lands in ~/.dacip/session.json (mode 0600). dacip logout deletes it; dacip whoami prints your login.

The trial meter

On a non-public repo with a session and no license, each run sends exactly one request:

{ "session": "...", "repo_id": "r_<sha256 of the origin URL, truncated>" }

The repo_id is an opaque one-way hash — it lets the server count distinct repos per user (the free tier is 1 private repo, matching the App) without knowing which repo it is. The ping contains no source, no file names, no routes, no findings. What we can see: that user ana scanned some private repo, and how many times. What we never see: everything else — and public-repo runs and licensed runs never ping at all.

Over the cap, DACIP refuses with a pointer to pricing. It never degrades output silently.

Licensed binaries

A license is a signed JSON file (customer, plan, expires) verified fully offline against a public key embedded in the binary — no phone-home on the paid path. Default location ~/.dacip/license.json (override with DACIP_LICENSE). Licenses are issued for 30 days; renewal is one command against your customer token:

curl -H 'Authorization: Bearer <your token>' \
  https://dacip-app.fly.dev/license -o ~/.dacip/license.json

States, in order: validexpiring (≤14 days left, runs with a warning) → grace (expired ≤14 days, runs with a loud warning) → hard stop, exit 3. dacip license prints the current state and is never gated itself.

Team seats

The Team tier is $15 per active contributor per month, unlimited private repos. A seat is any unique PR author whose PR DACIP gated in the billing month — counted automatically from webhook events, never self-reported. Bot logins (*[bot], plus dependabot, renovate, github-actions) are excluded. If a seat limit is hit, new contributors' PRs are visibly ungated — never blocked, never silently skipped. Details in /docs/github-app/.

The honest ceiling

Because DACIP never uploads source, it can never fully prove a local working tree is private. A determined user can spoof the public check by patching the binary. We accept that: the check raises the bar from "rename a remote" to "publish your code or patch the binary", and we stop there rather than adding phone-home to the paid path. More on this trade-off in the FAQ.

New to DACIP? Start at /docs/quickstart/ — no account needed on a public repo.