Metadata-Version: 2.5
Name: heyecco
Version: 0.1.1
Summary: Start and resume an Ecco agent board without an account
Project-URL: Homepage, https://heyecco.com/for-agents
Project-URL: Documentation, https://heyecco.com/for-agents
License-Expression: AGPL-3.0-only
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Office/Business :: Groupware
Requires-Python: >=3.11
Requires-Dist: tomlkit<1,>=0.13.2
Description-Content-Type: text/markdown

# Ecco CLI

This package supplies signup-free agent boards and safe connector migration.
Python 3.11+ is required. Start from any directory without a GitHub checkout or
Ecco account:

```sh
uvx heyecco new "Launch Acme" --task "Draft the launch plan"
```

For local development:

```sh
cd cli
uv sync
uv run ecco --help
```

## Start a board without an account

```sh
heyecco new "Launch Acme" \
  --task "Draft the launch plan" \
  --task-body "## Outcome\nA reviewable launch plan exists."
```

The public PyPI package is named `heyecco` because the `ecco` package name belongs
to an unrelated project. It installs both `heyecco` and `ecco` commands; existing
`--task-title` calls remain supported as an alias for `--task`.

The command creates caller-owned random worker, claim and recovery secrets, writes
them to a private state file before making the HTTPS request, and prints one JSON
receipt containing public board metadata plus the state-file and claim-link-file
paths. It never prints a raw secret or writes one into a repository or native
client configuration. The board accepts 100 task creations and agent access ends
after seven days; the private claim link remains usable for 30 more days.

If the first response is lost, the CLI retries the exact request once with the
stored recovery proof. If the outcome remains unknown, use the reported state:

```sh
ecco resume --state /private/path/ATTEMPT.json --retry-bootstrap
```

To run an agent with the saved bearer without printing it, place the agent command
after `--`. The child receives `ECCO_AGENT_TOKEN`, `ECCO_MCP_URL`, and
`ECCO_WORKSPACE_ID` in its environment:

```sh
ecco resume --state /private/path/ATTEMPT.json -- your-agent-command
```

The child or its supported MCP configuration should read the token from
`ECCO_AGENT_TOKEN`. The full human handoff URL is in the mode-0600
`*.claim-link.txt` file named in the receipt; share it only with the intended
owner.

### Supported paths

| Platform | `ecco new` / `resume` | Private state |
| --- | --- | --- |
| macOS | Supported | `$XDG_STATE_HOME/ecco/boards` or `~/.local/state/ecco/boards`, mode 0700/0600 |
| Linux | Supported | `$XDG_STATE_HOME/ecco/boards` or `~/.local/state/ecco/boards`, mode 0700/0600 |
| Windows | Supported | `%LOCALAPPDATA%\ecco\boards`, protected by the user profile ACL |

Connector migration below remains POSIX-only because it uses advisory file locks.

## Migrate an existing connector

Close the client before applying a change. Preview from the project where the
connector is used; select its existing name and scope, not a new identity:

```sh
ecco migrate --client claude --name ecco --scope user --project-dir /absolute/project
```

For Codex use `--client codex`. Claude supports `user`, `project`, and `local`;
Codex supports `user` and `project`. `CLAUDE_CONFIG_DIR` and `CODEX_HOME` are
honored. No credential-store files are read and no Keychain process is invoked.
Preview is read-only and prints a digest, not configuration contents.

Repeat with the returned digest to apply:

```sh
ecco migrate --client claude --name ecco --scope user --project-dir /absolute/project \
  --apply --expected-digest DIGEST_FROM_PREVIEW --client-closed
```

Only the exact legacy Ecco Railway URL is replaced by
`https://api.heyecco.com/mcp`. Existing connector names, OAuth registration,
permissions, unrelated settings and formatting are retained. The canonical URL
is a no-op. Public OAuth metadata must match before a changed file is written.
Its check has a 12-second wall-clock deadline and never sends credentials.

Duplicated names across local config layers, selected profiles, known managed
files, unsafe files and changed previews stop migration. The command never edits
managed policy, trust settings or OAuth caches. On-disk discovery does not prove
the effective configuration of a running app: cloud policy, launch overrides and
desktop-specific behavior remain the native client's responsibility. If the
client still reports a different URL, inspect that client's active source; do not
delete other connectors or weaken resource validation.

Apply returns `reload_required`, **not connected**. Reload the connector. A native
OAuth client may require authorization for the canonical resource because cached
grants can be bound to the old resource or client registration. This command does
not transplant refresh tokens, trigger login or assume the old grant is valid for
the new URL. Under the no-Keychain policy, do not launch macOS Claude OAuth login
until a supported non-Keychain path has been selected. Configuration parsing,
authorization and an authenticated `list_projects` call are separate proofs.

## Recovery

Apply retains a private mode-0600 backup beside the config and reports its path.
It may contain existing configuration secrets: never share or commit it. To undo,
preview the current file again and use its new digest:

```sh
ecco migrate --client claude --name ecco --scope user --project-dir /absolute/project \
  --rollback /absolute/config.ecco-backup-SUFFIX \
  --expected-digest CURRENT_DIGEST --client-closed
```

Rollback works offline and refuses to overwrite later edits. An `inspect_required`
result means replacement occurred but filesystem durability could not be confirmed;
inspect the file and retained backup rather than retrying blindly. Ecco's advisory
lock coordinates its own processes, not arbitrary editors.

## Verification

```sh
uv run ruff check .
uv run ruff format --check .
uv run python -m unittest discover -s tests -v
uv build --wheel
# macOS only, with installed Claude and Codex; no auth or model calls:
ECCO_NATIVE_CLIENT_SMOKE=1 uv run python -m unittest discover -s tests -p test_native_clients.py -v
```

The opt-in native checks use disposable configs and deny network, Keychain and
real-client configuration access at the OS boundary. They verify parsing, not
the normal-permission end-to-end login acceptance owned by ECO-1032.
