Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 43 additions & 7 deletions QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,57 @@ source .venv/bin/activate
pip install -e .
```

## 2) Run (basic)
## 2) One-word entrypoint (recommended)

```bash
codexloop
```

Show supported features/commands:

```bash
codexloop help
```

Behavior:
- First run: prompts for Telegram token/chat id, uses current shell directory as run working directory, writes `.codex_daemon/daemon_config.json`, starts daemon.
- Later runs: auto-reuse previous config, auto-start daemon if needed, and attach to live logs.
- `codexloop init`: stop all current codexloop daemons, prompt token/chat id/model preset/play mode, start a fresh daemon in background, and exit.
- After `init`, run `codexloop` to attach monitor.
- In attach console, terminal control works directly:
- `/run <objective>`
- `/inject <instruction>`
- `/status`, `/stop`, `/disable` (same as `/daemon-stop`), `/daemon-stop`
- plain text: running => inject, idle => run

Play Mode:
- `execute-only`: only execute user commands, no plan agent.
- `fully-plan` (default): 10 minutes after run completion, daemon proposes next request; if not overridden within another 10 minutes, it auto-runs.
- `record-only`: plan agent only writes markdown table records; reviewer remains unchanged.

Daemon-launched runs use `--yolo` by default.

Disable daemon quickly:

```bash
codexloop disable
```

## 3) Run (basic)

```bash
codex-autoloop \
--max-rounds 100 \
--max-rounds 500 \
"帮我在这个文件夹写一下pipeline"
```

## 3) Run with Telegram (secure remote visibility)
## 4) Run with Telegram (secure remote visibility)

```bash
export TELEGRAM_BOT_TOKEN='123456789:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

codex-autoloop \
--max-rounds 100 \
--max-rounds 500 \
--telegram-bot-token "$TELEGRAM_BOT_TOKEN" \
--telegram-events "loop.started,round.review.completed,loop.completed" \
"帮我在这个文件夹写一下pipeline"
Expand All @@ -33,7 +69,7 @@ Notes:
- Live terminal streaming is on by default.
- Telegram live deltas are sent every 30s only when content changes.
- Telegram control commands are enabled by default (`/inject`, `/status`, `/stop`).
- Daemon defaults to the `quality` model preset (`gpt-5.4` + `high`) unless you override it.
- Daemon defaults to the `codex-xhigh` model preset (`gpt-5.3-codex` + `xhigh`) unless you override it.

Control examples from Telegram Web:

Expand Down Expand Up @@ -90,7 +126,7 @@ Defaults:
- Idle daemon tries to resume from the last saved `session_id`.
- One Telegram token can only be used by one active daemon.
- Operator messages are recorded into per-run markdown files in `.codex_daemon/logs/`.
- Daemon child model preset defaults to `cheap`.
- Daemon child model preset defaults to `codex-xhigh`.
- Re-running setup/start will stop the previous daemon for the same `.codex_daemon` before starting a new one.

One-click kill:
Expand Down Expand Up @@ -118,7 +154,7 @@ codex-autoloop \
--dashboard \
--dashboard-host 127.0.0.1 \
--dashboard-port 8787 \
--max-rounds 100 \
--max-rounds 500 \
"your objective"
```

Expand Down
64 changes: 48 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ This solves the common "agent stopped early and asked for next instruction" prob

Current defaults:

- `max_rounds` defaults to `100`.
- Daemon child model preset defaults to `quality` (`gpt-5.4` + `high`) unless overridden.
- `max_rounds` defaults to `500`.
- Daemon child model defaults now inherit Codex CLI global settings unless you explicitly set a preset/override.
- Daemon-launched idle runs try to resume from the last saved `session_id` before starting a fresh thread.

## Current Feature Snapshot
Expand All @@ -27,8 +27,10 @@ Current defaults:
- Daemon follow-up prompt: after a run ends, Telegram can offer the planner's next suggested objective as a one-click continuation.
- Planner modes: `off`, `auto`, `record`; setup defaults to `auto`.
- Dual control channels for daemon: Telegram and terminal (`codex-autoloop-daemon-ctl`).
- Single-word operator entrypoint: `codexloop` (first run setup, later auto-attach monitor).
- Token-exclusive daemon lock: one active daemon per Telegram token.
- Operator message history persisted to markdown and fed to reviewer decisions.
- Run archive persisted as JSONL with date/workspace/session metadata for resume continuity.
- Utility scripts: start/kill/watch daemon logs, plus sanitized cross-project setup examples.

## Why this is a plugin, not a native flag
Expand All @@ -43,27 +45,53 @@ source .venv/bin/activate
pip install -e .
```

## Build and Launch
## One-word operator workflow (`codexloop`)

For a local development setup:
Run:

```bash
python -m venv .venv
source .venv/bin/activate
pip install -e .
python -m codex_autoloop.setup_wizard --run-cd .
codexloop
```

This gives you:
List supported features/commands:

```bash
codexloop help
```

Behavior:

- First run: asks for Telegram token/chat id, uses current shell directory as run working directory, writes `.codex_daemon/daemon_config.json`, starts daemon.
- Later runs: reuses config, ensures daemon is running, then directly attaches to live output.
- `codexloop init`: stops all current codexloop daemons, prompts token/chat id/model selection/play mode, starts daemon in background, then exits.
- After `init`, run `codexloop` to attach monitor to that background daemon.
- Same terminal can control daemon/run:
- `/run <objective>`
- `/inject <instruction>`
- `/status`, `/stop`, `/fresh`, `/disable` (alias of `/daemon-stop`), `/daemon-stop`
- plain text auto-routes: running => inject, idle => run

- the CLI entrypoints
- an interactive daemon setup
- a Telegram-controlled long-running loop
Play Mode semantics:

If you do not want the daemon yet, run the loop directly:
- `execute-only`: only execute user commands, no plan agent.
- `fully-plan` (default): after a run finishes, daemon generates next request after 10 minutes; if not overridden within another 10 minutes, it auto-runs that request.
- `record-only`: plan agent degrades to markdown table recorder; reviewer behavior stays unchanged.

YOLO policy:

- Daemon-launched runs always use `--yolo` by default.

Directly disable daemon from terminal:

```bash
codex-autoloop --max-rounds 10 "Implement feature X and keep iterating until tests pass"
codexloop disable
```

You can still use low-level commands when needed:

```bash
codex-autoloop-daemon-ctl --bus-dir .codex_daemon/bus status
codex-autoloop-daemon-ctl --bus-dir .codex_daemon/bus inject "先修测试再继续"
```

## Run
Expand Down Expand Up @@ -300,10 +328,14 @@ Default behavior for daemon-launched runs:

- `--yolo` is enabled by default.
- No default `--check` is enforced unless you set one.
- Daemon defaults to the `cheap` model preset unless you override it.
- Daemon-launched runs inherit Codex CLI default model settings unless you explicitly set preset/overrides.
- When the daemon is idle, a new `/run` or terminal `run` command will reuse the last saved `session_id` if available.
- One Telegram token can only be owned by one active daemon process (second daemon returns an error).
- Operator messages (initial objective + terminal/Telegram injects) are written to per-run markdown files in the daemon logs directory.
- In daemon mode, only daemon polls Telegram updates; child runs receive control via daemon bus (avoids getUpdates 409 conflicts).
- If daemon detects `invalid encrypted content` from a resumed run, it raises a warning and auto-arms fresh session for the next run.
- Inside a running child loop, `invalid_encrypted_content` now triggers an immediate in-loop fresh-session retry instead of spinning reviewer `continue` loops.
- Operator messages (initial objective + terminal/Telegram injects) are appended to a shared `.codex_daemon/logs/operator_messages.md` so reviewer can see global inject history across runs.
- Each run also appends start/finish records into `.codex_daemon/logs/codexloop-run-archive.jsonl` (includes date + workspace + session metadata) for continuity and auditing.
- Re-running setup or start script will stop the previous daemon under the same `home-dir` before launching the new one.

After setup, use terminal control:
Expand Down
2 changes: 1 addition & 1 deletion codex_autoloop/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ def build_parser() -> argparse.ArgumentParser:
parser.add_argument("objective", nargs="+", help="Task objective passed to the primary agent.")
parser.add_argument("--codex-bin", default="codex", help="Codex CLI binary path.")
parser.add_argument("--session-id", default=None, help="Resume an existing Codex exec session id.")
parser.add_argument("--max-rounds", type=int, default=100, help="Maximum primary-agent rounds.")
parser.add_argument("--max-rounds", type=int, default=500, help="Maximum primary-agent rounds.")
parser.add_argument(
"--max-no-progress-rounds",
type=int,
Expand Down
3 changes: 3 additions & 0 deletions codex_autoloop/codex_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ def consume_pipe(stream_name: str, pipe) -> None:
fatal_error = watchdog_reason
elif turn_completed and not turn_failed:
fatal_error = None
elif process.returncode != 0 and fatal_error is None:
turn_failed = True
fatal_error = f"Process exited with code {process.returncode} before turn completion."

return CodexRunResult(
command=command,
Expand Down
Loading
Loading