feat: per-change-block hunk actions (#50), codex lanes without a pipeline, macOS LaunchAgent

- git (#50): stage-hunk/discard-hunk take an optional `block` — one run of
  consecutive +/- lines inside an @@ hunk. `onlyBlock` (server/lib/git-diff.js)
  cuts git's fresh hunk down to it, folding the other blocks into the side
  being checked; LaneDiffView hangs one review bar per block (unified + split)
  and its arrows walk blocks.
- git exclude: entries AgentHub writes for a lane go to the COMMON git dir with
  the lane's path prefix (server/lib/git-exclude.js, used by router-apply and
  lane-mcp) — a linked worktree's own info/exclude is never read by git, and a
  subdir lane has no .git. MCP sync no longer fails with ENOTDIR on a worktree
  lane or creates a stray .git in a non-repo lane.
- codex lanes carry no pipeline: codex-ingest mirrors only idle/running,
  codex-nudge is removed, agents install writes nothing for codex, the
  Workspace hides stage/pipeline/feature pickers/PipelineMap for them, and
  every server start clears leftover codex stage data and the old AGENTS.md
  stage block.
- Changes panel: a whole file opens for reading and enters the editor on a
  click on its text (caret at the clicked line), not automatically.
- macOS: LaunchAgent start-at-login (scripts/launchd-service.js, picked by
  scripts/service-manager.js).
- Adds the AgentHub introduction slides and their image-embedding script.
This commit is contained in:
2026-09-25 17:30:28 +07:00
parent 3f6e903c22
commit 952e8584f0
48 changed files with 3336 additions and 1579 deletions
+21 -12
View File
@@ -31,7 +31,7 @@ dashboard, run it from source, or stay on Node 20.
| npm | 9+ | Comes with Node.js |
| Claude Code | 2.x+ | Required for hook integration |
| Git | Any | Cloning the repository, and every lane operation (worktrees, branch/status reads) |
| **tmux** | 3.x | **Required for the run console** — the browser terminal, `agenthub lanes shell`, typing `/reload-plugins` into a live pane, and the Codex nudge. See [Step 0](#step-0--system-packages) |
| **tmux** | 3.x | **Required for the run console** — the browser terminal, `agenthub lanes shell`, and typing `/reload-plugins` into a live pane. See [Step 0](#step-0--system-packages) |
| Codex CLI | Any | Optional — only for lanes whose tool is `codex` |
| GitHub CLI (`gh`) | Any | Optional — only for `agenthub lanes ci status` and the PR stages of `/agenthub:ship-full` |
| Python | 3.6+ | Optional — only for `scripts/expand-ts-module-docs.py` (doc generation) |
@@ -101,9 +101,14 @@ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc # where the plugin put
`node:sqlite`); a checkout still runs on Node 20. The `agenthub` launcher
pins the node that installed it and falls back to `node` on `PATH` when a
`brew upgrade` or `nvm` switch deletes that binary.
- **No systemd, so no auto-start on boot.** The server is a detached process
that runs until logout or reboot. It comes back at the next Claude Code
session start (within about 10 s), or by hand with `agenthub start`. A
- **Starts at login by itself (LaunchAgent).** The plugin bootstrap installs
`~/Library/LaunchAgents/io.smartgift.agenthub.plist` (a checkout: `agenthub
service install`), so the dashboard comes back after every login with no
Claude Code session, and launchd restarts it if it dies. Lane panes survive
a restart of the server. Its output goes to `~/Library/Logs/agenthub.log`.
A LaunchAgent needs a login at the Mac itself; over SSH only, or when
`launchctl` fails, the server is a detached process started by the next
Claude Code session (within about 10 s) or by `agenthub start`, as before. A
discovery entry left over from before the reboot is ignored, so a recycled
pid can never pass for a live dashboard.
- **Started from a Claude Code session.** The server drops the variables that
@@ -124,15 +129,17 @@ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc # where the plugin put
**Mac checklist** — please run it and report the result on issue #22:
1. Fresh plugin install from a Terminal `claude` session: `/agenthub-doctor` is all OK (the systemd row says not available) and the dashboard answers on `http://localhost:4820`.
1. Fresh plugin install from a Terminal `claude` session: the dashboard answers on `http://localhost:4820`, `~/Library/LaunchAgents/io.smartgift.agenthub.plist` exists, and `/agenthub-doctor`'s launchd row says the LaunchAgent is current and running.
2. `tmux show-environment -g | grep -i claude` prints nothing.
3. Add a Repo lane by typing its path in a different case: sessions bind to it, and `agenthub stage plan` inside it moves the map.
4. **Start Run** in the browser: the terminal attaches, typing works, an image paste into `claude` works, and `exit` returns to the run form.
5. Changes panel: diff, stage and commit on a lane.
6. Switch profile and check `claude /status` shows the new account. Repeat with a non-default `CLAUDE_HOME`, which also checks the Keychain service name.
7. `brew upgrade node && brew cleanup`, then `agenthub status` still works.
8. Reboot, open `claude`, and the dashboard comes back within about 10 s.
9. `/agenthub-update` completes and the server restarts on the new version.
8. Reboot and log in WITHOUT opening `claude`: the dashboard answers within about 10 s (`agenthub service status` shows `state = running`).
9. `kill <server pid>` (from `agenthub status`): it is back within a few seconds.
10. With a lane run open, `/agenthub-update` completes, the server restarts on the new version, the plist names the new cache directory, and the run's terminal is still alive.
11. `agenthub service uninstall`: the plist is gone and nothing restarts the server after a `kill`.
---
@@ -287,13 +294,15 @@ npm start # Start Express serving client/dist on port 4820
Open **http://localhost:4820** in your browser.
`npm start` (and `agenthub start`, its backgrounded form) only run while that
process is alive — a reboot loses it. On Linux, run the server as a systemd
`--user` service instead so it comes back on its own after every reboot, with
no manual step and no Claude Code (or any other tool) needed to trigger it:
process is alive — a reboot loses it. Run the server as a systemd `--user`
service (Linux) or a LaunchAgent (macOS) instead so it comes back on its own
after every reboot, with no manual step and no Claude Code (or any other tool)
needed to trigger it:
```bash
agenthub service install # writes + enables ~/.config/systemd/user/agenthub.service
agenthub service status # systemctl --user status agenthub
agenthub service install # Linux: ~/.config/systemd/user/agenthub.service
# macOS: ~/Library/LaunchAgents/io.smartgift.agenthub.plist
agenthub service status # systemctl --user status / launchctl print
agenthub service uninstall # disable and remove it
```