~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-
~handleCloudflare 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 (Patent M, 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
-
Subscribes to your per-
~handleCloudflare Durable Object over Server-Sent Events athttps://mcp.truealter.com/events/~yourhandle/stream. Events arrive with ~50ms latency worldwide. -
Falls back gracefully to direct polling of the ALTER MCP endpoint at
https://api.truealter.com/api/v1/mcpwhen the DO is unreachable for more than 3 seconds. Your surfaces never know which path served them. -
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.Identity1on 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
- Unix socket at
-
Collects ambient signals via adapters (Wave 2):
- Git commits, branch switches, pushes (via
watchdogon.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, Patent M)
- Git commits, branch switches, pushes (via
-
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 (lifted from backend/openclaw-skill)
│ ├── 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.SRCINFOwithmakepkg --printsrcinfo > .SRCINFObefore AUR upload. truealterPyPI shim - thin console-script package atpypi-truealter/that execs the npm-installedalterbinary. Distinct fromalter-runtime:pip install truealtergets pip-centric users a fourth CLI install channel alongside npm, Homebrew (planned), and the AUR (planned). Tag formattruealter-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-~handlestream) andhttps://api.truealter.com/api/v1/mcp(HTTP fallback). Both are documented at truealter.com.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file alter_runtime-0.3.0.tar.gz.
File metadata
- Download URL: alter_runtime-0.3.0.tar.gz
- Upload date:
- Size: 214.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
23657d4f5cd50b22e3442c71fa0a0a1ef9e5efd5145ced3cb095f45d41af1e05
|
|
| MD5 |
a3c11bc7893f30d2e46767bb47b47201
|
|
| BLAKE2b-256 |
6fa6d1986e1bcd38672a7de318530f8c051bb39e3b7a638f2f1d976f27430516
|
Provenance
The following attestation bundles were made for alter_runtime-0.3.0.tar.gz:
Publisher:
ci.yml on true-alter/alter-runtime
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
alter_runtime-0.3.0.tar.gz -
Subject digest:
23657d4f5cd50b22e3442c71fa0a0a1ef9e5efd5145ced3cb095f45d41af1e05 - Sigstore transparency entry: 1698844644
- Sigstore integration time:
-
Permalink:
true-alter/alter-runtime@19054ab2f94b0686e81b5032ab591ff3665e832c -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/true-alter
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@19054ab2f94b0686e81b5032ab591ff3665e832c -
Trigger Event:
push
-
Statement type:
File details
Details for the file alter_runtime-0.3.0-py3-none-any.whl.
File metadata
- Download URL: alter_runtime-0.3.0-py3-none-any.whl
- Upload date:
- Size: 274.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43a8f8b314ceaa81ff6a5b53dbcefa0be4defa22e4c3114c7602726b0d40928a
|
|
| MD5 |
42a4d2f573a51ed153b7d25f515704ff
|
|
| BLAKE2b-256 |
900991049e96b673d0e85254284bf83492bb9396c8022f0b483f8413d123f9fd
|
Provenance
The following attestation bundles were made for alter_runtime-0.3.0-py3-none-any.whl:
Publisher:
ci.yml on true-alter/alter-runtime
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
alter_runtime-0.3.0-py3-none-any.whl -
Subject digest:
43a8f8b314ceaa81ff6a5b53dbcefa0be4defa22e4c3114c7602726b0d40928a - Sigstore transparency entry: 1698844702
- Sigstore integration time:
-
Permalink:
true-alter/alter-runtime@19054ab2f94b0686e81b5032ab591ff3665e832c -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/true-alter
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@19054ab2f94b0686e81b5032ab591ff3665e832c -
Trigger Event:
push
-
Statement type: