tq

May 14, 2026 · View on GitHub

DEPRECATED — use tmuxlet instead. This repo is archived and the npm package @codefilabs/tq is no longer maintained. Please migrate to CodefiLabs/tmuxlet.

Send a message. Get a Claude Code session. Reply to continue.

How It Works

You (Telegram)  →  tq daemon  →  tmux session  →  Claude Code
                ←             ←                ←  /tq-reply

Every Telegram message spawns a Claude Code session in tmux. Reply to the bot's response to continue that conversation. Send a new message to start a new session.

Two routing rules. That's the whole system.

Requirements

  • macOS (uses security CLI for keychain OAuth)
  • Python 3 (stdlib only — no pip install)
  • tmux
  • claude CLI (Claude Code)
  • A Telegram bot token (from @BotFather)

Setup

# 1. Configure Telegram
tq setup

# 2. Start the daemon
tq daemon start

# 3. Send a message to your bot on Telegram

That's it. You're running Claude Code from your phone.

Installation

CLI only

npm install -g @codefilabs/tq

This puts tq on your PATH. You can immediately use tq setup, tq daemon start, etc.

CLI + Claude Code plugin

npm install -g @codefilabs/tq
claude plugin install "$(npm root -g)/@codefilabs/tq"

The Claude Code plugin gives spawned sessions the /tq-reply slash command so they can send responses back to Telegram.

CLI + OpenClaw plugin

npm install -g @codefilabs/tq
openclaw plugins install "$(npm root -g)/@codefilabs/tq/openclaw-plugin"

Provides 3 tools (tq_run, tq_status, tq_stop), a health-check service, and auto-injects active session context into agent prompts.

Everything

npm install -g @codefilabs/tq
claude plugin install "$(npm root -g)/@codefilabs/tq"
openclaw plugins install "$(npm root -g)/@codefilabs/tq/openclaw-plugin"

CLI

tq daemon start|stop|status   Start/stop the Telegram daemon
tq status                     List all sessions
tq stop <id>                  Kill a session
tq run <prompt> [--cwd DIR]   One-shot session (no Telegram)
tq run queue.yaml [--cwd DIR] Batch sessions from YAML
tq reply <id> <text>          Send reply to Telegram (internal)
tq setup                      Configure Telegram bot

Queue Files

For batch automation without Telegram:

cwd: ~/project
tasks:
  - Review yesterday's commits
  - Run the test suite
  - Add documentation
tq run morning.yaml

Optional features:

  • schedule: "0 9 * * *" — cron scheduling
  • reset: daily — auto-clear state so tasks re-run
  • sequential: true — run tasks one at a time in order

State

Everything lives in ~/.tq/:

~/.tq/
  tq.db          SQLite database (all sessions + messages)
  config.json    Telegram bot token + chat ID
  hooks/<id>/    Generated per-session hooks (runtime)
  daemon.pid     Daemon process ID
  daemon.log     Daemon output

One database. One config file. No scattered state directories.

Plugins

tq ships as both a Claude Code plugin and an OpenClaw plugin — see Installation for setup commands.

Architecture

tq/
  __init__.py     Version
  __main__.py     python -m tq entry point
  cli.py          320 lines  Entry point + queue parser
  daemon.py       183 lines  Telegram long-poll + health
  session.py      149 lines  tmux lifecycle + hooks
  store.py        104 lines  SQLite (2 tables)
  telegram.py      63 lines  Bot API

.claude-plugin/            Claude Code plugin
.claude/commands/          /tq-reply slash command
skills/tq/                 Skill definition

openclaw-plugin/           OpenClaw plugin
  src/index.ts             3 tools + 1 service + 1 hook
  src/tq-bridge.ts         CLI bridge

~820 lines of Python. ~150 lines of TypeScript. Zero external dependencies.

Migrating from v1

If you're upgrading from tq v1 (the bash version):

bash migrate-v1-to-v2.sh

The migration script:

  1. Stops v1 processes and removes v1 symlinks
  2. Cleans v1 crontab entries
  3. Removes v1 files (scripts/, tools/, docs/, etc.)
  4. Promotes v2/ contents to repo root
  5. Renames all tq2 references to tq
  6. Installs a tq wrapper to PATH
  7. Preserves ~/.tq/ runtime state

v1 state (~/.tq/queues/.tq/) is not migrated — v2 uses SQLite (~/.tq/tq.db). If you had v1 queue files, they still work with tq run queue.yaml.

Session Management

Sessions are tracked in SQLite with a claude_session_id that enables suspend/resume:

tq suspend <id>    # gracefully stop a session (resumable)
tq resume <id>     # resume a suspended session
tq status          # shows session IDs in brackets, e.g. [a3f5a3d0]

Recovering stale tmux sessions

If you have orphaned tmux sessions from before session tracking was added (or from a crash), you can extract the Claude session IDs without losing them:

# Send /exit to claude in the tmux pane — it exits and prints the resume command
tmux send-keys -t "<session_name>:0.0" "/exit" Enter

# Wait a few seconds, then grab the session ID
tmux capture-pane -t "<session_name>:0.0" -p -S -30 | grep 'claude --resume'
# → claude --resume 063eaae1-68a1-4638-8c1a-ab5c86252a52

# Now you can safely kill the tmux session
tmux kill-session -t "<session_name>"

# And resume later from the correct project directory
cd ~/project && claude --resume 063eaae1-68a1-4638-8c1a-ab5c86252a52

This works because /exit gracefully shuts down Claude Code's TUI but leaves the parent shell alive in tmux.

Security

  • OAuth tokens read from macOS keychain at runtime — never stored in files
  • --dangerously-skip-permissions is required for headless automation
  • Telegram bot token lives in ~/.tq/config.json — never commit this
  • SQLite database may contain message text — treat ~/.tq/ as private

License

MIT