> ## Documentation Index
> Fetch the complete documentation index at: https://pilot.muyan.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Getting started

# Getting started

This page takes you from a fresh clone to a first verified tick. Every
command works at any clone path — nothing here depends on a specific
machine layout.

## Prerequisites

| Requirement                                    | What it is used for                                                         | Check                              |
| ---------------------------------------------- | --------------------------------------------------------------------------- | ---------------------------------- |
| Python 3.14                                    | The Runner and the test contract (CI pins the same minor version)           | `python3 --version`                |
| [uv](https://docs.astral.sh/uv/)               | Installs the `muyan-pilot` CLI into an isolated tool environment            | `uv --version`                     |
| [Pi](https://github.com/earendil-works/pi) CLI | The development agent; one full session per task                            | `pi --version`                     |
| Git                                            | Worktrees, branches, base freshness                                         | `git --version`                    |
| GitHub CLI (`gh`)                              | Issues, labels, PRs, merge                                                  | `gh auth status`                   |
| systemd (user session)                         | The timer that triggers one tick every 5 minutes                            | `systemctl --user status`          |
| A working OpenAI-compatible model endpoint     | Pi's model provider — a local llama.cpp server or any OpenAI-compatible API | one real `pi --print` call (below) |

Pi must be configured with a provider that can serve a coding agent
stably (system prompt + tool schemas + long sessions). Verify the endpoint
with one real call before dispatching work — do not assume the key or the
model service works:

```bash theme={null}
pi --print "reply with the single word: ok"
```

If this fails, fix the model endpoint first; the Runner will fail fast on
every task otherwise.

<Note>
  The `local-llm-kv-cache` proxy is an **optional** enhancement (faster
  prefix reuse for local llama.cpp models), not a core prerequisite — see
  [Optional components](/optional-kv-cache).
</Note>

## 1. Clone the repository

```bash theme={null}
git clone https://github.com/xqliu/muyan-pilot.git
cd muyan-pilot
```

## 2. Install the CLI

The official usage is the installed `muyan-pilot` console script (the
PEP 621 packaging in `pyproject.toml` maps
`muyan-pilot = muyan_pilot:main`). Install it with `uv tool` from the
clone directory — `--python` pins the production interpreter (3.14):

```bash theme={null}
uv tool install --python /usr/bin/python3 .
muyan-pilot --help
```

`uv tool` keeps the CLI in an isolated tool environment; the executable
lands in `~/.local/bin` (on the PATH of the systemd unit). After a merge
to main, refresh it with `uv tool upgrade muyan-pilot` (when the version
changes) or `uv tool install --force --reinstall .` from the clone
directory (when the version is unchanged — `--reinstall` bypasses the
build cache). The release package carries no third-party runtime
dependency, no token and no user directory — the config file and the
user systemd dir stay machine-local. The direct-execution entry of
`muyan_pilot.py` (running the file with the interpreter) stays a
development/compatibility path.

## 3. Create the configuration

The repository ships a committed example; the real config is local state
(gitignored). Copy it and edit it:

```bash theme={null}
cp .muyan-pilot.example.toml muyan-pilot.toml
```

All fields (TOML, relative paths resolve against the config file's
directory):

| Field             | Required | Default            | Meaning                                                                                                        |
| ----------------- | -------- | ------------------ | -------------------------------------------------------------------------------------------------------------- |
| `source_repos`    | yes      | —                  | Ordered list of `owner/repo` task pools scanned each tick (e.g. your pilot repo first, then your backlog repo) |
| `repo_dir`        | no       | `.`                | The Runner checkout the service starts from (where `bootstrap_runner.py` lives)                                |
| `workspace_root`  | no       | `..`               | Directory that contains the task worktrees and the repositories the agent may modify                           |
| `prompt`          | no       | `prompt.md`        | Implementer prompt template (placeholders like `{{SOURCE_REPO}}` are rendered by the Runner)                   |
| `prompt_review`   | no       | `prompt_review.md` | Review prompt template for the independent post-PR review session                                              |
| `base_branch`     | no       | `main`             | Delivery base branch; every task worktree is created from the frozen `origin/<base_branch>` SHA                |
| `max_concurrency` | no       | `1`                | Concurrent Pilot tasks on this machine (positive integer; a local model/GPU usually serves one stable task)    |
| `skills`          | no       | `[]`               | Optional Pi skill paths (absolute, `~`, or relative to the config file)                                        |
| `context_files`   | no       | `[]`               | Optional Markdown context files injected into the prompt as paths                                              |

Minimal example:

```toml theme={null}
source_repos = [
  "OWNER/PILOT-REPO",
  "OWNER/BACKLOG-REPO",
]

repo_dir = "."
workspace_root = ".."
prompt = "prompt.md"
prompt_review = "prompt_review.md"
base_branch = "main"
max_concurrency = 1
skills = []
context_files = []
```

## 4. Run the one-time setup

The setup entry does the whole initialization in one command: it
verifies `gh auth status` and the repo permissions, aligns the platform
labels from the repo-managed `labels.toml` (the single source of truth
for label name, color and description — a commit never creates labels,
and a missing label makes the scan silently skip that state), installs
the systemd user units and enables the timer, checks the checkout, and
reports the optional model proxy:

```bash theme={null}
muyan-pilot setup --config muyan-pilot.toml
```

It is idempotent (re-running it never creates duplicate labels, units
or timers) and fail-fast (a wrong repo, insufficient permission, a
dirty checkout or a missing systemd user bus stops it with the concrete
reason). See [One-time setup](/setup) for the full output contract,
success and failure examples.

## 5. Run one tick manually

The manual command is for first verification and troubleshooting only —
normal operation is scheduled by the timer (step 7):

```bash theme={null}
python3 bootstrap_runner.py --config muyan-pilot.toml
```

One tick does at most one thing: resume an opened PR (review/fix/merge) or
claim one `ai-ready` Issue (`p0`-labeled Issues are picked first, then
bug-labeled Issues, then plain features), then it exits. With an empty
ready queue it exits cleanly without claiming anything.

## 6. Smoke walkthrough (from zero)

The smallest end-to-end proof that your setup works. Run it in the clone
directory from step 1; every command is relative to that directory.

```bash theme={null}
# a. Dispatch a tiny task into the first configured source repo.
#    `add` creates the Issue and labels it ai-ready in one step.
muyan-pilot add "Docs: verify smoke walkthrough" \
  --body "Read README.md and confirm the smoke walkthrough commands exist." \
  --config muyan-pilot.toml

# b. Watch the queue: the new Issue is ready.
muyan-pilot status --config muyan-pilot.toml

# c. Run one tick: the Runner claims the Issue, starts Pi in a fresh
#    worktree, and works toward a PR.
python3 bootstrap_runner.py --config muyan-pilot.toml

# d. Follow the live activity while the tick runs (second terminal):
journalctl --user -u muyan-pilot.service -f
# or, for a manual tick, follow the session JSONL directly:
muyan-pilot session --follow --config muyan-pilot.toml

# e. After the PR is opened, the Issue carries ai-pr-opened and the
#    delivery continues (independent review, in-session fix, merge) on
#    later ticks. Watch the Issue and the PR on GitHub.
gh issue list --repo OWNER/PILOT-REPO --label ai-pr-opened
```

You are done when: the Issue moves `ai-ready → ai-in-progress →
ai-pr-opened → ai-merged`, a PR exists with `Fixes #<issue>` in its body,
and the journal shows `run_end ... result=pr_opened`. If any step fails,
the Issue is marked `ai-blocked` with the scene — see
[Operations](/operations) for recovery.

## 7. Verify the timer

The setup step already installed the units and enabled the timer; verify
it:

```bash theme={null}
systemctl --user list-timers muyan-pilot.timer
```

The setup output carries `timer=enabled active=true next=...` (the next
trigger time). The timer fires every 5 minutes, 24 hours a day
(00:00–23:55). While a task is running, further timer starts are ignored
by systemd; the next real start picks up the latest code (the service
fast-forwards `main` before starting — see [Operations](/operations)).

<Note>
  The committed unit templates reference the author's clone layout via
  `%h` specifiers (`%h/Documents/muyan/muyan-pilot`). If your clone lives
  elsewhere, install the CLI from **your** clone path (step 2) and edit
  the **installed** units in your user unit directory
  (`~/.config/systemd/user/`) to point `WorkingDirectory` and
  `MUYAN_PILOT_CONFIG` at **your** clone path, then
  `systemctl --user daemon-reload`. `ExecStart` is the installed
  `muyan-pilot` CLI and stays relative. The repo templates stay the single
  source of truth for everything else — see [Operations](/operations) on
  drift detection.
</Note>
