Metadata-Version: 2.4
Name: pileless-waitless
Version: 0.1.0
Summary: Event-driven notify layer for agentic CLIs. Turn passive AI assistants into tapped-on-the-shoulder agents.
Author: -less (Pileless)
License: MIT License
        
        Copyright (c) 2026 -less (Pileless)
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://pileless.com
Project-URL: Repository, https://github.com/pileless/waitless
Keywords: claude-code,codex,agents,notifications,hooks,agentic,cli
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# waitless

**Turn your AI assistant into a tapped-on-the-shoulder agent.**

When something finishes in the background - a build, a test suite, a deploy, a scrape, an email arriving, a long-running Codex/Claude task - `waitless` makes sure the active session finds out on its very next tool call. No polling. No HTTP server. No middleware. Just a file and a hook.

Born out of [Pileless](https://pileless.com) (the agent-to-agent workflow platform) and spun off free under the `-less` brand.

---

## Why

Claude Code, Codex CLI, and similar agentic tools are passive by default - they wait for you to type. If a background job finishes while you're not looking, neither of you notices. `waitless` flips that: the moment a thing happens, the next tool call surfaces it in the model's attention. You stop being the middleman.

The pattern is deliberately small:

- **The file IS the bus.** Every event is one JSON line appended to `~/.waitless/events.jsonl`.
- **The hook IS the tap.** A `PostToolUse` hook reads the file on every tool call and surfaces undelivered events as a system-reminder.
- **No server.** No port, no auth surface, no subscriber registry, no process to crash.

## Install

```
pip install pileless-waitless
```

Or vendor the three files in `waitless/` directly into your project - no dependencies beyond Python 3.9+.

## Wire it into Claude Code

Add to `.claude/settings.json`:

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash|Edit|Write|MultiEdit",
        "hooks": [
          { "type": "command", "command": "python -m waitless.tap" }
        ]
      }
    ]
  }
}
```

That's it. Now anything that writes to `~/.waitless/events.jsonl` will tap your session.

## Emit events

From Python:

```python
from waitless import emit

emit(
    source="my-build",
    lane="default",
    severity="attention",
    title="deploy finished",
    body="shipped v1.2.3 to prod",
    action_hint="verify the rollout",
)
```

From the CLI:

```bash
python -m waitless.core \
  --source my-build \
  --lane default \
  --severity attention \
  --title "deploy finished" \
  --action-hint "verify the rollout"
```

Wrap any command so it taps on completion:

```bash
# (use waitless.wrap - ships with the package)
python -m waitless.wrap --lane default --source build --title "tests" -- pytest
```

## Severity ladder

You decide how urgent each event is. The hook decides what to do with it:

| Severity | What happens |
|---|---|
| `info` | Queue silently; drain at session start |
| `attention` | Surface to the active session - the model acts on it |
| `emergency` | Surface + the model acts NOW |
| `operator-needed` | **The only rung that pages the human** (via a Telegram bot, webhook relay, or any URL you point it at) |

The whole point: the AI handles everything it can. The human only hears about things that genuinely need a human.

## Lanes

Events are tagged with a `lane` (e.g. `default`, `scrape`, `money`, `pile`). The hook only surfaces events on the active session's lane, so multiple sessions don't cross-talk. Set `WAITLESS_LANE=your-lane` per session, or write `~/.waitless/lane.json` keyed by session id.

## Security model

The events file is writable by your user. That means any process running as you can emit events - including, in theory, a malicious one trying to prompt-inject the model via a crafted event title. `waitless` defends against this:

- Event titles/bodies are sanitized (brackets + newlines stripped, length-capped).
- Every surfaced line is labeled `(untrusted source=X)` so the model knows not to treat event content as a system instruction.

If you want stronger isolation, restrict the events file's permissions to a dedicated user, or run `waitless` under a separate account.

## Self-monitoring

`waitless` ships with a deadman (`waitless.deadman`) that checks the tap is actually draining. If a live session ran and still failed to clear a stale `attention`+ event, or the events file grows unbounded, the deadman emits an `operator-needed` event that pages the human. It won't page just because nobody's been using their agent - it only fires when a consumer demonstrably ran and the backlog still didn't clear. Wire it as a cron job / scheduled task every 30 minutes.

## What's NOT in waitless

- **No HTTP server.** (Use ntfy, ifttt, or any webhook relay if you need cross-machine paging.)
- **No real-time interrupt.** The tap lands at the next tool boundary, not mid-call. Reviewers agreed this is the right tradeoff.
- **No subscriber registry.** Lane env-var is the only per-session state.

## License

MIT. Free as in beer and speech. Use it, fork it, sell it, just don't blame us.

## Acknowledgements

Spun off from [Pileless](https://pileless.com) - if waitless is useful, you'll probably love Pileless for the full agent-to-agent workflow (structured handoffs, approvals, real-time piles). Check it out.
