Ninchi CLI & MCP
Run Ninchi checks from a terminal, Git hook, CI job, or MCP-capable editor such as Cursor or Claude Code.
Each check records evidence of demonstrated understanding tied to the submitted artifact. Programmatic checks are a separate evidence class from pull-request verification; they are not a measurement of latent ability or competency.
Prerequisites
You need a Ninchi account, membership in the target organization, and an administrator who has enabled the programmatic surface.
Installed the GitHub App but do not see your organization?
Sign in to Ninchi with the GitHub account that installed the App. Organizations are linked through your GitHub identity; an email/password account without that GitHub identity cannot claim the installed organization.
- Find the organization ID in the dashboard URL — the segment after
/dashboard/orgs/. Both forms work: a numeric ID (42) or the org's UUID public ID; newer dashboard URLs use the UUID form, and numeric IDs in existing configs keep working. The CLI does not currently list organizations. - Ask an org admin to open organization settings, find Programmatic Checks (CLI & MCP), and turn on “Enable CLI & MCP check submission.”
- Programmatic-check quotas are hard limits per developer across a trailing 30-day window. A 429 response includes the time when the next check becomes available.
| Plan | Checks per developer | Window |
|---|---|---|
| Hobbyist / Free | 0 | Trailing 30 days |
| Standard | 20 | Trailing 30 days |
| Pro | 100 | Trailing 30 days |
| Enterprise | 100+ | Trailing 30 days |
Install and make the binary visible
pipx keeps the CLI isolated and exposes the ninchi executable. Ninchi CLI 0.2.0 is published on PyPI.
Verified public installation
The command below was tested successfully against public PyPI in a clean pipx environment without access to the private Ninchi repository.
pipx install ninchi-cliAdd pipx applications to your shell PATH, open a new shell, and verify the executable.
pipx ensurepath
# Close and reopen your shell, then verify:
command -v ninchi
ninchi --helpspawn ninchi ENOENT
If an editor reports “spawn ninchi ENOENT”, it cannot find the executable. GUI editors often do not inherit the PATH from your interactive shell. Run command -v ninchi in a terminal and use that absolute path as the MCP command.
command -v ninchi
# Use the printed absolute path in your MCP configuration.Authenticate
Interactive login uses a device flow, so the terminal never handles your website password.
ninchi login- The CLI prints a verification URL and an eight-character code such as XXXX-XXXX.
- Open the URL, sign in, and approve the code at
/dashboard/device. - The CLI polls until approval and saves the resulting personal access token.
Credentials are stored at ~/.config/ninchi/credentials with file mode 0600. NINCHI_CONFIG_DIR and XDG_CONFIG_HOME can change the location.
CI and manually created tokens
export NINCHI_API_TOKEN="ninchi_pat_..."
export NINCHI_ORG_ID=42For CI, store the token as NINCHI_API_TOKEN. Create or revoke PATs from /dashboard/profile. Tokens carry checks:read and checks:write scopes by default, are shown once, are stored by Ninchi as HMAC digests, and stop working immediately after revocation.
CLI commands
The check command defaults to the working-tree diff. Choose exactly one alternate source when needed.
# Working-tree diff (default)
ninchi check --org-id 42
# Other subject sources
git diff | ninchi check --stdin --org-id 42
ninchi check --staged --org-id 42
ninchi check --commit HEAD --org-id 42
ninchi check --file src/app.py --language python --org-id 42
# Reuse the org ID from your environment
export NINCHI_ORG_ID=42
ninchi check --staged
# Automation: answer non-interactively and emit JSON
ninchi check --staged \
--answer "$ANSWER" \
--actor agent_assisted \
--json
# Inspect an existing challenge
ninchi result CHALLENGE_ID
ninchi result CHALLENGE_ID --json
ninchi history --limit 20
ninchi history --limit 20 --jsonAnswering actor
- An answer typed at the prompt defaults to human_attested.
- --answer or a non-interactive process defaults to agent_assisted.
- --actor can explicitly set human_attested, agent_assisted, or agent_autonomous. Use the value that honestly describes who authored the answer.
Exit codes
0— the challenge passed1— the challenge failed2— pending state or an operational, authentication, configuration, or API error
login supports --timeout, --api-url, and --json. check also supports --poll-interval and --timeout. result takes a challenge ID; history supports --limit. Put --json after the subcommand.
Git hooks and CI
The same command can run before a push or inside automation. Non-interactive answers must carry honest actor provenance.
Pre-push hook
#!/usr/bin/env bash
set -euo pipefail
base="${NINCHI_BASE_REF:-origin/main}"
git diff --patch "$base"...HEAD | ninchi check \
--stdin \
--org-id "${NINCHI_ORG_ID:?set NINCHI_ORG_ID}"Save this as .git/hooks/pre-push and make it executable. Omit --answer so the human answers interactively in the terminal.
Minimal GitHub Actions job
name: Ninchi check
on:
pull_request:
jobs:
ninchi:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pipx install ninchi-cli
- name: Submit Ninchi check and surface the challenge
run: |
git diff --patch origin/${{ github.base_ref }}...HEAD |
ninchi check --stdin --json | tee ninchi-challenge.json || true
env:
NINCHI_API_TOKEN: ${{ secrets.NINCHI_API_TOKEN }}
NINCHI_ORG_ID: ${{ vars.NINCHI_ORG_ID }}Install the CLI directly from public PyPI. Store credentials in GitHub secrets, never in the workflow file. This job stops at submission by design: without --answer, the CLI prints the challenge JSON and exits 2. The answer must come from whoever authored the change — have authors answer interactively, for example via the pre-push hook or an MCP-capable editor. Do not wire a canned answer into CI: the question is generated per submission, and the answer window starts once the challenge is first viewed.
MCP server
The ninchi package includes a stdio MCP server for agent-capable editors. Authenticate with ninchi login first.
Use the absolute binary path as the primary configuration. Replace the placeholder with the output of command -v ninchi.
{
"mcpServers": {
"ninchi": {
"command": "/absolute/path/from/command-v-ninchi",
"args": ["mcp"]
}
}
}Use a bare command only when the editor definitely inherits a PATH that contains ninchi.
{
"mcpServers": {
"ninchi": {
"command": "ninchi",
"args": ["mcp"]
}
}
}| Tool | Purpose |
|---|---|
submit_check | Submit one diff, content block, or file region and start question generation. |
get_challenge | Fetch the generated question, optionally waiting while generation finishes. |
submit_answer | Submit an answer with a required, honest actor claim. |
get_result | Fetch the score and feedback, optionally waiting while evaluation finishes. |
list_history | List the authenticated developer's recent challenges. |
Agent answers follow organization policy
submit_answer requires actor. If the organization policy is blocked, the tool tells the agent to hand the question to the human and relay the human's own answer as human_attested. If the policy is recorded, agent_assisted and agent_autonomous answers are accepted and stored with that provenance. Never change the actor merely to bypass policy.
MCP submissions stamp client_attribution: "mcp:<client>". This names the submitting channel and feeds AI-authorship analytics as a detection-floor signal; it does not by itself assert that AI assisted the work.
Evidence and score semantics
Programmatic checks use origin="api" and remain a distinct, lower-weight evidence class. The stored question, answer, score, artifact context, actor claim, client attribution, and timestamps are inspectable evidence about that event.
Score counting is opt-in
By default, programmatic checks do not count toward Ninchi Scores. An org admin may enable “Count programmatic checks toward Ninchi Scores” in the Programmatic Checks card. Pull-request evidence is unaffected either way.
Troubleshooting
| Symptom | Resolution |
|---|---|
spawn ninchi ENOENT | The editor cannot find the executable. Run pipx ensurepath, open a new shell, run command -v ninchi, and place that absolute path in the MCP config. |
403 "not enabled" | An org admin must enable “Enable CLI & MCP check submission” in the Programmatic Checks (CLI & MCP) settings card. |
429 | The per-developer trailing-30-day quota is exhausted. Read the response for the exact UTC reset time. |
403 agent answer | The organization blocks agent-authored answers. Hand the question to the human and submit only their own words as human_attested. |
Challenge expired | The answer window starts when the ready challenge is first viewed. The organization configures the TTL; the default is 5 minutes. |
202 "generating" / "evaluating" | Question generation and answer evaluation are asynchronous. A 202 state is normal; keep polling get_challenge or get_result until a terminal response or your timeout. |
Still stuck? Visit Support and include the response's X-Request-ID when available.