Skip to main content
Glama

no_human

From ticket to reviewed pull request.Free and open-source, on your machine.

English · 简体中文 · 日本語 · 한국어 · Español · Français · Deutsch · Português (Brasil)

latest release CI python 3.12+ license MIT downloads Discord

getnohuman.com · Quickstart · Docs · Watch it work a sprint · Discord

Download for macOS Download for Windows Download for Linux

▶ Watch the loop — a ticket in, a reviewed pull request out; the whole loop in 57 seconds.

The AI coding factory you can trust:

  • A plan before any code, from the ticket plus what it finds in your repo. When planning fails, the coder is told it is working without one; when the change is judged trivial the plan is skipped without telling the coder, by design — the skip is still stated in the run's event stream.

  • An adversarial review. A different model, in a session that never saw the coder's transcript, told to refute "done". You get a pass/fail checklist citing file and line — never a numeric self-score.

  • A tamper guard. Deleted tests, new skips, an assertion turned into a tautology — counted mechanically before the review gate runs, then justified against your acceptance criteria or the attempt stops.

  • Proof the fix fixed the bug. The tests offered as evidence must fail at the merge base and pass on the new tree — the reproduction gate runs both. Out of the box that binds a Python bug fix; repro_gate.mode: required binds every kind and every change.

  • Your tests run, locally and optionally through your CI — and a PR that found no test command says NOT RUN on its face.

  • An honest stop. When it cannot finish it stops and says why — a specific question when your answer would unblock it, a structured record when it has simply run out of budget — never an invented plausible diff.

What the gate caught

no_human builds no_human. Over 65 days on its own board, none of this reached a pull request:

  • 505 of 1,709 attempts the coder called done were sent back by the second model, each with a pass/fail checklist citing file and line.

  • 44 attempts were stopped before the review even ran, for deleting or weakening a test.

  • 46 bug-fix proofs were refused because the test offered as evidence passed on the old code too.

How these were counted

Install

One line (CLI + board)

uv tool install no-human   # or: pipx install no-human — the wheel ships the board
nh init && nh doctor       # token, config, first repo; then prove the install is real

Desktop app

Download for macOS Download for Windows Download for Linux

Each release ships a SHA-256 alongside the artifact. Platform notes and the first-run walk-through: docs/quickstart.md.

From source

git clone https://github.com/no-human-ai/no_human.git && cd no_human
uv sync                 # installs the `nh` entry point into .venv
(cd web && npm install && npm run build)   # builds the board (cold first install can take minutes)
uv run nh init          # token, config, first repo (about 2 minutes)
uv run nh doctor        # verify the install is real before relying on it

The web build is not optional if you want the board: a source checkout ships no web/dist, so without it nh start serves the API only and renders no UI. Needs Python 3.12+, uv, git, and Node with npm for the board build.

Related MCP server: letmediff

Product highlights

Stills: the real board on a demo workload.

Run one task

Run nh with no arguments for the shell: your lanes, a live event tail, and an intake you describe a task to in plain English. Every command below still works.

nh                                   # the shell
nh start                             # board + worker on 127.0.0.1:8420
nh task add https://github.com/org/repo/issues/42 --repo ~/git/repo
nh status                            # needs-you / working / waiting / done
nh review <id>                       # the reviewer's evidence checklist
nh diff <id>                         # the diff it wants to ship
nh approve <id>                      # your approval squash-lands the PR (git.approve_identity)
nh reject <id> --reason "..."        # send it back with feedback

Integrations

Point no_human at the tracker you already use and it pulls the tickets to your board — a tracker's filter lives in your config, never in a task's own text, and a transport error logs and retries on the next tick instead of crashing the pool.

Tracker

How tickets arrive

Filter you configure

Jira Cloud

Polled via REST search/jql (HTTP Basic email:token)

integrations.jira.jql

Linear

Polled via the GraphQL API

integrations.linear.team_key + state_types + label

monday.com

Polled via GraphQL v2

integrations.monday.board_id + status_column + todo_labels

With write-back on (write_back, off by default), the ticket moves with the task — matched by status category, type, or the label you name, never a hard-coded transition id — and gets the PR link; a task that needs a human is commented on, never transitioned. GitHub and GitLab issues import as tasks by URL, and PRs or MRs open on your own host; Slack and Teams get a message when a task needs you; Jenkins and CircleCI can run your test layers and gate the loop. Setup for each: docs/adapters.md.

Watch the Jira flow end to end — tickets synced from a Jira board, scoped, implemented, and delivered as a review-passed pull request (click for the full video with every step):

Jira flow demo

GitHub Action

Run the same adversarial reviewer and tamper guard as a pull-request check — one shot, no daemon, no ~/.no_human database, and not the queueing nh review CLI path. It judges the diff alone: unlike a local run, it collects no lint, wiring or type evidence and does not explore the repository. It posts a single pass/fail checklist comment with file:line citations, found by its own marker and updated in place on every run rather than creating a new one each time.

# .github/workflows/review-gate.yml
name: no_human review gate
on:
  pull_request:

permissions:
  contents: read
  pull-requests: write

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
          ref: ${{ github.event.pull_request.head.sha }}
      - uses: no-human-ai/no_human@main # no versioned tag yet — see below
        with:
          credential: ${{ secrets.ANTHROPIC_API_KEY }}
          github_token: ${{ github.token }}

permissions.contents: read lets actions/checkout read this repository; pull-requests: write is what lets the Action post/update its own comment. Neither grants anything broader. The checkout step's explicit ref: ${{ github.event.pull_request.head.sha }} matters too: on a pull_request event, actions/checkout otherwise checks out an ephemeral merge commit rather than the PR's actual head, and the Action reviews and cites line numbers against whatever tree is on disk — it refuses to run rather than review the wrong one, so omitting ref: here turns into a red, actionable exit 2, not a silent misreview.

This Action has no versioned release yet — no-human-ai/no_human's tags today run v0.1.0 through v0.2.3, none of which contain action.yml. A v1 tag will be cut at the first release that ships it. Until then, pin to @main for the latest revision, or better, pin to the exact commit SHA you've reviewed (no-human-ai/no_human@<sha>) so a later change to main can't alter what your workflow runs.

credential takes either shape of your own Anthropic credential — an ANTHROPIC_API_KEY (sk-ant-api...) or a Claude subscription OAuth token minted with claude setup-token (sk-ant-oat...) — auto-detected from its prefix, or pinned explicitly with credential_mode: oauth / credential_mode: api_key. Whichever shape you pass, the other credential path is scrubbed from the job's environment before the reviewer runs, and the value itself is masked in the log the moment it is read.

A credential is required, and there is no silent fallback. If secrets.ANTHROPIC_API_KEY (or whatever secret you wire into credential) is empty, unset, or a shape the Action can't recognize even in auto mode, the run fails loudly at exit code 2 — naming the credential input and the secret it expects — before the reviewer, or any GitHub API call, ever runs. The same fail-closed rule applies if the reviewer itself errors out or the model call is rejected: those runs exit 2 too. The Action never posts a PASS, and never exits 0, for a credential or reviewer failure — but a green check does not always mean the gate reviewed code: a fork pull request skips with exit 0 and no reviewer call (see below), and a pull request with an empty diff (nothing to review) posts a synthetic PASS with no reviewer or tamper-guard call. If you make this a required check, treat both of those as "did not review," not as an approval. A diff larger than the reviewer's single-turn cap is refused with exit 2 instead of being reviewed as a truncated prefix, so that case is never a green check: lower max_files or split the pull request.

Forks are skipped, not reviewed. A pull request whose head is not this repository — including one from an already-deleted fork — never reaches the reviewer or the model; the Action exits 0 with a comment-free explanation instead of running review code against an unvetted head in a job that can see your secrets. pull_request_target is refused outright (exit 2), even with a valid credential, because that trigger is the one shape that can carry a fork's head into a secret-bearing job.

workflow_run is also a supported trigger, reconstructing the pull request's number, head commit, and changed files over the GitHub REST API instead of from a pull_request payload; because that mode has no checked-out repository tree, the tamper guard does not run, and the posted comment says so explicitly rather than implying a clean tamper check.

Dependabot pull requests fail closed with exit 2, and that is GitHub's restriction, not this Action's. A Dependabot-opened pull request has the same repository as its head — it is not a fork, so the check above does not skip it — but GitHub itself withholds repository secrets (and downgrades GITHUB_TOKEN to read-only) from workflow runs it triggers on the pull_request event, as a platform-level guard against a lockfile update carrying a malicious install script into a secret-bearing job. credential therefore arrives empty on those runs, and this Action's own fail-closed rule (above) makes that a red, actionable exit 2 naming the missing secret, not a silent skip or a false PASS. If you require this check and want Dependabot PRs to go green, either exempt them in your branch protection rules or accept that they need a maintainer's manual re-run/approval like any other check that needs a secret GitHub won't hand to a bot-triggered job.

Cost is bounded by files, not tokens or time. max_files (default 15) caps how many changed files are sent to the reviewer, sorted by path, first-N; the comment reports how many of the total were actually reviewed. The reviewer runs single_turn, so a passing run is one model call over the capped diff, and a failing one may add a single bounded refute pass — in rough terms, a few cents to a few tens of cents of your own Anthropic usage depending on diff size, similar in shape to one local nh review. That is separate from the one-time cost of the runner building the Docker image itself (a few tens of seconds, GitHub-hosted-runner compute, not model spend) on each run unless your workflow caches the image. Lower max_files (or split large pull requests) to spend less.

The Action never merges, pushes, approves, or edits anything about the pull request beyond its own single comment — enforced in code, not just by convention: every GitHub API call is checked against a two-endpoint allowlist (list/create/update that one comment thread) before it is sent. Set fail_on_findings: false to keep the comment without failing the check, or dry_run: true to print the verdict to the job log/summary and make no GitHub API calls at all.

Known limitation: the tamper guard's "full test tree" claim holds for ASCII test filenames, not non-ASCII ones. The tamper check walks every test file in the repository (not just the max_files-capped subset sent to the reviewer) via an unquoted git ls-tree, so a test file whose name contains non-ASCII bytes is listed in git's C-quoted string form (e.g. "r\303\251gression_test.py") instead of its real path, and silently drops out of the guard's before/after comparison — deleting or weakening such a file will not currently be caught. This Action's own diffed/reviewed file list is not affected by the equivalent problem (it explicitly re-quotes and re-verifies every path it hands to the reviewer), but the underlying tamper-check module is out of scope for this Action to change. If your test suite has non-ASCII test filenames, treat the tamper guard as best-effort for those specific files until that's fixed upstream.

Known limitation: two runs racing each other, or a pull request already carrying 1,000+ other comments, can produce a duplicate. The Action finds its own prior comment by listing the PR's comments (up to 10 pages of 100) and picking the lowest-id one carrying its marker; two runs started close together can both list before either creates, and each will create its own comment. A later run of either still converges — it lists again, finds the lowest-id marked comment, and updates that one — but the extra comment is not deleted. The same "list, then act" gap means a marked comment that would only appear on page 11 or later (over 1,000 other comments already on the pull request) reads as absent and gets a new one created rather than updated. Both are accepted, documented bounds rather than silent failures: if your workflow can trigger two runs for the same commit, add a concurrency: group keyed on the pull request to serialize them.

MCP server — hand it work from the agent you are already in

no_human ships an MCP (Model Context Protocol) server: a stdio bridge, built on the official Python MCP SDK, that lets Claude Code, Cursor or any MCP client file work with your local no_human and check on it.

nh mcp-serve        # the MCP server, over stdio

Two tools, and no more:

Tool

What it does

task_add(title, description, repo_path)

Files a task. no_human then plans it, writes the change, runs your tests, has a second model review it, and opens the pull request.

task_status(task_id_or_external_id)

Returns that task's current state — status, attempts, the PR link once there is one.

It talks to your own no_human at http://127.0.0.1:8420 and nothing else: no auth, because that address is localhost, and no service of ours in between. For Claude Code, the same server ships as a plugin — this repository is its own plugin marketplace, so the two tools appear in your session after:

/plugin marketplace add no-human-ai/no_human
/plugin install no-human@no-human-ai

Any other MCP client takes the usual stdio entry:

// .mcp.json
{ "mcpServers": { "no_human": { "command": "nh", "args": ["mcp-serve"] } } }

The plugin also ships the review-this-branch skill, which does not need the MCP server or ~/.no_human at all: it runs nh gate, a one-shot CLI verb that puts the fresh-session adversarial reviewer and the tamper guard directly on your current branch or a GitHub pull request, using your own Claude credential, and exits with a pass/fail Markdown checklist, with nothing installed or running beyond the nh CLI itself.

nh gate                        # current branch vs. its merge base with origin's default branch
nh gate --pr <github-pr-url>   # a GitHub pull request's head vs. its merge base

Docs

quickstart.md

Zero to first task, per platform

configuration.md

Every setting and default

verification.md

The gates, the bounded loop, the limits

security.md

Auth boundary, the never-merge rule, guards

blockers.md

Escalation, wake watcher, nh reply

adapters.md

Intake, context, VCS and CI backends

eval.md

Golden set, replay scoring, shadow mode

CHANGELOG.md

What changed, per release

Development

uv sync
uv run pytest -q
uv run nh --help

Issues and pull requests welcome; run uv run pytest -q before submitting.

If no_human saved you a review cycle, a star helps other people find it: GitHub stars

Community

Questions, bug reports and runs worth showing: join the Discord, post on r/no_human, or open a GitHub issue.

License

MIT — see LICENSE. The licence covers the code, not the name: TRADEMARK.md is the policy on using "no_human" and the logo. Packaging a binary carries obligations the source tree does not, listed in THIRD-PARTY-NOTICES.md.

Available Tools

2 tools
task_addA

Create a no_human task via POST /api/tasks (source="mcp"). Returns compact JSON {"task_id": str, "source": str} — source is whatever the server actually stored (the "mcp" source is first-class, see module docstring).

ParametersJSON Schema
NameRequiredDescriptionDefault
titleYes
repo_pathYes
descriptionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must disclose behavioral traits. It does so by specifying the return format (compact JSON) and noting that the source is whatever the server actually stored, which informs the agent of potential variability. It also mentions the source is first-class, referencing module docstring, which adds context. However, it does not discuss side effects, error states, or idempotency, but given it's a creation endpoint, the info is reasonably transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, two sentences, and front-loaded with the core purpose. Every sentence adds value: the first states the action and endpoint, the second clarifies the response format and a behavioral nuance. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool is simple (3 required params, no nested objects), and there is an output schema (though not provided in the input), the description is fairly complete. It covers the endpoint, source handling, and return format. It could mention potential errors or idempotency, but for a POST creation endpoint, it covers the essentials. The absent annotation makes it carry more weight, but it handles that well.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 0% description coverage, so the description must compensate. It explains that the 'source' parameter (implied by the endpoint) is set to 'mcp' and describes the response, but it does not provide specific details on 'title', 'description', or 'repo_path' beyond what's in the schema. However, it adds value by clarifying the 'source' semantics and response structure, which is useful for the agent. Since all parameters are required and self-explanatory from their names, the description's addition is reasonably helpful.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: creating a no_human task via a specific endpoint and source. It clearly distinguishes from the sibling tool 'task_status' which presumably handles status queries, by focusing on task creation. It uses a specific verb ('Create') and specifies the resource ('task'), making it clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use this tool (to create a no_human task) but does not explicitly contrast with alternatives. Since there is only one sibling and no elaboration on when not to use it, it only provides moderate guidance. It does not mention any prerequisites or conditions for use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

task_statusA

Fetch a task's full current state via GET /api/tasks. Resolves by task id (or unique id prefix) first; if that 404s, falls back to matching external_id across the task list (GET /api/tasks does not index by external_id, so this is a client-side scan). Returns the complete task object as compact JSON.

ParametersJSON Schema
NameRequiredDescriptionDefault
task_id_or_external_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully carries the burden and discloses important non-obvious behavior: resolution by task id or unique prefix, fallback to a client-side external_id scan, and the reason for that fallback. This gives the agent accurate expectations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with no filler. Each sentence adds functional value: the endpoint, the lookup strategy, and the return format.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the single parameter, presence of an output schema, and absence of annotations, the description is sufficiently complete. It covers the lookup method, fallback behavior, and return representation without needing to describe output schema fields.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides only the parameter name and type with no description, and schema description coverage is 0%. The description compensates fully by explaining that the parameter accepts a task id, unique id prefix, or external_id and by detailing the resolution order.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool fetches a task's full current state via a specific endpoint. It uses a precise verb and resource, and the read-oriented purpose distinguishes it from the sibling task_add.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides clear context for when to use the tool: whenever a task's current state is needed. It does not explicitly name alternatives or exclusions, but the intended use is evident.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.1.0
    • First observedtask_add
    • First observedtask_status

TDQS

A4.1/5.0

Scored across 2 tools

Disambiguation5/5

task_add creates a task while task_status retrieves the current state of a task; their purposes are entirely distinct with no overlap. An agent would not confuse which tool to call.

Naming Consistency4/5

Both tools share a consistent task_ prefix and use snake_case, so they form an obvious family. The minor deviation is that one second token is a verb (add) while the other is a noun (status), but at only two tools this is easy to parse.

Tool Count3/5

Two tools is on the thin side for a task-management server, though the narrow create-and-check scope keeps it acceptable. It falls in the borderline range rather than feeling egregiously over- or under-built.

Completeness3/5

The domain appears to be task management, and the server supports creation plus status lookup, which covers the core add-and-monitor workflow. Missing operations include list, update, cancel/delete, and resubmission, which are notable but work-around-able for a minimal no_human API.

Maintenance

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    A review handoff tool for agent-driven coding sessions that captures worktree diffs, creates shareable review URLs, and streams reviewer feedback back to the agent.
    1
    -
  • A
    license
    A
    quality
    B
    maintenance
    Enables an MCP-capable assistant to review GitLab merge requests, GitHub pull requests, and pre-push local branches against ticket requirements, domain rubrics, compiler/lint pre-passes, blast-radius analysis, and SonarQube findings, and to draft inline comments or follow-up tasks in the user's chosen language. Nothing reaches a remote host until a human approves the exact content in an interactive terminal.
    3
    MIT