@shiyuphan/follow-me 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -69
- package/dist/src/cli.js +1069 -140
- package/dist/src/comments.js +361 -0
- package/dist/src/git.js +32 -3
- package/dist/src/host.js +106 -9
- package/dist/src/install.js +22 -1
- package/dist/src/naive.js +26 -0
- package/dist/src/plan.js +282 -26
- package/dist/src/prompt.js +711 -98
- package/dist/src/server.js +573 -140
- package/dist/src/session.js +106 -104
- package/dist/src/syntax.js +199 -0
- package/dist/src/types.js +3 -1
- package/dist/ui/dist/assets/abnfDiagram-WEYOIA3C-DcmzRkVZ.js +1 -0
- package/dist/ui/dist/assets/arc-T5QB0T1C.js +1 -0
- package/dist/ui/dist/assets/architecture-WOLXFQ4H-DUIkQTeE.js +1 -0
- package/dist/ui/dist/assets/architectureDiagram-ZHVYKT53-BUYi4-bA.js +36 -0
- package/dist/ui/dist/assets/array-BifhSqXX.js +1 -0
- package/dist/ui/dist/assets/blockDiagram-RJAE7QA3-dyJxtT9e.js +140 -0
- package/dist/ui/dist/assets/c4Diagram-XDPPPE54-CrAgiaZR.js +38 -0
- package/dist/ui/dist/assets/channel-wW7ebm0i.js +1 -0
- package/dist/ui/dist/assets/chunk-2E7WHVMD-C6fAf4Vj.js +88 -0
- package/dist/ui/dist/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/dist/ui/dist/assets/chunk-4EMNKR2T-BLZjwZ4Q.js +1 -0
- package/dist/ui/dist/assets/chunk-55XCU76K-DGLK2Q-L.js +1 -0
- package/dist/ui/dist/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/dist/ui/dist/assets/chunk-7S6XSTFO-BablszTX.js +2 -0
- package/dist/ui/dist/assets/chunk-AQDTSKZB-Cuk3B_vb.js +72 -0
- package/dist/ui/dist/assets/chunk-DSNLSHJZ-DiC78RqE.js +127 -0
- package/dist/ui/dist/assets/chunk-DUW6YSOI-Dgx8z5s3.js +1 -0
- package/dist/ui/dist/assets/chunk-HAGFOTED-X_RbvixX.js +62 -0
- package/dist/ui/dist/assets/chunk-HNE4Q36P-C14_x5ck.js +1 -0
- package/dist/ui/dist/assets/chunk-J5ZVWO5B-oDCd-gWO.js +1 -0
- package/dist/ui/dist/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/dist/ui/dist/assets/chunk-NGNAAXSQ-C2Wy9Xmz.js +136 -0
- package/dist/ui/dist/assets/chunk-NQOKRVIF-Dxd0dtYR.js +213 -0
- package/dist/ui/dist/assets/chunk-UHW7PFBP-BIxePNUS.js +1 -0
- package/dist/ui/dist/assets/chunk-VQ5W62QI-CKSKLbj4.js +1 -0
- package/dist/ui/dist/assets/chunk-WQQL4CDK-CWNmZGlR.js +10 -0
- package/dist/ui/dist/assets/chunk-XXDRQBXY-D-I5QHgG.js +1 -0
- package/dist/ui/dist/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/dist/ui/dist/assets/chunk-YZO67HFG-DFP68CFd.js +1 -0
- package/dist/ui/dist/assets/chunk-ZAUX2LTX-DY90d4QG.js +1 -0
- package/dist/ui/dist/assets/chunk-ZCHMQSOR-Dlpr-5UC.js +2 -0
- package/dist/ui/dist/assets/classDiagram-v2-4MYWR3UA-CH9uhoLJ.js +217 -0
- package/dist/ui/dist/assets/cose-bilkent-JH36ORCC-DtYHrp8D.js +1 -0
- package/dist/ui/dist/assets/cynefin-EF2NZ3EQ-BtslbtrY.js +1 -0
- package/dist/ui/dist/assets/cynefinDiagram-WF24UDRP-DUU1Jcc7.js +62 -0
- package/dist/ui/dist/assets/cytoscape.esm-BegBNzOV.js +321 -0
- package/dist/ui/dist/assets/dagre-NK4GIZVX-CDlP-dRW.js +4 -0
- package/dist/ui/dist/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/dist/ui/dist/assets/diagram-CBK3MWTC-DiV2fn-r.js +24 -0
- package/dist/ui/dist/assets/diagram-I5XIIV2D-Bg5RehGi.js +24 -0
- package/dist/ui/dist/assets/diagram-ODIL2UCW-CFmazz3f.js +30 -0
- package/dist/ui/dist/assets/diagram-PFBEJUXE-uw3ZBqDp.js +3 -0
- package/dist/ui/dist/assets/diagram-RJA3I4VV-uEOYYRYa.js +41 -0
- package/dist/ui/dist/assets/diagram-TYUNFSNR-BN58LF_3.js +200 -0
- package/dist/ui/dist/assets/dist-tWS_lXDS.js +1 -0
- package/dist/ui/dist/assets/ebnfDiagram-V4P3TTPT-B68Tz-w8.js +1 -0
- package/dist/ui/dist/assets/elk-QONTBCTQ-DZZohNea.js +27 -0
- package/dist/ui/dist/assets/erDiagram-KYQIGQAA-BH_m74pv.js +99 -0
- package/dist/ui/dist/assets/eventmodeling-K75KTNOO-CTp5FHos.js +1 -0
- package/dist/ui/dist/assets/flowDiagram-IUGLLWBU-CsCvexry.js +1 -0
- package/dist/ui/dist/assets/ganttDiagram-R7GPNTJY-BDau7_0f.js +292 -0
- package/dist/ui/dist/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dist/ui/dist/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dist/ui/dist/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dist/ui/dist/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/ui/dist/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dist/ui/dist/assets/gitGraph-VSP46ZUC-Bv84IoCm.js +1 -0
- package/dist/ui/dist/assets/gitGraphDiagram-PDYL7XHY-DzXcMlm8.js +106 -0
- package/dist/ui/dist/assets/graphlib-DS17s2tU.js +1 -0
- package/dist/ui/dist/assets/index-BTJoqVVN.js +133 -0
- package/dist/ui/dist/assets/index-D60U3smc.css +1 -0
- package/dist/ui/dist/assets/info-OHQRW6UA-222J0O_j.js +1 -0
- package/dist/ui/dist/assets/infoDiagram-MVDRKAX5-DE2sa3Vz.js +2 -0
- package/dist/ui/dist/assets/init-C-OQMol4.js +1 -0
- package/dist/ui/dist/assets/ishikawaDiagram-HPEHV2GE-BJDk0Zcj.js +70 -0
- package/dist/ui/dist/assets/journeyDiagram-BOSHW7O7-JSUXX5Hb.js +139 -0
- package/dist/ui/dist/assets/kanban-definition-FNSA4HC5-Bg79b49M.js +89 -0
- package/dist/ui/dist/assets/katex-B_JcIwqj.js +257 -0
- package/dist/ui/dist/assets/line-Bk5qQSIa.js +1 -0
- package/dist/ui/dist/assets/linear-PFnVMru5.js +1 -0
- package/dist/ui/dist/assets/mermaid-parser.core-Dcxlzc-S.js +7 -0
- package/dist/ui/dist/assets/mermaid.core-TeOHQJ00.js +44 -0
- package/dist/ui/dist/assets/mindmap-definition-6OY57UG3-IaNk8NnW.js +98 -0
- package/dist/ui/dist/assets/ordinal-BDEzSJ7C.js +1 -0
- package/dist/ui/dist/assets/packet-JDAUHWVQ-DMff5cVK.js +1 -0
- package/dist/ui/dist/assets/path-fybaL0A-.js +1 -0
- package/dist/ui/dist/assets/pegDiagram-ECIUJNBX-66Xu4YRc.js +1 -0
- package/dist/ui/dist/assets/pie-XZMESJXO-GEtzLCIM.js +1 -0
- package/dist/ui/dist/assets/pieDiagram-GNMPY74T-7jMBi-kU.js +39 -0
- package/dist/ui/dist/assets/prism-bash-D6zCJ74D.js +1 -0
- package/dist/ui/dist/assets/prism-c-04YixN25.js +1 -0
- package/dist/ui/dist/assets/prism-clike-DapgWyxx.js +1 -0
- package/dist/ui/dist/assets/prism-core-FDHlWQ43.js +1 -0
- package/dist/ui/dist/assets/prism-cpp-C-lJbC-6.js +1 -0
- package/dist/ui/dist/assets/prism-css-CPgOzxXp.js +1 -0
- package/dist/ui/dist/assets/prism-go-C_8qAH5n.js +1 -0
- package/dist/ui/dist/assets/prism-java-6wtusvIl.js +1 -0
- package/dist/ui/dist/assets/prism-javascript-BnO-swvr.js +1 -0
- package/dist/ui/dist/assets/prism-json-Dp_-W-Hv.js +1 -0
- package/dist/ui/dist/assets/prism-jsx-D-D0NWtC.js +1 -0
- package/dist/ui/dist/assets/prism-kotlin-BUlJgC-o.js +1 -0
- package/dist/ui/dist/assets/prism-markdown-Bc9-36OC.js +1 -0
- package/dist/ui/dist/assets/prism-markup-Cp04rIa1.js +1 -0
- package/dist/ui/dist/assets/prism-markup-templating-KkSMBj6Y.js +1 -0
- package/dist/ui/dist/assets/prism-php-Co4fM40K.js +1 -0
- package/dist/ui/dist/assets/prism-python-CfiSVtM6.js +1 -0
- package/dist/ui/dist/assets/prism-ruby-DFCASkuD.js +1 -0
- package/dist/ui/dist/assets/prism-rust-Bu9N8X3N.js +1 -0
- package/dist/ui/dist/assets/prism-sql-CYhVDMEE.js +1 -0
- package/dist/ui/dist/assets/prism-swift-B0kWc-ne.js +1 -0
- package/dist/ui/dist/assets/prism-toml-DKb54GAT.js +1 -0
- package/dist/ui/dist/assets/prism-tsx-p6J2Kc_4.js +1 -0
- package/dist/ui/dist/assets/prism-typescript-BMqONzxf.js +1 -0
- package/dist/ui/dist/assets/prism-yaml-C0JHu8gr.js +1 -0
- package/dist/ui/dist/assets/quadrantDiagram-D57K4MC3-8hIWayC2.js +7 -0
- package/dist/ui/dist/assets/radar-ABXABTNO-BTdwUOOF.js +1 -0
- package/dist/ui/dist/assets/railroad-I3PHUGI6-DcMbDqBL.js +1 -0
- package/dist/ui/dist/assets/railroad-abnf-LNEFI6M7-gTzUTWeI.js +1 -0
- package/dist/ui/dist/assets/railroad-ebnf-DWYD2UWJ-CNtdUPtk.js +1 -0
- package/dist/ui/dist/assets/railroad-peg-JR7BVNR7-DOiExAtE.js +1 -0
- package/dist/ui/dist/assets/railroadDiagram-Y72NRBL7-2kE_ygvM.js +1 -0
- package/dist/ui/dist/assets/requirementDiagram-EQYSW5RA-CoIAHRq2.js +84 -0
- package/dist/ui/dist/assets/rough.esm-Dy-Kn_BL.js +1 -0
- package/dist/ui/dist/assets/sankeyDiagram-SY24JHO5-7p8D3wim.js +40 -0
- package/dist/ui/dist/assets/sequenceDiagram-BLEHNHQU-C6QFnMvn.js +169 -0
- package/dist/ui/dist/assets/sizeCapture-INFHLROL-3uHXrFqA.js +1 -0
- package/dist/ui/dist/assets/src-FgijoBVs.js +1 -0
- package/dist/ui/dist/assets/stateDiagram-v2-A6IESKWZ-n9eAb_bT.js +291 -0
- package/dist/ui/dist/assets/swimlanes-B3ENRKFQ-U18mtUzX.js +1 -0
- package/dist/ui/dist/assets/swimlanesDiagram-AYQRV4AK-DX07QVy9.js +8 -0
- package/dist/ui/dist/assets/timeline-definition-JXYKGLGB-CD2Z8QGP.js +120 -0
- package/dist/ui/dist/assets/treeView-D4JQ5SDB-sqUjH5gB.js +1 -0
- package/dist/ui/dist/assets/treemap-SAJKECNS-DvZ38FP7.js +1 -0
- package/dist/ui/dist/assets/usecaseDiagram-WPOLBNNX-CqOGidaZ.js +328 -0
- package/dist/ui/dist/assets/vennDiagram-Q3Y3IDCW-D1SXSBQ5.js +34 -0
- package/dist/ui/dist/assets/wardley-7MLQ67FV-Bpwio-Dx.js +1 -0
- package/dist/ui/dist/assets/wardleyDiagram-IVAIDKWA-JSUXHMnk.js +78 -0
- package/dist/ui/dist/assets/xychartDiagram-4URNHDU4-B4IFqQTN.js +7 -0
- package/dist/ui/dist/index.html +15 -0
- package/dist/ui/dist/style.css +121 -0
- package/package.json +31 -8
- package/skills/follow-me/SKILL.md +15 -61
- package/dist/src/anthropic.js +0 -101
- package/dist/ui/app.js +0 -797
- package/dist/ui/index.html +0 -40
- package/dist/ui/playback.js +0 -175
- package/dist/ui/style.css +0 -466
package/README.md
CHANGED
|
@@ -1,104 +1,154 @@
|
|
|
1
|
+
<p align="center"><img src="assets/logo.png" width="200" alt="A sweaty cyan blob with mismatched googly eyes and its tongue out chases a smug red blob in a party hat labelled HEAD along a git branch"></p>
|
|
2
|
+
|
|
1
3
|
# follow-me
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
follow-me splits a branch's net change into small commits in an order a reader can follow, proves the result equals the original, and lets you review it line by line.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@shiyuphan/follow-me)
|
|
8
|
+
[](https://github.com/phanshiyu/follow-me/actions/workflows/ci.yml)
|
|
9
|
+
|
|
10
|
+
## Why
|
|
11
|
+
|
|
12
|
+
People commit in the order things happened: wip, fix, actually fix, revert. A reviewer then reads that history or gives up and reads one big diff. Neither shows how the change was thought through.
|
|
13
|
+
|
|
14
|
+
The blob with its tongue out is you, on commit 31 of someone's 47-commit branch.
|
|
15
|
+
|
|
16
|
+
follow-me is for two people:
|
|
17
|
+
|
|
18
|
+
- **The author** commits however they like, then wants a branch that reads like a story before asking for review.
|
|
19
|
+
- **The reviewer** wants to read someone else's branch in an order that makes sense, ask questions about it, and post the review to the merge request.
|
|
20
|
+
|
|
21
|
+
## Use it
|
|
22
|
+
|
|
23
|
+
You do not run follow-me yourself. Your coding agent does.
|
|
4
24
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
hunk or line, and hand the comments to a coding agent for the next version.
|
|
25
|
+
1. Install it once, with Node 24 or newer and git: `npm i -g @shiyuphan/follow-me`.
|
|
26
|
+
2. Tell your agent to review a branch with follow-me. The first time it runs, follow-me copies its skill into the skill directory of every agent it finds (Claude Code, OpenCode, Codex CLI, Cursor, Gemini CLI, GitHub Copilot CLI), so every repo sees it. The agent plans the commits, and a review page opens in your browser.
|
|
27
|
+
3. Use the page. Read the commits in order, flag what is wrong, ask what you do not understand. Questions go to the agent at once and it answers under them. Flags are held until you press **Submit**.
|
|
28
|
+
4. Tell the agent to post the review. It reads `follow-me report --json` and posts the items you did not exclude to your GitLab merge request or GitHub pull request with `glab` or `gh`. follow-me never holds a token.
|
|
10
29
|
|
|
11
|
-
|
|
30
|
+
follow-me never calls a model and holds no API key; your agent writes the plan. [Using follow-me from your coding agent](docs/harnesses.md) has the per-harness details. `follow-me uninstall` removes exactly the skill files the agent run wrote.
|
|
12
31
|
|
|
13
|
-
|
|
14
|
-
stack before asking for review. Comments on the split go back to the agent, which writes
|
|
15
|
-
the next plan.
|
|
16
|
-
- **The reviewer** runs `follow-me walk` on someone else's branch to watch it being written,
|
|
17
|
-
with narration spoken as each line appears, and leaves comments on the code. The result is
|
|
18
|
-
a code review for the author.
|
|
32
|
+
## What the agent runs
|
|
19
33
|
|
|
20
|
-
|
|
34
|
+
An agent runs `follow-me` with no command, again and again. Each call does the next thing that is missing and ends with a `next:` line: it writes `.follow-me/<branch>/prompt.md` for the agent to answer, prints the problems with the agent's draft, applies a valid draft to `<branch>-split` and opens the page, then listens to the reviewer for up to 60 seconds (`--wait <seconds>`) and prints what they flagged or asked. When the reviewer submits it prints the report. `follow-me help` lists the other commands an agent uses (`reply`, `explain`, `report`); `follow-me help --all` lists the steps by hand:
|
|
21
35
|
|
|
22
|
-
|
|
36
|
+
### Splitting your own branch
|
|
23
37
|
|
|
24
|
-
|
|
38
|
+
With the branch checked out, from the repo root:
|
|
25
39
|
|
|
26
40
|
```sh
|
|
27
|
-
|
|
28
|
-
cd follow-me && npm install && npm link # puts `follow-me` on your PATH
|
|
41
|
+
follow-me split --base main # extract, apply your agent's draft and open the review in one go
|
|
29
42
|
```
|
|
30
43
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
Run everything from the repo whose branch you want to split, with that branch checked out.
|
|
44
|
+
Until there is a valid draft, `split` writes `.follow-me/<branch>/prompt.md` and stops: the agent follows it, then runs `follow-me check` and `follow-me split` again. Every command ends with a `next:` line naming the step after it. The steps `split` runs are also commands of their own:
|
|
34
45
|
|
|
35
46
|
```sh
|
|
36
|
-
follow-me extract --base main
|
|
37
|
-
follow-me prompt
|
|
38
|
-
# the agent writes .follow-me/<branch>/draft.json
|
|
39
|
-
follow-me check
|
|
40
|
-
follow-me apply
|
|
41
|
-
follow-me review
|
|
42
|
-
follow-me
|
|
47
|
+
follow-me extract --base main # snapshot the diff from main to the tip, list the units
|
|
48
|
+
follow-me prompt # instructions and every unit, for your coding agent
|
|
49
|
+
# the agent writes .follow-me/<branch>/draft.json
|
|
50
|
+
follow-me check # print every problem with the draft at once
|
|
51
|
+
follow-me apply # write the commits to <branch>-split
|
|
52
|
+
follow-me review # open the review page in your browser
|
|
53
|
+
follow-me report [--json] # print the review as markdown, or as items to post
|
|
43
54
|
```
|
|
44
55
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
`.
|
|
56
|
+
A unit is a text hunk (`h_…`), a whole file that cannot be split by line (`f_…`), or a mode change (`m_…`). The draft assigns every change line to exactly one commit. `h_x:0-3,7` takes change lines 0 to 3 and 7 of hunk `h_x`, so one hunk can spread across several commits.
|
|
57
|
+
|
|
58
|
+
`check` and `apply` also parse every file each commit writes, so a split can leave a commit that does not build but never one that ends inside a function. `.js`, `.ts`, `.json`, `.sh` and `.py` files are checked and other types are listed as skipped; `--syntax "<command with {file}>"` swaps in your own checker and `apply --allow-syntax-errors` goes ahead anyway. Without an agent, `follow-me plan --naive` writes one `wip: <path>` commit per touched file, which is enough to run `check`, `apply` and the tree proof on any branch.
|
|
59
|
+
|
|
60
|
+
`apply` never writes your original branch, your index, or your working tree. It builds the commits in a temporary index and points `<branch>-split` at them, or the branch you name with `--name`. It refuses the branch being split and any branch checked out in a worktree, even with `--force`. `--force` only lets it move a branch follow-me did not create. Then it compares the last commit's tree hash with the original tip's and prints both:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
created feature-split at c90eb5350284 from plan v1 (3 commits)
|
|
64
|
+
signing: off
|
|
65
|
+
proof: feature-split^{tree} ae948488c55a3606fa2419eb1c018fff8014093d equals feature^{tree} ae948488c55a3606fa2419eb1c018fff8014093d
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
If the hashes differ, `apply` exits with code 1. The commits are signed when your git config signs commits (`commit.gpgsign`), and `--sign` or `--no-sign` overrides that. Running `apply` again with the same plan prints `unchanged` and leaves the branch alone, signed or not.
|
|
69
|
+
|
|
70
|
+
The red blob in the party hat is your branch tip. Nothing follow-me does moves it.
|
|
71
|
+
|
|
72
|
+

|
|
73
|
+
*The review page. Pick any line, changed or not, or a range; Ask or Flag opens right under it. The agent answers inline in Markdown.*
|
|
74
|
+
|
|
75
|
+

|
|
76
|
+
*Diagrams sit full width under the commit or reply they explain, and open full size on click.*
|
|
48
77
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
`.follow-me/<branch>/plans/`, reviews under `reviews/`, and a comment counts as answered when
|
|
52
|
-
a later plan lists it.
|
|
78
|
+

|
|
79
|
+
*Submit review. Each item carries the original branch's path and line, so your agent can post it to the merge request as is.*
|
|
53
80
|
|
|
54
|
-
|
|
81
|
+
Keys: `j` and `k` move between commits, arrows and Shift+arrows pick rows inside a hunk, `c` comments on the pick, `v` marks a commit viewed, `?` lists the rest. An unfinished review autosaves and comes back when the page is opened again.
|
|
82
|
+
|
|
83
|
+
### Reviewing someone else's branch
|
|
84
|
+
|
|
85
|
+
When the branch is not yours, `follow-me` plans a reading order instead of a split: nothing is applied and no branch is written. You read the commits in order and comment on the code, and `follow-me report` prints it as a code review for the author, grouped by file, with each comment quoting its hunk as it reads in that commit and its line number on the branch. `--reviewer` and `--author` override the guess, which is whether you wrote every commit of the branch.
|
|
86
|
+
|
|
87
|
+
### One server for every review
|
|
88
|
+
|
|
89
|
+
The first review starts a review server for your user and serves the page. Every later one, from any repo or worktree, adds its session to that server, prints the URL, and exits. The server's index page lists every open session.
|
|
55
90
|
|
|
56
91
|
```sh
|
|
57
|
-
|
|
58
|
-
follow-me
|
|
92
|
+
follow-me review --detach # start the server in the background and return
|
|
93
|
+
follow-me review --no-open # print the URL without opening a browser
|
|
94
|
+
follow-me review --wait # return only once the review ends, so an agent can go on to report
|
|
95
|
+
follow-me server status # the server, its port, and the sessions it hosts
|
|
96
|
+
follow-me server stop # stop it, autosaved reviews are kept
|
|
59
97
|
```
|
|
60
98
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
`follow-me feedback` renders it as a code review grouped by file.
|
|
99
|
+
The server listens on `127.0.0.1` only. If the `--port` you ask for is taken by another program, it picks a free port and prints `port N is in use by another program, using M`. It exits on its own 30 seconds after its last session ends. It is the only one at the party who knows when to leave. Its record lives in `$FOLLOW_ME_HOME`, else `$XDG_STATE_HOME/follow-me`, else `~/.local/state/follow-me`.
|
|
100
|
+
|
|
101
|
+
Each worktree has its own `.follow-me/` directory, which git ignores, and each branch has its own session in it. A lock stops two agents from applying or reviewing one session at once. `follow-me clean` removes what no live session needs: sessions of deleted branches, review drafts that a finished review replaced, and locks and temp files of dead processes. It keeps plan versions, because reviews refer to them. `clean --dry-run` lists what it would remove, and `clean --all` removes `.follow-me/` entirely unless a live process holds a session.
|
|
65
102
|
|
|
66
|
-
|
|
103
|
+
### How it works
|
|
67
104
|
|
|
68
|
-
|
|
105
|
+
Every unit comes from one `git diff base..tip`, so the hunks of a file never overlap in base coordinates. A commit's version of a file is therefore the base lines with that commit's change lines swapped in. Nothing is patched. Hunks can go in any order and split at any line, and nothing can fail to apply.
|
|
69
106
|
|
|
70
|
-
|
|
71
|
-
coordinates. A commit's version of a file is the base lines with that commit's change lines
|
|
72
|
-
swapped in. Nothing is patched, so hunks can be assigned in any order and split by line.
|
|
73
|
-
See `docs/DESIGN.md`.
|
|
107
|
+
Two checks replace patching. While parsing, every context line and removed line must equal the base file at its position. After the last commit, every path's bytes and mode must equal the tip, and then git's own tree hash is compared once more.
|
|
74
108
|
|
|
75
|
-
|
|
76
|
-
temporary index with dates derived from the tip, so the same plan always yields the same
|
|
77
|
-
SHAs and re-running `apply` is a no-op.
|
|
109
|
+
There is one limit. A commit can only contain lines that exist in the base or in the tip, so follow-me cannot invent an intermediate version of a line that the author typed and later deleted.
|
|
78
110
|
|
|
79
|
-
|
|
111
|
+
[docs/DESIGN.md](docs/DESIGN.md) has the full design.
|
|
112
|
+
|
|
113
|
+
### The agent loop
|
|
114
|
+
|
|
115
|
+
Each `apply` freezes the draft as the next plan version, `.follow-me/<branch>/plans/vN.json`. Each review belongs to one version. `follow-me report` gives every comment an id like `c_abc234`. After a review, `follow-me prompt` includes the previous plan and the open comments, and the agent answers each comment in the next draft:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
"responses": [
|
|
119
|
+
{ "comment": "c_abc234", "status": "addressed", "note": "Moved the guard before its first use." }
|
|
120
|
+
]
|
|
121
|
+
```
|
|
80
122
|
|
|
81
|
-
|
|
82
|
-
- The review server binds `127.0.0.1` only and rejects cross-origin requests.
|
|
83
|
-
- Everything under `.follow-me/` is ignored by git.
|
|
84
|
-
- Outside the repo, follow-me writes only its state dir (`~/.local/state/follow-me`, or
|
|
85
|
-
`$XDG_STATE_HOME/follow-me`), which holds the review server's `server.json` and `server.log`.
|
|
86
|
-
- One review server per user hosts every session. `follow-me server stop` signals it only after
|
|
87
|
-
it answers as follow-me on its recorded port, so a reused pid is never killed.
|
|
123
|
+
`status` is `addressed`, `declined`, or `deferred`. A comment counts as answered once a later plan lists it. `check` warns about unanswered comments but does not block `apply`. `follow-me status` shows the plans, the reviews, how many comments are still open, and the branch `apply` writes.
|
|
88
124
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
125
|
+
## Upgrade and uninstall
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
follow-me upgrade # npm install -g @shiyuphan/follow-me@latest, then refresh the skill copies
|
|
129
|
+
follow-me uninstall --all # remove the skill from every agent's skill directory
|
|
130
|
+
npm uninstall -g @shiyuphan/follow-me
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
`upgrade` matters because the skill copies in `~/.claude/skills/` and the other agents' directories
|
|
134
|
+
are files, so they stay at the old version until they are written again. Uninstalling the package
|
|
135
|
+
leaves per-repo state in `.follow-me/` (remove it with `follow-me clean --all` first, or delete the
|
|
136
|
+
directory) and the server record under `~/.local/state/follow-me`.
|
|
95
137
|
|
|
96
138
|
## Development
|
|
97
139
|
|
|
98
140
|
```sh
|
|
99
|
-
npm
|
|
100
|
-
node
|
|
141
|
+
npm install
|
|
142
|
+
npm run check # biome, strict tsc, and node --test, the same as CI
|
|
143
|
+
node bin/follow-me.ts <command> # run the CLI from source
|
|
101
144
|
```
|
|
102
145
|
|
|
103
|
-
Tests run
|
|
104
|
-
|
|
146
|
+
There is no build step for development. Node 24 runs the TypeScript sources directly, and `npm run build` exists only for publishing. Tests run real git against repositories built by `test/fixture-repo.ts`. Non-obvious decisions go in `docs/decisions.tsv` through `scripts/log-decision.sh`.
|
|
147
|
+
|
|
148
|
+
To release, run `npm version patch`, `minor`, or `major`, then `git push --follow-tags`. The tag triggers the publish workflow. [docs/releasing.md](docs/releasing.md) has the details.
|
|
149
|
+
|
|
150
|
+
## Credits
|
|
151
|
+
|
|
152
|
+
Inspired by the "split your own changes" idea in [spark-joy](https://github.com/Dansyuqri/spark-joy). Built with [pstack](https://github.com/alexanderop/pstack).
|
|
153
|
+
|
|
154
|
+
MIT licensed.
|