Account · Getting started
CLI & npm guide
Install Lintora in any JavaScript project, tune what is scanned, silence specific lines when justified, and use the same CLI locally and in CI. By default the terminal shows a short summary; full findings and hub upload paths are one flag away.
Install, CI, and command reference: @lintora/core on npm (README).
Install from npm
Add the engine to your repo (Node 20+). You can use npx without a global install.
npm install @lintora/core --save-dev
Run the binary via:
npx lintora run
Sign in from the terminal (required for a normal run)
lintora run talks to the hosted license gate. On your workstation, save a session once per machine (or after you replaced the active device). From the project root where @lintora/core is installed:
cd /path/to/your/repo
npm install
npx lintora login
The CLI prints a https://lintora.dev/account/cli-link.html?... URL. Open it in a browser that is signed into the same Lintora account, approve the link, then return to the terminal. Next:
npx lintora run
Clear saved credentials and license cache under ~/.lintora/ (or LINTORA_HOME):
npx lintora logout
Show local paths, install key fingerprint, and short license state:
npx lintora status
List server-side devices (needs a saved session):
npx lintora status --devices
No node_modules yet? Either install first (npm install @lintora/core --save-dev) or invoke the published package directly (same commands, one-off download):
npx --yes -p @lintora/core@latest lintora login
npx --yes -p @lintora/core@latest lintora run
License server HTTP 500 (internal_error): that is a server-side failure inside license-check (not "you forgot login" by itself). Fix the Supabase Edge deploy, migrations, and Edge secrets for your project, wait a moment, then run npx lintora login again and npx lintora run. If you ever exported a stale LINTORA_INSTALL_KEY, run unset LINTORA_INSTALL_KEY so the key from lintora login wins on a normal laptop.
Update an existing project
npx lintora run uses the package already in node_modules; it does not fetch a new release each time. From your
project root, bump within the semver range in package.json (for example ^1.2.2) with:
npm update @lintora/core
To install one exact published version (for example after a changelog fix), run
npm install @lintora/core@1.2.2 --save-dev with the version you want, then commit the updated lockfile. See
@lintora/core on npm
for what is published.
After lintora login, the CLI keeps your session under ~/.lintora/ by default (for example
credentials.json and license.json). They are never created in your project root by
npm; treat that directory as local-only and do not commit it.
Multiple accounts on one computer: signing out on the website and signing in with another email only changes the
browser session. The CLI still reads whatever is stored on disk for the active shell. To keep accounts isolated, set
LINTORA_HOME to a dedicated directory before npx lintora login and every
npx lintora run for that account (for example export LINTORA_HOME="$HOME/.lintora-work" in a shell profile or per-project script).
Use npx lintora logout to clear credentials and license cache under whichever directory is currently in effect.
Install key precedence: on a normal workstation, the key saved by lintora login in
credentials.json is used before LINTORA_INSTALL_KEY from the shell (CI is the opposite so job secrets work without a home directory). If you once exported an old key, either unset LINTORA_INSTALL_KEY or set it to the current key so it matches what you expect.
If run prints that the license backend did not return WASM policy keys, that is separate from "device replaced"
or the rolling device-change limit: it means the online license response did not include encrypted policy keys (the hosted
license-check stack must expose that field). Creating a new install key does not fix that by itself.
If your terminal is not already in the project root, set the scan root with --cwd (absolute or relative path). Example from a parent directory:
npx lintora run --cwd ./my-app
Prefer pinning the version in package.json so CI and teammates stay aligned.
Sign in, active device, replace flow, and CI service keys
Run lintora login on a machine you trust, then approve the session in the browser. Your account keeps
one active workstation key; replacing it is limited per rolling 30-day window. Use
lintora status for local state and lintora status --devices (with a saved session) to fetch the server-side device list.
If the terminal says "This device was replaced"
In an interactive terminal (TTY, not CI), npx lintora run can open the same browser re-bind flow automatically once; you still approve replacement on the site. Headless runners keep the explicit lintora login or LINTORA_INSTALL_KEY path.
Two different things live side by side: your browser session on lintora.dev (Sign in /
Sign out in the header) and the CLI install key under ~/.lintora/. Creating a
new personal key on Install keys does not automatically
replace what the terminal already saved until you complete a login flow or set LINTORA_INSTALL_KEY
to the full secret (shown only once at creation time).
- Fix the wrong browser account first (if applicable). If you might have approved a device link while signed into a different Google or GitHub identity than the one you use for Lintora, use Sign out (top right on account pages), then Sign in again. That only refreshes the website session; it is still required so the next step matches the right account.
-
Re-bind this machine to the active install key. In the project terminal run
npx lintora login(orlintora loginif your PATH has the binary). Complete the browser flow; approve replacing the active device when the site asks. After it succeeds, runnpx lintora runagain.
For GitHub Actions and other headless runners, create a service install key on
Install keys, set LINTORA_INSTALL_KEY in the job, and rotate or revoke the key from the same page when a secret leaks.
Replace this workstation (no second laptop required)
Lintora allows one active personal install key per account. Moving to a new machine means approving a replacement in the browser. You do not need a second physical laptop: any separate environment with its own shell is enough, for example a cloud IDE (Codespaces, Gitpod), a disposable cloud VM, or a colleague's computer where you are allowed to run the CLI once.
-
In the new environment, install Node 20+, install
@lintora/core, then runnpx lintora login(orlintora login --token ...if you use a token). - Copy the
https://lintora.dev/account/cli-link.html?...URL the CLI prints. - On your everyday browser (already signed into the same Lintora account), open that URL. If you already have an active device, the page shows Replace and authorize or Cancel. Confirm only if you intend to move the active key to the new environment.
- Return to the new environment's terminal and wait for the CLI to finish; it stores the new install key under
~/.lintora/on that machine.
Limits and counts: lintora status --devices (with a saved session on the machine that has your access token) shows how many replacements you used in the rolling window. Full policy: device binding doc in the monorepo.
Run checks and capture output
With --format human (the default), the CLI prints a short English summary (counts and a hub hint), not the full per-policy listing in the terminal. That keeps logs readable in CI and large repos.
To print the full findings list to the terminal (older-style output), add
--show-findings or set LINTORA_SHOW_FINDINGS=1 for the same process.
npx lintora run --show-findings
For machines or CI parsers, use agent JSON:
npx lintora run --format agent
Lossless report file (full violations + metadata, schema lintora.lossless-report.v1). This is what the hub ingests and what you should archive for audits:
npx lintora run --report-path ./lintora-report.json
Optional --report-on issues only writes the report file when there are findings. For a plain-text list on disk (no ANSI), use:
npx lintora run --violations-log ./violations.txt
Run a single policy for faster iteration: --policy API-001-009 (replace with the policy ID you need).
Customize with lintora.config.json
Create lintora.config.json at the project root. Empty {} is valid: defaults apply (wide include globs, common build folders excluded).
Useful keys:
rootDir— scan root in config (default: shell cwd, or the path passed with--cwdon the CLI).include/exclude— glob arrays; add paths to skip whole trees (policies never run there).enableTypeAwareAnalysis— settruefor type-aware ARC policies (recommended for TS-heavy apps).maxConcurrentFiles— tune parallelism on large repos.
Example shape (trim to your stack):
{
"enableTypeAwareAnalysis": true,
"rootDir": ".",
"include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"],
"exclude": ["node_modules/**", "dist/**", "build/**", ".next/**"]
}
Deactivate policies for a whole project: exclude files where they should not apply, or run with --policy <id> for a single rule.
There is no per-policy "off switch" in config today; narrowing include/exclude is the supported scope control.
Line-level suppressions (bypass)
When a violation is a documented exception, place a suppression comment on the line immediately above the reported line. Use the exact policy ID (case-sensitive). The engine only reads line comments in this form:
// lintora-disable-next-line POLICY-ID
Multiple policies on one line: list several IDs separated by spaces. Each token must look like a real policy id (uppercase letters, digits, hyphens). The next line is waived for every listed id that would otherwise fire on that line.
// lintora-disable-next-line TSQ-001-029 TSQ-001-002
useQuery({ queryKey: ['x'], queryFn: () => fetch('/api') });
Single-policy example:
// lintora-disable-next-line PERF-006-004
for (const x of items) {
await process(x);
}
Wrong IDs never suppress. Exception metadata ids (ending in -EXC) are not substitutes. Prefer fixing the code; use bypass only with a clear rationale (audit trail).
Hub upload (default after lintora run)
When you are signed in on the machine (lintora login) and the CLI can reach Supabase, npx lintora run already performs the
hybrid hub handoff after the scan: it writes ~/.lintora/last-report.json and uploads the lossless payload to your account when
LINTORA_HUB_PUBLISH is not set to 0. You do not need the deprecated --web-publish flag on
run (it is ignored and may print a short notice).
Typical local flow: write a report file and open the hub URL in your default browser after upload:
npx lintora run --report-path ./lintora-report.json --web-open
If the report file was skipped (--report-on issues with a clean run), there is nothing to upload until you change --report-on or introduce a finding.
CI / Docker: set LINTORA_PUBLIC_SUPABASE_URL, LINTORA_PUBLIC_SUPABASE_ANON_KEY, and the same
LINTORA_INSTALL_KEY you use for license checks. Then npx lintora run --report-path ./lintora-report.json uploads straight to your hub without a browser login, provided the matching Supabase migration is applied in your project.
Upload an existing JSON file: use the standalone command (for files produced earlier):
npx lintora web publish --report-path ./lintora-report.json --open
After upload, open Hub and pick a run in the list for the grouped policy view.
What is uploaded (lossless JSON)
Schema lintora.lossless-report.v1 (see the published types / monorepo sources). Summary of fields:
schemaVersion,generatedAtUtc,runFingerprintcontext.cwd(absolute scan root),context.format,context.policy,context.reportOnsummary: counts and per-severity / per-policy breakdownsoutput.errorsandoutput.violations(violations may include absolutefilepaths; source snippets are not included)
Opt-out: set LINTORA_HUB_PUBLISH=0 for the CLI process to disable hub upload; local --report-path files still work.