Installation
Polylogue is available from PyPI, the Sinity Homebrew tap, and its Nix flake. Container and browser-extension artifacts remain version-specific: a GitHub tag or release page alone is not proof that those channels carry a matching artifact, so use the linked verification for the channel you plan to install from.
| Channel | Audience | Install after its artifact smoke passes | Verification |
|---|---|---|---|
nix develop |
Local development, source checkout, verification | nix develop |
Contributing |
| Nix flake | NixOS / nix-darwin users | nix run github:Sinity/polylogue -- --help |
flake.nix |
| PyPI / pipx | Python CLI users | pipx install polylogue |
polylogue --version, polylogued --help, polylogue-mcp --help |
| GHCR | Container deployments | podman pull ghcr.io/sinity/polylogue:X.Y.Z |
podman run --rm --entrypoint polylogue ghcr.io/sinity/polylogue:X.Y.Z --version |
| Homebrew | macOS/Linuxbrew users | brew tap sinity/polylogue && brew install polylogue |
brew test polylogue |
| Browser extension | Browser-capture users | Download the matching release .zip / .xpi |
verify build-manifest.json version equals X.Y.Z |
| NixOS / Home Manager module | Managed local daemon deployment | see below | systemctl status polylogued.service |
For the release-channel recovery sequence and exact smoke matrix, see the release checklist.
The source and Nix paths expose the same three console scripts: polylogue,
polylogued, and polylogue-mcp.
Source checkout
Clone the repository and enter the dev shell:
git clone https://github.com/Sinity/polylogue.git
cd polylogue
nix develop
From inside the dev shell:
polylogue --help
polylogue ops status
polylogued run
polylogue-mcp --help
Use this route for local work, operator dogfooding, browser-capture debugging,
and repository verification. The dev shell also provides devtools, which owns
generated docs, verification, deployment smoke probes, and release checks.
Nix / NixOS quick start
The flake exposes app outputs for the CLI, daemon, and MCP server. Use
github:Sinity/polylogue for a one-shot smoke of the current published flake,
or nix develop inside a checkout when you need the repo-local devtools
surface. One-shot commands are enough for smoke testing a host:
nix run github:Sinity/polylogue -- --help
nix run github:Sinity/polylogue#polylogued -- run
nix run github:Sinity/polylogue#polylogued -- browser-capture status
nix run github:Sinity/polylogue#polylogue-mcp -- --help
Inside a checkout, use the dev shell when you want the repo-local command surface and verification helpers:
nix develop -c polylogue --help
nix develop -c polylogued run
nix develop -c devtools workspace deployment-smoke --browser --browser-executable "$(command -v google-chrome)"
On NixOS hosts where Chrome lives in the per-user profile rather than under a distribution path, pass that path explicitly for browser first-paint diagnostics:
nix develop -c devtools workspace deployment-smoke --browser \
--browser-executable /etc/profiles/per-user/$USER/bin/google-chrome
That smoke launches a fresh headless profile against Polylogue's web root. It
does not claim MCP DevTools control, copied-profile cookies, or live provider
pages; those are local operator proof modes covered by
docs/dev-loop.md.
On NixOS, import the flake module shown in the Nix section below. It creates a
managed polylogued.service; check that deployed surface with:
systemctl status polylogued.service
polylogue ops status
PyPI and Homebrew
pipx is the recommended isolated Python CLI install. uv tool provides the
same isolation model if uv is already your package frontend:
pipx install polylogue
# or: uv tool install polylogue
polylogue --version
polylogued --help
polylogue-mcp --help
The Homebrew tap installs the published PyPI release into a formula-owned virtual environment:
brew tap sinity/polylogue
brew install polylogue
brew test polylogue
Containers
For containers, use --version for the concise human build identity and query
the packaged runtime's VERSION_INFO.commit for the full revision before
deploying:
podman pull ghcr.io/sinity/polylogue:X.Y.Z
podman run --rm --entrypoint polylogue ghcr.io/sinity/polylogue:X.Y.Z --version
podman run --rm --entrypoint python ghcr.io/sinity/polylogue:X.Y.Z \
-I -c 'from polylogue.version import VERSION_INFO; print(VERSION_INFO.commit)'
git ls-remote https://github.com/Sinity/polylogue refs/tags/vX.Y.Z
The published workflow performs this smoke for both slim and distroless images; it requires the concise version to match the source prefix and the machine- readable runtime field to equal the complete source revision.
Recovering an already-created tag
If a GitHub Release exists without its artifacts, do not re-cut its tag. Follow the release checklist recovery sequence, which requires the tag, checked-out source, and GitHub Release target commit to agree before publication.
For local container or formula experiments before their artifacts exist, build from the checkout:
docker buildx build -f packaging/Containerfile --target runtime -t polylogue:slim .
docker buildx build -f packaging/Containerfile --target distroless -t polylogue:distroless .
For formula work, build the in-repo template explicitly:
brew install --build-from-source nix/homebrew-tap-template/Formula/polylogue.rb
brew test polylogue
brew audit --strict --online polylogue
Nix flake
The flake exposes three apps, a default package, a NixOS module, and a Home
Manager module. Build artifacts for x86_64-linux are mirrored to the
sinity cachix cache; enable it on a fresh host
to avoid rebuilding the dependency closure.
One-shot invocation
nix run github:Sinity/polylogue # polylogue (CLI)
nix run github:Sinity/polylogue#polylogued -- --help # daemon
nix run github:Sinity/polylogue#polylogue-mcp # MCP server
Enable the binary cache for hit-on-first-pull:
nix-env -iA cachix -f https://cachix.org/api/v1/install # if cachix is not on PATH
cachix use sinity
External flake input
{
inputs.polylogue.url = "github:Sinity/polylogue";
# or, via FlakeHub:
# inputs.polylogue.url = "https://flakehub.com/f/Sinity/polylogue/*";
outputs = { self, nixpkgs, polylogue, ... }: {
# Use polylogue.packages.x86_64-linux.default in any derivation
# or wire the NixOS / HM module below.
};
}
NixOS module
{ inputs, pkgs, ... }: {
imports = [ inputs.polylogue.nixosModules.default ];
services.polylogue = {
enable = true;
package = inputs.polylogue.packages.${pkgs.system}.default;
settings = {
archive.root = "/var/lib/polylogue";
daemon-api.port = 8766;
browser-capture.port = 8765;
embedding.enabled = false;
};
};
}
The module wires a polylogued.service systemd unit running polylogued run
(watch + browser-capture + HTTP API). services.polylogue.settings.* renders
the same polylogue.toml schema used outside Nix; polylogued run reads that
effective config instead of receiving duplicated ExecStart flags. Keep bearer
tokens in environment/secret-manager wiring when possible, because setting them
in settings.* writes them into the generated TOML. Per-unit hardening defaults
(Nice = 10, IOSchedulingClass = idle, MemoryHigh = 2G, MemoryMax = 2G)
are tunable under services.polylogue.service.*; they are deployment policy,
not archive config.
After deploying, use polylogue config --format json to inspect effective
values and source layers, and devtools workspace deployment-smoke --json to capture the
package versions, archive root, daemon URL, browser-capture receiver URL,
optional browser executable path, and cgroup resource signals visible on the
host.
Home Manager module
{ inputs, pkgs, ... }: {
imports = [ inputs.polylogue.homeManagerModules.default ];
programs.polylogued = {
enable = true;
package = inputs.polylogue.packages.${pkgs.system}.default;
settings.daemon-api.port = 8766;
};
}
The HM module declares a systemd.user.services.polylogued unit and renders the
same TOML schema as the NixOS module. Set programs.polylogued.autoStart = false; to keep the unit available but not started at login.
Building locally
nix build .#polylogue # the package
nix build .#api-python # python interpreter with polylogue importable
nix flake check # smoke + format + lint
Browser extension
The Manifest V3 browser-capture extension lives in
browser-extension/ and ships as packed artifacts
attached to every GitHub release by
.github/workflows/extension-release.yml.
| Artifact | Browsers | Use |
|---|---|---|
polylogue-browser-capture-<version>-chrome.zip |
Chrome, Chromium, Edge, Brave, Vivaldi | Developer-mode unpacked install |
polylogue-browser-capture-<version>-firefox.xpi |
Firefox | Temporary install via about:debugging |
polylogue-browser-capture-<version>-store-submission.json |
Store operators | Version, source revision, Gecko ID, SHA-256, and size for both archives |
store-screenshots-<tag>.tar.gz |
— | Submission media for store listings |
Download the artifacts from the
latest release.
The version is locked to the polylogue Python project version on the same
tag — the workflow rewrites manifest.json from pyproject.toml before
packaging so the extension version always matches the daemon protocol it
was built against. Before uploading to a store, verify each downloaded archive
against the matching store-submission.json; it binds the pair to the release
version and complete source revision.
Install paths
The full per-browser steps live in
browser-extension/README.md. At
a glance:
- Start the receiver.
polylogued browser-capture serve(orpolylogued runfor the full daemon). Default endpointhttp://127.0.0.1:8765. - Chrome / Chromium (unpacked from clone).
chrome://extensions→ Developer mode → Load unpacked → selectbrowser-extension/. - Chrome / Chromium (packed
.zip). Download the release.zip, extract, then Load unpacked against the extracted directory. - Firefox. Download the release
.xpi. Visitabout:debugging#/runtime/this-firefox→ Load Temporary Add-on → select the.xpi.
Distribution status
| Channel | Status | Tracking |
|---|---|---|
Packed .zip on GitHub Releases |
release-backed; verify the matching asset exists | this doc |
Packed .xpi on GitHub Releases |
release-backed; verify the matching asset exists | this doc |
| Chrome Web Store | not submitted (store sign-up + review have non-engineering blockers) | follow-up |
| Mozilla AMO | not submitted (same blockers) | follow-up |
The extension is local-only by design — it talks to 127.0.0.1:8765 and
nothing else. See docs/browser-capture.md for the
receiver protocol and docs/daemon-threat-model.md for the security model.
Local rebuild
cd browser-extension
npm install
npm run validate # in-tree manifest validator
npm run build # → dist/polylogue-browser-capture-*-{chrome.zip,firefox.xpi}
npm run screenshots # optional; needs Playwright Chromium
scripts/build.mjs --version X.Y.Z overrides the autodetected version when
producing a one-off bundle.