@vs4vijay/piverse 0.1.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.
@@ -0,0 +1,229 @@
1
+ ---
2
+ name: pi-extension
3
+ description: Scaffold a new Pi coding-agent extension in the piverse monorepo following the established project structure, naming, and code conventions. Use when adding a new extension (a `pi-<name>` package under `extensions/`), creating its src/index.ts entry, README, and package.json, or when asked to "add another extension", "onboard a new extension", or "create a pi extension".
4
+ ---
5
+
6
+ # Creating a Pi extension in piverse
7
+
8
+ This skill encodes the conventions used by the existing extensions in this repo
9
+ (`pi-queue`, `pi-notes`). Follow them exactly so new extensions are consistent,
10
+ publishable to npm, and discoverable on the [pi.dev gallery](https://pi.dev/packages).
11
+
12
+ Read `extensions/pi-queue/` and `extensions/pi-notes/` as living references before
13
+ and while you scaffold.
14
+
15
+ ---
16
+
17
+ ## 1. Project structure & naming
18
+
19
+ Each extension is its own npm package inside the monorepo root:
20
+
21
+ ```
22
+ extensions/
23
+ ├── pi-queue/ # /queue — message queueing
24
+ ├── pi-notes/ # /notes — project notes (CLI + TUI)
25
+ └── pi-<name>/ # <-- NEW extension lives here
26
+ ├── src/
27
+ │ └── index.ts # required extension entry point
28
+ ├── README.md # required
29
+ ├── package.json # required
30
+ └── plan.md # optional (planning notes; tracked like others)
31
+ ```
32
+
33
+ ### Naming rules
34
+
35
+ - Folder: `extensions/pi-<name>/` — always the `pi-` prefix, lowercase, hyphenated.
36
+ - npm name: `@vs4vijay/pi-<name>` — **always the `@vs4vijay` scope**.
37
+ - Default export registers one or more `/` slash commands. Pick clear, short command
38
+ names. If the extension has several related commands, prefix them (e.g. `pi-queue`
39
+ registers `/queue-*` and `/q-*` aliases).
40
+ - `keywords` must include `"pi-package"` for pi.dev gallery discovery.
41
+
42
+ ### tsconfig conventions (repo root, no per-extension change needed)
43
+
44
+ `strict: true`, `module: ESNext`, `moduleResolution: bundler`, `noEmit: true`,
45
+ `verbatimModuleSyntax: true`, `isolatedModules: true`. The root tsconfig includes
46
+ `extensions/*/src/**/*.ts`.
47
+
48
+ ---
49
+
50
+ ## 2. package.json template
51
+
52
+ Copy this shape exactly (values change per extension). Match the existing files'
53
+ field ordering for consistency:
54
+
55
+ ```json
56
+ {
57
+ "name": "@vs4vijay/pi-<name>",
58
+ "version": "0.1.0",
59
+ "description": "<one-line: what the /<command> does>",
60
+ "type": "module",
61
+ "keywords": ["pi-package"],
62
+ "license": "MIT",
63
+ "repository": {
64
+ "type": "git",
65
+ "url": "git+https://github.com/vs4vijay/piverse.git"
66
+ },
67
+ "author": "vs4vijay",
68
+ "homepage": "https://github.com/vs4vijay/piverse",
69
+ "bugs": {
70
+ "url": "https://github.com/vs4vijay/piverse/issues"
71
+ },
72
+ "pi": {
73
+ "extensions": ["./src/index.ts"]
74
+ },
75
+ "scripts": {
76
+ "typecheck": "tsc --noEmit"
77
+ },
78
+ "peerDependencies": {
79
+ "@earendil-works/pi-coding-agent": "*",
80
+ "@earendil-works/pi-tui": "*",
81
+ "typebox": "*"
82
+ },
83
+ "devDependencies": {
84
+ "typescript": "^5.0.0"
85
+ }
86
+ }
87
+ ```
88
+
89
+ - The `pi` manifest tells Pi where the resources live: `"extensions": ["./src/index.ts"]`.
90
+ - `peerDependencies` **must** use `"*"` ranges for the bundled Pi core packages
91
+ (`@earendil-works/pi-coding-agent`, `@earendil-works/pi-tui`, `typebox`) — Pi provides
92
+ them at runtime; do not bundle them.
93
+ - If the extension only ships as part of the parent `@vs4vijay/piverse` package, list
94
+ the same resource path in the root `package.json` `pi.extensions` array. Each
95
+ extension normally also ships standalone via its own package (the repo's
96
+ `.github/workflows/release.yml` publishes every `extensions/*/` sub-package).
97
+
98
+ ---
99
+
100
+ ## 3. src/index.ts — extension entry point
101
+
102
+ Use the `ExtensionAPI` type and a default export. This is the canonical structure
103
+ (see `extensions/pi-queue/src/index.ts` and `extensions/pi-notes/src/index.ts`):
104
+
105
+ ```ts
106
+ import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
107
+
108
+ export default async function (pi: ExtensionAPI) {
109
+ // Register /<command>
110
+ pi.registerCommand("<command>", {
111
+ description: "<one line: what it does and how to use it>",
112
+ handler: async (args: string, ctx: ExtensionCommandContext) => {
113
+ // args: the raw string after the command name
114
+ // ctx.ui.notify(message, level) — levels: "info" | "warning" | "error"
115
+ ctx.ui.notify(`Hello: ${args}`, "info");
116
+ },
117
+ });
118
+ }
119
+ ```
120
+
121
+ ### Key rules
122
+
123
+ - **`import type` for types**: with `verbatimModuleSyntax`, use `import type` when
124
+ importing only types (e.g. `ExtensionAPI`, `ExtensionCommandContext`).
125
+ - **`.js` extensions on relative imports**: ESM/NodeNext-style — `from "./store.js"`,
126
+ not `"./store"`.
127
+ - **No build step**: Pi loads TypeScript extensions directly (via jiti). No compile.
128
+ - **State in closure scope**: keep per-extension state as module/closure variables
129
+ inside the default export (see `pi-queue`'s `let queue`).
130
+
131
+ ### Lifecycle hooks
132
+
133
+ Use `pi.on("<event>", handler)` for session lifecycle (see both extensions):
134
+
135
+ ```ts
136
+ pi.on("session_start", async (_event, ctx) => { /* reset/load state */ });
137
+ pi.on("session_shutdown", async () => { /* flush/persist */ });
138
+ pi.on("agent_settled", async (_event, ctx) => { /* run after each turn */ });
139
+ pi.on("tool_result", async (event) => { /* observe tool outcomes */ });
140
+ ```
141
+
142
+ When you need state to survive across turns, persist it — either to a file (see the
143
+ store pattern) or to the session (`pi.appendEntry(type, data)` and read it back in
144
+ `session_start` via `ctx.sessionManager.getEntries()` — see `pi-queue`).
145
+
146
+ ---
147
+
148
+ ## 4. Persistence store pattern (file-backed)
149
+
150
+ For persisted data, create a small `src/store.ts` following `pi-notes/src/store.ts`:
151
+
152
+ - A `class` that wraps read/write, with `load()`, `save()`, `getAll()`, `getById()`,
153
+ `create()`, `update()`, `delete()`, and any domain methods.
154
+ - **Atomic writes**: write to a temp path then `fs.rename` (never write in place).
155
+ - A module-level singleton (`getNoteStore`) with a `reset` function so a fresh
156
+ instance is created per session.
157
+ - **Lifecycle ordering matters**: on `session_start`, `reset()` the store **first**,
158
+ then `getStore(cwd)` and `await store.load()`, so the same loaded instance is used
159
+ all session and the `session_shutdown` flush writes real data (not an emptied one).
160
+
161
+ ---
162
+
163
+ ## 5. CLI UX
164
+
165
+ - Use `ctx.ui.notify(message, level)` for all user feedback (`info | warning | error`).
166
+ - Use `ctx.ui.confirm(title, message)` for destructive actions that need confirmation.
167
+ - Use `ctx.ui.editor(title, initial)` to open the external editor for multi-line content.
168
+ - Validate input and return early with a usage/error message:
169
+ `ctx.ui.notify("Usage: /<command> <arg>", "error")`.
170
+ - For slash-command dispatch helpers, see `pi-queue/src/index.ts`.
171
+
172
+ ---
173
+
174
+ ## 6. TUI (optional)
175
+
176
+ For interactive full-screen UI, follow `pi-notes/src/tui.ts`:
177
+
178
+ - Build a component class implementing `Focusable` using primitives from
179
+ `@earendil-works/pi-tui` (`VStack`, `HStack`, `Box`, `Text`, `ScrollView`,
180
+ `Markdown`, `SelectList`).
181
+ - Export a factory function (e.g. `create<Name>TUI`) returning `Component & Focusable`.
182
+ - Show it from the extension via `ctx.ui.custom(fn, { overlay: true, overlayOptions })`.
183
+ Note: `OverlayOptions` supports `width`/`maxHeight` (percentages), **not** `height`.
184
+ - Keep a module-level `tuiHandle` you can call to programmatically close/reopen it.
185
+ - Keep TUI state in the component; persist via the store.
186
+
187
+ ---
188
+
189
+ ## 7. README.md
190
+
191
+ Include, in this order (match `pi-queue/README.md` and `pi-notes/README.md`):
192
+
193
+ 1. `# @vs4vijay/pi-<name>` heading
194
+ 2. One-paragraph description
195
+ 3. **Install** — `pi install npm:@vs4vijay/pi-<name>`
196
+ 4. **Commands** table (command → description)
197
+ 5. **Usage / Examples** — transcript-style examples with realistic output
198
+ 6. Any additional sections (How it works, Features, Persistence, TUI, etc.)
199
+
200
+ ---
201
+
202
+ ## 8. Verification
203
+
204
+ Before finishing:
205
+
206
+ 1. Run the typecheck from the repo root and confirm it passes:
207
+ ```bash
208
+ npm run typecheck
209
+ ```
210
+ 2. Quick-test without installing:
211
+ ```bash
212
+ pi -e ./extensions/pi-<name>/src/index.ts
213
+ ```
214
+ 3. Confirm the `package.json` has all required fields (name scope, `pi-package`
215
+ keyword, `pi` manifest, repository, license, peerDependencies with `"*"`).
216
+ 4. Add the new extension under `extensions/` and, if it should ship with the parent
217
+ ecosystem package, register it in the root `package.json` `pi.extensions`.
218
+
219
+ ---
220
+
221
+ ## Checklist
222
+
223
+ - [ ] Folder named `extensions/pi-<name>/`
224
+ - [ ] npm name `@vs4vijay/pi-<name>`
225
+ - [ ] `src/index.ts` with default `export default function(pi)` and `registerCommand`
226
+ - [ ] `package.json` with `pi-package` keyword, `pi` manifest, repository/license, peerDeps `"*"`
227
+ - [ ] `README.md` with install + commands + usage examples
228
+ - [ ] `npm run typecheck` passes
229
+ - [ ] Tested with `pi -e`
@@ -0,0 +1,18 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+
7
+ jobs:
8
+ validate:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+
13
+ - uses: actions/setup-node@v4
14
+ with:
15
+ node-version: 20
16
+
17
+ - name: Typecheck
18
+ run: npx tsc --noEmit
@@ -0,0 +1,106 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ version:
10
+ description: "Release version (e.g., v1.0.0)"
11
+ required: true
12
+ type: string
13
+
14
+ permissions:
15
+ contents: write
16
+ id-token: write
17
+
18
+ jobs:
19
+ validate:
20
+ name: Validate
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ with:
25
+ fetch-depth: 0
26
+
27
+ - uses: actions/setup-node@v4
28
+ with:
29
+ node-version: 20
30
+
31
+ - name: Validate version consistency
32
+ run: |
33
+ if [[ "${{ github.ref }}" == refs/tags/* ]]; then
34
+ TAG_VERSION=${GITHUB_REF#refs/tags/v}
35
+ PKG_VERSION=$(node -p "require('./package.json').version")
36
+ if [[ "$TAG_VERSION" != "$PKG_VERSION" ]]; then
37
+ echo "Error: Tag version ($TAG_VERSION) doesn't match package.json version ($PKG_VERSION)"
38
+ exit 1
39
+ fi
40
+ fi
41
+
42
+ - name: Install dependencies
43
+ run: npm ci
44
+
45
+ - name: Typecheck
46
+ run: npm run typecheck
47
+
48
+ create-release:
49
+ name: Create GitHub Release
50
+ runs-on: ubuntu-latest
51
+ needs: validate
52
+ if: startsWith(github.ref, 'refs/tags/')
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+ with:
56
+ fetch-depth: 0
57
+
58
+ - name: Generate changelog
59
+ id: changelog
60
+ run: |
61
+ PREV_TAG=$(git describe --tags --abbrev=0 HEAD~1 2>/dev/null || echo "")
62
+ CURRENT_TAG=${GITHUB_REF#refs/tags/}
63
+
64
+ if [[ -n "$PREV_TAG" ]]; then
65
+ echo "## Changes since $PREV_TAG" > CHANGELOG.md
66
+ git log --pretty=format:"- %s (%h)" $PREV_TAG..HEAD >> CHANGELOG.md
67
+ else
68
+ echo "## Initial Release" > CHANGELOG.md
69
+ fi
70
+
71
+ - name: Create Release
72
+ uses: softprops/action-gh-release@v2
73
+ with:
74
+ tag_name: ${{ github.ref_name }}
75
+ name: Release ${{ github.ref_name }}
76
+ body_path: CHANGELOG.md
77
+ draft: false
78
+ prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc') }}
79
+
80
+ publish-npm:
81
+ name: Publish to npm
82
+ runs-on: ubuntu-latest
83
+ needs: [validate, create-release]
84
+ if: startsWith(github.ref, 'refs/tags/') && !contains(github.ref_name, 'alpha') && !contains(github.ref_name, 'beta')
85
+ steps:
86
+ - uses: actions/checkout@v4
87
+
88
+ - uses: actions/setup-node@v4
89
+ with:
90
+ # npm trusted publishing (OIDC) requires npm >= 11.5.1 / Node >= 22.14
91
+ node-version: 24
92
+ registry-url: https://registry.npmjs.org
93
+
94
+ - name: Publish root package
95
+ run: npm publish --access public --provenance
96
+
97
+ - name: Publish sub-packages
98
+ run: |
99
+ for dir in extensions/*/; do
100
+ if [ -f "$dir/package.json" ]; then
101
+ echo "Publishing $dir"
102
+ cd "$dir"
103
+ npm publish --access public --provenance
104
+ cd -
105
+ fi
106
+ done
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Vijay
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,64 +1,107 @@
1
- # Piverse
1
+ # Piverse 🌌
2
2
 
3
- A multi-extension ecosystem for the [Pi coding agent](https://github.com/earendil-works/pi).
3
+ A multi-extension ecosystem for the [Pi coding agent](https://pi.dev).
4
4
 
5
- ## Install
5
+ ## Extensions
6
+
7
+ | Extension | Command | Description |
8
+ |-----------|---------|-------------|
9
+ | [pi-queue](./extensions/pi-queue) | `/queue` | Queue messages to run after the current agent turn settles |
10
+ | [pi-notes](./extensions/pi-notes) | `/notes` | Project-level notes with TUI, tags, search, and pinning |
6
11
 
7
- **All extensions:**
12
+ ## Install
8
13
 
9
14
  ```bash
10
15
  pi install npm:@vs4vijay/piverse
11
16
  ```
12
17
 
13
- **Individual extensions:**
18
+ ## Usage
14
19
 
15
- ```bash
16
- pi install npm:@vs4vijay/pi-queue
17
- ```
20
+ ### `/queue <message>`
18
21
 
19
- **From git (latest):**
22
+ Queue a message that automatically sends after the current turn finishes.
20
23
 
21
- ```bash
22
- pi install git:github.com/vs4vijay/piverse
24
+ ```
25
+ /queue refactor the auth module next
26
+ /queue run the test suite
23
27
  ```
24
28
 
25
- ## Extensions
29
+ - `/queue` (no args) — show pending messages
30
+ - `/queue-clear` — empty the queue
26
31
 
27
- | Extension | Package | Description |
28
- |-----------|---------|-------------|
29
- | [pi-queue](./extensions/pi-queue) | `@vs4vijay/pi-queue` | Queue messages to run after the current turn settles |
32
+ Messages fire one at a time, in order, after each `agent_settled` event.
30
33
 
31
- ## Development
34
+ ### `/notes`
32
35
 
33
- ### Quick test (single extension)
36
+ Project-level notes persisted in `.pi/notes/notes.json` (committed to git, team-shared).
34
37
 
35
- ```bash
36
- pi -e ./extensions/pi-queue/src/index.ts
38
+ ```
39
+ /notes # Open the full-screen TUI (list, view, create, edit, delete)
40
+ /notes "API contract" # Quick-add a note with that title (opens editor for content)
41
+ /notes list # List all notes in the CLI
42
+ /notes show <id> # Show a note's full content
43
+ /notes edit <id> # Edit a note's title/content via external editor
44
+ /notes search <query> # Search notes by title/content
45
+ /notes tag <id> <tag> # Add a tag to a note
46
+ /notes pin <id> # Pin a note to the top of the list
47
+ /notes rm <id> # Delete a note (with confirmation)
48
+ /notes export [path] # Export all notes to a JSON file
49
+ /notes import <path> # Import and merge notes from a JSON file
37
50
  ```
38
51
 
39
- ### Hot-reload via symlink
52
+ - Persists as JSON, auto-saves on every mutation
53
+ - Loads on `session_start`, flushes on `session_shutdown`
54
+ - TUI keys: `↑/↓` or `j/k` to navigate, `Enter` to view, `n` new, `e` edit, `d` delete, `p` pin, `/` to filter by typing, `q`/`Esc` to quit
40
55
 
41
- Link an extension into Pi's auto-discovery directory:
56
+ ## Development
57
+
58
+ ```bash
59
+ git clone git@github.com:vs4vijay/piverse.git ~/GitHub/piverse
60
+ ```
61
+
62
+ ### Hot-reload (symlink into Pi)
42
63
 
43
64
  ```bash
44
65
  ln -sf ~/GitHub/piverse/extensions/pi-queue ~/.pi/agent/extensions/pi-queue
45
66
  ```
46
67
 
47
- Then `/reload` inside Pi to pick up changes.
68
+ Edit source → `/reload` in Pi changes are live. No build step.
69
+
70
+ ### Quick test (no install)
71
+
72
+ ```bash
73
+ pi -e ./extensions/pi-queue/src/index.ts
74
+ ```
48
75
 
49
76
  ### Type checking
50
77
 
51
78
  ```bash
79
+ npm install
52
80
  npm run typecheck
53
81
  ```
54
82
 
55
- ## Structure
83
+ ## Project Structure
56
84
 
57
85
  ```
58
86
  piverse/
59
87
  ├── extensions/
60
- │ ├── pi-queue/ # /queue - message queueing
61
- └── ... # future extensions
62
- ├── package.json # pi-package root
63
- └── tsconfig.json # shared type checking
88
+ │ ├── pi-queue/ # /queue - message queueing
89
+ ├── pi-notes/ # /notes - project notes
90
+ │ └── ... # more extensions coming
91
+ ├── package.json # workspace root
92
+ ├── tsconfig.json # shared type checking
93
+ └── README.md
64
94
  ```
95
+
96
+ ## Contributing
97
+
98
+ 1. Fork & clone
99
+ 2. `mkdir extensions/pi-<name>/src`
100
+ 3. Add `package.json` with `"pi": { "extensions": ["./src/index.ts"] }`
101
+ 4. Implement in `src/index.ts`
102
+ 5. Test with `pi -e ./extensions/pi-<name>/src/index.ts`
103
+ 6. PR
104
+
105
+ ## License
106
+
107
+ MIT
@@ -0,0 +1,152 @@
1
+ # @vs4vijay/pi-notes
2
+
3
+ Project-level notes for the Pi coding agent. Persists notes as JSON in `.pi/notes/notes.json` (committed to git, team-shared).
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ pi install npm:@vs4vijay/pi-notes
9
+ ```
10
+
11
+ Or add to your Pi config:
12
+
13
+ ```json
14
+ {
15
+ "pi": {
16
+ "extensions": [
17
+ "./extensions/pi-queue/src/index.ts",
18
+ "./extensions/pi-notes/src/index.ts"
19
+ ]
20
+ }
21
+ }
22
+ ```
23
+
24
+ ## Commands
25
+
26
+ | Command | Description |
27
+ |---------|-------------|
28
+ | `/notes` | Open TUI (list, view, create, edit, delete) |
29
+ | `/notes <title>` | Quick-add note with title (opens editor for content) |
30
+ | `/notes list` | List all notes in CLI |
31
+ | `/notes show <id>` | Show full note content |
32
+ | `/notes edit <id>` | Edit a note's title/content via external editor |
33
+ | `/notes rm <id>` | Delete note (with confirmation) |
34
+ | `/notes search <query>` | Search notes by title/content |
35
+ | `/notes tag <id> <tag>` | Add tag to note |
36
+ | `/notes untag <id> <tag>` | Remove tag from note |
37
+ | `/notes pin <id>` | Pin note to top of list |
38
+ | `/notes unpin <id>` | Unpin note |
39
+ | `/notes export [path]` | Export all notes to a JSON file (default: `./notes.json`) |
40
+ | `/notes import <path>` | Import and merge notes from a JSON file |
41
+
42
+ ## TUI Interface
43
+
44
+ ```
45
+ /notes
46
+ ```
47
+
48
+ Opens full-screen TUI with:
49
+
50
+ - **Left pane**: Note list (title + preview, live filter as you type)
51
+ - **Right pane**: Markdown preview of selected note
52
+ - **Keys**:
53
+ - `↑/↓` / `j/k` — navigate
54
+ - `Enter` — view full note
55
+ - `n` — new note
56
+ - `e` — edit selected
57
+ - `d` — delete selected (with confirmation)
58
+ - `p` — toggle pin
59
+ - `/` — start filtering: type to filter the list live, `Esc`/`Enter` to finish
60
+ - `q` / `Esc` — quit (or back from view/edit)
61
+
62
+ ### View Mode
63
+ Full markdown render. Keys: `e` to edit, `q`/`Esc` back to list.
64
+
65
+ ### Create/Edit Mode
66
+ Opens external editor via `ctx.ui.editor()` for title and content. On save, persists and returns to list.
67
+
68
+ ## Persistence
69
+
70
+ - File: `.pi/notes/notes.json` in project root
71
+ - Format:
72
+ ```json
73
+ {
74
+ "notes": [
75
+ {
76
+ "id": "uuid",
77
+ "title": "Architecture decisions",
78
+ "content": "# Architecture decisions\n\nKey choices...",
79
+ "createdAt": "2025-01-15T10:30:00.000Z",
80
+ "updatedAt": "2025-01-15T10:30:00.000Z",
81
+ "tags": ["architecture", "decision"],
82
+ "pinned": false
83
+ }
84
+ ],
85
+ "version": 1
86
+ }
87
+ ```
88
+ - Auto-saves on every mutation
89
+ - Loads on `session_start`, flushes on `session_shutdown`
90
+
91
+ ## Usage / Examples
92
+
93
+ ```
94
+ > /notes
95
+ # Opens the full-screen TUI (list, view, create, edit, delete)
96
+
97
+ > /notes "API contract"
98
+ # Quick-add: title is "API contract" (quotes stripped), opens editor for content
99
+
100
+ > /notes list
101
+ Notes (3):
102
+ 1. 📌 API contract — Endpoint specs for v2...
103
+ 2. TODO: refactor auth [backend] — Pending work items...
104
+ 3. Architecture decisions — Summary of key choices...
105
+
106
+ > /notes show a1b2c3
107
+ # API contract
108
+ Pinned | Tags: none | Created: 2025-01-15T10:30:00.000Z | Updated: 2025-01-16T09:12:00.000Z
109
+
110
+ ## Endpoints
111
+ ...
112
+
113
+ > /notes search refactor
114
+ Search results (1):
115
+ 1. TODO: refactor auth [backend] — Pending work items...
116
+
117
+ > /notes tag a1b2c3 api
118
+ Added tag "api" to "API contract"
119
+
120
+ > /notes untag a1b2c3 api
121
+ Removed tag "api" from "API contract"
122
+
123
+ > /notes pin a1b2c3
124
+ Pinned "API contract"
125
+
126
+ > /notes unpin a1b2c3
127
+ Unpinned "API contract"
128
+
129
+ > /notes edit a1b2c3
130
+ # Opens external editors prefilled with the note's current title and content
131
+ Updated note: API contract
132
+
133
+ > /notes export
134
+ Exported 3 notes to /path/to/project/notes.json
135
+
136
+ > /notes export backup.json
137
+ Exported 3 notes to /path/to/project/backup.json
138
+
139
+ > /notes import backup.json
140
+ Imported 2 note(s) from /path/to/project/backup.json (1 already present, skipped)
141
+
142
+ > /notes rm a1b2c3
143
+ # Confirmation dialog... "Deleted note: API contract"
144
+ ```
145
+
146
+ ### Export/Import format
147
+
148
+ `/notes export` writes the same JSON shape used for persistence. `/notes import` reads a file shaped like `{ "notes": [...], "version": 1 }` and **merges** it into the store: notes whose `id` already exists locally are skipped (existing notes win), new ids are appended.
149
+
150
+ ## Roadmap
151
+
152
+ See [plan.md](./plan.md) for planned features: linking, templates, and other ideas.