pi-anchor 0.5.0 → 0.6.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 +93 -34
- package/README_ja.md +90 -0
- package/README_zh.md +100 -36
- package/bin/anchor.js +16 -16
- package/dist/{chunk-VXEQDTK4.js → chunk-6NYXKR4F.js} +219 -25
- package/dist/{extension-Cq1NH1jT.d.cts → extension-09AVvgl-.d.cts} +31 -2
- package/dist/{extension-Cq1NH1jT.d.ts → extension-09AVvgl-.d.ts} +31 -2
- package/dist/extension.cjs +219 -25
- package/dist/extension.d.cts +1 -1
- package/dist/extension.d.ts +1 -1
- package/dist/extension.js +1 -1
- package/dist/index.cjs +168 -23
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +3 -2
- package/src/extension.ts +82 -8
- package/src/store.ts +146 -14
- package/src/tui.ts +25 -12
- package/src/types.ts +11 -1
package/README.md
CHANGED
|
@@ -1,73 +1,132 @@
|
|
|
1
1
|
# ⌖ Anchor
|
|
2
2
|
|
|
3
|
-
> **A digital sticky note docked below your Pi editor —
|
|
4
|
-
> Stick a note in 0ms (`pin: ...`), see it persistently below your editor (`belowEditor`, zero collision with `aboveEditor` extensions), track long tasks with micro progress bars `[■■□□ 2/4]`, jump straight back to the original conversation session (`↪`), and auto-tear off on `git commit`.
|
|
3
|
+
> **A digital sticky note docked below your Pi editor — 0ms instant stick, micro progress bars `[■■□□ 2/4]`, 1-click session teleport (`↪`), and automatic teardown on `git commit`.**
|
|
5
4
|
|
|
5
|
+
[](https://www.npmjs.com/package/pi-anchor)
|
|
6
|
+
[](https://www.npmjs.com/package/pi-anchor)
|
|
7
|
+
[](https://github.com/3ZEROS12/anchor/stargazers)
|
|
6
8
|
[](https://github.com/3ZEROS12/anchor/actions/workflows/ci.yml)
|
|
7
|
-
[](package.json)
|
|
8
|
-
[](tsconfig.json)
|
|
9
9
|
[](tests/store.test.ts)
|
|
10
10
|
[](LICENSE)
|
|
11
11
|
|
|
12
|
-
**English** | [简体中文](./README_zh.md)
|
|
12
|
+
**English** | [日本語](./README_ja.md) | [简体中文](./README_zh.md)
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
15
|
pi install npm:pi-anchor
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
<p align="center">
|
|
19
|
-
<img src="assets/hero-en.svg" alt="Anchor Sticky
|
|
19
|
+
<img src="assets/hero-en.svg" alt="Anchor Below-Editor Sticky Strip" width="820">
|
|
20
20
|
</p>
|
|
21
21
|
|
|
22
22
|
```text
|
|
23
|
-
|
|
23
|
+
┌─ [aboveEditor stays 100% free for pi-lingual and other HUD widgets] ────────────┐
|
|
24
|
+
╭─┴─ Pi Editor ────────────────────────────────────────────────────────────────────╮
|
|
24
25
|
│ ❯ pin: Refactor auth flow: 1. Extract interface 2. HttpOnly cookie 3. Unit tests │
|
|
25
|
-
|
|
26
|
-
⌖ #1 [■■□□ 2/4] Refactor auth flow ▸ Unit tests (app · auth.ts ↪)
|
|
26
|
+
╰─┬────────────────────────────────────────────────────────────────────────────────╯
|
|
27
|
+
└─► ⌖ #1 [■■□□ 2/4] Refactor auth flow ▸ Unit tests (app · auth.ts ↪)
|
|
27
28
|
```
|
|
28
29
|
|
|
29
30
|
---
|
|
30
31
|
|
|
31
|
-
##
|
|
32
|
+
## Core Value
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
- Writing a `TODO.md` inside your repo pollutes `git status` and burns prompt tokens on every turn.
|
|
35
|
-
- Normal startup banners vanish the second you send a message, so you forget what you wrote.
|
|
34
|
+
Late at night, mid-way through fixing a bug, you spot a second issue in `src/auth.ts` or need to pause a multi-step refactor until tomorrow. Standard ways of recording that note create immediate friction:
|
|
36
35
|
|
|
37
|
-
**
|
|
36
|
+
1. **Terminal Exit Wipes Working Memory**: Closing the terminal or running `/new` clears the agent's context. Yesterday's unfinished steps and the conversation history behind them vanish.
|
|
37
|
+
2. **`TODO.md` Pollutes Git & Burns Context Tokens**: Tracking personal reminders inside repository markdown files dirties `git status` and re-injects stale checklists into the system prompt on every turn.
|
|
38
|
+
3. **Splash Banners Vanish When You Start Typing**: Traditional startup widgets disappear on the first message. For the rest of a two-hour session, your notes are hidden unless you manually run a slash command.
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
- **
|
|
41
|
-
- **0ms Human
|
|
40
|
+
**Anchor acts like a physical sticky note stuck to the bottom bezel of your Pi editor**:
|
|
41
|
+
- **Persistent Below-Editor Strip (`belowEditor`)**: Docks a single-line note strip directly beneath your input box. It stays in view while you code, leaves `aboveEditor` untouched for extensions like `pi-lingual`, and collapses to 0 lines when empty.
|
|
42
|
+
- **0ms Human-First Capture (`pin: ...`)**: Type `pin: Check token expiry` (or `/pin ...`) straight into the editor. An input hook intercepts the text in `0.00ms` without calling the language model or spending tokens.
|
|
43
|
+
- **Micro Progress Bar (`[■■□□ 2/4]`)**: Write `[2/4]` or numbered steps (`1. Extract interface 2. HttpOnly cookie 3. Unit tests`) in your note to get an inline 4-cell progress bar with next-step hints.
|
|
44
|
+
- **Session Teleport (`↪ Jump to session`)**: Every note bookmarks the exact `.jsonl` session file where it was created or last touched. Select `↪ Jump to session` in `/anchor` to switch Pi straight back to that conversation.
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
- Write a ratio (`[2/4]` or `5/30`) or numbered steps (`1. Extract interface 2. HttpOnly cookie 3. Unit tests`) in your note:
|
|
45
|
-
```text
|
|
46
|
-
/pin Refactor auth flow: 1. Extract interface 2. HttpOnly cookie 3. Unit tests
|
|
47
|
-
```
|
|
48
|
-
- Anchor renders a crisp micro progress bar (`[■■□□ 2/3] ▸ Unit tests`) right on the sticky strip. Run `/step 1` (or select `▶ Advance step` in `/anchor`) to tick it forward. Simple one-off notes stay 100% bar-free.
|
|
46
|
+
---
|
|
49
47
|
|
|
50
|
-
|
|
51
|
-
- Every sticky note automatically bookmarks the Pi conversation session (`sessionFile`) where it was created or last worked on.
|
|
52
|
-
- Days later, open `/anchor` and pick **`↪ Jump to session`** (or run `/anchor jump 1`) to teleport Pi straight back into that exact conversation history.
|
|
48
|
+
## How It Works
|
|
53
49
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
| Mode / Action | What You Input | What the Engine Does | What You See | Best For |
|
|
51
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
52
|
+
| **Stick a Note (0ms)** | Type `pin: Fix auth in src/auth.ts` or `/pin ...` | Intercepts via input hook in `0ms`, extracts file paths, and links current `sessionFile` | 1-line strip appears below editor: `⌖ #1 Fix auth (app · auth.ts ↪)` | Capturing a tangent without derailing the current prompt |
|
|
53
|
+
| **Track Multi-Step Work** | Type `/pin Refactor: 1. API 2. Cookie 3. Tests` then `/step 1` | Parses step list and increments `done / total` counter in `~/.anchor/state.json` | Strip updates in place: `⌖ #1 [■■□□ 2/3] Refactor ▸ Tests` | Multi-session features and long-running study goals |
|
|
54
|
+
| **Resume Context (`↪`)** | Run `/anchor` ➔ select `↪ Jump to session` (or `/anchor jump 1`) | Invokes Pi's native `ctx.switchSession(note.sessionFile)` | Terminal switches directly back to the original conversation transcript | Picking up a complex task days later with full history |
|
|
55
|
+
| **Auto-Tear on Commit** | Commit code (`git commit -m "feat: fix auth"`) or run `/done 1` | Matches commit message against active notes (filtering generic stop-words) | Note archives to `archive.jsonl`; strip clears (`⌖ Auto-torn off #1`) | Keeping the sticky strip clean without manual bookkeeping |
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Features & Engineering Answers
|
|
60
|
+
|
|
61
|
+
### 1. Will the sticky strip collide with `pi-lingual` or overflow narrow split panes?
|
|
62
|
+
Anchor mounts its widget with `{ placement: "belowEditor" }`. Extensions that render translation cards or diagnostics above the input box (`aboveEditor`) never overlap with Anchor.
|
|
63
|
+
On narrow terminal splits (such as 50-column tmux panes), the strip measures visual column widths using Unicode East Asian Width rules (CJK/emoji = 2 cells, ASCII = 1 cell) and dynamically folds multiple notes into `⌖ 3: #1 [■■□□ 2/4] Refactor… +2` while stripping unclosed brackets before ellipses.
|
|
64
|
+
|
|
65
|
+
### 2. Does keeping sticky notes cost tokens on every turn?
|
|
66
|
+
**Turn 2+ consumes 0 system prompt tokens.**
|
|
67
|
+
Anchor injects a compact summary of active notes only on Turn 1 of a cold session. From Turn 2 onwards, the system prompt hook returns nothing. When the agent reads or edits a file that matches a note's path or glob (`src/auth/*.ts`), Anchor appends a single syntax-safe comment line (`// ⌖ Note #1: ...`) to that tool result, while returning `null` for `.json`, `.env`, lockfiles, and binaries.
|
|
68
|
+
|
|
69
|
+
### 3. What happens to old notes or accidental `git commit` matches?
|
|
70
|
+
- **7-Day Quiet Mode (Zero Silent Deletion)**: Notes untouched for more than 7 days transition to `sleeping` (`quiet`). They stop appearing in Turn-1 prompts for unrelated workspaces, remain 100% visible in `/anchor`, and wake up automatically when you open their target project.
|
|
71
|
+
- **Stop-Word Filtered Commit Matching & 1-Tap Undo**: Commit matching strips generic words (`fix`, `feat`, `chore`, `bug`, `update`) so a commit like `fix: typo in bug template` never tears off a note titled `fix bug in login`. If you ever tear off a note by mistake, `/anchor undo` pops the last entry from `archive.jsonl` right back onto your strip.
|
|
72
|
+
- **Bracketed Ratio Parsing**: Progress ratios require explicit brackets (`[2/4]` or `(5/30)`), ensuring calendar dates in note titles (like `Before 10/12 release`) are never mistaken for progress bars.
|
|
73
|
+
|
|
74
|
+
### 4. Storage Topology & Cross-Process Lock Safety
|
|
75
|
+
All state lives in `~/.anchor/` outside your git repository:
|
|
76
|
+
```text
|
|
77
|
+
~/.anchor/
|
|
78
|
+
├── state.json # Active and quiet sticky notes (< 2KB, atomic temp-file + rename)
|
|
79
|
+
├── state.lock # Cross-process exclusive lock (fs.openSync 'wx' + dead-PID reclamation)
|
|
80
|
+
└── archive.jsonl # Append-only history of torn-off notes (powers /anchor undo)
|
|
81
|
+
```
|
|
57
82
|
|
|
58
83
|
---
|
|
59
84
|
|
|
60
85
|
## Commands
|
|
61
86
|
|
|
62
|
-
| Where | Input / Command |
|
|
87
|
+
| Where | Input / Command | Description |
|
|
63
88
|
| :--- | :--- | :--- |
|
|
64
89
|
| **Pi Editor** | `pin: <note>` or `便签: <note>` | Stick a note in **0ms** without calling the LLM |
|
|
65
|
-
| **Pi Slash** | `/pin <note>` | Stick a note (supports `[1/4]` or `1. A 2. B` steps) |
|
|
66
|
-
| **Pi Slash** | `/anchor` | Open interactive board (tear off, `+1` step,
|
|
90
|
+
| **Pi Slash** | `/pin <note>` | Stick a note (supports `[1/4]` or `1. A 2. B 3. C` steps) |
|
|
91
|
+
| **Pi Slash** | `/anchor` | Open interactive sticky note board (tear off, `+1` step, `↪` jump to session, or read details) |
|
|
67
92
|
| **Pi Slash** | `/step 1` | Advance progress bar on note `#1` by `+1` |
|
|
68
93
|
| **Pi Slash** | `/anchor jump 1` | Switch Pi back to the conversation session linked to note `#1` |
|
|
69
|
-
| **Pi Slash** | `/done 1` / `/anchor
|
|
70
|
-
| **
|
|
94
|
+
| **Pi Slash** | `/done 1` / `/anchor 1` | Tear off note `#1` and archive it |
|
|
95
|
+
| **Pi Slash** | `/anchor undo` | Put back the most recently torn-off note |
|
|
96
|
+
| **Terminal CLI** | `anchor` / `anchor "<note>"` | View or stick notes from any shell outside Pi |
|
|
97
|
+
| **Terminal CLI** | `anchor step 1` / `anchor done 1` / `anchor undo` | Advance progress, tear off, or restore notes from the command line |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Author's Note
|
|
102
|
+
|
|
103
|
+
Anchor started because I hated watching `TODO.md` files rot inside my git repositories, yet closing my terminal at night always meant losing track of what I still needed to fix the next morning.
|
|
104
|
+
|
|
105
|
+
In its early versions, I over-engineered the solution. By `v0.3`, Anchor had grown into a 10-file miniature project manager with four cognitive quadrants (`Today`, `Upcoming`, `Habits`, `Backlog`), `[P0]` priority tags, daily recurring habit trackers, pre-flight shell test runners on startup, and a graveyard eviction state machine. Ironically, the more features it gained, the less I wanted to use it. Worse, its startup banner disappeared the moment I typed my first message, hiding my notes for the rest of the coding session.
|
|
106
|
+
|
|
107
|
+
In `v0.4` and `v0.5`, I threw away 60% of the codebase and rebuilt Anchor around four files (`types.ts`, `store.ts`, `tui.ts`, `extension.ts`) as a simple digital sticky note:
|
|
108
|
+
1. Dock the 1-line note strip **below** the editor (`belowEditor`) so it stays in sight while coding and never fights with `pi-lingual` above the editor.
|
|
109
|
+
2. Let human hands stick a note in `0ms` by typing `pin: ...` without waiting on a model call.
|
|
110
|
+
3. Add a 4-cell progress bar (`[■■□□ 2/4]`) for multi-step refactors and bookmark the session file (`↪`) so clicking a note teleports you back to the exact conversation where the work started.
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npm run typecheck # Strict tsc --noEmit check (0 errors)
|
|
114
|
+
npm test # Native Node test runner (10/10 passing)
|
|
115
|
+
npm run build # Dual ESM/CJS compilation via tsup + declaration emit
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Ecosystem: Pi Terminal Suite
|
|
121
|
+
|
|
122
|
+
Each extension occupies a distinct terminal slot (`aboveEditor`, `belowEditor`, `status-only` footer, and runtime tool hooks) so all four run together with zero widget overlap:
|
|
123
|
+
|
|
124
|
+
| Package | Terminal Slot & Mechanism | Install |
|
|
125
|
+
| :--- | :--- | :--- |
|
|
126
|
+
| **[`pi-lingual`](https://github.com/3ZEROS12/pi-lingual)** | `二 ⇄ two` `aboveEditor` HUD (≤9 lines, UAX #11 tree layout) & prompt-to-English transformer (0 chat history tokens) | `pi install npm:pi-lingual` |
|
|
127
|
+
| **[`toolflow`](https://github.com/3ZEROS12/toolflow)** | `⌬` Runtime tool hooks — stage-gated MCP mounting & >40-line log dehydration to disk (-95% log tokens) | `pi install npm:toolflow` |
|
|
128
|
+
| **[`pi-tui-status-beautifier`](https://github.com/3ZEROS12/pi-tui-status-beautifier)** | `status-only` footer hook — 6 badge presets, `<80`-col idle folding `(+N idle)`, 0 render-loop disk reads | `pi install npm:pi-tui-status-beautifier` |
|
|
129
|
+
| **[`pi-anchor`](https://github.com/3ZEROS12/anchor)** *(Current)* | `⌖` `belowEditor` 1-line sticky strip, 0ms `pin:` intercept, `[■■□□]` step bar & `↪` session jump | `pi install npm:pi-anchor` |
|
|
71
130
|
|
|
72
131
|
---
|
|
73
132
|
|
package/README_ja.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# ⌖ Anchor
|
|
2
|
+
|
|
3
|
+
> **Pi エディタ直下に常駐するデジタル付箋(Sticky Note)拡張機能。**
|
|
4
|
+
> `pin: ...` で **0ms 即時貼り付け**、エディタ直下(`belowEditor`)に 1 行で常駐表示(`aboveEditor` 拡張と干渉ゼロ)、長期タスク用の**ミニ進捗バー `[■■□□ 2/4]`**、**元の会話セッションへのワンタッチ復帰(`↪`)**、および **`git commit` 時の自動剥がし**に対応。
|
|
5
|
+
|
|
6
|
+
[](https://www.npmjs.com/package/pi-anchor)
|
|
7
|
+
[](https://www.npmjs.com/package/pi-anchor)
|
|
8
|
+
[](https://github.com/3ZEROS12/anchor/stargazers)
|
|
9
|
+
[](https://github.com/3ZEROS12/anchor/actions/workflows/ci.yml)
|
|
10
|
+
[-brightgreen)](tests/store.test.ts)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
|
|
13
|
+
[English](./README.md) | **日本語** | [简体中文](./README_zh.md)
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pi install npm:pi-anchor
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<img src="assets/hero-en.svg" alt="Anchor Sticky Notes" width="820">
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
╭─ Pi Editor ──────────────────────────────────────────────────────────────────────╮
|
|
25
|
+
│ ❯ pin: Refactor auth flow: 1. Extract interface 2. HttpOnly cookie 3. Unit tests │
|
|
26
|
+
╰──────────────────────────────────────────────────────────────────────────────────╯
|
|
27
|
+
⌖ #1 [■■□□ 2/4] Refactor auth flow ▸ Unit tests (app · auth.ts ↪)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## なぜ Anchor なのか?
|
|
33
|
+
|
|
34
|
+
コーディング中にふと *「この後 `src/gateway.ts` のレート制限フォールバックも確認しないと」* と思いついたときや、数日かかるタスクを夜に中断するとき:
|
|
35
|
+
- リポジトリ内に `TODO.md` を作ると `git status` が汚れ、毎ターンのプロンプトで無駄なトークンを消費します。
|
|
36
|
+
- 起動時だけのバナー表示は、最初のメッセージを送信した瞬間に消えてしまい、書いた内容を忘れてしまいます。
|
|
37
|
+
|
|
38
|
+
**Anchor は Pi の入力欄のすぐ下(`belowEditor`)に貼る本物のデジタル付箋です。** リポジトリ外の `~/.anchor/state.json` に保存され(全 4 ソースファイル・外部依存ゼロ)、人間の手になじむ 4 つの工夫を備えています:
|
|
39
|
+
|
|
40
|
+
### 1. エディタ直下に 1 行常駐(`belowEditor`)& 0ms 即時貼り付け(`pin: ...`)
|
|
41
|
+
- **ウィジェット干渉ゼロ**:付箋バーはエディタ**直下(`placement: "belowEditor"`)**に 1 行で配置されるため、エディタ上部(`aboveEditor`)を `pi-lingual` などのツールに 100% 空けておけます。
|
|
42
|
+
- **0ms ダイレクト入力**:入力欄で直接 `pin: トークン有効期限を確認`(または `note: ...`、`/pin ...`)と打つだけ。LLM 呼び出しやトークン消費なしで **0.00ms** で即座に貼り付けられ、直前に編集していたファイルが自動リンクされます。
|
|
43
|
+
|
|
44
|
+
### 2. 長期タスク用のミニ進捗バー(`[■■□□ 2/4]`)
|
|
45
|
+
- メモの中に比率(`[2/4]` や `5/30`)または番号付きステップ(`1. Extract interface 2. HttpOnly cookie 3. Unit tests`)を書くだけ:
|
|
46
|
+
```text
|
|
47
|
+
/pin Refactor auth flow: 1. Extract interface 2. HttpOnly cookie 3. Unit tests
|
|
48
|
+
```
|
|
49
|
+
- 付箋バーにミニ進捗バーと次のステップ(`[■■□□ 2/3] ▸ Unit tests`)が表示されます。`/step 1`(または `/anchor` メニューの `▶ Advance step`)で 1 ステップ進みます。単発のメモには進捗バーは表示されません。
|
|
50
|
+
|
|
51
|
+
### 3. 会話セッションのブックマーク(`↪ Jump to session`)
|
|
52
|
+
- 各付箋は、作成時や関連ファイル編集時の Pi 会話セッション(`sessionFile`)を自動的にブックマークします。
|
|
53
|
+
- 数日後に別ウィンドウから作業を再開したいときも、`/anchor` を開いて **`↪ Jump to session`** を選ぶ(または `/anchor jump 1` を実行する)だけで、当時の会話履歴そのものに直接復帰できます。
|
|
54
|
+
|
|
55
|
+
### 4. ファイル接触時の 1 行メモ注入 & `git commit` 自動剥がし
|
|
56
|
+
- **ファイル接触時の 1 行メモ(待機時 0 トークン)**:Turn 1 で一度だけ AI に概要を伝え、Turn 2 以降は **0 トークン**。AI が関連ファイルを読み書きした際、結果の末尾に構文安全な 1 行コメント(`// ⌖ Note #1: ...`)を添えます(`.json` や `.env` は厳格にスキップ)。
|
|
57
|
+
- **コミットで自動剥がし**:`git commit -m "..."` のメッセージが付箋内容と一致すると、自動的に付箋を剥がしてアーカイブします(`⌖ Auto-torn off #1`)。誤って剥がした場合は `/anchor undo` でいつでも戻せます。
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## コマンド一覧
|
|
62
|
+
|
|
63
|
+
| 場所 | 入力 / コマンド | 動作 |
|
|
64
|
+
| :--- | :--- | :--- |
|
|
65
|
+
| **Pi エディタ** | `pin: <メモ>` または `note: <メモ>` | LLM を呼ばずに **0ms** で付箋を貼り付け |
|
|
66
|
+
| **スラッシュコマンド** | `/pin <メモ>` | 新しい付箋を貼る(`[1/4]` や `1. A 2. B` で進捗バー自動生成) |
|
|
67
|
+
| **スラッシュコマンド** | `/anchor` | 対話ボードを開く(剥がす、進捗 `+1`、`↪` セッション復帰) |
|
|
68
|
+
| **スラッシュコマンド** | `/step 1` | 付箋 `#1` の進捗バーを `+1` 進める |
|
|
69
|
+
| **スラッシュコマンド** | `/anchor jump 1` | 付箋 `#1` に紐づく元の会話セッションへ切り替え |
|
|
70
|
+
| **スラッシュコマンド** | `/done 1` / `/anchor undo` | 付箋 `#1` を剥がす / 直前に剥がした付箋を貼り直す |
|
|
71
|
+
| **ターミナル CLI** | `anchor` / `anchor step 1` / `anchor done 1` | Pi の外から付箋の一覧確認・進捗更新・完了を実行 |
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Ecosystem: Pi Terminal Suite
|
|
76
|
+
|
|
77
|
+
4 つの拡張機能はそれぞれ異なるターミナルスロット(`aboveEditor`、`belowEditor`、`status-only` フッター、実行時ツールフック)にマウントされるため、単体でも全種併用でも UI が干渉しません:
|
|
78
|
+
|
|
79
|
+
| パッケージ | ターミナル配置スロットと機構 | インストール |
|
|
80
|
+
| :--- | :--- | :--- |
|
|
81
|
+
| **[`pi-lingual`](https://github.com/3ZEROS12/pi-lingual)** | `二 ⇄ two` `aboveEditor` 二言語 HUD(最大 9 行・UAX #11 ツリーレイアウト)&英語プロンプト変換(履歴トークン消費 0) | `pi install npm:pi-lingual` |
|
|
82
|
+
| **[`toolflow`](https://github.com/3ZEROS12/toolflow)** | `⌬` 実行時ツールフック —— フェーズ別 MCP マウント&40 行超のログ自動ディスク退避(ログトークン 95% 削減) | `pi install npm:toolflow` |
|
|
83
|
+
| **[`pi-tui-status-beautifier`](https://github.com/3ZEROS12/pi-tui-status-beautifier)** | `status-only` フッターフック —— 6 種のバッジプリセット、`<80` 列での待機バッジ折りたたみ `(+N idle)`、描画ループ内ディスク I/O ゼロ | `pi install npm:pi-tui-status-beautifier` |
|
|
84
|
+
| **[`pi-anchor`](https://github.com/3ZEROS12/anchor)** *(現在)* | `⌖` `belowEditor` 1 行常駐付箋バー、0ms `pin:` インターセプト、ミニ進捗バー `[■■□□]` & `↪` セッション復帰 | `pi install npm:pi-anchor` |
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## ライセンス
|
|
89
|
+
|
|
90
|
+
MIT © [Jason Song](https://github.com/3ZEROS12)
|
package/README_zh.md
CHANGED
|
@@ -1,71 +1,135 @@
|
|
|
1
1
|
# ⌖ Anchor
|
|
2
2
|
|
|
3
|
-
> **贴在 Pi 输入框正下方的电子便签 ——
|
|
4
|
-
> 敲 `便签: ...` 0ms 瞬贴上屏,在输入框**正下方 (`belowEditor`)** 常驻 1 行极简便签条(与上方 `pi-lingual` 零冲突),支持长线任务**迷你进度条 `[■■□□ 2/4]`**、**一键穿越回当时的对话上下文 (`↪`)**,以及 **`git commit` 自动撕便签**。
|
|
3
|
+
> **贴在 Pi 输入框正下方的电子便签 —— `便签: ...` 0ms 瞬贴上屏、长线任务迷你进度条 `[■■□□ 2/4]`、一键切回原对话上下文 (`↪`),`git commit` 提交代码自动撕便签。**
|
|
5
4
|
|
|
5
|
+
[](https://www.npmjs.com/package/pi-anchor)
|
|
6
|
+
[](https://www.npmjs.com/package/pi-anchor)
|
|
7
|
+
[](https://github.com/3ZEROS12/anchor/stargazers)
|
|
6
8
|
[](https://github.com/3ZEROS12/anchor/actions/workflows/ci.yml)
|
|
7
|
-
[](package.json)
|
|
8
|
-
[](tsconfig.json)
|
|
9
9
|
[](tests/store.test.ts)
|
|
10
10
|
[](LICENSE)
|
|
11
11
|
|
|
12
|
-
[English](./README.md) | **简体中文**
|
|
12
|
+
[English](./README.md) | [日本語](./README_ja.md) | **简体中文**
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
15
|
pi install npm:pi-anchor
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
<p align="center">
|
|
19
|
-
<img src="assets/hero-zh.svg" alt="Anchor
|
|
19
|
+
<img src="assets/hero-zh.svg" alt="Anchor 输入框下方常驻便签条预览" width="820">
|
|
20
20
|
</p>
|
|
21
21
|
|
|
22
22
|
```text
|
|
23
|
-
|
|
23
|
+
┌─ [输入框上方 aboveEditor 完全留给 pi-lingual 等插件,上下零冲突] ─────────────┐
|
|
24
|
+
╭─┴─ Pi 输入框 ────────────────────────────────────────────────────────────────────╮
|
|
24
25
|
│ ❯ 便签: 重构登录鉴权流: 1. 抽出接口 2. 替换Cookie 3. 补单测 4. 压测 │
|
|
25
|
-
|
|
26
|
-
⌖ #1 [■■□□ 2/4] 重构登录鉴权流 ▸ 补单测 (app · auth.ts ↪)
|
|
26
|
+
╰─┬────────────────────────────────────────────────────────────────────────────────╯
|
|
27
|
+
└─► ⌖ #1 [■■□□ 2/4] 重构登录鉴权流 ▸ 补单测 (app · auth.ts ↪)
|
|
27
28
|
```
|
|
28
29
|
|
|
29
30
|
---
|
|
30
31
|
|
|
31
|
-
##
|
|
32
|
+
## Core Value
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
* **绝不跟上方插件抢地盘**:便签条挂载在输入框**正下方 (`belowEditor`)**,把输入框上方 (`aboveEditor`) 完全留给 `pi-lingual` 等高频伴学卡片,上下分工井然有序。
|
|
35
|
-
* **真·便签常驻视野**:有便签时在输入框下沿安静显示 1 行,不再像以前那样“刚发第一句话就神秘消失”;无便签时 0 行完全隐形。
|
|
36
|
-
* **自己随手写,0ms 上屏**:直接在输入框敲 `便签: 明天检查网关重试`(或 `pin: ...`、`/pin ...`),**0.00ms 当场拦截贴上便签条**,不用苦等大模型转圈调工具,不花 1 个 Token,还会自动关联你当前正在改的代码文件。
|
|
34
|
+
深夜写代码查问题时,你经常顺眼看到另一个文件里的隐患,或者手头的长线重构今天只做了一半。传统的记录方式总有三处具体的别扭:
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
便签: 重构登录鉴权流: 1. 抽出接口 2. 替换Cookie 3. 补单测
|
|
42
|
-
```
|
|
43
|
-
* 便签条会自动渲染出 4 格迷你进度条与下一步提示:`[■■□□ 2/3] ▸ 补单测`。敲 `/step 1`(或在 `/anchor` 菜单里点 `▶ Advance step`)即可推进一格;普通单句备忘则保持纯粹文字,绝不画蛇添足。
|
|
36
|
+
1. **关掉终端或开新会话即失忆**:按下 `Ctrl+C` 或敲 `/new` 开启新会话,昨晚改到哪一步、当时那场对话聊了什么上下文,瞬间断线。
|
|
37
|
+
2. **`TODO.md` 弄脏 Git 且每轮白烧 Token**:在项目根目录维护待办文件,既制造杂乱的 Git 修改记录,又在每一轮对话里反复把旧清单塞进系统提示词。
|
|
38
|
+
3. **开局闪现横幅一打字就消失**:普通插件只在打开终端时闪一下提示,你发完第一句话它就自我隐藏。接下来两个小时写代码,除非专门敲命令查询,否则根本看不见自己记了什么。
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
**Anchor 的定位很单纯:贴在 Pi 输入框下边框的一张电子便签**:
|
|
41
|
+
- **输入框正下方常驻 1 行 (`belowEditor`)**:便签条固定在输入框下沿,写代码时抬眼可见;输入框上方空间完全留给 `pi-lingual` 等插件;没有便签时自动收起为 0 行。
|
|
42
|
+
- **自己随手敲,0ms 瞬贴 (`便签: ...`)**:直接在输入框敲 `便签: 检查网关超时重试`(或 `pin: ...`、`/pin ...`),输入钩子在 `0.00ms` 内直接拦截上屏,不调用大模型、不耗费 1 个 Token,并自动关联当前刚修改过的代码文件。
|
|
43
|
+
- **长线任务迷你进度条 (`[■■□□ 2/4]`)**:在便签里写 `[2/4]` 或分步序号 `1. 抽出接口 2. 替换Cookie 3. 补单测`,便签条自动显示 4 格进度条与下一步提示。
|
|
44
|
+
- **原对话一键穿越 (`↪ Jump to session`)**:每张便签自动记录创建或施工时的会话文件路径(`sessionFile`)。在 `/anchor` 面板中点击 `↪ Jump to session`,直接切回当时那场对话。
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## How It Works
|
|
49
|
+
|
|
50
|
+
| 操作场景 | 你的输入 | 后台执行逻辑 | 界面即时反馈 | 适用时刻 |
|
|
51
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
52
|
+
| **0ms 随手贴便签** | 输入框敲 `便签: 把 src/auth.ts 改用 Cookie` | `input` 钩子 0ms 拦截,提取文件路径并记录当前 `sessionFile` | 输入框下方立即浮现:`⌖ #1 把 src/auth.ts 改用 Cookie (app · auth.ts ↪)` | 改代码中途冒出支线念头,不想打断当前对话 |
|
|
53
|
+
| **分步推进长任务** | 敲 `/pin 重构: 1. 接口 2. Cookie 3. 单测` 后敲 `/step 1` | 解析分步列表并在 `~/.anchor/state.json` 推进完成步数 | 下方便签条实时变为:`⌖ #1 [■■□□ 2/3] 重构 ▸ 单测` | 跨天重构、分步排障或刷课程章节 |
|
|
54
|
+
| **切回原对话 (`↪`)** | 敲 `/anchor` 选中便签点 `↪ Jump to session`(或 `/anchor jump 1`) | 调用 Pi 原生 `ctx.switchSession(note.sessionFile)` | 终端直接切回贴这张便签时的完整历史对话上下文 | 隔了几天回来继续施工,需要找回当时的讨论细节 |
|
|
55
|
+
| **提交代码自动撕** | 执行 `git commit -m "feat: 登录改用 Cookie"` 或敲 `/done 1` | 过滤通用停用词后比对提交信息与便签关键词 | 便签自动归档至 `archive.jsonl`,下方便签条同步消失 | 写完代码顺手提交,免去手动打勾销账 |
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Features & Engineering Answers
|
|
60
|
+
|
|
61
|
+
### 1. 下方常驻便签条会和 `pi-lingual` 冲突,或者在窄分屏下撑爆换行吗?
|
|
62
|
+
Anchor 显式指定 `{ placement: "belowEditor" }` 挂载在输入框下方,与挂载在输入框上方(`aboveEditor`)的 `pi-lingual` 物理隔离,上下各司其职。
|
|
63
|
+
面对 50 列宽度的窄分屏终端,排版函数按 Unicode 东亚字符宽度标准(中文/Emoji 计 2 列,ASCII 计 1 列)动态计算剩余预算:窄屏下自动折叠为 `⌖ 3: #1 [■■□□ 2/4] 重构登录… +2`,并在省略号截断前自动清理未闭合的左括号。
|
|
64
|
+
|
|
65
|
+
### 2. 便签常驻显示,会不会每一轮对话都偷偷消耗上下文 Token?
|
|
66
|
+
**第 2 轮起系统提示词消耗为 0 Token。**
|
|
67
|
+
界面上的便签条是纯本地终端 TUI 渲染组件。仅在会话第 1 轮冷启动时,Anchor 向系统提示词注入一次简短摘要;从第 2 轮起完全静默。只有当 AI 读取或编辑了便签关联的代码文件时,Anchor 才在该文件工具返回结果末尾追加 1 行对应语言的注释(`// ⌖ Note #1: ...`),遇到 `.json`、`.env`、锁文件与二进制文件则严格返回 `null` 跳过。
|
|
68
|
+
|
|
69
|
+
### 3. 很久没碰的旧便签会丢吗?普通的 `git commit -m "fix bug"` 会不会误撕便签?
|
|
70
|
+
- **7 天转静默,永不自动删数据**:超过 7 天未触碰的便签自动标记为 `quiet`(不在无关工程的首轮提示词里刷存在感),但在 `/anchor` 列表中始终保留,一旦进入对应工程目录即自动唤醒。
|
|
71
|
+
- **停用词过滤与一键反悔**:Git 提交匹配会自动剔除 `fix`、`feat`、`bug`、`修复`、`优化` 等高频泛化词,杜绝无关提交误删便签。万一手动撕错了,敲 `/anchor undo` 即可从 `archive.jsonl` 原样贴回。
|
|
72
|
+
- **进度比防误判守卫**:比例进度条严格要求带括号(如 `[2/4]` 或 `(5/30)`),日常写 `10/12 前发布接口` 等日期数字绝不会被误判为进度条。
|
|
73
|
+
|
|
74
|
+
### 4. 全局存储拓扑与多窗口并发锁
|
|
75
|
+
所有便签数据独立存放在用户主目录 `~/.anchor/`,项目仓库保持 100% 干净:
|
|
76
|
+
```text
|
|
77
|
+
~/.anchor/
|
|
78
|
+
├── state.json # 当前便签状态表 (< 2KB,临时文件写入 + 原子 rename)
|
|
79
|
+
├── state.lock # 跨进程排他文件锁 (fs.openSync 'wx' + 死进程 PID 自动回收)
|
|
80
|
+
└── archive.jsonl # 已撕下便签的追加式历史记录 (支撑 /anchor undo 秒级恢复)
|
|
81
|
+
```
|
|
52
82
|
|
|
53
83
|
---
|
|
54
84
|
|
|
55
|
-
##
|
|
85
|
+
## Commands
|
|
86
|
+
|
|
87
|
+
| 位置 | 输入 / 命令 | 作用说明 |
|
|
88
|
+
| :--- | :--- | :--- |
|
|
89
|
+
| **Pi 输入框直敲** | `便签: <内容>` 或 `pin: <内容>` | **0ms 直接贴便签**(不触发大模型请求,自动绑定当前改过的文件与 Session) |
|
|
90
|
+
| **Pi 斜杠命令** | `/pin <内容>` | 贴一张新便签(支持写 `[1/4]` 或 `1. A 2. B 3. C` 自动生成进度条) |
|
|
91
|
+
| **Pi 斜杠命令** | `/anchor` | 打开交互面板(回车可撕便签、推进度 `+1`、`↪` 切回原对话 Session、看详情) |
|
|
92
|
+
| **Pi 斜杠命令** | `/step 1` | 将 `#1` 便签的进度条往前推进 `+1` 步 |
|
|
93
|
+
| **Pi 斜杠命令** | `/anchor jump 1` | 直接切换回 `#1` 便签绑定的那场历史对话 (`switchSession`) |
|
|
94
|
+
| **Pi 斜杠命令** | `/done 1` / `/anchor 1` | 按编号 `#1` 直接撕下便签并归档 |
|
|
95
|
+
| **Pi 斜杠命令** | `/anchor undo` | 把刚刚撕下的便签重新贴回原位 |
|
|
96
|
+
| **系统命令行** | `anchor` / `anchor "<内容>"` | 不进 Pi 也能在外部终端查看或贴便签 |
|
|
97
|
+
| **系统命令行** | `anchor step 1` / `anchor done 1` / `anchor undo` | 在外部终端推进进度、撕便签或撤销 |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Author's Note
|
|
102
|
+
|
|
103
|
+
做 Anchor 的初衷很简单:我讨厌项目仓库里的 `TODO.md` 弄脏 Git 提交历史,但每天深夜关掉终端时,又需要有个地方随手记一句“明天接着改哪儿”。
|
|
104
|
+
|
|
105
|
+
早期版本里,我犯了典型的过度设计病。到 `v0.3` 时,Anchor 膨胀成了 10 个源码文件的小型任务管理系统:塞进了四象限分类(`Today`、`Upcoming`、`Habits`、`Backlog`)、`[P0]` 优先级标签、每日习惯打卡、启动时同步阻塞跑测试脚本,甚至还有一套自动把过期任务移入坟场的淘汰机制。结果功能越堆越多,我自己反而越用越别扭——尤其荒诞的是,开局弹出的便签提示在我发出第一句话后就自动隐藏了,真正写代码的几个小时里根本看不见它。
|
|
106
|
+
|
|
107
|
+
在 `v0.4` 和 `v0.5` 中,我删掉了 60% 的代码,只留 4 个核心文件(`types.ts`、`store.ts`、`tui.ts`、`extension.ts`),让它老老实实回归一张贴在输入框下沿的电子便签:
|
|
108
|
+
1. 用 `belowEditor` 把单行便签条固定在输入框正下方,写代码时一眼能瞥见,同时把输入框上方的位置让给 `pi-lingual`。
|
|
109
|
+
2. 便签本来就是给人自己随手写的,敲一句 `便签: ...` 在 0ms 内直接上屏,不必等大模型转圈。
|
|
110
|
+
3. 针对跨天的大活,顺手加上 4 格迷你进度条(`[■■□□ 2/4]`)和原对话书签(`↪`),点一下就能切回当时的对话上下文接着干。
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npm run typecheck # TypeScript 严格类型检查 (0 错误)
|
|
114
|
+
npm test # 原生 Node 测试运行器 (10/10 全绿通过)
|
|
115
|
+
npm run build # tsup 双格式打包与类型声明生成
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 配套生态套件 (Pi Terminal Suite)
|
|
121
|
+
|
|
122
|
+
四款扩展分别挂载于终端的不同物理槽位(`aboveEditor`、`belowEditor`、`status-only` 底栏与运行时工具钩子),独立运行或组合安装均不产生小部件重叠:
|
|
56
123
|
|
|
57
|
-
|
|
|
124
|
+
| 插件仓库 | 终端挂载槽位与核心机制 | 一键安装 |
|
|
58
125
|
| :--- | :--- | :--- |
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
| **斜杠命令** | `/anchor jump 1` | 直接切换回 `#1` 便签绑定的那次历史对话 (`switchSession`) |
|
|
64
|
-
| **斜杠命令** | `/done 1` / `/anchor undo` | 撕掉 `#1` 便签,或把刚撕掉的便签重新贴回来 |
|
|
65
|
-
| **终端 CLI** | `anchor` / `anchor step 1` / `anchor done 1` | 不进 Pi 也能在外部终端查看、推进度或撕便签 |
|
|
126
|
+
| **[`pi-lingual`](https://github.com/3ZEROS12/pi-lingual)** | `二 ⇄ two` `aboveEditor` 双语伴学视窗(≤9 行 UAX #11 树状排版)与母语提示词转写(0 会话历史 Token 注入) | `pi install npm:pi-lingual` |
|
|
127
|
+
| **[`toolflow`](https://github.com/3ZEROS12/toolflow)** | `⌬` 运行时工具钩子 —— 按阶段动态挂载重型 MCP,>40 行终端长日志自动落盘脱水(削减 95% 日志 Token) | `pi install npm:toolflow` |
|
|
128
|
+
| **[`pi-tui-status-beautifier`](https://github.com/3ZEROS12/pi-tui-status-beautifier)** | `status-only` 底栏微钩子 —— 6 套徽章预设、`<80` 列窄屏折叠 `(+N idle)`、重绘循环 0 磁盘读取 | `pi install npm:pi-tui-status-beautifier` |
|
|
129
|
+
| **[`pi-anchor`](https://github.com/3ZEROS12/anchor)** *(当前)* | `⌖` `belowEditor` 1 行常驻便签条、0ms `pin:` 输入拦截、迷你进度条 `[■■□□]` 与原会话跳转 `↪` | `pi install npm:pi-anchor` |
|
|
66
130
|
|
|
67
131
|
---
|
|
68
132
|
|
|
69
|
-
##
|
|
133
|
+
## License
|
|
70
134
|
|
|
71
135
|
MIT © [Jason Song](https://github.com/3ZEROS12)
|
package/bin/anchor.js
CHANGED
|
@@ -30,8 +30,8 @@ if (args.length === 0 || args[0] === 'list' || args[0] === 'ls') {
|
|
|
30
30
|
const sorted = sortAnchorsForDisplay(allNotes, process.cwd());
|
|
31
31
|
console.log(`\n⌖ Notes (${sorted.length}):\n`);
|
|
32
32
|
|
|
33
|
-
sorted.forEach((a
|
|
34
|
-
const num =
|
|
33
|
+
sorted.forEach((a) => {
|
|
34
|
+
const num = a.id.replace(/^anc-/, '').padStart(2, '0');
|
|
35
35
|
const bar = a.progress ? `${formatProgressBar(a.progress)} ` : '';
|
|
36
36
|
const origin = formatOrigin(a) + (a.sessionFile ? ' ↪' : '');
|
|
37
37
|
const age = a.status === 'sleeping'
|
|
@@ -66,13 +66,13 @@ if (args[0] === 'step' || args[0] === '+') {
|
|
|
66
66
|
const idInput = args[1] || '1';
|
|
67
67
|
const delta = args[2] ? parseInt(args[2], 10) : 1;
|
|
68
68
|
try {
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
69
|
+
const direct = store.get(idInput);
|
|
70
|
+
let targetId = direct ? direct.id : idInput;
|
|
71
|
+
if (!direct && /^\d+$/.test(idInput)) {
|
|
72
|
+
const allNotes = store
|
|
73
|
+
.list({ cwd: process.cwd(), all: true })
|
|
74
|
+
.filter(a => a.status === 'active' || a.status === 'sleeping');
|
|
75
|
+
const sorted = sortAnchorsForDisplay(allNotes, process.cwd());
|
|
76
76
|
const seqIndex = parseInt(idInput, 10);
|
|
77
77
|
if (seqIndex >= 1 && seqIndex <= sorted.length) {
|
|
78
78
|
targetId = sorted[seqIndex - 1].id;
|
|
@@ -111,13 +111,13 @@ if (args[0] === 'done' || args[0] === 'rm' || args[0] === 'close') {
|
|
|
111
111
|
process.exit(1);
|
|
112
112
|
}
|
|
113
113
|
try {
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
114
|
+
const direct = store.get(idInput);
|
|
115
|
+
let targetId = direct ? direct.id : idInput;
|
|
116
|
+
if (!direct && /^\d+$/.test(idInput)) {
|
|
117
|
+
const allNotes = store
|
|
118
|
+
.list({ cwd: process.cwd(), all: true })
|
|
119
|
+
.filter(a => a.status === 'active' || a.status === 'sleeping');
|
|
120
|
+
const sorted = sortAnchorsForDisplay(allNotes, process.cwd());
|
|
121
121
|
const seqIndex = parseInt(idInput, 10);
|
|
122
122
|
if (seqIndex >= 1 && seqIndex <= sorted.length) {
|
|
123
123
|
targetId = sorted[seqIndex - 1].id;
|