Metadata-Version: 2.5
Name: ony
Version: 0.4.0
Summary: A phone call before your AI coding agent (Claude Code, Codex) does something it can't undo - plus the self-hostable server behind it.
Project-URL: Homepage, https://ony.ai
Project-URL: Documentation, https://docs.ony.ai
Project-URL: Repository, https://github.com/ony-ai/ony
Project-URL: Issues, https://github.com/ony-ai/ony/issues
Author: Ony.ai
License-Expression: AGPL-3.0-or-later
License-File: LICENSE
Keywords: agent,approval,claude-code,codex,devtools,on-call,self-hosted
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.12
Requires-Dist: alembic>=1.13
Requires-Dist: cryptography>=50
Requires-Dist: fastapi>=0.115
Requires-Dist: httpx>=0.27
Requires-Dist: itsdangerous>=2.2
Requires-Dist: prometheus-client>=0.21
Requires-Dist: pydantic-settings>=2.5
Requires-Dist: pydantic>=2.9
Requires-Dist: pyjwt[crypto]>=2.12
Requires-Dist: python-multipart>=0.0.12
Requires-Dist: rich>=13
Requires-Dist: segno>=1.6
Requires-Dist: sqlalchemy>=2.0.35
Requires-Dist: typer>=0.12
Requires-Dist: uvicorn[standard]>=0.32
Requires-Dist: websockets>=13
Provides-Extra: dev
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: ruff>=0.7; extra == 'dev'
Provides-Extra: postgres
Requires-Dist: psycopg[binary]>=3.2; extra == 'postgres'
Provides-Extra: redis
Requires-Dist: redis>=5.0; extra == 'redis'
Description-Content-Type: text/markdown

# Ony.ai

> The on-call layer for AI coding agents. When your agent needs you, Ony.ai calls your phone - answer
> from anywhere and the agent keeps moving.

[![CI](https://github.com/ony-ai/ony/actions/workflows/ci.yml/badge.svg)](https://github.com/ony-ai/ony/actions/workflows/ci.yml)
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](LICENSE)
[![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue.svg)](pyproject.toml)

Your coding agent (Claude Code, OpenAI Codex, OpenCode) hits a decision it cannot make alone: a
risky command, a permission prompt, a question with three options. Normally it stalls until you are
back at a screen. With Ony.ai, a hook holds the action and raises a *handoff*: the Ony.ai server
classifies the risk, places a real phone call, and reads the situation out. You decide on the
keypad. The verdict comes back signed and the agent proceeds or is blocked - and when the agent asks
a multiple-choice question, Ony.ai reads the options as a phone menu and delivers your choice back as
the answer.

It is built for developers who let agents run long tasks and leave the desk: a phone call reaches
you on a walk, a commute, or in a meeting, when every screen-bound approval flow does not. Risk
classification keeps calls rare and worth answering.

**Open-core.** This repository is the complete open-source product (AGPL-3.0): self-host it with
your own domain, telephony provider, models, and database. The hosted service at
**[ony.ai](https://ony.ai)** is a separate offering built on this core. See
[LICENSING.md](LICENSING.md) and [docs/04-self-hosting.md](docs/04-self-hosting.md).

<!-- TODO: quickstart demo GIF (record the Lite flow) -->

## Quickstart (30 seconds, no Docker)

The Lite tier runs a full Ony.ai server on SQLite - no Docker, Postgres, or Redis. Requires Python 3.12+.

```bash
pip install ony
ony up
#   Ony is running at http://127.0.0.1:8001  (dashboard + API)
```

Open http://127.0.0.1:8001 and create your account, then from your project directory:

```bash
ony init          # enrolls this machine + wires Claude Code (/ony command, gate, hooks)
ony away          # phone me for every step Claude would stop on
```

That is the whole loop: the agent hits a step that needs you, Ony.ai raises a handoff, you decide,
the agent keeps going.

Out of the box `ony up` uses the built-in **mock carrier**, so no phone actually rings yet: handoffs
surface in the **dashboard**, where you approve or deny (the Overview page's **"Simulate a handoff"**
button walks the whole flow with no agent or phone at all). Real calls start once you add a
telephony provider (SignalWire, Twilio, Telnyx, or Plivo) in **Integrations -> Telephony** and
verify your number. So you can try the loop end to end first, then flip on real calls.

### Production: Docker all-in-one

For a team or a public host: Postgres 18 + Valkey + API + dashboard behind one origin, migrations
applied on start.

```bash
cp .env.example .env          # set ONY_SIGNING_SECRET (telephony is optional - add it in the dashboard)
docker compose --project-directory . -f deploy/docker-compose.prod.yml up -d --build
#   GET http://localhost:8080/health  ->  {"status": "ok", ...}
#   Dashboard at http://localhost:8080 - create your account there.
```

The `--project-directory .` flag makes Compose read the root `.env` for `${...}` interpolation. For
automatic HTTPS on a public host, use the Caddy edge stack in
[deploy/PROXMOX-RUNBOOK.md](deploy/PROXMOX-RUNBOOK.md). See
[docs/04-self-hosting.md](docs/04-self-hosting.md) for telephony setup and production configuration,
and [docs/06-security-hardening.md](docs/06-security-hardening.md) before going to production.

## What works today

| Agent | What you get | Status |
| --- | --- | --- |
| **Claude Code** | Full blocking gate: risky tool calls hold until your phone decision; multiple-choice questions become phone menus; `/ony` modes. Wire a project with `ony init`, or install the [marketplace plugin](clients/claude-code/). | Works today |
| **OpenAI Codex** | Deny-only hook (`ony hooks codex`): a phone denial blocks the tool, an approval defers to Codex's own flow. An app-server bridge and a forwarding proxy additionally route **VS Code and desktop-app** approvals through Ony.ai with full allow/deny. Details in [clients/codex/](clients/codex/). | Hook: beta, verified live against codex-cli 0.144.5 (note: Codex requires a one-time hook trust approval). Bridge/proxy: experimental, pinned against codex-cli 0.142.x (handshake re-verified on 0.144.5) |
| **OpenCode** | Attach to your running `opencode serve` with `ony opencode --url http://127.0.0.1:4096`; each permission ask is answered by phone, one decision at a time, never a standing grant. | Works today |
| **SMS / Telegram / Slack fallback** | Escalation channels when the call goes unanswered ([ADR 0009](docs/adr/0009-escalation-and-fallback-channels.md)), behind `ONY_ESCALATION_ENABLED`. | SMS is carrier-dependent: US numbers require 10DLC campaign approval before SMS delivers |

Claude Code alternative install, as a marketplace plugin (the connector must be enrolled first:
`pip install ony` then `ony enroll --url <your server>`):

```
/plugin marketplace add ony-ai/ony
/plugin install ony@ony-ai
```

## The /ony modes

Set the mode inside Claude Code (`/ony away`, or `/ony:ony away` with the marketplace plugin) or
from any terminal (`ony away`):

- `off` - Ony.ai does nothing.
- `on` - phone only for high-risk actions.
- `away` - phone for every step Claude would stop on.
- `here` - back to high-risk only.

`ony status` shows the current mode and checks connectivity; `ony doctor` checks the wiring end to end.

## How it works

- A hook in your agent blocks the pending action and raises a handoff to the Ony.ai server.
- The server classifies the action's risk from a closed taxonomy - the agent's own risk hint is
  never trusted ([ADR 0007](docs/adr/0007-server-authoritative-risk-and-signed-decisions.md)).
- Your phone rings; Ony.ai reads out the action, or the question and its options.
- You decide on the keypad, never by voice.
- A signed, expiring verdict bound to that specific action returns to the hook; the agent proceeds
  or is blocked, and the exchange lands in a tamper-evident audit chain.

**Security model in one line:** the server is authoritative for risk, every decision is a signed
per-action verdict (never a standing grant), and unresolved gates on risky actions do not fail into
silent approval - the full analysis is in the [threat model](docs/09-threat-model.md).

## Repository layout

```
apps/api/ony_api/   FastAPI control plane (handoffs, telephony webhooks, agent decision API)
apps/web/           React dashboard (sessions, handoffs, audit, settings)
packages/ony_core/  Domain models, risk map, state machines, policy, telephony engine
packages/ony/       The `ony` CLI + agent hooks: ony up, ony init, modes, daemon
clients/            Agent integrations: Claude Code plugin, Codex hook + bridge + proxy
docs/               Architecture, ADRs, self-hosting, security
deploy/             docker-compose stacks, runbooks, monitoring, backups
```

## Documentation

**Architecture & design** - [architecture review](docs/01-architecture-review.md) · [ADRs](docs/adr/)

**Deploy & operate** - [self-hosting](docs/04-self-hosting.md) · [Proxmox bring-up](deploy/PROXMOX-RUNBOOK.md) ·
[operations runbook](deploy/RUNBOOK.md) · [backups & DR](deploy/BACKUP.md) ·
[monitoring](deploy/MONITORING.md) · [scaling & HA](deploy/SCALING.md) ·
[incident response](deploy/INCIDENT-RESPONSE.md)

**Security & compliance** - [security hardening](docs/06-security-hardening.md) ·
[threat model](docs/09-threat-model.md) · [data handling & privacy](docs/08-data-handling.md) ·
[vulnerability disclosure](SECURITY.md)

**Features** - [SSO (OIDC)](docs/07-sso.md) · [telephony setup](docs/03-signalwire.md) ·
[editions & pricing](docs/05-editions-and-pricing.md)

## Contributing

Dev setup, test gates, and the engineering rules live in [CONTRIBUTING.md](CONTRIBUTING.md) and
[AGENTS.md](AGENTS.md). The short version:

```bash
python -m venv venv
venv/bin/python -m pip install -e ".[dev]"   # venv\Scripts\python on Windows
venv/bin/python -m pytest                    # in-memory SQLite, no Docker needed
```

## License

AGPL-3.0-or-later for the open-source core. A separate commercial license is available for
organizations that cannot meet the AGPL's terms. See [LICENSE](LICENSE) and
[LICENSING.md](LICENSING.md).
