---
title: "How the install works"
description: "Why the installer asks for an invite code, what it checks before it unpacks anything, why the scope goes in your home directory, and the Chrome profile it opens."
---

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

# How the install works

An install fetches code from this site and runs it, so the first question is
who the installer lets through, the second is what stops a tampered copy, and
the third is why the steps ask for what they do — a home-directory file,
developer mode, a directory in your home folder and a Chrome profile of its own.
[Install the Chrome extension](/docs/install/) and [Install a
server](/docs/install-server/) are the steps.

## The invite code

Commentware is invite-only for now, and the installer asks for the same invite
code the homepage takes. The check runs on your own machine, so it is a gate and
not a lock: it keeps out anybody who does not read the installer's source, and
nobody who does.

The installer asks on its first run, before it fetches anything from the
registry. It opens your terminal itself, so it asks under `curl … | sh` as well.
A code is twelve letters and digits, and its first four characters name its
batch. The site publishes a list for each batch at `/codes/<batch>.json`. The
list holds the SHA-256 digest of every code in the batch, not the codes. The
installer downloads the list for your code's batch and looks for your code's
digest in it. Capitals, spaces and dashes do not matter, so `ABCD EFGH JKMN` is
`abcd-efgh-jkmn`. A wrong answer is refused with `That is not a valid invite
code.`, and the installer asks again, three tries in all; after the third it
stops and installs nothing.

A valid code is kept in `~/Commentware/invite` (`%USERPROFILE%\Commentware\invite`
on Windows), and every later run checks it against the list again. A `404` for
the batch, or a list that does not hold the digest, removes the file and the
installer asks for a new code. An error other than not found, such as a server
that is down or a timeout, keeps the code and the run goes on. Delete the file to
be asked again.

Two cases stop a run with nothing installed. On a first run, or with `--invite`,
a hub that cannot be reached stops the run, because nothing has admitted the
machine yet. A code given with `--invite` that is not valid stops the run too.

Only a run with no controlling terminal needs `--invite`: CI, cron, or `ssh`
without `-t`. A script started from a terminal, and `curl … | sh`, are still
asked. A run with no terminal, no `--invite` and no kept code stops before it
downloads anything. The flag goes after the install command:
`curl -fsSL … | sh -s -- --invite <code>`. A code given that way is checked,
replaces a different kept code when it is valid, and is the kept code when it is
the same. `--path`, `--version` and `--licenses` print and exit without asking.

## What a run installs and updates

Each install command names what it installs in its address:
`/install/extension`, `/install/server` or `/install/extension-and-server`. The
script there runs `commentware-installer-cli` with `--install` and those parts.
A run also updates every part already on the machine, so running any of the
commands again is how you update. With nothing named and nothing installed, a
run installs the extension. A machine that runs only a server never gets an
extension.

A flag that asks something of a part the run neither installs nor finds
installed, such as `--profile` on a run with no extension, stops the run before
anything is installed.

## What the installer checks before it unpacks anything

`commentware-installer-cli` reads the registry's listing for each part it
installs once, resolves one version, and checks the signature over that version. Then it
downloads that version's tarball and refuses unless the bytes hash to exactly
the number the signature covered. One version, one download, no gap between what
was checked and what lands on disk.

Which key it checks against depends on the build, and it says which:

- **A key pinned into the binary.** This is the check worth having. An attacker
  who took over the host serving this registry could rewrite the tarball, the
  listing, the hash and the key document that sits beside them, and they would
  all agree with each other — but they cannot produce a signature that the key
  in your copy of the binary accepts. That copy did not come from the listing,
  so rewriting the listing does not reach it.
- **The key this registry publishes**, in a build with no pinned key. That key
  is served by the same host, so a match proves the registry is internally
  consistent — a mirror, a truncated deploy or mismatched releases would fail —
  rather than that it has not been tampered with.
- **No check**, when a build with no pinned key meets a registry that publishes
  no key. It says "signature not checked", and why.

It prints which check ran, every time, because a check that says nothing when it
passes cannot be told from one that never ran.

What it cannot check is its own arrival: the install command fetches a binary
from this site and runs it, and that has already happened by the time any of the
above does. An update runs the install command again, so the same is true of
every update: each one fetches the newest installer from this site and runs it.
If you would rather read the script before running it, fetch it with `-o` and
open it.

## The home directory, not a project

Installing the server is a global install, and none of the four package managers
reads a project's own configuration for one. A file beside a `package.json`
works for that project and then the next command fails with a 404 from the
public registry, which reads as "this package does not exist" rather than as
"you configured the wrong file".

`config set` goes to the home directory on its own, in both npm and pnpm — the
project file is somewhere you have to ask for, with `--location=project`. That
is why the npm and pnpm tabs in [Install with a package
manager](/docs/server/#install-with-a-package-manager) are a command and not a
line to paste: the mistake this step has is not reachable from the command.

Yarn and bun each have a reason not to be. bun reads `~/.npmrc` and has no
command that writes it. Yarn 2 and later has one, `yarn config set … --home`,
and yarn 1 accepts that command too, prints `success`, and writes a file yarn 2
never reads — so the yarn tab is the file, in the syntax of the yarn that reads
it. Check with `yarn --version` if you want the command: outside a project, a
bare `yarn` is often still yarn 1.

The line sends only the names that start with `@commentware-private` to this
registry, the part of a package's name npm calls its _scope_. A `registry=` line
in `~/.npmrc` would send every package any project installs here instead, and
this registry holds only Commentware's, so every other install would fail with
a 404. The packages are public: the scope's name does not mean that an npm
login is needed.

The setup page behind the invite code prints the same command, ready to copy. It
is built from the address this site is served at, so a self-hosted Commentware
prints its own — and so do both installer commands in [Install the Chrome
extension](/docs/install/), and the
binaries they fetch: a self-hosted deployment serves its own, pointed at its own
registry.

## Developer mode and its standing warning

The extension is loaded unpacked, which means Chrome needs developer mode
switched on. A browser whose policy forbids developer mode cannot run it, and
there is no way around that.

Chrome will show a standing warning about extensions running in developer mode.
That warning is about the mode, not about this extension, and it cannot be
dismissed permanently.

## Where the extension is unpacked

The directory is in your home folder rather than in the place an application
would normally keep its files, and that is deliberate: it is a directory you
have to find in a file dialog, and every platform hides its application-data
folder from exactly that dialog.

## A Chrome profile only for this

The installer finds Google Chrome and opens the setup page in a profile whose
directory is `Commentware`. A first install makes it; every run after reuses it.
Chrome names a new profile itself, so it shows as `Person 1` or `Your Chrome`
until you rename it from the profile menu at the top right of Chrome.

An extension is loaded into one profile, not into Chrome. Load unpacked in one
window puts Commentware in that profile and in no other, and
**[/ext/](/ext/)** answers for the profile its tab is open in. That is why the
installer picks the window rather than leaving it to whichever one the system
opens: the one it opened is the one to load the extension into.

The extension consults the servers you connect to about the URLs you visit, so a
profile dedicated to the sites you comment on limits what any of them could ever
be asked about. See [What Commentware stores](/docs/what-commentware-stores/).

The cost is that a new profile is signed into nothing, and the sites you want to
comment on are usually ones you log into. Sign into those in the new profile,
once. Opening a profile also makes it the one Chrome starts in next time, so the
next time you open Chrome it may be this one; the profile menu switches back.

Three things change that:

- **`--profile <directory>`** opens the page in a profile you already have, by
  its directory in Chrome's data folder: `Default`, `Profile 2`. It refuses a
  directory that is not there and lists the ones that are, so a typo does not
  make a new profile. `--profile Commentware` is the dedicated one.
- **`--default-browser`** leaves the choice to your system, as an installer
  without this step would: whichever browser and profile it picks. It is also the
  way to use a browser that is not Google Chrome.
- **An update does not make a profile.** If you installed Commentware before
  the installer chose profiles, it is loaded in some profile of yours, and an
  update opens the page through your system unless a `Commentware` profile
  exists. Run it with `--profile <directory>` for the profile that holds the
  extension, or `--profile Commentware` to move to the dedicated one.

When Google Chrome is not in the usual place, or will not start, the installer
says so and opens the page through your system. The flags go after the install
command: `curl -fsSL … | sh -s -- --profile "Profile 2"`.

## Next steps

- [Install the Chrome extension](/docs/install/): install the extension and load
  it into Chrome.
- [Install a server](/docs/install-server/): run a server, connect the extension,
  and leave your first comment.