Install qq
Put qq and qqsync on your machine in three copy-paste commands (four on a Mac), check them, and know what to do on a Mac.
You install two tools, both from source on GitHub, into one folder in your
home directory: qq, the command line, and qqsync, the tool that reads
a repo's infra/repo.toml. Nothing needs root. Outside ~/qq-tools, the
only changes are one line that puts it on your PATH (on a Mac, or when
qq-setup picks a newer python3.N, also one line that sets QQ_PYTHON),
qq's own cache in ~/.cache/qq, and pip's download cache.
The three commands below, run on a fresh Linux account with an earlier qqsync pin. The last step opens a new shell and checks both versions.
Before you start
qq runs on Linux and macOS. You need git and Python 3.11.4 or newer with
its venv module (on Debian or Ubuntu, the python3-venv package). That is
all qq itself needs. qq uses python3 unless you set QQ_PYTHON to another
Python, and the commands below do the same. The toolchains a repo builds
with (Python 3.14.8, Node 24 with pnpm) are fetched later by qq sync, on
Linux x86_64.
On a Mac, set up Python first. The python3 that comes with macOS is
3.9, too old for qq. brew install python@3.13 adds python3.13 but leaves
python3 as it was, so tell qq to use it, then open a new terminal:
brew install python@3.13 && { grep -qs 'QQ_PYTHON=' ~/.zshrc || echo 'export QQ_PYTHON=python3.13' >> ~/.zshrc; }If your shell is bash, add that export line instead to the first of
~/.bash_profile, ~/.bash_login or ~/.profile that you already have
(~/.bash_profile if you have none). Bash reads only that one, and step 3
uses the same file.
Each command below runs inside ( … ), so it leaves your shell as it was,
and each is safe to run again. To have them run for you instead, see
Let qq-setup install it for you.
1. Install qq
qq is a git checkout, like depot_tools. This clones it and prints its version.
( set -e; mkdir -p ~/qq-tools; rm -rf ~/qq-tools/depot; git clone -q https://github.com/quirq-ai/qq ~/qq-tools/depot; ~/qq-tools/depot/bin/qq --version )It prints qq 0.1.0. The first run also prints a line saying it set up its
launcher under ~/.cache/qq.
2. Install qqsync
qqsync is the only program allowed to read or edit infra/repo.toml. It
goes in its own Python environment, made with the same Python as qq and
pinned to the same sync commit that qq pins, so the two always agree.
( set -e; mkdir -p ~/qq-tools; rm -rf ~/qq-tools/qqsync; "${QQ_PYTHON:-python3}" -m venv ~/qq-tools/qqsync; ~/qq-tools/qqsync/bin/pip install -q --disable-pip-version-check "qqsync @ git+https://github.com/quirq-ai/sync@9821f745690d5150cac70cd2eee54c97d431e6c3"; ~/qq-tools/qqsync/bin/qqsync --version )It prints qqsync 0.1.0.
3. Put both on your PATH
This links both into ~/qq-tools/bin and adds that folder to your PATH:
in ~/.bashrc for bash, in ~/.zshrc otherwise, and on a Mac in the first
of ~/.bash_profile, ~/.bash_login or ~/.profile that bash already
reads.
( case "$SHELL:$(uname)" in */bash:Darwin) for rc in ~/.bash_profile ~/.bash_login ~/.profile ~/.bash_profile; do [ -f "$rc" ] && break; done ;; */bash:*) rc=~/.bashrc ;; *) rc=~/.zshrc ;; esac; mkdir -p ~/qq-tools/bin && ln -sf ~/qq-tools/depot/bin/qq ~/qq-tools/qqsync/bin/qqsync ~/qq-tools/bin/ && { grep -qs 'qq-tools/bin:' "$rc" || printf '\nexport PATH="$HOME/qq-tools/bin:$PATH"\n' >> "$rc"; } && echo "qq-tools/bin is on PATH in $rc; open a new terminal" )Open a new terminal and check:
qq --version && qqsync --versionYou should see qq 0.1.0 and qqsync 0.1.0. Next: your first
build.
How qq stays up to date
You rarely update qq by hand. Each repo pins the qq version it runs in its
infra/repo.toml, and inside that repo qq runs exactly that version,
installing it under ~/.cache/qq the first time. When the pin moves, the
next qq you run picks up the new version.
Today: qq has no release tag yet, so a repo's 0.1.0 pin runs your own
checkout in ~/qq-tools/depot. To update it, run step 1 again.
Auto-update
qq-setup can keep qq and qqsync up to
date for you. It is off until you turn it on: tick the Auto-update box on
This machine, or in a terminal add install --auto-update to the end of
its command (--no-auto-update turns it off). It then writes ~/qq-tools/auto-update, naming the commits
it installed.
- At most once a day, in the background, qq reads the commits qq-setup has
reviewed (
pins.jsonon itsmain), so no command waits on the network. - When they are newer, the next
qqfirst moves~/qq-tools/depotto them, reinstalls qqsync if it is still the one qq-setup installed, then runs your command. - A checkout with changes of yours or at another commit, and a qqsync you
installed another way, are left alone. Nothing runs when
CIorQQ_PINNEDis set. - What it did is in
~/qq-tools/auto-update.log. Inside a repo, the repo's pin still decides which qq runs.
On a Mac
qq and qqsync install the same way, once QQ_PYTHON points at a new enough
Python (Before you start). What differs is the
toolchains, which are published for Linux x86_64 only:
qq syncstops withno pin for platform macos-arm64.qq fetchclones the repo, then stops at the same point; carry on in the clone.- Install the pinned version yourself (Python 3.14.8, or Node 24 with pnpm)
and pass it in:
qq test --toolchain python=ROOT, whereROOTis the folder that holds itsbin. qq runuses the tools on yourPATHand names the pinned toolchains it could not use.
Let qq-setup install it for you
qq-setup can run steps 1 to 3 for you, and later update or remove qq. It
runs straight from GitHub with npx. Replace <commit> with the full id of
the latest commit on main,
so the link serves exactly that commit:
npx --allow-remote=root https://codeload.github.com/quirq-ai/setup/tar.gz/<commit>It needs Node 22 or newer, and installs qq on Linux and macOS. On Windows it installs only xo, and for qq suggests WSL with Node 22 or newer installed inside it (qq-setup is not tested in WSL).
It checks your tools and opens a page in your browser, on step 1, This
machine (it says "Start here" when qq is missing). It shows what is already
here: qq and qqsync in ~/qq-tools, and whether they are on your PATH. Each
tool starts at Keep (or Don't install), so nothing changes until you
choose. For qq, pick Install if it is missing, or Update, Add to
PATH or Remove if it is there; for xo, the same, or
leave it. The page shows the exact commands, and Run runs them one at a
time, with their output on the page, stopping at the first that fails. Press
Done: close qq-setup when you are finished, then open a new terminal.
To install or update, it runs steps 1 to 3 of this page. On a Mac with no new
enough Python, it first runs brew install python@3.13 and writes
export QQ_PYTHON=python3.13 to the same file as the PATH line, so your
shell finds it, bash or zsh. Otherwise, if python3 is too old but a newer
python3.N is installed, it writes a QQ_PYTHON line for that one.
- Update runs steps 1 to 3 again, which re-clones
~/qq-tools/depot. If that checkout has work of yours in it, the page warns you first; pick Keep to leave it. - Remove deletes
~/qq-tools, qq's cache and thePATHline, as "Remove everything" below does. The demo folders~/qq-tryand~/qq-ci-venv, and theQQ_PYTHONline, are boxes left unticked: they stay unless you tick them.
Step 2 of the page, Set up repos in an org you own, prints the plan for
putting an org's repos on qq
in your terminal.
In a terminal without a browser, add install --only qq to the end of the
command: it asks the same questions there, and --dry-run shows the commands
without running them.
Today: qq-setup is not on npm yet. It never writes to GitHub, and on
your machine it changes only your home folder (and Homebrew's, for the Mac
Python step). For an org, it only prints the plan: it creates no repo
and changes no setting. The page listens on 127.0.0.1 only and its link
works once. qq-setup refuses to open the page while GH_TOKEN,
GITHUB_TOKEN or a GitHub Enterprise token variable is set, so it only
ever acts as your own gh login.