Metadata-Version: 2.4
Name: ninchi-cli
Version: 0.2.0
Summary: Command-line client and MCP server for Ninchi checks
Author-email: Ninchi <support@ninchi.ai>
License: Proprietary
Project-URL: Homepage, https://ninchi.ai
Project-URL: Documentation, https://ninchi.ai/docs/cli
Keywords: ninchi,code-review,verification,mcp,cli
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: httpx<1.0,>=0.27
Requires-Dist: mcp<2,>=1.2
Provides-Extra: dev
Requires-Dist: pytest<9,>=8; extra == "dev"

# Ninchi CLI

Thin HTTP client for running Ninchi checks from a terminal, hook, or CI job.
The CLI does not import the backend or core engine; it talks to the public API.

## Install

```bash
pipx install .
```

From this repo during development:

```bash
cd cli
python -m pip install -e ".[dev]"
```

## Auth

Interactive login uses the Ninchi device-code flow and stores a personal
access token in `~/.config/ninchi/credentials` with mode `0600`:

```bash
ninchi login
```

CI can skip the credentials file:

```bash
export NINCHI_API_TOKEN="ninchi_pat_example_for_docs"
```

Use `NINCHI_API_URL` or `--api-url` to target a local/dev backend.

## Checks

Submit a diff from stdin and answer the generated challenge interactively:

```bash
git diff | ninchi check --stdin --org-id "$NINCHI_ORG_ID"
```

Other subject sources:

```bash
ninchi check --staged --org-id "$NINCHI_ORG_ID"
ninchi check --commit HEAD --org-id "$NINCHI_ORG_ID"
ninchi check --file src/app.py --language python --org-id "$NINCHI_ORG_ID"
```

Automation mode uses JSON output and exit codes:

```bash
git diff --staged | ninchi check --stdin --answer "$ANSWER" --json --org-id "$NINCHI_ORG_ID"
```

Exit codes:

- `0`: challenge passed
- `1`: challenge failed
- `2`: pending, configuration, auth, API, or other operational error

When an answer is typed interactively, the CLI submits
`answering_actor=human_attested`. When `--answer` is supplied or the process has
no terminal to prompt from, it submits `answering_actor=agent_assisted` unless
`--actor` overrides it. The server enforces org policy.

## Pre-push Hook

Example `.git/hooks/pre-push`:

```bash
#!/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}" \
```

For human-attested hook usage, omit `--answer` and let the CLI prompt in the
terminal.

## MCP Server (`ninchi mcp`)

The same client, served over the Model Context Protocol for agent-capable
editors (Cursor, Claude Code, etc.). Authenticate once with `ninchi login`,
then register the server — e.g. in Cursor (`.cursor/mcp.json` or global MCP
settings):

```json
{
  "mcpServers": {
    "ninchi": { "command": "ninchi", "args": ["mcp"] }
  }
}
```

Tools: `submit_check`, `get_challenge`, `submit_answer`, `get_result`,
`list_history`.

Two things agents (and their humans) should know:

- `submit_answer` requires an honest `actor` argument
  (`human_attested` / `agent_assisted` / `agent_autonomous`). Provenance is
  recorded with the attempt; organizations may block agent-authored answers
  by policy, in which case the tool returns guidance to hand the question to
  the human. There is no client-side human-only rule — policy lives with the
  org.
- Submissions carry `client_attribution: "mcp:<client-name>"` from the MCP
  handshake, which feeds Ninchi's AI-authorship analytics.
