Whilly — Getting Started

Step-by-step walkthroughs for the most common flows. If you want the full flag/config reference, see Whilly-Usage.md.

For OpenCode runs, including the free opencode/big-pickle model and where to set WHILLY_MODEL, see OpenCode-Developer-Guide.md.

If the repo is already cloned and you want an agent to bring it up locally, send it Agent-Local-Whilly-Setup.md. The fast path in that runbook is:

whilly quick-setup --yes

(If whilly is not yet on $PATH, python3 -m whilly.cli quick-setup --yes runs the same command.)


0. Install (one-time)

⚠️ Python 3.12+ required. pip install whilly-orchestrator==4.4.0 (and every release since) will fail on Python 3.10 / 3.11 with Could not find a version that satisfies the requirement whilly-orchestrator==4.4.0. Install on a 3.12+ interpreter instead — e.g. python3.12 -m pip install whilly-orchestrator or pipx install --python python3.12 whilly-orchestrator. To install 3.12 if you don’t have it: pyenv install 3.12 && pyenv local 3.12.

# macOS / Linux / Windows (needs Python 3.12+)
pipx install whilly-orchestrator

# verify
whilly --help
whilly --config path           # prints the OS-native user config file location

Locations --config path prints:

OS Path
macOS ~/Library/Application Support/whilly/config.toml
Linux $XDG_CONFIG_HOME/whilly/config.toml
Windows %APPDATA%\whilly\config.toml

Secrets live in the OS keyring, never in repo files. To write one:

python3 -c "import keyring; keyring.set_password('whilly', 'github', 'ghp_xxx')"
python3 -c "import keyring; keyring.set_password('whilly', 'jira',  'jira_api_token')"

1. First-time GitHub setup

unset GITHUB_TOKEN                   # clear any stale shell token
gh auth login                        # browser flow, one-time
gh auth refresh -s project           # extra scope for Projects v2 automation
gh auth status                       # should list: gist, project, read:org, repo

If you had a legacy .env:

cd /path/to/your/repo
whilly --config migrate              # .env → whilly.toml + secrets → keyring

Minimal whilly.toml for a GitHub-backed repo:

MAX_PARALLEL = 1
MODEL = "claude-opus-4-7[1m]"
BUDGET_USD = 20                      # hard cap
AUTO_MERGE = "yes"                   # yes | claude | ask | no

[project_board]                      # optional but recommended
url = "https://github.com/users/<you>/projects/<N>"
default_repo = "<you>/<your-repo>"

Verify:

whilly --config show                 # merged config, tokens redacted

2. Scenario: «Run whilly on all GitHub issues with a label»

Most common flow. Whilly fetches every open issue with the given label, converts each into a task, and works through them.

# sanity: see the issues that would be picked up
gh issue list --label whilly:ready --state open

# one-time: make sure the Projects v2 board has the columns whilly needs
whilly --ensure-board-statuses

# one-time: put those issues on the board so you can watch them move
python3 /path/to/whilly-orchestrator/scripts/populate_board.py \
    --project <board-url> --repo <you>/<repo> --label whilly:ready

# now the main event
whilly --from-github whilly:ready --go

What you’ll see:

  1. Whilly fetches issues, writes tasks-from-github.json.
  2. A Rich TUI dashboard opens showing active agents, queue, cost, time.
  3. For every task: card on the board moves Todo → In Progress when the agent picks it up, → In Review when the agent finishes.
  4. After all tasks done: whilly pushes the branch; cards move → Done per the --post-merge hook.

Dashboard hotkeys: q quit, r refresh, R resume workers, 1-5=switch between Overview, Compliance, Plans/Tasks, Workers, and Events, / filter, p pause workers, j/k select review gaps, and a/x/c approve, reject, or request changes.


3. Scenario: «Only one specific issue»

Three equivalent forms:

whilly --from-issue owner/repo/42          --go   # slash form — shell-safe
whilly --from-issue 'owner/repo#42'        --go   # '#' form, always quote in zsh/bash
whilly --from-issue https://github.com/owner/repo/issues/42 --go

Whilly writes tasks-issue-owner-repo-42.json and runs it. Idempotent — re-running the same issue ref refreshes description / acceptance criteria / priority without losing status.


4. Scenario: «Use Jira instead of (or alongside) GitHub»

Add [jira] to whilly.toml:

[jira]
server_url = "https://company.atlassian.net"
username   = "you@example.com"
token      = "keyring:whilly/jira"          # looks up OS keyring
enabled    = true                            # gates auto-close too
enable_board_sync = true                     # perform Jira transitions

Then:

whilly jira import ABC-123
# writes out/jira-ABC-123.json with plan_id=jira-abc-123

whilly jira import ABC-123 --import-db
whilly run --plan jira-abc-123

# one-shot import + run
whilly jira import ABC-123 --run
whilly jira import https://company.atlassian.net/browse/ABC-123 --run

For an interactive one-ticket workflow, use jira intake:

whilly jira intake ABC-123

It fetches the Jira ticket, asks which repository the work belongs to, writes repo_targets into the plan JSON, and then asks what to do next:

  • same repo: use the current checkout’s origin remote, or paste a clone URL.
  • new repo: paste the clone URL for the repo you created for this work.
  • other repo: paste the clone URL for an existing target repo.

The next-step choices are PRD/context first, plan preflight, autonomous run, or save-only. plan runs strict Decision Gate plus TRIZ/challenge preflight. run also starts with strict apply and only then launches the worker. Scripted equivalents:

whilly jira intake ABC-123 --repo-kind same --action prd
whilly jira intake ABC-123 --repo-url git@gitlab.example:team/app.git --action run --max-iterations 1
whilly jira intake ABC-123 --repo-kind skip --action save

jira intake classifies the issue as feature, bug, task, or devops, adds normal/hotfix urgency, and stores context hashes in jira_work for later Jira refresh checks. To require local test evidence before run, pass a checkout path:

whilly jira intake ABC-123 --repo-kind same --readiness-repo-path . --action run

If Whilly cannot find both a test command and unit-test files, it stops before the worker starts. Use whilly jira readiness . to inspect the verdict without running intake.

To refresh the task later without starting work:

whilly jira poll ABC-123
whilly jira poll ABC-123 --persist --plan-id jira-abc-123

poll rereads the issue, comments, changelog, linked issues, remote links, and repo hints. With --persist, it stores the latest snapshot and history event in Postgres.

If Jira settings are missing and the command runs in a terminal, Whilly asks for the missing values. When the API token/PAT is missing, it opens the Jira Cloud token page in your browser. In non-interactive shells, use:

whilly jira import ABC-123 --interactive-config

While the task runs, whilly transitions the Jira ticket in step with its internal status — the mapping (overridable via [jira.status_mapping]):

whilly status Jira transition (default)
pending To Do
in_progress In Progress
done In Review
merged Done
blocked Blocked
human_loop Waiting for Customer
failed Failed
skipped Cancelled

GitHub Projects v2 + Jira can be configured at the same time — whilly drives both on every status change.


5. Scenario: «I want to do the coding myself but let whilly orchestrate»

The claude_handoff backend turns each task into a file-based RPC:

WHILLY_AGENT_BACKEND=claude_handoff whilly --from-issue owner/repo/42 --go

Whilly writes .whilly/handoff/GH-42/prompt.md and blocks. In another shell (or in a Claude Code session you have open):

whilly --handoff-list                    # see pending
whilly --handoff-show GH-42              # read the brief
# ... do the work: edit code, run tests, create PR ...
whilly --handoff-complete GH-42 --status complete --message "PR #123 merged"

Accepted statuses:

status meaning task lands as card lands in
complete done, ready to merge done In Review
failed tried and couldn’t finish failed Failed
blocked waiting on external thing (CI / dep / decision) blocked On Hold
human_loop needs a human decision human_loop Human Loop
partial progress but not complete done In Review

This is the visible-every-step flow — each transition on the board corresponds to a real filesystem event you can inspect.


6. Scenario: «I merge PRs through GitLab / GitHub web UI, not whilly»

Whilly’s automated merge assumes it owns the git push. If you merge elsewhere, use the out-of-band hook:

whilly --post-merge tasks-from-github.json

Iterates every done task in the plan, moves its card to Done, and transitions its Jira ticket to Done (whichever is configured).


7. Common problems

Symptom Fix
gh: Bad credentials (HTTP 401) unset GITHUB_TOKEN && gh auth status — if that’s clean, set WHILLY_GH_PREFER_KEYRING=1 in whilly.toml
Legacy .env detected warning each run whilly --config migrate
Dashboard doesn’t render non-TTY stdout → auto-headless; run whilly in a real terminal. Workspace isolation is off by default since v3.3.0 (pass --workspace to opt in).
Card doesn’t move gh auth refresh -s project (Projects scope) + whilly --ensure-board-statuses
Windows: some hotkeys don’t work expected — the TUI key listener is POSIX-first; dashboard rendering still works
Task stuck “in_progress” across restarts whilly resets stale in_progress tasks automatically on start
Budget exceeded WHILLY_BUDGET_USD=N caps spend; whilly stops at 100 %, warns at 80 %

8. Cost + safety knobs worth knowing

BUDGET_USD = 20              # hard cap ($0 = unlimited)
MAX_TASK_RETRIES = 5         # before a task is skipped
TIMEOUT = 0                  # per-plan wall clock, seconds ($0 = unlimited)
MAX_PARALLEL = 1             # 1 = sequential (recommended for handoff + demos)
RESOURCE_CHECK_ENABLED = true
MAX_CPU_PERCENT = 80
MAX_MEMORY_PERCENT = 75

Kill signals:

export TASK=TASK-001                       # placeholder — the stuck task id
# any running whilly exits cleanly on SIGINT — just Ctrl+C
pkill -f whilly                            # nuclear option
tmux kill-session -t "whilly-$TASK"        # single stuck agent (when USE_TMUX=1)

9. Full reference

  • Whilly-Usage.md — every flag, env var, config field.
  • whilly.example.toml — annotated config template.
  • whilly --help — terse CLI help.
  • whilly --config show — what values are actually in effect right now.