Skip to content

CLI as a standalone binary

The CLI without an installer, for CI runners, Docker, Linux, and macOS.

On CI runners, in Docker images, and on Linux or macOS developer machines, the standalone CLI build is the right approach. A self-contained archive (the CLI plus its bundled runtime), no separate runtime install needed.

Which build for which platform

File For
codecharter-X.Y.Z-win-x64.zip Windows x64
codecharter-X.Y.Z-linux-x64.tar.gz Linux x64 (glibc-based)
codecharter-X.Y.Z-osx-x64.tar.gz macOS Intel
codecharter-X.Y.Z-osx-arm64.tar.gz macOS Apple Silicon

All four are available in the portal at /downloads.

Install as a .NET global tool

If you already have the .NET 9 SDK, installing the CodeCharter.Cli package from nuget.org is the quickest path on any platform:

dotnet tool install --global CodeCharter.Cli
codecharter --version

To update to the latest version:

dotnet tool update --global CodeCharter.Cli

The global tool still requires a valid CodeCharter license / API key at runtime, exactly like the standalone archives below; installing the package does not by itself grant a usage right. See CLI licensing for how to configure CODECHARTER_API_KEY or a codecharter.license file.

Download and unpack

# Example: Linux x64
curl -L -o codecharter.tar.gz \
    -H "Authorization: Bearer $CODECHARTER_API_KEY" \
    https://codecharter.tools/api/v1/cli/linux-x64/latest

mkdir -p /opt/codecharter
tar -xzf codecharter.tar.gz -C /opt/codecharter
chmod +x /opt/codecharter/codecharter
/opt/codecharter/codecharter --version

The archive contains only the CLI and its runtime; no rules are bundled. Rules come from the profiles in your .codecharter/config.yml, resolved against the portal (run codecharter restore to fetch them into the local cache).

The API key does double duty: besides authorizing the download, the CLI uses the CODECHARTER_API_KEY environment variable at runtime to automatically obtain a short-lived license from the portal. Without a valid license, every command exits with code 6. See CLI licensing.

On macOS you may need to click through the Gatekeeper check on first launch (System Settings → Privacy & Security → "Open Anyway") or remove the quarantine attribute:

xattr -dr com.apple.quarantine /opt/codecharter

The binaries are currently not notarized. Use one of the workarounds above on macOS.

In Docker

Never bake the API key into an image layer. Using ARG for secrets writes the value into the build-layer history and makes it extractable from the image. Use a BuildKit secret mount instead (requires Docker 18.09+ with DOCKER_BUILDKIT=1 or BuildKit enabled by default).

# syntax=docker/dockerfile:1
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /app
COPY . .
RUN dotnet build -c Release

FROM mcr.microsoft.com/dotnet/runtime:9.0
WORKDIR /app

RUN --mount=type=secret,id=cgkey \
    mkdir -p /opt/codecharter \
    && curl -sSL \
    -H "Authorization: Bearer $(cat /run/secrets/cgkey)" \
    -o codecharter.tar.gz \
    https://codecharter.tools/api/v1/cli/linux-x64/latest \
    && tar -xzf codecharter.tar.gz -C /opt/codecharter \
    && rm codecharter.tar.gz \
    && chmod +x /opt/codecharter/codecharter

ENV PATH="/opt/codecharter:${PATH}"
COPY --from=build /app/publish ./

Build with:

DOCKER_BUILDKIT=1 docker build --secret id=cgkey,src=<(echo "$CODECHARTER_API_KEY") -t myapp .

Alternatively, keep the codecharter binary out of the image entirely and run the analysis on the CI runner before the Docker build. analyze expects the path to a .sln, .slnx, or .csproj file:

codecharter analyze MySolution.sln --output sarif:codecharter.sarif
docker build -t myapp .

Caching in CI

The archives are self-contained and weigh in at a few tens of megabytes. If your CI provider supports caching, cache the unpacked directory rather than the archive. Unpacking is the more expensive operation compared to downloading.

The official GitHub Action does not use the standalone archives; it runs CodeCharter from a container image. See GitHub Actions.

Automatic updates

The CLI keeps itself current. On every run, right after the license check, it starts a quick background check for a newer release and — if one is published — fetches it. The update is out-of-band and next-run: the command you started always finishes on its current version, and the newer version becomes active on a later launch. Nothing ever blocks on the update, and a binary is never swapped mid-run, so the long-lived mcp server is never disrupted mid-session.

The check is throttled to once every 24 hours (a small state file records when it last ran), so most runs do no network work at all.

How the update is applied depends on how the CLI was installed:

  • .NET global tool (dotnet tool install --global CodeCharter.Cli): the CLI runs dotnet tool update --global CodeCharter.Cli for you.
  • Standalone archive / Docker: the CLI downloads the matching archive from the portal (using the same short-lived license the license check just renewed), verifies its SHA-256, and atomically swaps it into the install directory once no codecharter process is holding those files open. The previous version is kept as an .bak sibling for rollback.

State and staged downloads live under your per-user config directory — $XDG_CONFIG_HOME/codecharter, %APPDATA%\CodeCharter, or ~/.config/codecharter: self-update.json (the throttle/state file) and staging/<version>/ (a verified release waiting to be activated).

Opting out (CI)

For reproducible pipelines you generally pin a version and turn auto-update off. Either flag suppresses the check:

# Per run:
codecharter analyze MySolution.sln --skip-update

# Or for the whole pipeline, set the environment variable once:
export CODECHARTER_SKIP_UPDATE=1

CODECHARTER_UPDATE_INTERVAL overrides the throttle interval, in whole seconds (0 forces a check on every run — useful for testing the update path):

export CODECHARTER_UPDATE_INTERVAL=3600   # check at most once an hour

Version pinning

Instead of /latest/ you can pin a specific version:

https://codecharter.tools/api/v1/cli/linux-x64/1.0.12

The version selector also accepts prefixes such as 1.0 or v1; the newest matching release is served. Download responses carry an X-CodeCharter-Sha256 header that your pipeline can use to verify the integrity of the archive. If your subscription has expired, the download endpoint returns HTTP 402.

We recommend pinning for reproducible builds. See Versioning.

PATH setup

If you do not have the CLI directory on the PATH, you can use the full path. For a persistent PATH setup on a workstation:

# Linux/macOS, in .bashrc or .zshrc
export PATH="/opt/codecharter:$PATH"
# Windows — reads and writes the persistent User PATH (survives reboots)
$current = [Environment]::GetEnvironmentVariable("PATH", "User")
[Environment]::SetEnvironmentVariable("PATH", "$current;C:\codecharter", "User")