Metadata-Version: 2.4
Name: rly
Version: 0.6.3
Summary: PyPI launcher for the ReplyLayer CLI
Project-URL: Homepage, https://replylayer.ai
Project-URL: Repository, https://github.com/replylayer/ReplyLayer
Project-URL: Issues, https://github.com/replylayer/ReplyLayer/issues
Author: ReplyLayer
License-Expression: MIT
Keywords: agent,ai,cli,email,mailbox,replylayer
Classifier: Development Status :: 3 - Alpha
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 :: Communications :: Email
Requires-Python: >=3.10
Provides-Extra: dev
Requires-Dist: build==1.2.2.post1; extra == 'dev'
Requires-Dist: pytest==8.3.4; extra == 'dev'
Requires-Dist: wheel==0.45.1; extra == 'dev'
Description-Content-Type: text/markdown

# rly

`rly` is the PyPI launcher for the ReplyLayer CLI.

```bash
pipx install rly
rly --help
```

Installing the `rly` package exposes **both** the `rly` and `replylayer`
commands — they are aliases for the same launcher, mirroring the npm package.
Use whichever name you prefer:

```bash
replylayer --help   # identical to `rly --help`
```

On Debian and Ubuntu systems that enforce PEP 668, plain `pip install rly`
may fail with `externally-managed-environment`. Use `pipx install rly` for a
global CLI install, or install inside a virtual environment:

```bash
python3 -m venv .venv
. .venv/bin/activate
pip install rly
```

On the supported binary-wheel install, the `rly` command execs a bundled
native `replylayer` binary directly — no Node toolchain is involved. The
`npx replylayer@<pinned>` path is reached only when you explicitly set
`RLY_FORCE_NPX=1` (the launcher's emergency fallback). If the bundled binary
is absent (a source/sdist install on an unsupported platform), `rly` exits
with an actionable error pointing at `RLY_FORCE_NPX=1` — it does **not** fall
back to `npx` automatically. The version-pin contract still holds for that
`npx` fallback — `rly@X.Y.Z` resolves `replylayer@X.Y.Z` exactly (see
[Strict pin policy](#strict-pin-policy) below).

## Requirements

- Python 3.10+
- pipx for the recommended global install path

> **Optional (fallback only):** Node 22+ with `npx` on `PATH` is required
> **only** when you opt into the emergency `RLY_FORCE_NPX=1` fallback — which
> is also how you run a source/sdist install on an unsupported platform (set
> `RLY_FORCE_NPX=1` with Node on `PATH`; the launcher does not switch to `npx`
> on its own). The binary wheel needs neither Node nor `npx`.

## Examples

```bash
rly auth login
rly mailbox list
rly inbox list --mailbox support-bot
```

For full CLI documentation, see the ReplyLayer repository:
https://github.com/replylayer/ReplyLayer

## Environment variables

### `RLY_TIMEOUT_SECONDS`

Opt-in subprocess timeout, in seconds. When set, every `rly` invocation is
bounded by `subprocess.run(..., timeout=RLY_TIMEOUT_SECONDS)`; if the
underlying CLI subprocess does not exit in time the launcher prints a
diagnostic to stderr and exits with code `124`. This bounds the bundled-binary
exec on the supported path (and the `npx` process under `RLY_FORCE_NPX=1`).

By default there is no timeout, with one narrow exception: the help and
version short-circuits (`--help`, `-h`, `--version`, `-V`) carry a built-in
10-second timeout. Those commands should never need to touch the network
beyond an initial registry resolve; bounding them lets you diagnose a
restricted-network sandbox without affecting legitimate long-poll commands
like `rly inbox wait --timeout 60`.

```bash
RLY_TIMEOUT_SECONDS=30 rly inbox list --mailbox support-bot
```

Set the value high enough to cover the slowest command you reasonably
expect. Setting it to a non-integer string is treated as "no timeout"
(graceful fallback rather than a launcher crash).

### `RLY_OFFLINE`

`RLY_OFFLINE` is a **no-op on the default bundled-binary path** — it applies
only under the `RLY_FORCE_NPX=1` fallback (the only path that invokes `npx`).

Set `RLY_OFFLINE=1` to force `npx` to resolve `replylayer` from the local
cache only. The launcher passes both `--offline` on the command line **and**
`npm_config_offline=true` in the subprocess environment (belt-and-suspenders;
`--prefer-offline` is NOT a no-network guarantee).

If the pinned `replylayer` version isn't cached locally, `npx` exits fast
with its own non-zero exit code (typically `1` with `ENOTCACHED`); the
wrapper passes that exit code through verbatim — it does NOT normalize it
to `124`. Exit code `124` is reserved for the wrapper's own timeout branch.

```bash
# Populate the cache once, online:
rly --version
# Subsequent calls can run offline:
RLY_OFFLINE=1 rly --version
```

`RLY_OFFLINE=1` is useful in network-restricted CI sandboxes, air-gapped
deployments, or any environment where you want a hard guarantee that the
launcher will not reach out to the npm registry.

## Strict pin policy

`rly@X.Y.Z` always resolves `replylayer@X.Y.Z` exactly — there is no
`@latest` resolution and no semver range. The launcher computes the pinned
package string at runtime via `importlib.metadata.version('rly')`, so the
two artifacts always move together.

This means:

- A published `rly@X.Y.Z` cannot ride a later patch-level `replylayer`
  release; both packages must be republished together. The matched-pair
  release runbook lives at `docs/runbooks/cli-release.md` in the
  ReplyLayer repository.
- Source installs from the repository between a launcher-only PR and the
  paired version bump are intentionally unsupported. Use `pipx install rly`
  (PyPI) or `npm install -g replylayer` (npm) as the supported install
  paths.
