diff --git a/.env.example b/.env.example index 9b1bcaf..6ee4b13 100644 --- a/.env.example +++ b/.env.example @@ -6,4 +6,4 @@ ELECTROBUN_ENABLE_CODESIGN=false ELECTROBUN_ENABLE_NOTARIZE=false # Optional: enable sanitized hook debug logs locally -LOOPNDROLL_ENABLE_HOOK_DEBUG_LOGS=true +LOOPNDROLL_ENABLE_HOOK_DEBUG_LOGS=false diff --git a/README.md b/README.md index db902ab..2abe821 100644 --- a/README.md +++ b/README.md @@ -1,141 +1,237 @@ +
Let Codex run until the task is actually done.
+Download current published release
+https://github.com/user-attachments/assets/1deba634-a305-4686-8654-65f889162932 +Loopndroll is a local macOS app for keeping Codex chats moving after Codex tries to stop. It uses Codex Hooks to observe chats, decide what should happen at Stop, send notifications, and optionally feed a Telegram reply back into the same Codex chat when the chat is already waiting. -Let Codex run until the task is actually done.
- +## Features -https://github.com/user-attachments/assets/1deba634-a305-4686-8654-65f889162932 +- Keep Codex running with a configurable continue prompt. +- Wait for a Telegram reply before continuing a Codex chat. +- Run completion checks, such as tests, lint, or typecheck, before allowing a chat to stop. +- Limit continuation to one, two, or three extra turns. +- Send Codex Stop replies to Telegram and Slack. +- Mirror observed Codex user prompts and assistant Stop replies to connected channels. +- Configure modes globally or per Codex chat. +- Attach Telegram or Slack destinations globally or per chat. +- Store new Telegram bot tokens and Slack webhook URLs in macOS Keychain. +- Manage Loopndroll's own Codex hooks without deleting unrelated hooks. -If you've ever had to send dozens of follow-up messages just to keep Codex running, or felt frustrated when it skipped tests, lint, or typecheck even though you clearly asked for them in Agents.md, this might help. +## Safety model -## With Loopndroll, you can: +Loopndroll runs locally on your machine. It does not send your chats, prompts, app database, or hook state to a Loopndroll server. -- keep Codex running until you stop it -- require specific commands at the end of a task, and keep going until they pass -- get progress updates in Telegram or Slack, and even reply to redirect the work or change the mode +If you connect Telegram or Slack, delivery goes through your own Telegram bot token or your own Slack Incoming Webhook URL. Those provider endpoints are controlled by you. -## How does it work +Important safety defaults: -Loopndroll plugs into Codex through Codex Hooks. +- New Telegram bot tokens are stored in macOS Keychain. +- New Slack webhook URLs are stored in macOS Keychain. +- The local SQLite database stores non-secret Keychain references for new secrets. +- Telegram control is direct-message only. +- Telegram groups and channels are filtered out for control. +- Slack is outbound-only in v1. +- Passive wake is disabled in v1. +- Telegram input does not wake idle Codex threads. +- If no hook-backed channel is active, Telegram input is not delivered to Codex. +- Pause is a soft disable: hooks remain installed but Loopndroll stays inert. +- Stop/Clear removes only Loopndroll-managed hook entries. + +## How it works -When a chat starts, Loopndroll registers it and remembers the settings for that task. +Loopndroll plugs into Codex through Codex Hooks. -When Codex tries to stop, Loopndroll gets a chance to decide what should happen next. Depending on the mode you picked, it can: +When a Codex chat starts or resumes, Loopndroll registers the chat locally. When Codex reaches Stop, Loopndroll evaluates the active mode and either lets Codex stop or returns a follow-up prompt that keeps the chat going. -- let the chat stop -- send another prompt and keep Codex going -- run your completion checks first, and keep going if they fail -- wait for a reply from Telegram and feed that reply back into the same chat +Depending on the mode, Loopndroll can: -At the same time, it can send the latest assistant message to Telegram or Slack so you can see progress without sitting in front of Codex the whole time. +- let the chat stop normally; +- send the default continue prompt; +- send a Telegram-provided prompt; +- run completion checks and continue if they fail; +- wait for a Telegram reply while Codex is already stopped inside an active hook; +- notify Telegram or Slack with the latest assistant message. -**IMPORTANT:** Loopndroll runs fully locally on your machine. It does not send your chats, prompts, or app data to any Loopndroll server. If you connect Telegram or Slack, you are using **your own bot** or **your own webhook**, under your control. +Loopndroll does not use Telegram or Slack as a general remote shell. Remote input is deliberately limited to active, hook-backed flows. ## Modes -You can set a mode globally for all chats, or override it per task. +You can set a mode globally for all chats, or override it per chat. If no mode is active, Codex stops normally. -- **Infinite**: every time Codex stops, Loopndroll sends the default follow-up prompt and keeps the chat going. You can change that default prompt in Settings, or override it for one task by replying to that task in Telegram. -- **Await Reply**: when Codex stops, Loopndroll waits for your reply in Telegram, then sends that reply back into the same chat. -- **Completion Checks**: when Codex stops, Loopndroll runs your commands like tests, lint, or typecheck. If any command fails, it tells Codex to keep going until they pass. +- **Infinite**: every time Codex stops, Loopndroll sends the default continue prompt and keeps the chat going. You can edit the default prompt in Settings. +- **Await Reply**: when Codex stops, Loopndroll sends a Telegram notification and waits for your Telegram reply. The reply is then sent back into the same Codex chat. +- **Completion Checks**: when Codex stops, Loopndroll runs configured commands such as tests, lint, or typecheck. If any command fails, Loopndroll tells Codex to keep going. - **Max Turns 1 / 2 / 3**: Loopndroll keeps Codex going for a fixed number of extra turns, then lets it stop. +- **Off**: Loopndroll does not continue the chat and does not accept Telegram input for that chat. + +## What v1 does not do + +Loopndroll v1 does not wake idle Codex threads from Telegram. + +That means a Telegram message cannot currently open chat `C2` and start a new Codex turn as if you typed into the Codex UI. Telegram input only works when Loopndroll already has a safe hook-backed channel, such as Await Reply waiting inside a Stop hook. + +This is intentional. Starting a new Codex turn from an idle chat needs a reliable supported input surface from Codex. Loopndroll v1 keeps the product boundary conservative and safe instead of pretending that Telegram can wake idle chats. + +## Notifications and mirror mode + +Control-mode notifications require an active Loopndroll mode. + +Mirror mode is separate. When enabled, Loopndroll mirrors observed Codex user prompts and assistant Stop replies to attached Telegram and Slack destinations. Mirror mode is output-only: Telegram replies are still ignored unless Await Reply is active. -This gives you a simple choice: keep pushing automatically, wait for human input, require checks to pass, or allow only a small number of extra turns. +Default behavior when everything is off: -## Use cases +- no Stop notifications; +- no mirror messages; +- no Telegram replies delivered to Codex; +- no pending prompts kept for inactive chats. -- **Keep pushing on a messy refactor without making me send "keep going" every 5 minutes** - Use **Infinite** when the work is real, but there is no clean automatic way to evaluate "done" yet. This fits tasks like cross-file refactors, bug hunts, and long review-comment cleanup where the next step depends on what Codex finds. +Administrative Telegram commands such as `/status`, `/help`, `/list`, `/mode`, and `/failsafe` may still respond because they control the integration itself. -- **Make sure `pnpm test` passes before marking the task as done** - Use **Completion Checks** when you want Codex to stop only after the repo is actually green. This is for the common case where the agent says it is done, but tests, lint, or typecheck still fail. +## Hook lifecycle -- **Send me the result in Telegram and wait for my decision** - Use **Await Reply** when Codex reaches a decision point and should wait for you instead of guessing. This works well when you want to review a draft, approve a plan, or redirect the work while you are away from your desk. +Loopndroll manages only its own Codex hook entries. -## Telegram Setup +Codex can load matching hooks from both global and repo-local hook files: -### Get a Telegram bot token +- `~/.codex/hooks.json` +- `+ {description} +
+ ) : null} + > )} @@ -156,16 +169,11 @@ export function ChatCard({ footerClassName, )} > -