Telegram remote-control daemon for Claude Code CLI sessions running in dtach
Project description
aipager
Telegram remote-control for Claude Code
CLI sessions. Run Claude inside a detached terminal (dtach), drive it
from your phone — read responses, send prompts, approve permission
requests, switch sessions — without an SSH session staying open.
Install
Linux or macOS, any architecture. dtach is installed automatically
via the dtach-bin dependency —
no separate system package needed.
One-line install (recommended)
curl -fsSL https://raw.githubusercontent.com/dev-aly3n/aipager/main/install.sh | sh
This auto-detects uv / pipx / brew and uses whichever is already on
your system. If none is present, it bootstraps uv (Astral's Python tool
manager) and installs through it.
uv (recommended on macOS)
uv tool install aipager # if uv is already installed
— or to install uv first:
curl -LsSf https://astral.sh/uv/install.sh | sh
uv tool install aipager
uv bundles its own Python interpreter, so this works on any macOS / Linux version regardless of what system Python is doing — it sidesteps the Homebrew-Python-vs-Xcode breakage described under the Homebrew section below.
pipx
pipx install aipager
Homebrew tap (macOS, Linuxbrew)
Note:
uv tool install aipageris the recommended path on macOS. The brew formula works when Homebrew'spython@3.12bottle and your Xcode / Command Line Tools are in sync, but they periodically drift apart — most recently on macOS Tahoe (26.x), where install fails with apyexpat _XML_SetAllocTrackerActivationThresholdsymbol error (upstream issue). Updating Xcode + Command Line Tools usually fixes it, but it's easier to just use uv.
brew install dev-aly3n/tap/aipager
Pulls dtach from Homebrew's standard formula and installs aipager into
a Homebrew-managed Python venv.
Docker
Self-contained image with python, node, claude and dtach baked in
— good for VPS / NAS / Pi deployments where you don't want a Python
or Node toolchain on the host. Multi-arch (amd64, arm64).
# 1. Run the setup wizard once (interactive)
docker run --rm -it \
-v "$HOME/.claude:/home/aipager/.claude" \
-v aipager-config:/home/aipager/.config/aipager \
ghcr.io/dev-aly3n/aipager:latest config
# 2. Start the daemon (background, auto-restart)
docker run -d --restart=unless-stopped --name aipager \
-v "$HOME/.claude:/home/aipager/.claude" \
-v aipager-config:/home/aipager/.config/aipager \
-v "$PWD:/workspace" \
ghcr.io/dev-aly3n/aipager:latest
Mount the directories you want claude to edit under /workspace. The
~/.claude mount carries over your claude credentials and
conversation history — run claude on the host once to authenticate,
or docker exec -it aipager claude for an interactive login in the
container.
Tags: latest, 0.4, 0.4.2 (semver track + minor track).
Nix flake
nix run github:dev-aly3n/aipager -- --version
nix profile install github:dev-aly3n/aipager
Builds aipager from source against pinned nixpkgs deps. dtach is
provided by Nix; claude is not — install it separately
(nix profile install nixpkgs#nodejs && npm install -g @anthropic-ai/claude-code, or follow Anthropic's docs).
For declarative NixOS / Home Manager configs, add aipager as a flake
input and pick its package up from environment.systemPackages:
{
inputs.aipager.url = "github:dev-aly3n/aipager";
outputs = { self, nixpkgs, aipager, ... }: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
modules = [{
environment.systemPackages = [
aipager.packages.${pkgs.system}.default
];
}];
};
};
}
aipager service install will then wire up a systemd-user unit.
Group mode (multi-user)
aipager runs by default as a 1:1 DM bot. To run it in a Telegram
group with multiple devs (mention @aipagerbot deploy,
@aipagerbot /jim run the tests), re-run aipager config and
pick Team at the mode prompt. You'll set up an allow-list of
Telegram user IDs and roles (admin / developer / read_only)
plus optional deny_tools rules that auto-block dangerous tool
calls. Adding a user grants them code-execution rights on the
host — see docs/groups.md for the full trust
model.
AUR (Arch Linux)
yay -S aipager # or paru, pikaur — any AUR helper
System dtach and python-telegram-bot come from pacman; install
the Anthropic claude CLI separately
(sudo pacman -S npm && sudo npm install -g @anthropic-ai/claude-code).
PKGBUILD lives at packaging/aur/ for review.
Snap
snap install aipager
Strict-confinement snap that bundles python + node + claude +
dtach + aipager. Because of snap's sandbox model, workspaces must
live under ~/ (e.g. ~/projects/foo). Manifest at
packaging/snap/.
Configure
aipager config
Interactive wizard — asks for your Telegram bot token (from
@BotFather) and chat ID, validates them, then
patches ~/.claude/settings.json to wire the necessary hooks
automatically. You never edit any file by hand.
Run
aipager start
The daemon stays in the foreground. Launch a Claude session in another terminal:
aipager session dev
This creates (or reattaches to) a dtach session named claude-dev
running Claude Code. The aipager daemon discovers it within seconds
and Telegram starts mirroring it. Re-run the same command to reattach
later; detach with Ctrl-\.
If the dtach session was killed (machine reboot, etc.) but you want
to pick up the Claude conversation from disk, add --resume:
aipager session dev --resume # resume the last claude conversation in this cwd
You can also pass --resume <session-id> (or any other claude flag)
through as trailing args:
aipager session dev -- --resume abc1234
Run as a service (survives logout)
aipager service install
On Linux this writes a systemd-user unit at
~/.config/systemd/user/aipager.service and starts it. On macOS it
writes a launchd plist at ~/Library/LaunchAgents/com.aipager.daemon.plist
and bootstraps it. Subcommands: start, stop, status, logs,
uninstall.
What it does
- Mirrors Claude Code session state to Telegram: busy/idle, tool calls, context %, cost, line counts
- Lets you reply to messages to inject prompts back into the session
- Surfaces permission prompts and
AskUserQuestiondialogs as Telegram inline keyboards - Notifies on context warnings, compaction, session end, and stalls
- Supports multiple concurrent sessions with one bot
- Optional read-only observer bots
Note on model buttons (Bedrock / Vertex users)
The persistent keyboard's Model submenu sends /model sonnet,
/model opus, /model haiku, and /model opusplan — Claude Code's
aliases. On the Anthropic API these resolve to the latest in each
family (currently Opus 4.7, Sonnet 4.6, Haiku 4.5). On Bedrock and
Vertex the same aliases may resolve to older snapshots depending on
your provider's available versions. If you target those backends and
want a specific model, tap the alias as a starting point, then /model <full-id> from chat.
Developing locally
git clone <repo-url> aipager && cd aipager
python3 -m venv .venv && source .venv/bin/activate
pip install -e '.[dev]'
pytest -q
When iterating on code changes you'll generally want to also install
dtach-bin from a local checkout — or pip install dtach-bin — so the
runtime can find dtach on PATH.
Release process is in CONTRIBUTING.md.
License
MIT — see LICENSE.
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 aipager-0.4.2.tar.gz.
File metadata
- Download URL: aipager-0.4.2.tar.gz
- Upload date:
- Size: 319.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ecc2b7b3b38e17474f5f0a9fecb9f15ad07168af0289a43583b7f28f548bc5d
|
|
| MD5 |
8347d74a3b61a05462e24ad5e9af6149
|
|
| BLAKE2b-256 |
cebe3317f3fde20c3e6d22e4be3b2c9c99e898bf6f179d10df52409e0e7472a7
|
Provenance
The following attestation bundles were made for aipager-0.4.2.tar.gz:
Publisher:
publish.yml on dev-aly3n/aipager
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aipager-0.4.2.tar.gz -
Subject digest:
2ecc2b7b3b38e17474f5f0a9fecb9f15ad07168af0289a43583b7f28f548bc5d - Sigstore transparency entry: 1587300219
- Sigstore integration time:
-
Permalink:
dev-aly3n/aipager@d97dfb512052c7f437fc47d320d0f0761f0b2785 -
Branch / Tag:
refs/tags/v0.4.2 - Owner: https://github.com/dev-aly3n
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d97dfb512052c7f437fc47d320d0f0761f0b2785 -
Trigger Event:
push
-
Statement type:
File details
Details for the file aipager-0.4.2-py3-none-any.whl.
File metadata
- Download URL: aipager-0.4.2-py3-none-any.whl
- Upload date:
- Size: 198.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
991f4f450d16bdd2d9330fc4a48c7f47da7172a1713811c82f7fe896e895739a
|
|
| MD5 |
de49fadbc78f852f462a6aa8aa60bdb4
|
|
| BLAKE2b-256 |
6a73142c5ffb588c8e0113f071dff4d9c276f0e114e9493e0360224620d1394e
|
Provenance
The following attestation bundles were made for aipager-0.4.2-py3-none-any.whl:
Publisher:
publish.yml on dev-aly3n/aipager
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aipager-0.4.2-py3-none-any.whl -
Subject digest:
991f4f450d16bdd2d9330fc4a48c7f47da7172a1713811c82f7fe896e895739a - Sigstore transparency entry: 1587300332
- Sigstore integration time:
-
Permalink:
dev-aly3n/aipager@d97dfb512052c7f437fc47d320d0f0761f0b2785 -
Branch / Tag:
refs/tags/v0.4.2 - Owner: https://github.com/dev-aly3n
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d97dfb512052c7f437fc47d320d0f0761f0b2785 -
Trigger Event:
push
-
Statement type: