Metadata-Version: 2.4
Name: bund
Version: 0.2.0
Summary: Telegram pings for coding agents. Approve from your phone. Free. Zero dependencies.
License: MIT
Keywords: telegram,claude,coding-agent,hooks,notifications,approval
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

<h1 align="center">bund</h1>

<p align="center"><b>Your AI agent is waiting for you. Again.</b></p>

<p align="center">
  <img src="https://api.memegen.link/images/fine/claude_has_been_waiting_for_2_hours/this_is_fine.png?width=450" width="450" alt="this is fine">
</p>

<p align="center">
  Telegram pings for coding agents.<br>
  Approve from your phone. Free. Zero dependencies.
</p>

---

## The problem

<p align="center">
  <img src="https://api.memegen.link/images/db/you/agent_needing_approval/just_one_more_meeting.png?width=450" width="450" alt="distracted boyfriend">
</p>

## How it works

<p align="center">
  <img src="https://api.memegen.link/images/gru/claude_asks_permission/bund_pings_your_telegram/you_tap_approve_from_anywhere/claude_keeps_working.png?width=450" width="450" alt="gru plan">
</p>

## Setup (2 minutes)

```bash
pip install bund

bund set --token <botfather-token>
bund set --chat auto
bund install
bund test
```

`bund install` wires Claude Code's `PermissionRequest` and `Stop` hooks. On any
other agent or script, use `bund ask` (below) — no install needed.

<p align="center">
  <img src="https://api.memegen.link/images/success/set_up_in_two_minutes/phone_buzzed_immediately.png?width=400" width="400" alt="success kid">
</p>

## What you get

| Button | Does |
|---|---|
| ✅ Approve | Lets it run, once |
| ❌ Deny | Nope |
| ♾ Approve all similar | Never asks again for that kind of command |

And a ping when the task is done:

<p align="center">
  <img src="https://api.memegen.link/images/fry/not_sure_if_agent_finished/or_waiting_for_my_approval.png?width=450" width="450" alt="fry">
</p>

Now you know which one.

## Sample message

```
🙄 Your AI intern wants to run Bash. Please supervise.

📁 my-project
npm run build

[ ✅ Approve ] [ ❌ Deny ]
[ ♾ Approve all similar: Bash(npm run *) ]
```

The joke is on top. The real command is always shown in full below it.

## Works with any agent

`bund ask` is the universal protocol: any CLI, script, or agent asks a
question, your phone answers.

```bash
bund ask "deploy to prod?" && echo let's go
# stdout: allow | deny | timeout
# exit:   0      1      2
```

```python
import subprocess
r = subprocess.run(["bund", "ask", "run the migration?"], capture_output=True, text=True)
if r.stdout.strip() == "allow":
    ...
```

No config files to wire. If bund isn't configured, `bund ask` fails fast with
exit code 2 instead of hanging your agent.

## One command per project

Tell any agent to use bund for **every** question and approval, scoped to the
current project:

```bash
bund setup opencode      # writes the prompt into ./AGENTS.md
bund setup claudecode    # writes the prompt into ./CLAUDE.md
bund setup codex         # AGENTS.md
bund setup gemini        # GEMINI.md
bund setup generic       # just prints it — paste anywhere
bund -setup opencode     # same thing, if you like dashes
```

You get a ready-made instruction block (also printed to stdout) that tells the
agent: whenever you'd block waiting for me — permission, decision, or
confirmation — run `bund ask "<full question>"`, honor the `allow | deny |
timeout` answer, and fall back to the terminal on timeout. Running it twice
updates the block in place instead of duplicating it.

## Safety

<p align="center">
  <img src="https://api.memegen.link/images/drake/approve_all_for_rm_rf/no_button_for_dangerous_commands.png?width=400" width="400" alt="drake">
</p>

- Only **your** Telegram chat can approve anything
- Every button works once (random request ids, no replaying old taps)
- Dangerous commands (`rm -rf`, `sudo`, force pushes, `curl | sh`, …) get a
  serious warning and **no** "approve all" button
- No answer? The agent falls back to the normal terminal prompt
- bund can never block your work — any error means silent fallback
- Token and chat id live in `~/.config/bund/config.json` with `chmod 600`

## Dependencies

<p align="center">
  <img src="https://api.memegen.link/images/buzz/zero_dependencies/zero_dependencies_everywhere.png?width=400" width="400" alt="buzz">
</p>

Python 3.9+. Standard library only. That's it.

## Cost

<p align="center">
  <img src="https://api.memegen.link/images/oprah/you_get_a_free_bot/and_you_get_free_approvals.gif?width=400" width="400" alt="oprah">
</p>

## Tone

```bash
bund set --tone sarcasm   # default
bund set --tone plain     # for people who have no joy
```

Add your own lines in `~/.config/bund/templates.json`.

## Also

```bash
bund -m "build finished, come back"
```

Works with any script or agent.

<p align="center">
  <img src="https://api.memegen.link/images/pigeon/claude/_/is_this_a_permission_prompt~q.png?width=400" width="400" alt="is this a pigeon">
</p>

---

**Commands**

```
bund set --token <token>        # botfather token
bund set --chat auto|<id>       # pick your chat
bund set --tone sarcasm|plain   # message tone
bund install                    # add Claude Code hooks
bund uninstall                  # remove only bund's hooks
bund setup <provider>           # project-scope prompt: use bund for every question
bund test                       # send a test message
bund ask "<question>"           # ask anything (allow|deny|timeout)
bund -m "<text>"                # send any message
bund hook                       # internal, called by hooks
```

<p align="center">
  <sub>Memes by <a href="https://memegen.link">memegen.link</a>. If they don't load, that's on them, not us.</sub><br>
  <sub>MIT License</sub>
</p>
