← All docs
TensorCheck — code review agentEarly access

TensorCheck documentation.

TensorCheck reviews GitHub.com pull requests and posts its findings back to the pull request as a GitHub review and a Check Run. Run it hosted on TensorPlane, or run the daemon yourself against your own GitHub App.

Overview

What TensorCheck is.

TensorCheck watches a GitHub organization through a GitHub App. When an eligible pull request is opened or updated, it checks the change out into a sandbox, reviews it, and posts the result as a pull request review (a summary plus inline comments) and a Check Run. There are two ways to run it, and each runs the review differently: hosted on TensorPlane, where the platform centrally manages the GitHub App installation and runs the review for you on the platform, using the inference provider and model alias you select for the repository in the console; or self-hosted, where you build and run the daemon against your own GitHub App and it invokes a local CLI (for example codex) that you have logged in on your host. TensorCheck integrates with GitHub.com only; GitHub Enterprise Server is not supported, and no other source-control host is integrated.

Hosted on TensorPlane

Run TensorCheck without operating it.

On the hosted platform, TensorPlane centrally manages the GitHub App installation and enrolls your installation; reviews run on the platform. You configure everything from the console.

  1. Create an account

    Sign up with your email and complete email verification. You can add multi-factor authentication — an authenticator app (TOTP) or a WebAuthn security key or passkey.

  2. Create an organization

    Create a TensorPlane organization to hold your repositories, billing, and settings.

  3. Install the GitHub App and select repositories

    Install the centrally managed TensorPlane GitHub App on your GitHub organization and choose which repositories it may review. The installation is what lets TensorCheck read pull requests and post reviews and Check Runs.

  4. Add a provider credential

    Add an inference-provider API key in the console's provider-credential settings. After you save it, the console stores it sealed and shows only a fingerprint and the last four characters — the secret itself is never displayed again. You can replace or delete a credential later.

  5. Set the repository's review provider and model

    For each repository, select one review inference provider and one provider-scoped model alias in the repository's review configuration.

  6. Open a pull request for an automatic review

    Open a pull request on a selected repository and TensorCheck reviews it automatically, posting a review and a Check Run.

  7. Rerun with a /review comment

    To rerun a review on demand, comment /review on the pull request. Manual reruns are authorized: the comment author must have GitHub repository permission of write or higher (maintain and admin also satisfy it); read and triage are denied.

  8. See review history and operational status

    The console lists your organization's review history and shows current operational status.

  9. Trial and billing

    New organizations get a 14-day trial with no card required. When you're ready, start a subscription through Stripe checkout, and manage your subscription and payment details in the Stripe billing portal from the console. The hosted MVP does not claim an availability SLA.

What is skipped: draft pull requests (until they are marked ready for review) and pull requests from forks. Automatic reviews can also be switched off per repository (automatic_trigger); with them off, an exact /review comment still requests a manual run.

Exact-head ownership: the hosted platform binds every review attempt to one exact head SHA. Immediately before publishing, it re-resolves the pull request's current eligible head; if the head has moved, the older attempt's findings do not become the current pull request review or the merge-gating Check Run — the newest eligible head SHA owns the canonical Check Run.

Self-hosted

Build and run the daemon yourself.

The steps below stand up TensorCheck for development and evaluation against your own GitHub App. Production service activation is not documented here — there is no service unit or install recipe, and the standalone webhook endpoint is not a production ingress. Hosted production runs on TensorPlane.

Prerequisites

  • A Linux host (also builds and runs on macOS for local testing).
  • Rust ≥ 1.75 (rustup recommended).
  • git on PATH.
  • The claude and/or codex CLI installed and already logged in on the host, as the same OS user that will run tensorcheck.
  • A GitHub App installed on each organization you want to review.
  • GitHub.com (this build targets api.github.com; GitHub Enterprise Server is not supported).

1. Build

Clone the repository, then build the release binary. It is written to ./target/release/tensorcheck.

2. Create the GitHub App

In GitHub, under Settings → Developer settings → GitHub Apps → New GitHub App, set these repository permissions:

PermissionLevelWhy
Pull requestsRead & writeFetch PR data, post the review and inline comments.
ChecksRead & writeCreate and update the Check Run.
ContentsRead-onlyClone/fetch the PR head for the sandboxed checkout.
MetadataRead-onlyMandatory baseline.

Subscribe to two events: Pull request (drives open / reopen / ready-for-review / synchronize) and Issue comment (drives the /review command). For the webhook, use only an isolated development endpoint and a development webhook secret — keep the secret, GitHub won't show it again. Generate and download a private key (.pem), install the App on the org, and note the numeric App ID.

3. Confirm the CLIs are logged in

As the same OS user that will run the daemon, confirm the CLI you plan to use returns a JSON result rather than a login prompt:

4. Write a minimal config.toml

Config is layered TOML — secrets are referenced by env-var name or file path, never inlined. This minimal file defines one org:

[server]
listen   = "127.0.0.1:8080"
work_dir = "/var/lib/tensorcheck"
environment = "development"
development_standalone = true

[review]
cli = "claude"                       # or "codex"
[review.prompt]
system = "You are a rigorous senior code reviewer. Be specific and actionable."

[org.my-org]
app_id             = 123456
private_key_file   = "/etc/tensorcheck/my-org.pem"
webhook_secret_env = "MY_ORG_WEBHOOK_SECRET"   # NAME of the env var holding the secret

Export the webhook secret the tool reads from the env var you named:

5. Validate the configuration

check-config loads and validates the config, prints the org count, and exits.

6. Try one pull request

review-once runs the full pipeline synchronously against one real PR and posts a review and Check Run — no webhooks needed. It's the fastest way to confirm auth, the CLI, and posting work end-to-end. (It does not use the queue or the audit log.)

7. Run the daemon

serve starts the webhook listener, the job scheduler, and the reconciliation poll. Point your GitHub App's webhook at the host and open or update a PR to have it reviewed. Health and metrics are served on the same address; log verbosity is set with RUST_LOG (for example RUST_LOG=tensorcheck=debug).

Configuration reference

Every field, its default, and how layers merge.

Config is layered TOML, deep-merged global → [org.<name>] → [org.<name>.repo.<name>]; the most specific layer that sets a field wins. It is validated on load (check-config) and on startup. Secrets are referenced by env-var name or file path, never inlined. For max_diff_lines and daily_tokens, 0 means unlimited.

The [review] layer (global, org, or repo)

Every field below may appear in [review], [org.<o>.review], or [org.<o>.repo.<r>.review].

FieldTypeDefaultMeaning
cli"claude" | "codex"claudeWhich local CLI to invoke.
modelstring(CLI default)Passed to the CLI (--model for claude).
timeout_secsint1200Hard timeout for one CLI run; the child is killed on timeout.
max_diff_linesint4000Skip (don't review) diffs larger than this. 0 = no cap.
severity_thresholdinfo | warning | errorinfoDrop findings below this severity before posting.
skip_draftbooltrueSkip draft PRs until marked ready.
author_denylist[string][]PR authors to skip (e.g. ["dependabot[bot]"]).
path_exclude[string][]Glob patterns; matching files are dropped from the diff. If nothing remains, the review is skipped.
daily_tokensint0Per-org daily token budget. 0 = unlimited.
prompt.systemstring(built-in)The reviewer's system prompt (inline).
prompt.system_filepath—Load the system prompt from a file instead.

The [org.<name>] block (one per organization)

FieldTypeDefaultMeaning
app_idint—The GitHub App's numeric ID.
private_key_filepath—Path to the App private key .pem (chmod 600, owned by the service user).
webhook_secret_envstring—The NAME of an environment variable whose value is the webhook secret for this org's App. The daemon reads that env var at request time.

Webhooks cover any repo the App is installed on. The reconciliation poll, however, only reconciles repos that appear under an [org.<o>.repo.<r>] block — add a (possibly empty) one to give a repo the self-healing poll.

What gets reviewed

Triggers, skips, and supersession.

Triggers

  • opened / reopened / ready_for_review — a full review against the PR base branch.
  • synchronize (new pushes) — an incremental review: the diff is taken against the last-reviewed commit, so the CLI only sees new commits.
  • An exact /review pull-request comment — reviews the PR's current head on demand.
  • The reconciliation poll re-enqueues any configured open PR whose head differs from the last-reviewed SHA — the safety net for missed webhook deliveries.

What is skipped

Draft PRs (until ready, skip_draft), forks (always), denylisted authors, and files matched by path_exclude globs (dropped before review; if nothing else changed, the review is skipped). Diffs larger than max_diff_lines are skipped (0 = no cap).

Dedup, supersession, and budget

Each finding carries a hidden fingerprint marker; on re-review, the tool skips findings already posted. When a newer head arrives for the same PR, the daemon supersedes older pending work: the older pending queue rows are dropped and the newest head is enqueued. The reconciliation poll re-enqueues any configured open PR whose head differs from the last-reviewed SHA. Findings below severity_threshold are dropped before posting. Once an org reaches its daily_tokens budget for the UTC day, further reviews are skipped and the Check Run is closed neutral with an explanation (0 = unlimited).

Observability

Health, metrics, logs, and the audit trail.

  • GET /healthz — liveness (200 once the process is up).
  • GET /readyz — readiness.
  • GET /metrics — Prometheus exposition: reviews_total (counter, attempts started), reviews_failed_total (counter, attempts that ended in error), and review_seconds (histogram, end-to-end review time). Metrics register lazily — an idle daemon may not list a metric until the first review runs.
  • Logs — structured JSON, controlled by RUST_LOG. Each review runs inside a span carrying org/repo/pr.
  • Audit trail — every review attempt on the serve path writes a row to the audit table in state.db, with an outcome of reviewed, skipped (detail names the reason, e.g. fork, draft, denylisted_author, budget_exhausted), or failed. Synchronous review-once runs are not audited.
Troubleshooting

Symptoms and fixes.

SymptomLikely cause / fix
check-config warns private_key_file does not existPath or permission is wrong, or the key isn't provisioned yet. Validation only warns; the key is required at review time.
webhook secret env not setThe env var named by webhook_secret_env isn't exported to the process. Webhooks for that org will 401 (fail-closed). Export it before starting the daemon.
Webhook deliveries show 401Secret mismatch or unset; confirm the App's webhook secret equals the env var's value.
Webhook deliveries show 200 but nothing happensDraft, fork, denylisted author, all changed paths excluded, or over the daily budget — check the audit table for the skipped reason.
Check Run stuck / review silently failsCheck the logs; the daemon closes the Check Run as failure on any pipeline error. Reproduce with review-once, which prints the error to your terminal.
Reviews never parse / empty findingsThe CLI's output format. Test the exact pre-auth command as the service user and confirm claude -p --output-format json returns a JSON envelope.
A whole repo isn't reconciledAdd a [org.<o>.repo.<r>.review] block — the reconciliation poll only covers configured repos (webhooks still work regardless).
Budgets never triggerThe CLI isn't reporting token usage for that mode; accounting is best-effort and logs when usage is absent.
Duplicate comments after a deployExpected once after a binary upgrade — comment-dedup fingerprints are stable only within a binary build; they stabilize on the next review.

Fastest end-to-end diagnostic: tensorcheck --config … review-once --org O --repo R --pr N — it exercises auth, checkout, the CLI, and posting synchronously, with the error printed to your terminal.

Known limitations

What this version does not do.

  • GitHub.com only — the API base is api.github.com; GitHub Enterprise Server is not supported, and no other source-control host is integrated.
  • Forks are not reviewed in this version, by design.
  • Inline-comment placement — findings anchored to a line outside the PR diff would be rejected by GitHub, so the publisher falls back to posting them in the review body rather than failing the whole review.
  • codex output format — the JSONL handling is best-effort; verify it against your installed codex version with a review-once run. The claude path is exercised end-to-end.
  • Single instance — one serve process per state.db; no multi-node or HA yet.
  • The queue_depth metric is not yet exported.

Get early access to the platform.

Every product is included in one platform subscription. Request early access and we'll onboard your team hands-on — free while we build toward launch.