Discord to tmux session bridge for agent-driven workflows.
Project description
tetherly
Discord channel ↔ tmux session bridge.
📖 Documentation is in docs/ — split into user docs (setup, commands, troubleshooting) and contributing docs (internals). This README is a quick start.
Features
/bind session:<name>: bind the current Discord channel to a tmux session/config auto_send:<true|false>: enable or disable plain-text auto-send for the current bound channel/send text:<message>: send text plus Enter into the bound tmux session/key key:<Enter|Escape|Ctrl-C|Ctrl-D|Tab|Up|Down|Left|Right>: send a special key into the bound tmux session/tail lines:<n>: fetch recent tmux output/status: inspect the current binding and tmux session statustetherly discord-send --message <text>: let an agent inside a bound tmux session send a reply back to Discordtetherly codex-stop/tetherly codex-permission-request: Codex hook handlers that forward messages to the bound Discord channel
Requirements
- Python 3.11+
tmuxinstalled- A Discord bot token (Message Content Intent enabled if you want plain-text auto-send)
Setup
Install once on your machine:
pipx install tetherly
# or: uv tool install tetherly
tetherly init
tetherly init is interactive. It writes ~/.tetherly/.env and asks where to install Codex hooks:
- Global — writes
~/.codex/hooks.jsononce. Hooks fire in every project automatically; nothing per-project. - Project — skip global hooks and run
tetherly install-hooksinside each project where you want them. - Skip — don't touch Codex hooks.
Then start the bot:
tetherly
That's it. State lives at ~/.tetherly/state.json so a single bot can serve every project.
Per-project usage
For each project you want to drive from Discord:
tmux new -s <session-name>
# inside the bound channel on Discord:
# /bind session:<session-name>
# /config auto_send:true
If you chose Project mode during init, also run once per project:
cd <project>
tetherly install-hooks
install-hooks accepts --global to (re)install user-level hooks instead.
Sending from inside a session
tetherly discord-send --message "작업 끝났습니다"
cat result.txt | tetherly discord-send --stdin
tetherly discord-send --session t1 --message "..." # explicit session
Configuration
tetherly init writes everything you need. Advanced overrides live in ~/.tetherly/.env or shell env:
| Variable | Default | Notes |
|---|---|---|
DISCORD_BOT_TOKEN |
(required) | Bot token |
TETHERLY_ALLOWED_USER_IDS |
(required) | Comma-separated user IDs |
TETHERLY_ALLOWED_GUILD_IDS |
— | Restrict commands to these guilds |
TETHERLY_ALLOWED_ROLE_IDS |
— | Allow members holding any of these roles |
TETHERLY_TEST_GUILD_ID |
— | Dev guild for instant slash-command sync |
TETHERLY_STATE_PATH |
~/.tetherly/state.json |
Where bindings are persisted |
TETHERLY_DEFAULT_TAIL_LINES |
40 |
Default /tail line count |
TETHERLY_MAX_TAIL_LINES |
200 |
Cap for /tail |
TETHERLY_LOG_LEVEL |
INFO |
Logger verbosity |
A .env in the current working directory still overrides ~/.tetherly/.env.
Codex hooks
Both hooks only fire when the active tmux session has TETHERLY_NOTIFY_ON_FINISH=1 — /bind sets that flag automatically, so projects without a binding stay silent even when global hooks are installed.
Stop→tetherly codex-stopforwardslast_assistant_messageto the bound channel.PermissionRequest→tetherly codex-permission-requestforwards the tool/command/reason. It does not return anallow/denydecision, so Codex's normal approval prompt still appears.
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
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 tetherly-0.1.1.tar.gz.
File metadata
- Download URL: tetherly-0.1.1.tar.gz
- Upload date:
- Size: 668.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29d6ad638e7d6aea295e4defb3877f1d392f0fd31aa562d162907da841ed3699
|
|
| MD5 |
255240b4a6e7fc1537904233cda14d9f
|
|
| BLAKE2b-256 |
7707338c28e2c06addceded0d4c16271102cecf970880a5911fab0e33c237e3c
|
Provenance
The following attestation bundles were made for tetherly-0.1.1.tar.gz:
Publisher:
publish.yml on changhyeon363/tetherly
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tetherly-0.1.1.tar.gz -
Subject digest:
29d6ad638e7d6aea295e4defb3877f1d392f0fd31aa562d162907da841ed3699 - Sigstore transparency entry: 1396172249
- Sigstore integration time:
-
Permalink:
changhyeon363/tetherly@5e6044832f5204964e43e2d0466ed37cc6239ec1 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/changhyeon363
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5e6044832f5204964e43e2d0466ed37cc6239ec1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tetherly-0.1.1-py3-none-any.whl.
File metadata
- Download URL: tetherly-0.1.1-py3-none-any.whl
- Upload date:
- Size: 19.8 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 |
e3ab6c8f51cf8599e8f5d248d2667dff02f7118b6062d23b01b69dd6bc8b301f
|
|
| MD5 |
a8537c4e748781deb614b444840fe188
|
|
| BLAKE2b-256 |
4064654631245b357a51194da0921b3ff590610a0c62ece7d711e1caebf5042b
|
Provenance
The following attestation bundles were made for tetherly-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on changhyeon363/tetherly
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tetherly-0.1.1-py3-none-any.whl -
Subject digest:
e3ab6c8f51cf8599e8f5d248d2667dff02f7118b6062d23b01b69dd6bc8b301f - Sigstore transparency entry: 1396172258
- Sigstore integration time:
-
Permalink:
changhyeon363/tetherly@5e6044832f5204964e43e2d0466ed37cc6239ec1 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/changhyeon363
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5e6044832f5204964e43e2d0466ed37cc6239ec1 -
Trigger Event:
push
-
Statement type: