README.md (11146 bytes)
1 # deploy-handoff 2 3 A Claude Code plugin for the steps that an AI agent must not do alone. 4 5 An agent can build, test, and upload a release. Some steps must come from a person: publish the release, turn on live payments, accept an OAuth consent, or create a pull request. The agent drives the browser as far as it can. Then deploy-handoff shows a small dialog on top of the browser. The dialog tells you what to do, in short steps in [Simplified Technical English](https://asd-ste100.org). You do the final click. Then you click **Done** or **Not done**, and the agent continues. 6 7 deploy-handoff never makes the final click for you. It never asks for a password or a key. 8 9 ## Install 10 11 In Claude Code: 12 13 ``` 14 /plugin marketplace add equwal/deploy-handoff 15 /plugin install deploy-handoff@deploy-handoff 16 ``` 17 18 Then add the [rule](#rule). The rule tells Claude when to use the plugin. 19 20 Requirements: 21 22 - Python 3.11 or later, with Tk. The python.org installers for Windows and macOS include Tk. On Debian and Ubuntu, install `python3-tk`. 23 - `git` for the `pr` command. `gh` is optional. If `gh` is available, the `pr` command gives the URL of the new pull request. 24 - For the browser driver: Brave or Chrome, and Node.js with `npx`. The plugin starts [Playwright MCP](https://github.com/microsoft/playwright-mcp) with `npx`. 25 26 ## How it works 27 28 The plugin adds the skill `deploy-handoff` and the agent `browser-driver`. Claude uses the skill when a task reaches a human step, and when it opens a GitHub pull request. The skill drives your Brave profile, where you are signed in, and then runs `skills/deploy-handoff/handoff.py`. The agent starts only if you ask for a fresh browser. Other tools can run the script in the same way. 29 30 Open a page and show the steps: 31 32 ```bash 33 python3 skills/deploy-handoff/handoff.py open \ 34 --url https://play.google.com/console \ 35 --title "Send version 1.4.0 for review" \ 36 --step 'Open "Publishing overview".' \ 37 --step 'Click "Send changes for review".' 38 ``` 39 40 If the agent already drove a browser to the page, it adds `--no-open`. Then the script shows only the dialog. The script refuses a title or a step with more than 20 words or with a semicolon. 41 42 Show the steps for a question that a program asks in a terminal. The command opens no page and needs no allowed host: 43 44 ```bash 45 python3 skills/deploy-handoff/handoff.py terminal \ 46 --title "Install Herdr on the build server" \ 47 --where 'Terminal tab "herdr: add build server"' \ 48 --step 'Press "Y".' 49 ``` 50 51 Claude starts the program in a terminal that you see and stops at the question. You give the answer. 52 53 Open the pull request form for the current branch: 54 55 ```bash 56 python3 skills/deploy-handoff/handoff.py pr --title "Add CSV export" --body-file body.md 57 ``` 58 59 For a pull request from a fork to its upstream repository, push the branch to the fork and add `--repo UPSTREAM_OWNER/NAME`. The form then compares the branch of the fork with the upstream repository. 60 61 The script prints one JSON object, for example `{"status": "done", "note": ""}`. [SKILL.md](skills/deploy-handoff/SKILL.md) lists all statuses and exit codes. 62 63 ## Rule 64 65 The skill tells Claude how to hand off a step. The rule [rules/deploy-handoff.md](rules/deploy-handoff.md) tells Claude when to do it. Without the rule, Claude can refuse a deploy task because one step is for a human. With the rule, Claude does all the other work and hands off only that step. 66 67 The rule also tells Claude to: 68 69 - Run a deploy command, for example `vercel deploy` or `gh release create`, when a command can do the step. The permission prompt of Claude Code is your approval. In a permission mode with no prompt, Claude asks you in the chat before a production deploy, a release, or a live payment change. 70 - Continue the other tasks of a request while one task waits for you in the dialog. 71 - Drive the browser to the page of the last step, not only to the home page of a console. 72 - Use the browser profile in which you are signed in. Claude starts a fresh profile only if you ask for it. 73 - Push directly when you ask for a change, and open a pull request only when the repository needs one. The pull request form opens with `handoff.py pr`. 74 75 To use the rule in all your projects, copy it to `~/.claude/rules/`: 76 77 ```bash 78 mkdir -p ~/.claude/rules 79 curl -fsSL -o ~/.claude/rules/deploy-handoff.md https://raw.githubusercontent.com/equwal/deploy-handoff/main/rules/deploy-handoff.md 80 ``` 81 82 To use it in one project only, copy it to `.claude/rules/` in that project. Claude Code reads the Markdown files in these folders at the start of each session. Edit the rule to fit your work. For example, remove the pull request section if your team reviews each change. 83 84 ## Browser 85 86 The script opens pages in a new tab of your default browser. To use a different browser, set the `BROWSER` environment variable. The Python `webbrowser` module reads it. 87 88 To open pages in one Brave profile, add `brave_profile` to `~/.config/deploy-handoff/config.toml`. Write the name that Brave shows for the profile. The case does not matter. 89 90 ```toml 91 brave_profile = "Work" 92 ``` 93 94 Then the script opens each page in that profile, also when Brave runs already, and ignores `BROWSER`. If Brave has no profile with this name, the script stops with an error. It does not open another profile. Install the Claude in Chrome extension in this profile. The skill uses it for the browser steps. The skill never starts a fresh profile unless you ask for it. 95 96 ## Browser driver 97 98 The agent [browser-driver](agents/browser-driver.md) does the browser steps before the dialog in a fresh browser. It stops at the first human step. Then the dialog shows only that step. Claude does not start it unless you ask for a fresh browser. 99 100 The agent works in its own browser with a fresh profile, not in your browser. Start that browser with this command. Without `--fresh`, the command refuses to start: 101 102 ```bash 103 python3 skills/deploy-handoff/handoff.py browser --fresh 104 ``` 105 106 The command starts Brave, or Chrome if Brave is not installed. `--exe PATH` names a different Chromium browser. The browser uses its own profile in `~/.config/deploy-handoff/browser` and opens the remote debugging port 9333 on 127.0.0.1. If the browser runs already, the command only prints its status. The agent cannot use your Brave profile, because Chromium 136 and later ignores the remote debugging port for the default profile folder. 107 108 [Playwright MCP](https://github.com/microsoft/playwright-mcp) controls this browser through the port. Thus the agent works when the window is behind other windows, and you can keep working. It also fills in file dialogs without the mouse. On Windows, the agent can use [Windows-MCP](https://github.com/CursorTouch/Windows-MCP) for a window of the operating system, if you have it. 109 110 Sign in to each console one time in this browser. The profile keeps the sign-in. When the agent finds a sign-in page, it gives the sign-in to you as a human step. 111 112 The browser starts with no window. The agent opens a window when it opens a page. If you close the window, the browser does not stop, and the agent can open a new window. 113 114 Any program on your computer can control this browser through the port. Use the profile only for deploy consoles. When you do not need the browser, stop its process: the `brave.exe` or `chrome.exe` process with `--remote-debugging-port=9333` in its command line. On Windows, Task Manager shows the command line on the Details tab when you add the "Command line" column. On macOS and Linux, run `pkill -f -- --remote-debugging-port=9333`. 115 116 The agent gets only the tools that look at the page and act on it. It gets no tool that runs code in the page or reads the network traffic, and no shell, file, registry, or clipboard tool. It can upload only files in the project folder. 117 118 The agent never types a password, a code, a key, or a card number. It never signs in, solves a CAPTCHA, accepts terms, or makes the final click. If it cannot continue, it gives the status `not_done` and the error to the agent that started it. 119 120 ## Allowed hosts 121 122 The script opens only `https` pages on allowed hosts. This stops an agent that follows bad instructions from sending you to a fake sign-in page. The dialog also shows the host of the page. 123 124 [config.toml](skills/deploy-handoff/config.toml) has the default list: GitHub, GitLab, Stripe, Google Play, F-Droid, App Store Connect, and some cloud and hosting consoles. An entry also allows its subdomains. 125 126 To add hosts, make the file `~/.config/deploy-handoff/config.toml`. If `XDG_CONFIG_HOME` is set, the file is `$XDG_CONFIG_HOME/deploy-handoff/config.toml`. 127 128 ```toml 129 allowed_hosts = ["dashboard.example.com"] 130 ``` 131 132 ## Development 133 134 ```bash 135 python3 -m venv .venv 136 .venv/bin/python -m pip install --group dev 137 .venv/bin/python -m ruff format --check 138 .venv/bin/python -m ruff check 139 .venv/bin/python -m mypy skills/deploy-handoff 140 .venv/bin/python -m unittest discover -s skills/deploy-handoff 141 ``` 142 143 On Windows, use `.venv\Scripts\python`. `pip install --group` needs pip 25.1 or later. The dialog tests show small windows for a short time. One browser test starts Brave or Chrome with a temporary profile. If you have neither, unittest skips that test. 144 145 ## More projects 146 147 - [SubRead](https://subread.space/): read along with an audiobook, in the browser. 148 Also [for Android](https://github.com/equwal/subread-android/releases/latest), 149 [for YouTube](https://github.com/equwal/subread-extension/releases/latest) 150 and [for KOReader](https://github.com/equwal/subread.koplugin). 151 - [SubRead Overlay](https://github.com/equwal/subread-overlay/releases/latest): subtitle lines over any Android media player. 152 - [SubRead Dictionary](https://github.com/equwal/subread-dictionary/releases/latest): a pop-up dictionary for Android that reads Yomitan dictionaries. 153 - [SubRead Anki](https://github.com/equwal/subread-anki): one tap makes an Anki card from any Android app. 154 - [Subrep](https://github.com/equwal/subrep-android/releases/latest): live captions of the sound of your phone. 155 - [Book Simulator](https://booksimulator.com/): a reading room for Aozora Bunko and Project Gutenberg books. 156 - [honjimaku.com](https://honjimaku.com/): subtitles for Japanese audiobooks. 157 - [sbm Sync](https://sbmsync.com/): your bookmarks, the same on every device, 158 with [sbm](https://github.com/equwal/sbm) for dmenu, 159 [sbm for Android](https://github.com/equwal/sbm-android/releases/latest) 160 and the [sbm add-on](https://github.com/equwal/sbm-extension/releases/latest) for Firefox and Chrome. 161 - [Rebind](https://github.com/equwal/rebind/releases): remap the hardware buttons of e-ink readers and Android, 162 with [Ink Recents](https://github.com/equwal/ink-recents/releases/latest), 163 [Ink Dim](https://github.com/equwal/ink-dim/releases/latest) 164 and [Ink Update](https://github.com/equwal/ink-update/releases/latest). 165 - [dickt.store](https://dickt.store/): language-learning tools, flashcards and web toys. 166 - [hentaibun.online](https://hentaibun.online/): learn kanbun and kobun. 167 - [Recently Written](https://recentlywritten.com/): the blog, and a list of [all projects](https://recentlywritten.com/projects.html). 168 169 ## License 170 171 MIT