Skip to main content

~Alter Identity Runtime - local sovereign daemon for the continuous identity field. Subscribes to per-~handle Cloudflare Durable Objects, exposes Unix socket + D-Bus + CLI surfaces, falls back gracefully to direct MCP polling.

Project description

alter-runtime - ~Alter Identity Runtime

L3 of the six-layer identity distribution surface. The local sovereign daemon that lives alongside you, subscribes to your per-~handle Cloudflare Durable Object, and renders your identity field across every surface your device touches - terminal, IDE, status bars, desktop tray, browser extension. Falls back gracefully to direct MCP polling when the edge is unreachable.

The alter-runtime daemon architecture was established in April 2026.

Alpha release - filesystem key storage

0.1.0 is an alpha release. The public API surface (CLI flags, Unix-socket JSON schema, D-Bus interface, Python SDK signatures) may change in backwards-incompatible ways before the 0.2.0 stable cut. Pin exact versions in downstream tooling and read the CHANGELOG before upgrading.

Private keys are stored on the filesystem, not in an OS keychain. On first alter-runtime init, the device Ed25519 keypair is written to ~/.config/alter/keypair.json (or $XDG_CONFIG_HOME/alter/keypair.json if the XDG variable is set) with 0600 permissions. The file is readable only by the owning user and never leaves the device. This behaviour is deliberate for the alpha: it keeps the daemon self-contained on any POSIX host and avoids a hard dependency on distro-specific secret stores during early testing.

OS-native secret storage is deferred to 0.2.0: Linux libsecret / kwallet, macOS Keychain, and Windows Credential Manager integration will ship behind a keystore = "native" config knob. Filesystem storage will remain the documented fallback.

For high-stakes use during the alpha - any deployment where a device compromise would imply identity compromise - pair the runtime with hardware-attested passkey registration via the browser claim flow (graduated attestation). The filesystem-stored device key then scopes only to ambient signal ingestion, not to Sovereign-tier authorisations, which require a fresh hardware passkey ceremony per session.

Reporting issues. Security-relevant reports: please follow SECURITY.md and email security@truealter.com rather than filing a public issue. Non-security bugs and feature requests: email support@truealter.com.

Status

Wave Stream Status
1 1c - Daemon skeleton + AlterClient SDK Shipped
2 2b - Subscribers, Unix socket, D-Bus, git watcher Shipped
2 2c - systemd + launchd service units Shipped
2 2d - First pixel: CC hook + scripts upgrade Shipped
2 2e - eBPF subscriber (reference impl in alter-ebpf) Shipped
3 3a - Cross-platform tray surfaces Planned
3 3b - Windows Service + pam_alter stub Planned
3 3c - PyPI release CI + signed binaries Planned

Install

# PyPI (cross-platform)
pip install truealter

# Arch Linux (AUR)
pacman -S alter-runtime          # via your AUR helper (yay -S alter-runtime, paru -S alter-runtime, etc.)

# macOS / Linux Homebrew tap
brew install alter-runtime

# Optional extras (advanced - direct install of the runtime package)
pip install 'alter-runtime[dbus,systemd]'          # Linux desktop
pip install 'alter-runtime[windows]'                # Windows
pip install 'alter-runtime[all]'                    # Everything

Quickstart

# 1. Generate device keypair, install host service unit, authenticate via alter-cli
alter-runtime init

# 2. Start the daemon
alter-runtime start            # Launches via systemd/launchd/Windows Service
# or run in the foreground for debugging
alter-runtime daemon

# 3. Query current field state
alter-runtime status
alter-runtime query attunement

# 4. Manually ingest a signal (useful for testing)
alter-runtime ingest --kind git_commit --payload '{"sha":"abc123"}'

# 5. Stop
alter-runtime stop

What it does

  1. Subscribes to your per-~handle Cloudflare Durable Object over Server-Sent Events at https://mcp.truealter.com/events/~yourhandle/stream. Events arrive with ~50ms latency worldwide.

  2. Falls back gracefully to direct polling of the ALTER MCP endpoint at https://api.truealter.com/api/v1/mcp when the DO is unreachable for more than 3 seconds. Your surfaces never know which path served them.

  3. Exposes three local transports:

    • Unix socket at /run/user/$UID/alter.sock (Linux) or ~/Library/Application Support/alter/runtime.sock (macOS) - line-delimited JSON
    • D-Bus interface org.alter.Identity1 on the session bus (Linux) - used by GNOME/KDE/Waybar modules
    • HTTP/SSE loopback at http://127.0.0.1:<port>/events - used by the CC hook and shell scripts
  4. Collects ambient signals via adapters (Wave 2):

    • Git commits, branch switches, pushes (via watchdog on .git/refs/heads/)
    • CC hook events (forwarded from .claude/hooks/*.sh)
    • Shell command invocations (opt-in)
    • eBPF kernel attestations (shipped; reference impl in alter-ebpf)
  5. Maintains a local cache of your last-known-good field state so the first-paint tilde warmth renders in <1 second, even offline. Per IFA's Five OS-Native Properties, this is the monotonic continuity guarantee.

Layout

alter-runtime/
├── pyproject.toml
├── README.md
├── LICENSE
├── alter_runtime/
│   ├── __init__.py
│   ├── config.py                 # XDG loader, reads alter-cli session.json
│   ├── daemon.py                 # asyncio supervisor
│   ├── cli.py                    # argparse entrypoint: init|start|stop|status|query|ingest|daemon
│   ├── sdk/
│   │   ├── __init__.py
│   │   └── client.py             # AlterClient (async identity MCP client)
│   ├── subscribers/              # (Wave 2)
│   │   ├── do_sse.py             # primary - subscribes to handle-alter DO SSE
│   │   └── mcp_fallback.py       # fallback - polls api.truealter.com/api/v1/mcp
│   ├── sockets/                  # (Wave 2)
│   │   ├── unix.py               # /run/user/$UID/alter.sock
│   │   └── dbus.py               # org.alter.Identity1
│   ├── adapters/                 # (Wave 2)
│   │   └── git_watcher.py        # watchdog on .git/refs/heads/
│   └── services/                 # (Wave 2)
│       ├── systemd/alter-runtime.service
│       ├── launchd/com.alter.runtime.plist
│       └── windows/AlterRuntimeService.py
└── tests/
    ├── conftest.py
    ├── test_cli.py
    ├── test_daemon.py
    └── test_client.py

SDK usage

import asyncio
from alter_runtime import AlterClient

async def main():
    # Auto-discovers the local daemon's Unix socket first, falls back to
    # direct MCP if the daemon isn't running.
    client = AlterClient.auto_discover()

    async with client:
        whoami = await client.whoami()
        print(f"{whoami['handle']}: attunement={whoami['attunement']}")

        # Ingest an ambient signal
        await client.ingest(
            kind="tool_invocation",
            payload={"tool": "my-custom-cli", "duration_ms": 42},
        )

asyncio.run(main())

Packaging

  • PyPI - pip install alter-runtime (publish is tag-gated; see .github/workflows/ci.yml).
  • AUR - draft PKGBUILD at aur/PKGBUILD. Submission is blocked on the PyPI publish resolving the sdist URL. Regenerate .SRCINFO with makepkg --printsrcinfo > .SRCINFO before AUR upload.
  • truealter PyPI shim - thin console-script package at pypi-truealter/ that execs the npm-installed alter binary. Distinct from alter-runtime: pip install truealter gets pip-centric users a fourth CLI install channel alongside npm, Homebrew (planned), and the AUR (planned). Tag format truealter-v<version>; see .github/workflows/truealter-publish.yml.

Contributing

After cloning, wire the identity-trailer hook so commits land with Acted-By:, Drafted-With:, and Co-Authored-By: trailers automatically:

bash scripts/setup-githooks.sh

The helper sets the local core.hooksPath to .githooks/ and marks every hook executable. It is idempotent - safe to re-run after pulls. Equivalent one-liner without the helper:

git config core.hooksPath .githooks

The hook reads your ALTER session at ~/.config/alter/session.json (run alter login from the @truealter/cli once) plus $CLAUDE_MODEL for the Instrument tier attribution. It is silent when the session is missing or jq is unavailable, so a contributor without an ALTER session still gets a normal commit; the CI verifier catches missing trailers at PR time (warn-only during the Rung 1/2 migration window).

Python projects don't have npm's prepare-on-install lifecycle, so this step is manual - done once after clone and persisted in your local .git/config.

Related projects

  • @truealter/sdk - TypeScript SDK client for the public MCP server.
  • ALTER MCP endpoint - https://mcp.truealter.com (SSE per-~handle stream) and https://api.truealter.com/api/v1/mcp (HTTP fallback). Both are documented at truealter.com.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

alter_runtime-0.3.2.tar.gz (214.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

alter_runtime-0.3.2-py3-none-any.whl (261.9 kB view details)

Uploaded Python 3

File details

Details for the file alter_runtime-0.3.2.tar.gz.

File metadata

  • Download URL: alter_runtime-0.3.2.tar.gz
  • Upload date:
  • Size: 214.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for alter_runtime-0.3.2.tar.gz
Algorithm Hash digest
SHA256 16c339afef019e5ff2195a67e29034cbc86ba5efce96a1c7e95f67c52f5ef56b
MD5 1cbf3ff6d8c4fe83da260c132d15f6bb
BLAKE2b-256 0b36a738c1a7715e7db020024ff8bd46631387f6d07fcd472ce76773d612aa02

See more details on using hashes here.

Provenance

The following attestation bundles were made for alter_runtime-0.3.2.tar.gz:

Publisher: ci.yml on true-alter/alter-runtime

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file alter_runtime-0.3.2-py3-none-any.whl.

File metadata

  • Download URL: alter_runtime-0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 261.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for alter_runtime-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 935273dbed087ca0759654cf9d8313fc42f2460bc63429f89f5fcd1cd20866f5
MD5 cb0003e7ab79f6c7abd6ed99bb7c8d83
BLAKE2b-256 ea8c561514216d47337a5fe6251d42d4d30d850e44e839d833ddc4dbd89c2d1e

See more details on using hashes here.

Provenance

The following attestation bundles were made for alter_runtime-0.3.2-py3-none-any.whl:

Publisher: ci.yml on true-alter/alter-runtime

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page