pi-anchor 0.4.0 → 0.5.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 CHANGED
@@ -1,12 +1,12 @@
1
1
  # ⌖ Anchor
2
2
 
3
- > **A digital sticky note for Pi Coding Agent — with three clever touches.**
4
- > Stick a quick note across sessions (`/pin`), get a 1-line comment whisper when the AI touches that file, and watch the note tear itself off when you `git commit`. Zero `TODO.md` clutter in your repo.
3
+ > **A digital sticky note docked below your Pi editor — with four clever touches.**
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`.
5
5
 
6
6
  [![CI Status](https://github.com/3ZEROS12/anchor/actions/workflows/ci.yml/badge.svg)](https://github.com/3ZEROS12/anchor/actions/workflows/ci.yml)
7
7
  [![Node v20+](https://img.shields.io/badge/Node-v20+-22c55e.svg)](package.json)
8
8
  [![TypeScript Strict](https://img.shields.io/badge/TypeScript-Strict-3b82f6.svg)](tsconfig.json)
9
- [![Tests: 9 Passed](https://img.shields.io/badge/Tests-9%20Passed-22c55e.svg)](tests/store.test.ts)
9
+ [![Tests: 10 Passed](https://img.shields.io/badge/Tests-10%20Passed-22c55e.svg)](tests/store.test.ts)
10
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-f97316.svg)](LICENSE)
11
11
 
12
12
  **English** | [简体中文](./README_zh.md)
@@ -20,53 +20,54 @@ pi install npm:pi-anchor
20
20
  </p>
21
21
 
22
22
  ```text
23
- ⌖ Notes (3):
24
-
25
- 01 Switch session token to HttpOnly cookie app · auth.ts 25m ago
26
- 02 Double-check rate limit fallback on timeout app · gateway.ts 3h ago
27
- 03 Read external architecture notes first College/优化 · notes.md 8d ago · quiet
28
-
29
- Run `anchor done <num>` to tear off, or `anchor undo` to put back.
23
+ ╭─ Pi Editor ──────────────────────────────────────────────────────────────────────╮
24
+ │ ❯ 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 ↪)
30
27
  ```
31
28
 
32
29
  ---
33
30
 
34
- ## Why a Sticky Note Instead of `TODO.md`?
31
+ ## Why Anchor?
35
32
 
36
- When you're deep in a coding session at 11 PM and realize *"I still need to fix the token expiry in `src/auth.ts` tomorrow"*, you don't want a heavy task manager:
37
- - Putting a `TODO.md` inside your repo pollutes `git status` and forces the AI to re-read stale checklists on every single turn.
38
- - Closing the terminal wipes the agent's working memory clean.
33
+ When you're deep in a coding session and think *"Wait — I need to check the rate-limit fallback in `src/gateway.ts` after this"*, or when you pause a multi-day task for the night:
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.
39
36
 
40
- **Anchor is just a physical sticky note stuck to the bezel of your terminal** — stored outside your repo in `~/.anchor/state.json` (<10 KB, zero external dependencies, 4 source files), with three small, thoughtful touches:
37
+ **Anchor is a real sticky note stuck right under your Pi input box (`belowEditor`)** — stored outside your repo in `~/.anchor/state.json` (4 source files, 0 dependencies), designed for **human hands first**:
41
38
 
42
- ### 1. Stick It & Forget It (Smart Path Spotting)
43
- Write a note in plain language:
44
- ```text
45
- /pin Switch session token to HttpOnly cookie in src/auth.ts
46
- ```
47
- Anchor spots `src/auth.ts` (or any project path like `D:/College/...`) directly from your sentence — no forms or tags to fill out. Next time you open Pi in that project, a quiet card sits above your editor (`⌖ 1 note`) and disappears the moment you start typing.
39
+ ### 1. Docked Below Your Editor & 0ms Instant Stick (`pin: ...`)
40
+ - **Zero Widget Collision**: Anchor docks its 1-line strip **below** your editor (`placement: "belowEditor"`), leaving the space above your editor (`aboveEditor`) 100% free for tools like `pi-lingual`.
41
+ - **0ms Human Input**: Type `pin: Check token expiry` (or `note: ...`, `便签: ...`, `/pin ...`) directly in the editor. Anchor intercepts it in **0.00ms** without triggering an LLM call or burning tokens, and automatically links the file you were just editing.
48
42
 
49
- ### 2. A Gentle Whisper When Touching the File (0 Idle Tokens)
50
- Anchor briefs the AI once on Turn 1 of a session, then drops to **0 tokens** from Turn 2 onwards.
51
- When the AI reads or edits `src/auth.ts`, Anchor slips a single syntax-safe comment onto the end of that file read (`// ⌖ Note #1: Switch session token to HttpOnly cookie`), while strictly skipping `.json`, `.env`, and lockfiles.
43
+ ### 2. Micro Progress Bar for Long Tasks (`[■■□□ 2/4]`)
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.
52
49
 
53
- *(Notes untouched for more than 7 days automatically enter `quiet` mode so they don't spend Turn-1 tokens in unrelated workspaces, while staying 100% visible in `/anchor` and waking up as soon as you open their project.)*
50
+ ### 3. Conversation Session Bookmark (`↪ Jump to session`)
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.
54
53
 
55
- ### 3. Auto-Tears Off on `git commit`
56
- When you or the AI commits the fix (`git commit -m "feat: switch session token to HttpOnly cookie"`), Anchor matches the commit message against your sticky notes and tears the note off in real time (`⌖ Auto-torn off #1`).
57
- Tore one off by mistake? Run `/anchor undo` to stick it right back.
54
+ ### 4. File Whisper & Auto-Tear on `git commit`
55
+ - **1-Line File Whisper (0 Idle Tokens)**: Briefs the AI once on Turn 1, then consumes **0 tokens** on Turn 2+. When the AI reads or edits a matching file, Anchor slips a 1-line comment (`// ⌖ Note #1: ...`) onto that file result (strictly skipping `.json` and `.env`).
56
+ - **Auto-Tear on Commit**: When `git commit -m "..."` matches your note, Anchor tears the note off automatically (`⌖ Auto-torn off #1`). Run `/anchor undo` anytime to put it back.
58
57
 
59
58
  ---
60
59
 
61
60
  ## Commands
62
61
 
63
- | Where | Command | What It Does |
62
+ | Where | Input / Command | What It Does |
64
63
  | :--- | :--- | :--- |
65
- | **Inside Pi** | `/pin <note>` | Stick a new note (or just tell the AI *"Remember to..."*) |
66
- | **Inside Pi** | `/anchor` | Open the interactive sticky note list (press Enter to tear off or read) |
67
- | **Inside Pi** | `/done 1` | Tear off note `#01` directly |
68
- | **Inside Pi** | `/anchor undo` | Put back the last torn-off note |
69
- | **Terminal CLI** | `anchor` / `anchor "<note>"` / `anchor done 1` | Manage the exact same sticky notes outside Pi |
64
+ | **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, or `↪` jump to session) |
67
+ | **Pi Slash** | `/step 1` | Advance progress bar on note `#1` by `+1` |
68
+ | **Pi Slash** | `/anchor jump 1` | Switch Pi back to the conversation session linked to note `#1` |
69
+ | **Pi Slash** | `/done 1` / `/anchor undo` | Tear off note `#1`, or put back the last torn-off note |
70
+ | **Terminal CLI** | `anchor` / `anchor step 1` / `anchor done 1` | View, step, or tear off notes outside Pi |
70
71
 
71
72
  ---
72
73
 
package/README_zh.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # ⌖ Anchor
2
2
 
3
- > **贴在 Pi 终端边框上的电子便签 —— 带一点刚刚好的小巧思。**
4
- > 随手贴一张跨会话备忘(`/pin`),AI 读改关联文件时顺手递上一行注释提醒,`git commit` 提交代码时自动撕掉便签。不在代码仓库里留任何 `TODO.md` 垃圾。
3
+ > **贴在 Pi 输入框正下方的电子便签 —— 专为顺手盲打与跨会话续传设计。**
4
+ > 敲 `便签: ...` 0ms 瞬贴上屏,在输入框**正下方 (`belowEditor`)** 常驻 1 行极简便签条(与上方 `pi-lingual` 零冲突),支持长线任务**迷你进度条 `[■■□□ 2/4]`**、**一键穿越回当时的对话上下文 (`↪`)**,以及 **`git commit` 自动撕便签**。
5
5
 
6
6
  [![CI 状态](https://github.com/3ZEROS12/anchor/actions/workflows/ci.yml/badge.svg)](https://github.com/3ZEROS12/anchor/actions/workflows/ci.yml)
7
7
  [![Node v20+](https://img.shields.io/badge/Node-v20+-22c55e.svg)](package.json)
8
8
  [![TypeScript Strict](https://img.shields.io/badge/TypeScript-Strict-3b82f6.svg)](tsconfig.json)
9
- [![Tests: 9 Passed](https://img.shields.io/badge/Tests-9%20通过-22c55e.svg)](tests/store.test.ts)
9
+ [![Tests: 10 Passed](https://img.shields.io/badge/Tests-10%20通过-22c55e.svg)](tests/store.test.ts)
10
10
  [![开源协议: MIT](https://img.shields.io/badge/开源协议-MIT-f97316.svg)](LICENSE)
11
11
 
12
12
  [English](./README.md) | **简体中文**
@@ -20,53 +20,49 @@ pi install npm:pi-anchor
20
20
  </p>
21
21
 
22
22
  ```text
23
- ⌖ Notes (3):
24
-
25
- 01 把登录 Token 改用 HttpOnly Cookie 存储 app · auth.ts 25m ago
26
- 02 检查网关超时后的降级重试边界 app · gateway.ts 3h ago
27
- 03 College 重构前置查阅外部架构参考库 College/优化 · notes.md 8d ago · quiet
28
-
29
- Run `anchor done <num>` to tear off, or `anchor undo` to put back.
23
+ ╭─ Pi 输入框 ──────────────────────────────────────────────────────────────────────╮
24
+ │ ❯ 便签: 重构登录鉴权流: 1. 抽出接口 2. 替换Cookie 3. 补单测 4. 压测 │
25
+ ╰──────────────────────────────────────────────────────────────────────────────────╯
26
+ ⌖ #1 [■■□□ 2/4] 重构登录鉴权流 ▸ 补单测 (app · auth.ts ↪)
30
27
  ```
31
28
 
32
29
  ---
33
30
 
34
- ## 为什么是一张电子便签,而不是 `TODO.md`?
35
-
36
- 深夜写代码准备关机时,你突然想到 *“明天得把 `src/auth.ts` 里的 Token 改成 Cookie”*。这时候你不需要一套沉重的项目管理系统:
37
- - 往仓库里塞 `TODO.md` 会弄脏 `git status`,而且每一轮对话都在白白消耗上下文 Token;
38
- - 直接关掉终端,AI 的内存记忆瞬间清空。
31
+ ## 为什么这次真正顺手了?(四大巧思)
39
32
 
40
- **Anchor 就是贴在终端显示器边框上的一张电子便签** —— 独立保存在全局 `~/.anchor/state.json`(全工程仅 4 个核心源码文件、0 外部依赖、20KB 体积),只做三件有小巧思的事:
41
-
42
- ### 1. 随手一贴,自动认路(无需填表打标签)
43
- 直接用大白话敲一句:
44
- ```text
45
- /pin 把 src/auth.ts 的登录改用 HttpOnly Cookie
46
- ```
47
- Anchor 会自动从这句话里认出文件名 `src/auth.ts`(或诸如 `D:/College/...` 的目录路径),自动绑定到对应工程。下次打开终端时,输入框上方安静浮现小便签(`⌖ 1 note`),你一开始打字它就自动收起,绝不挡视线。
33
+ ### 1. 输入框正下方常驻 1 行便签条 (`belowEditor`) + 0ms 瞬贴
34
+ * **绝不跟上方插件抢地盘**:便签条挂载在输入框**正下方 (`belowEditor`)**,把输入框上方 (`aboveEditor`) 完全留给 `pi-lingual` 等高频伴学卡片,上下分工井然有序。
35
+ * **真·便签常驻视野**:有便签时在输入框下沿安静显示 1 行,不再像以前那样“刚发第一句话就神秘消失”;无便签时 0 行完全隐形。
36
+ * **自己随手写,0ms 上屏**:直接在输入框敲 `便签: 明天检查网关重试`(或 `pin: ...`、`/pin ...`),**0.00ms 当场拦截贴上便签条**,不用苦等大模型转圈调工具,不花 1 个 Token,还会自动关联你当前正在改的代码文件。
48
37
 
49
- ### 2. 碰文件时顺手递纸条(平时 0 Token)
50
- 会话第 1 轮冷启动时向 AI 交代一眼当前便签,从第 2 轮起 **0 Token 损耗**。
51
- 只有当 AI 真正读取或修改 `src/auth.ts` 时,Anchor 才会在文件内容末尾顺手附上 1 行合法注释(`// ⌖ Note #1: 把 src/auth.ts 的登录改用 HttpOnly Cookie`),遇到 `.json`、`.env` 等文件则严格跳过。
38
+ ### 2. 长线任务迷你进度条 (`[■■□□ 2/4]`)
39
+ * 遇到跨天或分步任务,随手在便签里写上进度比(如 `[5/30]`)或分步序号(`1. 抽出接口 2. 替换Cookie 3. 补单测`):
40
+ ```text
41
+ 便签: 重构登录鉴权流: 1. 抽出接口 2. 替换Cookie 3. 补单测
42
+ ```
43
+ * 便签条会自动渲染出 4 格迷你进度条与下一步提示:`[■■□□ 2/3] ▸ 补单测`。敲 `/step 1`(或在 `/anchor` 菜单里点 `▶ Advance step`)即可推进一格;普通单句备忘则保持纯粹文字,绝不画蛇添足。
52
44
 
53
- *(超过 7 天没动过的旧便签会自动加上 `· quiet` 静默省流标记,不在无关工程首轮刷存在感,但在 `/anchor` 列表里永远都在,绝不莫名消失;一旦你进入对应工程目录就会自动唤醒。)*
45
+ ### 3. 绑定原对话 Session,一键穿越回去 (`↪ Jump to session`)
46
+ * 贴便签或修改关联代码时,Anchor 会自动记录当前对话的 `sessionFile` 书签(显示 `↪` 标记)。
47
+ * 哪怕过了好几天、开了十几个新窗口,当你看到便签想接着干时,打开 `/anchor` 选中它点击 **`↪ Jump to session`**(或敲 `/anchor jump 1`),Pi 就会**直接切换回当时那场对话的完整上下文**!
54
48
 
55
- ### 3. 提交代码自动撕便签(支持一键反悔)
56
- 当你或 AI 执行 `git commit -m "feat: 登录改用 HttpOnly Cookie"` 时,Anchor 发现提交说明与便签吻合,当场自动帮你把这张便签撕掉归档(`⌖ Auto-torn off #1`)。
57
- 撕错了?敲一下 `/anchor undo` 就能原封不动贴回来。
49
+ ### 4. 碰文件顺手递纸条 & `git commit` 自动撕便签
50
+ * **碰文件递纸条(平时 0 Token)**:首轮对话简要提醒,第 2 轮起 **0 Token**;当 AI 读取或修改关联文件时,在文件结果末尾顺手附带 1 行语法安全注释(`// ⌖ Note #1: ...`,严格跳过 `.json`/`.env`)。
51
+ * **提交代码自动撕下**:执行 `git commit -m "..."` 命中便签内容时,当场自动撕下归档;撕错了敲 `/anchor undo` 一秒贴回。
58
52
 
59
53
  ---
60
54
 
61
- ## 常用命令
55
+ ## 常用操作速查
62
56
 
63
- | 场景 | 命令 | 作用 |
57
+ | 位置 | 输入 / 命令 | 作用 |
64
58
  | :--- | :--- | :--- |
65
- | **Pi 终端内** | `/pin <内容>` | 随手贴一张新便签(也可以直接对 AI 说 *“记一下明天…”*) |
66
- | **Pi 终端内** | `/anchor` | 打开便签列表,回车即可撕掉(Done)或查看详情 |
67
- | **Pi 终端内** | `/done 1` | 直接按编号撕掉第 1 张便签 |
68
- | **Pi 终端内** | `/anchor undo` | 把刚撕掉的便签重新贴回来 |
69
- | **系统命令行** | `anchor` / `anchor "<内容>"` / `anchor done 1` | 不开 Pi 也能随时在终端查看或贴便签 |
59
+ | **输入框直接敲** | `便签: <内容>` 或 `pin: <内容>` | **0ms 直接贴便签**(不触发大模型请求,自动绑定当前改过的文件与 Session) |
60
+ | **斜杠命令** | `/pin <内容>` | 贴一张新便签(支持写 `[2/5]` 或 `1. A 2. B` 自动生成进度条) |
61
+ | **斜杠命令** | `/anchor` | 打开交互面板(支持撕便签、推进度 `+1`、`↪` 穿越回原对话 Session) |
62
+ | **斜杠命令** | `/step 1` | 将 `#1` 便签的进度条往前推进 `+1` 步 |
63
+ | **斜杠命令** | `/anchor jump 1` | 直接切换回 `#1` 便签绑定的那次历史对话 (`switchSession`) |
64
+ | **斜杠命令** | `/done 1` / `/anchor undo` | 撕掉 `#1` 便签,或把刚撕掉的便签重新贴回来 |
65
+ | **终端 CLI** | `anchor` / `anchor step 1` / `anchor done 1` | 不进 Pi 也能在外部终端查看、推进度或撕便签 |
70
66
 
71
67
  ---
72
68
 
@@ -1,4 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 390" width="840" height="390">
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 410" width="840" height="410">
2
2
  <defs>
3
3
  <filter id="shadow" x="-5%" y="-5%" width="110%" height="115%" filterUnits="userSpaceOnUse">
4
4
  <feDropShadow dx="0" dy="12" stdDeviation="16" flood-color="#000000" flood-opacity="0.45" />
@@ -10,62 +10,79 @@
10
10
  </defs>
11
11
 
12
12
  <g filter="url(#shadow)">
13
- <rect x="20" y="15" width="800" height="350" rx="12" fill="#1e2326" stroke="#343f44" stroke-width="1.2" />
13
+ <rect x="20" y="15" width="800" height="370" rx="12" fill="#1e2326" stroke="#343f44" stroke-width="1.2" />
14
14
  <path d="M 20,27 A 12,12 0 0,1 32,15 L 808,15 A 12,12 0 0,1 820,27 L 820,52 L 20,52 Z" fill="url(#headerGrad)" stroke="#343f44" stroke-width="1" />
15
15
  <line x1="20" y1="52" x2="820" y2="52" stroke="#2d353b" stroke-width="1" />
16
16
  <circle cx="42" cy="33.5" r="5.5" fill="#e67e80" />
17
17
  <circle cx="60" cy="33.5" r="5.5" fill="#dbbc7f" />
18
18
  <circle cx="78" cy="33.5" r="5.5" fill="#a7c080" />
19
19
  <text x="420" y="38" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" font-size="12" font-weight="500" fill="#859289">
20
- ⌖ anchor · A Digital Sticky Note for Your Terminal
20
+ ⌖ anchor (v0.5.0) · Below-Editor Sticky Strip · Progress Bar · Session Teleport
21
21
  </text>
22
22
  </g>
23
23
 
24
24
  <g font-family="'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace" font-size="13" xml:space="preserve">
25
- <text x="45" y="86">
26
- <tspan fill="#a7c080" font-weight="bold">~/Workspace/app</tspan>
27
- <tspan fill="#7fbbb3"> ❯ </tspan>
28
- <tspan fill="#d3c6aa" font-weight="bold">anchor</tspan>
29
- </text>
30
-
31
- <text x="45" y="120">
25
+ <text x="45" y="84">
32
26
  <tspan fill="#7fbbb3" font-weight="bold">⌖ Notes (3):</tspan>
33
27
  </text>
34
28
 
35
- <text x="45" y="154">
29
+ <text x="45" y="116">
36
30
  <tspan fill="#859289"> 01 </tspan>
37
- <tspan fill="#d3c6aa">Switch session token to HttpOnly cookie </tspan>
38
- <tspan fill="#7fbbb3">app · auth.ts </tspan>
31
+ <tspan fill="#a7c080" font-weight="bold">[■■□□ 2/4] </tspan>
32
+ <tspan fill="#d3c6aa">Refactor auth flow </tspan>
33
+ <tspan fill="#7fbbb3">app · auth.ts ↪ </tspan>
39
34
  <tspan fill="#7a8478">25m ago</tspan>
40
35
  </text>
41
36
 
42
- <text x="45" y="182">
37
+ <text x="45" y="144">
43
38
  <tspan fill="#859289"> 02 </tspan>
44
- <tspan fill="#d3c6aa">Double-check rate limit fallback on timeout </tspan>
45
- <tspan fill="#7fbbb3">app · gateway.ts </tspan>
39
+ <tspan fill="#d3c6aa">Double-check rate limit fallback on timeout </tspan>
40
+ <tspan fill="#7fbbb3">app · gateway.ts ↪ </tspan>
46
41
  <tspan fill="#7a8478">3h ago</tspan>
47
42
  </text>
48
43
 
49
- <text x="45" y="210">
44
+ <text x="45" y="172">
50
45
  <tspan fill="#859289"> 03 </tspan>
51
- <tspan fill="#859289">Read external architecture notes first </tspan>
46
+ <tspan fill="#859289">Read external architecture notes first </tspan>
52
47
  <tspan fill="#7a8478">College/优化 · notes.md </tspan>
53
48
  <tspan fill="#56635f">8d ago · quiet</tspan>
54
49
  </text>
55
50
 
56
- <rect x="45" y="242" width="750" height="58" rx="6" fill="#232a2e" stroke="#3a464c" stroke-width="1" />
57
- <text x="62" y="266" fill="#dbbc7f">1. Stick a note: /pin Switch session token to HttpOnly cookie in src/auth.ts</text>
58
- <text x="62" y="287" fill="#a7c080">2. Auto-tear off: git commit -m "feat: switch session token to HttpOnly cookie" ➔ ⌖ Torn off #1</text>
51
+ <!-- Simulated Pi Input Box + Below-Editor Persistent Sticky Strip -->
52
+ <rect x="45" y="204" width="750" height="44" rx="6" fill="#232a2e" stroke="#4f5b58" stroke-width="1.2" />
53
+ <text x="62" y="231">
54
+ <tspan fill="#a7c080" font-weight="bold">❯ </tspan>
55
+ <tspan fill="#d3c6aa">pin: Refactor auth flow: 1. Extract interface 2. HttpOnly cookie 3. Unit tests</tspan>
56
+ </text>
57
+
58
+ <!-- Below-Editor Sticky Strip -->
59
+ <rect x="45" y="256" width="750" height="36" rx="6" fill="#292b28" stroke="#a7c080" stroke-width="1" stroke-dasharray="4,3" />
60
+ <text x="62" y="279">
61
+ <tspan fill="#a7c080" font-weight="bold">⌖ </tspan>
62
+ <tspan fill="#859289">#1 </tspan>
63
+ <tspan fill="#dbbc7f" font-weight="bold">[■■□□ 2/4] </tspan>
64
+ <tspan fill="#d3c6aa">Refactor auth flow </tspan>
65
+ <tspan fill="#7fbbb3">▸ HttpOnly cookie </tspan>
66
+ <tspan fill="#859289">(app · auth.ts ↪)</tspan>
67
+ </text>
59
68
 
60
- <text x="45" y="334" fill="#7a8478">
61
- <tspan> Commands: </tspan>
62
- <tspan fill="#7fbbb3" font-weight="bold">`/pin &lt;note&gt;`</tspan>
63
- <tspan> · </tspan>
64
- <tspan fill="#7fbbb3" font-weight="bold">`/anchor`</tspan>
65
- <tspan> · </tspan>
66
- <tspan fill="#7fbbb3" font-weight="bold">`/done 1`</tspan>
67
- <tspan> · </tspan>
68
- <tspan fill="#7fbbb3" font-weight="bold">`/anchor undo`</tspan>
69
+ <text x="45" y="324" fill="#859289">
70
+ <tspan> • </tspan>
71
+ <tspan fill="#d3c6aa" font-weight="bold">0ms Instant Stick</tspan>
72
+ <tspan>: Type </tspan>
73
+ <tspan fill="#7fbbb3">`pin: &lt;note&gt;`</tspan>
74
+ <tspan> (or </tspan>
75
+ <tspan fill="#7fbbb3">`/pin`</tspan>
76
+ <tspan>) — docked below editor, never collides with aboveEditor HUDs.</tspan>
77
+ </text>
78
+ <text x="45" y="348" fill="#859289">
79
+ <tspan> • </tspan>
80
+ <tspan fill="#d3c6aa" font-weight="bold">Session Teleport (↪)</tspan>
81
+ <tspan>: Select any note in </tspan>
82
+ <tspan fill="#7fbbb3">`/anchor`</tspan>
83
+ <tspan> or run </tspan>
84
+ <tspan fill="#7fbbb3">`/anchor jump 1`</tspan>
85
+ <tspan> to resume its conversation.</tspan>
69
86
  </text>
70
87
  </g>
71
88
  </svg>
@@ -1,4 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 390" width="840" height="390">
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 410" width="840" height="410">
2
2
  <defs>
3
3
  <filter id="shadow" x="-5%" y="-5%" width="110%" height="115%" filterUnits="userSpaceOnUse">
4
4
  <feDropShadow dx="0" dy="12" stdDeviation="16" flood-color="#000000" flood-opacity="0.45" />
@@ -10,62 +10,79 @@
10
10
  </defs>
11
11
 
12
12
  <g filter="url(#shadow)">
13
- <rect x="20" y="15" width="800" height="350" rx="12" fill="#1e2326" stroke="#343f44" stroke-width="1.2" />
13
+ <rect x="20" y="15" width="800" height="370" rx="12" fill="#1e2326" stroke="#343f44" stroke-width="1.2" />
14
14
  <path d="M 20,27 A 12,12 0 0,1 32,15 L 808,15 A 12,12 0 0,1 820,27 L 820,52 L 20,52 Z" fill="url(#headerGrad)" stroke="#343f44" stroke-width="1" />
15
15
  <line x1="20" y1="52" x2="820" y2="52" stroke="#2d353b" stroke-width="1" />
16
16
  <circle cx="42" cy="33.5" r="5.5" fill="#e67e80" />
17
17
  <circle cx="60" cy="33.5" r="5.5" fill="#dbbc7f" />
18
18
  <circle cx="78" cy="33.5" r="5.5" fill="#a7c080" />
19
19
  <text x="420" y="38" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" font-size="12" font-weight="500" fill="#859289">
20
- ⌖ anchor · 贴在终端边框上的电子便签
20
+ ⌖ anchor (v0.5.0) · 输入框下方常驻便签条 · 迷你进度条 · 原对话一键穿越
21
21
  </text>
22
22
  </g>
23
23
 
24
24
  <g font-family="'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace" font-size="13" xml:space="preserve">
25
- <text x="45" y="86">
26
- <tspan fill="#a7c080" font-weight="bold">~/Workspace/app</tspan>
27
- <tspan fill="#7fbbb3"> ❯ </tspan>
28
- <tspan fill="#d3c6aa" font-weight="bold">anchor</tspan>
29
- </text>
30
-
31
- <text x="45" y="120">
25
+ <text x="45" y="84">
32
26
  <tspan fill="#7fbbb3" font-weight="bold">⌖ Notes (3):</tspan>
33
27
  </text>
34
28
 
35
- <text x="45" y="154">
29
+ <text x="45" y="116">
36
30
  <tspan fill="#859289"> 01 </tspan>
37
- <tspan fill="#d3c6aa">把登录 Token 改用 HttpOnly Cookie 存储 </tspan>
38
- <tspan fill="#7fbbb3">app · auth.ts </tspan>
31
+ <tspan fill="#a7c080" font-weight="bold">[■■□□ 2/4] </tspan>
32
+ <tspan fill="#d3c6aa">重构登录鉴权流 </tspan>
33
+ <tspan fill="#7fbbb3">app · auth.ts ↪ </tspan>
39
34
  <tspan fill="#7a8478">25m ago</tspan>
40
35
  </text>
41
36
 
42
- <text x="45" y="182">
37
+ <text x="45" y="144">
43
38
  <tspan fill="#859289"> 02 </tspan>
44
39
  <tspan fill="#d3c6aa">检查网关超时后的降级重试边界 </tspan>
45
- <tspan fill="#7fbbb3">app · gateway.ts </tspan>
40
+ <tspan fill="#7fbbb3">app · gateway.ts ↪ </tspan>
46
41
  <tspan fill="#7a8478">3h ago</tspan>
47
42
  </text>
48
43
 
49
- <text x="45" y="210">
44
+ <text x="45" y="172">
50
45
  <tspan fill="#859289"> 03 </tspan>
51
46
  <tspan fill="#859289">College 重构前置查阅外部架构参考库 </tspan>
52
47
  <tspan fill="#7a8478">College/优化 · notes.md </tspan>
53
48
  <tspan fill="#56635f">8d ago · quiet</tspan>
54
49
  </text>
55
50
 
56
- <rect x="45" y="242" width="750" height="58" rx="6" fill="#232a2e" stroke="#3a464c" stroke-width="1" />
57
- <text x="62" y="266" fill="#dbbc7f">1. 随手贴一张: /pin 把 src/auth.ts 的登录改用 HttpOnly Cookie</text>
58
- <text x="62" y="287" fill="#a7c080">2. 提交自动撕: git commit -m "feat: 登录改用 HttpOnly Cookie" ➔ ⌖ Torn off #1</text>
51
+ <!-- Simulated Pi Input Box + Below-Editor Persistent Sticky Strip -->
52
+ <rect x="45" y="204" width="750" height="44" rx="6" fill="#232a2e" stroke="#4f5b58" stroke-width="1.2" />
53
+ <text x="62" y="231">
54
+ <tspan fill="#a7c080" font-weight="bold">❯ </tspan>
55
+ <tspan fill="#d3c6aa">便签: 重构登录鉴权流: 1. 抽出接口 2. 替换Cookie 3. 补单测 4. 压测</tspan>
56
+ </text>
57
+
58
+ <!-- Below-Editor Sticky Strip -->
59
+ <rect x="45" y="256" width="750" height="36" rx="6" fill="#292b28" stroke="#a7c080" stroke-width="1" stroke-dasharray="4,3" />
60
+ <text x="62" y="279">
61
+ <tspan fill="#a7c080" font-weight="bold">⌖ </tspan>
62
+ <tspan fill="#859289">#1 </tspan>
63
+ <tspan fill="#dbbc7f" font-weight="bold">[■■□□ 2/4] </tspan>
64
+ <tspan fill="#d3c6aa">重构登录鉴权流 </tspan>
65
+ <tspan fill="#7fbbb3">▸ 补单测 </tspan>
66
+ <tspan fill="#859289">(app · auth.ts ↪)</tspan>
67
+ </text>
59
68
 
60
- <text x="45" y="334" fill="#7a8478">
61
- <tspan> 常用命令: </tspan>
62
- <tspan fill="#7fbbb3" font-weight="bold">`/pin &lt;便签&gt;`</tspan>
63
- <tspan> · </tspan>
64
- <tspan fill="#7fbbb3" font-weight="bold">`/anchor`</tspan>
65
- <tspan> · </tspan>
66
- <tspan fill="#7fbbb3" font-weight="bold">`/done 1`</tspan>
67
- <tspan> · </tspan>
68
- <tspan fill="#7fbbb3" font-weight="bold">`/anchor undo`</tspan>
69
+ <text x="45" y="324" fill="#859289">
70
+ <tspan> • </tspan>
71
+ <tspan fill="#d3c6aa" font-weight="bold">输入框下方常驻 1 行便签条</tspan>
72
+ <tspan>:采用 </tspan>
73
+ <tspan fill="#7fbbb3">belowEditor</tspan>
74
+ <tspan> 挂载,与上方 </tspan>
75
+ <tspan fill="#7fbbb3">pi-lingual</tspan>
76
+ <tspan> 零冲突;敲 </tspan>
77
+ <tspan fill="#7fbbb3">便签: ...</tspan>
78
+ <tspan> 0ms 瞬贴。</tspan>
79
+ </text>
80
+ <text x="45" y="348" fill="#859289">
81
+ <tspan> • </tspan>
82
+ <tspan fill="#d3c6aa" font-weight="bold">原对话一键穿越 (↪)</tspan>
83
+ <tspan>:自动记录贴便签时的 Session,在 </tspan>
84
+ <tspan fill="#7fbbb3">/anchor</tspan>
85
+ <tspan> 中点击即可直接切回当时的对话上下文。</tspan>
69
86
  </text>
70
87
  </g>
71
88
  </svg>
package/bin/anchor.js CHANGED
@@ -7,6 +7,7 @@
7
7
  import {
8
8
  AnchorStore,
9
9
  formatOrigin,
10
+ formatProgressBar,
10
11
  formatRelativeAge,
11
12
  sortAnchorsForDisplay,
12
13
  padToWidth
@@ -31,19 +32,20 @@ if (args.length === 0 || args[0] === 'list' || args[0] === 'ls') {
31
32
 
32
33
  sorted.forEach((a, idx) => {
33
34
  const num = String(idx + 1).padStart(2, '0');
34
- const origin = formatOrigin(a);
35
+ const bar = a.progress ? `${formatProgressBar(a.progress)} ` : '';
36
+ const origin = formatOrigin(a) + (a.sessionFile ? ' ↪' : '');
35
37
  const age = a.status === 'sleeping'
36
38
  ? `${formatRelativeAge(a.createdAt)} · quiet`
37
39
  : formatRelativeAge(a.createdAt);
38
40
 
39
41
  const colNum = ` ${num} `;
40
- const colTitle = padToWidth(a.title, 42);
42
+ const colTitle = padToWidth(`${bar}${a.title}`, 42);
41
43
  const colOrigin = padToWidth(origin, 22);
42
44
 
43
45
  console.log(`${colNum}${colTitle} ${colOrigin} ${age}`);
44
46
  });
45
47
 
46
- console.log('\n Run `anchor done <num>` to tear off, or `anchor undo` to put back.\n');
48
+ console.log('\n Run `anchor step <num>` (+1 step), `anchor done <num>` (tear off), or `anchor undo`.\n');
47
49
  process.exit(0);
48
50
  }
49
51
 
@@ -59,21 +61,49 @@ if (args[0] === 'undo') {
59
61
  process.exit(0);
60
62
  }
61
63
 
62
- // 3. Help: `anchor --help`
64
+ // 3. Advance progress bar: `anchor step <num>`
65
+ if (args[0] === 'step' || args[0] === '+') {
66
+ const idInput = args[1] || '1';
67
+ const delta = args[2] ? parseInt(args[2], 10) : 1;
68
+ try {
69
+ const allNotes = store
70
+ .list({ cwd: process.cwd(), all: true })
71
+ .filter(a => a.status === 'active' || a.status === 'sleeping');
72
+ const sorted = sortAnchorsForDisplay(allNotes, process.cwd());
73
+
74
+ let targetId = idInput;
75
+ if (/^\d+$/.test(idInput)) {
76
+ const seqIndex = parseInt(idInput, 10);
77
+ if (seqIndex >= 1 && seqIndex <= sorted.length) {
78
+ targetId = sorted[seqIndex - 1].id;
79
+ }
80
+ }
81
+
82
+ const { anchor: updated } = store.step(targetId, isNaN(delta) ? 1 : delta);
83
+ console.log(`⌖ Advanced #${updated.id.replace(/^anc-/, '')} to ${formatProgressBar(updated.progress)}: "${updated.title}"`);
84
+ } catch (err) {
85
+ console.error(`Error: ${err.message}`);
86
+ process.exit(1);
87
+ }
88
+ process.exit(0);
89
+ }
90
+
91
+ // 4. Help: `anchor --help`
63
92
  if (args[0] === '--help' || args[0] === '-h' || args[0] === 'help') {
64
93
  console.log(`
65
94
  ⌖ Anchor — Digital sticky notes for AI coding sessions
66
95
 
67
96
  Usage:
68
97
  anchor View all sticky notes
69
- anchor "<note>" Stick a new note
98
+ anchor "<note>" Stick a new note (supports [1/4] or 1. A 2. B progress steps)
99
+ anchor step <num> Advance progress bar on a note (e.g. anchor step 1)
70
100
  anchor done <num> Tear off a completed note (e.g. anchor done 1)
71
101
  anchor undo Put back the last torn-off note
72
102
  `);
73
103
  process.exit(0);
74
104
  }
75
105
 
76
- // 4. Tear off note: `anchor done <num>`
106
+ // 5. Tear off note: `anchor done <num>`
77
107
  if (args[0] === 'done' || args[0] === 'rm' || args[0] === 'close') {
78
108
  const idInput = args[1];
79
109
  if (!idInput) {
@@ -103,7 +133,7 @@ if (args[0] === 'done' || args[0] === 'rm' || args[0] === 'close') {
103
133
  process.exit(0);
104
134
  }
105
135
 
106
- // 5. Stick a new note: `anchor <note text>`
136
+ // 6. Stick a new note: `anchor <note text>`
107
137
  const title = args.join(' ').trim();
108
138
  if (!title) {
109
139
  console.error('Error: Note text cannot be empty');
@@ -114,4 +144,5 @@ const created = store.create({
114
144
  title,
115
145
  cwd: process.cwd()
116
146
  });
117
- console.log(`⌖ Pinned #${created.id.replace(/^anc-/, '')}: "${created.title}"`);
147
+ const bar = created.progress ? ` ${formatProgressBar(created.progress)}` : '';
148
+ console.log(`⌖ Pinned #${created.id.replace(/^anc-/, '')}${bar}: "${created.title}"`);