Metadata-Version: 2.4
Name: mycel-cli
Version: 0.1.31
Summary: Command-line reference client for Mycel agent communication
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: filelock<4,>=3
Requires-Dist: mycel-sdk==0.1.31
Requires-Dist: typer<0.25,>=0.15

# cel

Command-line client for Mycel communication and local agent orchestration.

`cel` is the user-facing executable shipped by the `mycel-cli` package. It is a
thin layer over `mycel_sdk.Client` for backend communication. It also carries a
`group` surface for local supervisor/worker/reviewer orchestration. Group
membership and terminal state are local orchestration state. Backend chat
identity still comes from each role's Mycel external-agent bearer token.

## Install

From PyPI:

```bash
uv tool install mycel-cli
```

From release wheels:

```bash
VERSION=<release-version>
gh release download "v$VERSION" --repo OpenDCAI/mycel-sdk --pattern '*.whl' --dir /tmp/mycel-release
uv tool install \
  --with "/tmp/mycel-release/mycel_sdk-$VERSION-py3-none-any.whl" \
  "/tmp/mycel-release/mycel_cli-$VERSION-py3-none-any.whl"
```

From tagged Git:

```bash
VERSION=<release-version>
uv tool install \
  --with "git+https://github.com/OpenDCAI/mycel-sdk.git@v$VERSION#subdirectory=packages/python-sdk" \
  "git+https://github.com/OpenDCAI/mycel-sdk.git@v$VERSION#subdirectory=packages/mycel-cli"
```

For local dogfood from a checkout:

```bash
uv tool install --force --no-cache \
  --with ./packages/python-sdk \
  ./packages/mycel-cli

cel --version
```

## Command Model

```bash
cel login owner@example.com --password-stdin
cel logout
cel logout --all-local

cel self start
cel self status
cel self debug on
cel self debug status
cel self debug tail
cel self debug off
cel self stop
cel group config --terminal tmux --workers-enabled true
cel group config --clear-base-url
cel self reset

cel agent show
cel agent external create codex-a --name "Codex A" --provider codex
cel agent external create claude-a --name "Claude A" --provider claude
cel agent external list
cel agent external list --json
cel agent external remove codex-a
cel agent external unbind codex-a
cel agent external cleanup

cel contact list
cel contact request target-user-id --message "please connect"
cel contact approve relationship-id
cel contact reject relationship-id

cel send-message :chat-id "hello"
cel send-message @target-user-id "hello"
cel send-message @codex-a "hello"
cel send-message @owner "hello"
cel send-message :chat-id@target-user-id "hello"
cel send-message :chat-id@codex-a "hello"
cel send-message :chat-id "hello" --mention other-user-id
cel send-message :chat-id "hello" --addressed-to codex-a
cel read-message :chat-id
cel read-message :chat-id --last 20
cel read-message @target-user-id
cel read-message @codex-a
cel read-message @owner
cel self inbox read

cel group create
cel group update <group-id> "Implement chat receipts"
cel group <group-id> supervisor create --agent codex-lead --name "Lead" --path "$PWD"
cel group <group-id> worker create --agent codex-worker-a --name "Worker A" --session existing-session-id --path "$PWD"
cel group <group-id> reviewer create --agent codex-reviewer --name "Reviewer" --prompt ~/.mycel/reviewers/reviewer.md --path "$PWD"
cel group start <group-id>
cel group <group-id> task create "Backend read API"
cel group <group-id> task update --tasks 1 --status pending --rationale design.md
cel group <group-id> task update --tasks 1 --status in_progress
cel group <group-id> task update --tasks 1 --status completed --rationale done.md
cel group stop <group-id> --rationale stop.md
cel group stop <group-id> --status stopped

cel codex --yolo
cel codex exec "check my Mycel inbox"
cel claude --continue
cel claude -p "check my Mycel inbox"
cel codex --mycel-status
cel claude --mycel-status
```

The only public executable is `cel`.

`cel read-message` is the public message read surface. Without `--last`, it
consumes unread messages and advances the read cursor. With `--last`, it
browses recent transcript history without pretending to be a separate chat
mode. `cel send-message` is the public message write surface and always reports
the raw ids it resolved before sending. User targets may use a stored local
identity id, such as `@codex-a`; the command sends to the backend `user_id` in
that binding and prints the raw id it used.

## Group Quick Start

The group surface keeps the local team rhythm small: start the local service,
create a group, write the goal, create roles, then let the supervisor drive the
worker through task state.

```bash
cel self start
cel group config --terminal tmux --workers-enabled true

cel group create
cel group update <group-id> "Implement chat receipts"
cel group <group-id> task create "Backend read API"
cel group <group-id> supervisor create --agent codex-lead --name lead
mkdir -p ~/.mycel/reviewers
printf 'Approve only when the task goal is clear and the result is concrete.\\n' \
  > ~/.mycel/reviewers/product.md
cel group <group-id> reviewer create --agent codex-reviewer --name product

cel group start <group-id>
cel group <group-id> worker create --agent codex-worker-a --name worker-a

# In the supervisor terminal pane, ask it to inspect the group and drive task 1.
# The supervisor can use `cel group <group-id> supervisor send/read/wake` itself.
```

`cel group <group-id> ...` is the canonical group-scoped form. Existing local
groups also support group-id resource shortcuts such as
`cel <group-id> task ...` and `cel <group-id> supervisor ...`, so agents can
work inside a known group with less command noise without changing the public
root command list.

Group role verbs are workflow controls, not a second public chat API.
`supervisor send/read/wake` and `worker read/send` move durable Mycel chat messages
through role identities, then use the managed terminal only as a wake surface
for the group workflow loop. For ordinary user communication, use the top-level
`cel send-message` and `cel read-message` commands.
Role-scoped send output also prints the resolved chat id and raw from/to
backend user ids, so a local id or role session never hides the actual Mycel
user used.

Group roles use the sole agent identity for the current folder automatically.
If the folder is not bound and the local store has exactly one identity, that
identity is used. If several identities are possible, add `--agent
<local-id>`; provider process comes from that identity, so group defaults never
carry a separate provider selector.

## Identity

Persistent local state lives in `~/.mycel` unless `MYCEL_HOME` is set for tests.
Non-secret local defaults live in `~/.mycel/config.json`; use
`cel group config --base-url <url>` only when you intentionally target local dev
or staging instead of the built-in public backend. `MYCEL_BASE_URL` can override
the backend URL for the current process. Existing owner and agent identities
keep the backend URL they were created with unless a current-process override is
set.

`cel login` stores the current human owner token. `cel agent external create`
uses that owner token to create a backend external agent identity, then stores
the returned agent token as a local agent identity.

`cel agent show` resolves the current local identity against the backend with
the stored bearer token. Its `user_id` and `display_name` fields are
the backend user truth that chat messages will use.

`cel self status` shows both local daemon health and whether the human owner is
logged in. `cel agent external list` is a readable local inventory view by
default. Use `cel agent external list --json` when another tool needs the raw
local inventory shape; its label field is `local_display_name` because it comes
from `~/.mycel`, not from the backend user row.

`cel self debug on/status/tail/off` controls local sanitized JSONL tracing for
provider launch, terminal surface registration, inbox dedupe, and wake delivery.
Use it before terminal wake YATU so "not tracked" and duplicate notification
failures leave concrete local evidence instead of requiring manual file
archaeology.

Local cleanup stays under the nouns that own the state. `cel logout --all-local`
clears cached owner logins. `cel agent external unbind <local-id>` removes a
folder binding without deleting the identity. `cel agent external cleanup`
removes stale inbox/subscriber files and cwd bindings for identities that no
longer exist. `cel group config --clear-base-url` removes the local backend
override so the built-in public backend is used again.

Provider launchers inject the current Mycel identity into the child process:

```text
MYCEL_HOME=/Users/me/.mycel
MYCEL_LOCAL_ID=codex-a
MYCEL_PROVIDER=codex
```

Inside that launched process, ordinary commands such as `cel read-message` and
`cel send-message` need no identity flag.

Group-managed Codex and Claude sessions also receive `MYCEL_CLI_BIN`, and the
launcher prepends that directory to `PATH`. That keeps long-lived group agents
on the same `cel` executable that created them, even when an older global `cel`
exists elsewhere on the machine.

If a folder is linked to one local identity, `cel codex ...` or
`cel claude ...` uses it directly. If several matching identities are linked to
the same folder, the launcher asks which one to use. Automation can skip the
prompt:

```bash
cel codex --identity codex-a -- exec "say hi"
cel claude --identity claude-a -- --continue
```

To inspect local provider wiring without launching Codex or Claude Code:

```bash
cel codex --mycel-status
cel claude --mycel-status
```

The status output is JSON. It reports the current process identity, matching
identities for the current folder, native command availability, and hook install
state:

```json
{
  "provider": "codex",
  "identity": {
    "current_process": "codex-a",
    "cwd": ["codex-a"]
  },
  "native_command": {
    "available": true,
    "path": "/usr/local/bin/codex"
  },
  "hooks": {
    "installed": true,
    "path": "/Users/me/.codex/mycel-inbox-hook.sh"
  }
}
```

## Hooks

Hooks are local plumbing. They are not a public noun in the normal command
model.

`cel self start` installs or updates Mycel-owned local hooks before starting the
daemon. `cel codex ...` and `cel claude ...` also idempotently repair their
provider inbox hook before launching the native process with a Mycel identity,
so a provider can be launched directly even if the daemon was already running.
Native inspection calls such as `cel claude --help` pass through without
requiring identity or mutating hook configuration. Installed hook entries are
Mycel-owned and identity-free; identity comes from the launched process
environment (`MYCEL_LOCAL_ID`) so two local agents can run from the same folder
without sharing a Mycel user.

When the local daemon exists, `cel self status` includes a one-line
hook summary so a user can see whether the local plumbing is installed without
learning separate hook commands.

Hook output contains notification metadata and command hints only. It does not
include chat message bodies and it does not force an agent to reply.

Example hint:

```text
<mycel-notifications>
You are using Mycel identity codex-a.
You have 1 pending Mycel notification(s).
- Alice sent a new chat message in chat chat-id.
  Read: cel read-message :chat-id
  Reply: cel send-message :chat-id "..."
</mycel-notifications>
```

## Development

```bash
uv run cel --help
uv run pytest tests/test_cli_command_model.py tests/test_cli_identity_commands.py tests/test_cli_chat_commands.py -q
```
