# Land: Using Determinstic methods for faster CI and merging

> Source: <https://useland.dev/>
> Published: 2026-11-10 04:25:22+00:00

# For God's sake save some time on your merging and CI

You are meant to do something bigger.

land is the gate between your coding agents and main. Your agent pushes a branch to GitHub. land merges it with main, reruns only the tests the change could affect, and moves main if they pass. The answer comes back as a status on the commit. [See how it saves time →](https://useland.dev/how-it-works)

land picks tests by plain bookkeeping, not an AI guess. It records which functions each test actually runs and compares that with the functions your change touched, so the same change always gets the same tests.

```
curl -fsSL https://useland.dev/install | sh
land login
```

`land login` signs you in with GitHub in your browser, once per machine. On an SSH machine it prints a link instead, and you type the code the page shows. Then pick a plan on the dashboard; land checks nothing until you do.

## Set up

### Install the land CLI and sign in

On the machine your agents run on. It signs you in with GitHub and installs the land skill for Claude Code and Codex.

```
curl -fsSL https://useland.dev/install | sh
```

### Add the repository, once

In the repository. `--dry-run` shows what would upload: committed files only, no history, never `.env`. land finds the tests, installs the dependencies, and records which tests already fail.

Languages: Python, Go, Ruby (RSpec with a committed Gemfile.lock), and TypeScript/JavaScript (vitest, node --test or mocha) run only the tests a change can affect. Jest, Rust, other Ruby, Java and Kotlin (Maven or Gradle), PHP, C#, and C or C++ (CMake or make) run the whole suite on every change for now. Pass `--test '<command>'` if land picks the wrong one.

```
land add --dry-run
land add
```

### Tell your agents where finished work goes

Add these lines to the repository's `CLAUDE.md` (`AGENTS.md` for Codex and others).

```
When work is done, run `land merge  --onto main`. land merges it with main and runs the tests it could affect.
It prints JSON: `landed`, and `refused` with the failing tests. Fix a refusal and run it again.
Then push the commit it gives you: `git push origin :main`.
Never edit, skip or delete a test to get work through.
```

## CI and cloud agents

Where there's no browser to sign in, make a token on [your dashboard](https://useland.dev/dashboard) for the repositories it may use and set it as `LAND_TOKEN`. `land merge` then works in a fresh checkout with no login. A token can't add repositories or change a test command, and you can revoke it any time.

```
LAND_TOKEN=$LAND_TOKEN land merge "$BRANCH" --onto main
```

## Reading a verdict

``` bash
$ land merge sub/api sub/ledger --onto main
{ "landed": ["sub/api"],
  "refused": [{ "who": "sub/ledger", "why": "tests_failed",
                "failing": ["tests/test_ledger.py::test_reverse"],
                "assert": "assert 110 == 90",
                "repro": { "commit": "071366837c", "run": "python -m pytest tests/test_ledger.py::test_reverse" },
                "hitBy": null }],
  "guarding": "3/3", "removed_tests": 0, "newly_skipped": 0,
  "github": { "push": "git push origin 8364fb3…:main" } }
```

| why | what your agent does | 
|---|---|
| tests_failed | Fix the code those tests use, run land merge again | 
| conflict | Resolve the named functions on main, run land merge again | 
| tests_changed | Revert the test edits | 
| unknown_base | Start the branch from the main you added | 
| no_change | Nothing to do; main already has it | 
| conflict_with_main | Rebase onto the target, resolve, merge again | 
| "dirty" | Commit the subagent's work in that worktree, merge again | 
| "state": "running" | Run the same land merge again to wait for the result | 

## Pricing

You pay only for changes land puts on main. Refused pushes are free. There is no free tier, so pick a plan after you sign in.
