pi-files-widget-overlay 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/CHANGELOG.md ADDED
@@ -0,0 +1,198 @@
1
+ # Changelog
2
+
3
+ All notable changes to this extension will be documented in this file.
4
+
5
+ ## [0.3.0] - 2026-09-10
6
+
7
+ ### Fixed
8
+ - Highlight and select every wrapped visual row of a logical line; comments retain logical source-line ranges.
9
+ - Make `c` and `C` share changed-only state while preserving collapsed and expanded changed-path views.
10
+ - Preserve logical cursor and selection groups across width changes and page navigation.
11
+ - Clear agent-modified file markers before a session switch.
12
+ - Keep Diff searches and comments anchored to logical Diff lines across word-wrap and width changes.
13
+ - Reset rendered Markdown selection to the first raw source line before creating a source-aligned comment.
14
+ - Schedule Git line counts by expanded directory instead of queueing every tracked file at startup.
15
+ - Keep confirmed file-viewer searches available to `n` and `N`.
16
+ - Track observed `edit.file` activity alongside `write.path` using normalized paths.
17
+ - Show non-blocking directory-scan and Git-metadata errors in the browser; verify Git metadata paths from repository subdirectories.
18
+
19
+ ### Added
20
+ - Add Vitest coverage for wrapped-row grouping, logical-line navigation, selection, and comments.
21
+ - Add `C` to toggle the expanded changed view.
22
+ - Add `w` to toggle word wrap in the file viewer; wrapping is disabled by default.
23
+ - Show hidden project files such as `.pi/` and `.github/` while keeping `.git/` and common generated directories hidden.
24
+ - Add anonymous Git and non-Git browser performance benchmarks with a recorded baseline.
25
+
26
+ ### Changed
27
+ - Forked `files-widget` as `pi-files-widget-overlay`; retain upstream MIT attribution and add tallshort copyright.
28
+ - Replace Delta's split line-number diff renderer with a compact unified view: explicit `+`/`-` markers and one relevant line number.
29
+ - Highlight the full width of the current line and selection; align the viewer and file-browser default overlay heights.
30
+ - Remove the Delta runtime dependency.
31
+ - Replace the README demo video with a static screenshot and add Pi Packages Gallery image metadata.
32
+
33
+ ### Added
34
+ - `/readfiles` now supports browsing outside the current working directory. Press `u` to re-root to the parent, `.` to jump back to where you started, or pass an explicit starting path (`/readfiles <path>` or `/readfiles ~/somewhere`). The browser header shows the current root so you always know where you are, and comments on files outside the project use absolute paths so the agent can still find them.
35
+
36
+ ### Fixed
37
+ - Git status, diff stats, and untracked-file discovery now work when the browser root is a subdirectory of the git repository (e.g. after `u`, `.`, or `/readfiles <subdir>`, or when pi runs from a repo subdirectory). Previously repo-root-relative git paths were mixed with root-relative node keys, producing phantom tree entries, missing statuses, and unopenable nested paths.
38
+ - Re-rooting the browser while a background directory scan or line-count batch is in flight no longer lets the stale batch mutate the new root's tree, node index, or scan state.
39
+ - Use `where` instead of `which` on Windows to detect `bat`, `delta`, and `glow`, so the dependency check works when running from PowerShell or cmd.exe.
40
+
41
+ ## [0.1.21] - 2026-05-07
42
+
43
+ ### Changed
44
+ - Declare `@earendil-works` Pi development dependencies used by runtime imports.
45
+ - Update Pi extension imports and peer dependencies to the new `@earendil-works` namespace.
46
+
47
+
48
+ ## [0.1.20] - 2026-04-24
49
+
50
+ ### Removed
51
+ - Remove the external `/readfiles-review` and `/readfiles-diff` commands so files-widget stays focused on the `/readfiles` browser/viewer.
52
+
53
+
54
+ ## [0.1.18] - 2026-04-19
55
+
56
+ ### Changed
57
+ - Show symlinks with a `↗` marker in the `/readfiles` tree.
58
+
59
+ ### Fixed
60
+ - Let `/readfiles` navigate into directory symlinks in both non-git folders and git repos instead of rendering them as inert files or empty directories.
61
+ - Guard symlink directory scanning against ancestor cycles so links like `foo -> .` or `foo -> ..` don't recurse forever.
62
+ - Treat git-tracked and untracked directory symlinks as lazily scannable directories rather than plain files.
63
+
64
+ ### Thanks
65
+ - Thanks to @xapids for reporting the original macOS symlink navigation issue ([#9](https://github.com/tmustier/pi-extensions/issues/9)).
66
+
67
+ ## [0.1.17] - 2026-04-19
68
+
69
+ ### Changed
70
+ - Make the inline comment editor multiline with wrapped footer rendering, `Enter` for a new line, and `Ctrl+Enter`/`Ctrl+D` to send.
71
+ - Add an `m` toggle for rendered vs raw Markdown in the viewer, and fall back to raw mode before line-based search or selection.
72
+ - Show a sent/queued confirmation toast after returning an inline comment to the agent.
73
+
74
+ ### Thanks
75
+ - Thanks to avg8888 in the Pi Discord for surfacing the comment editor and Markdown review issues fixed in this release.
76
+
77
+ ## [0.1.16] - 2026-04-19
78
+
79
+ ### Fixed
80
+ - Let `/readfiles` browser search accept `j` and `k` as search text instead of hijacking them for navigation.
81
+ - Fix viewer scrolling so the last lines of a file remain reachable.
82
+ - Restore `G` / `Shift+G` navigation to jump to the bottom of the viewer.
83
+ - Refresh an open viewer when the file changes on disk while `/readfiles` is open.
84
+ - Accept pasted, multi-character, and chunked bracketed-paste input in browser search and the inline comment prompt.
85
+ - Keep viewer search results in sync after live refreshes.
86
+ - Pause live refresh while a line selection or inline comment is active so comments stay anchored to what the user selected.
87
+
88
+ ## [0.1.14] - 2026-02-03
89
+
90
+ ### Added
91
+ - Add preview video metadata for the extension listing.
92
+
93
+ ## [0.1.13] - 2026-02-02
94
+
95
+ ### Changed
96
+ - **BREAKING:** Renamed `/files` command to `/readfiles` to avoid conflict with Pi's new built-in `/files` command (Pi v0.50.2+)
97
+
98
+ ## [0.1.11] - 2026-01-26
99
+
100
+ ### Changed
101
+ - Require `bat`, `delta`, and `glow` before opening `/files`
102
+ - Add a postinstall reminder for required system tools
103
+ - Document install commands next to the Pi install steps
104
+
105
+ ## [0.1.10] - 2026-01-26
106
+
107
+ ### Fixed
108
+ - Treat git-reported directory entries as directories to avoid viewer errors
109
+ - Guard the viewer against opening directories directly
110
+ - Wrap delta diff output without breaking gutters and avoid truncation
111
+ - Add a safe fallback when `bat` fails to render with wrapping
112
+
113
+ ## [0.1.9] - 2026-01-26
114
+
115
+ ### Changed
116
+ - Bind render requests to avoid undefined context with the latest pi-tui
117
+
118
+ ## [0.1.8] - 2026-01-26
119
+
120
+ ### Changed
121
+ - Compute line counts asynchronously with loading indicators
122
+ - Build git repo trees from git file lists to avoid filesystem scans
123
+ - Add progressive filesystem scanning with safe mode for large folders
124
+ - Reduce refresh work to git metadata updates
125
+
126
+ ## [0.1.7] - 2026-01-26
127
+
128
+ ### Changed
129
+ - Cache line counts and skip large files to avoid freezes in big folders
130
+ - Avoid recomputing tree stats on every render
131
+ - Preserve line counts for open files across refreshes
132
+
133
+ ## [0.1.6] - 2026-01-24
134
+
135
+ ### Added
136
+ - Clearer install instructions and dependency notes in README
137
+
138
+ ## [0.1.5] - 2026-01-24
139
+
140
+ ### Added
141
+ - Demo recording embedded in README
142
+
143
+ ### Changed
144
+ - Comment sending now queues with follow-up delivery in streaming sessions
145
+ - Split viewer logic into `viewer.ts` and shared helpers
146
+ - Reduced browser render duplication with node format helpers
147
+
148
+ ## [0.1.4] - 2026-01-24
149
+
150
+ ### Changed
151
+ - Split viewer logic into `viewer.ts` and shared helpers
152
+ - Reduced browser render duplication with node format helpers
153
+
154
+ ## [0.1.3] - 2026-01-24
155
+
156
+ ### Changed
157
+ - `c` in viewer now opens an inline comment prompt and sends a follow-up message
158
+
159
+ ## [0.1.2] - 2026-01-24
160
+
161
+ ### Changed
162
+ - `c` in viewer now appends selection to editor input instead of sending immediately
163
+
164
+ ## [0.1.1] - 2026-01-24
165
+
166
+ ### Added
167
+ - README with install steps, dependencies, and keybindings
168
+
169
+ ### Changed
170
+ - Refactored into modular files (browser, git, tree, viewer, utils)
171
+
172
+ ## [0.1.0] - 2026-01-24
173
+
174
+ ### Added
175
+ - `/files` command opens full-screen file browser
176
+ - File tree with j/k navigation, Enter to open, h/l to collapse/expand
177
+ - File viewer with syntax highlighting via `bat`
178
+ - Markdown rendering via `glow`
179
+ - Git diff view via `delta` with line numbers
180
+ - Git status indicators (M, A, D, ?) on files
181
+ - Agent-modified file tracking (🤖 indicator)
182
+ - Changed files filter (`c` to toggle)
183
+ - Jump to next/prev changed file (`]`/`[`)
184
+ - Search in file tree (`/` then type)
185
+ - Search in file viewer (`/` then type, `n`/`N` for next/prev match)
186
+ - Select mode (`v`) to select lines and comment (`c`) to send to agent
187
+ - Line counts and diff stats (+/-) on files and collapsed folders
188
+ - Auto-refresh git status every 3 seconds (preserves expansion state)
189
+ - PageUp/PageDown support in browser and viewer
190
+ - Height adjustment (`+`/`-`)
191
+ - Works in non-git directories (git features gracefully disabled)
192
+
193
+ ### Dependencies
194
+ - `bat` - syntax highlighting (recommended)
195
+ - `glow` - markdown rendering (recommended)
196
+ - `delta` - diff formatting (recommended)
197
+
198
+ Install with: `brew install bat git-delta glow`
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Thomas Mustier
4
+ Copyright (c) 2026 tallshort
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # pi-files-widget-overlay
2
+
3
+ In-terminal floating-overlay file browser and diff viewer for Pi. Navigate files, view diffs, select code, and send comments to the agent without leaving the terminal and without interrupting your agent.
4
+
5
+ ## Origin
6
+
7
+ Forked from [tmustier/pi-extensions — files-widget](https://github.com/tmustier/pi-extensions/tree/main/files-widget), distributed under the MIT License. Modifications and overlay-focused maintenance are by tallshort.
8
+
9
+ Directory symlinks are shown with a `↗` marker and can be expanded like normal folders.
10
+
11
+ ![File browser overlay](demo.png)
12
+ ## Install
13
+
14
+ **Quick install (Pi package manager):**
15
+
16
+ ```bash
17
+ pi install npm:pi-files-widget-overlay
18
+ ```
19
+
20
+ **Local development:** add the repository path to `~/.pi/agent/settings.json`:
21
+
22
+ ```json
23
+ {
24
+ "extensions": [
25
+ "~/pi-files-widget-overlay"
26
+ ]
27
+ }
28
+ ```
29
+ ## Dependencies
30
+
31
+ - Pi built-in syntax highlighter: code colors follow the active Pi theme
32
+ - Pi built-in Markdown renderer: rendered Markdown follows the active Pi theme
33
+
34
+ The `/readfiles` browser has no `bat`, `glow`, or `delta` runtime dependency. Code, Markdown, and unified diffs use Pi's theme-aware renderers; Diff mode uses `git` when available.
35
+
36
+ ## Project layout
37
+
38
+ - `src/`: extension runtime and `/readfiles` entry point
39
+ - `test/`: browser and viewer regression tests
40
+ - `docs/`: design notes and anonymous benchmark baselines
41
+ - `benchmarks/`: locally run benchmark harnesses; excluded from the published package
42
+
43
+ ## Development
44
+
45
+ ```bash
46
+ npm install
47
+ npm test
48
+ npm run typecheck
49
+ ```
50
+
51
+ ## Commands
52
+
53
+ - `/readfiles` - open the file browser as a floating overlay in the current directory
54
+ - `/readfiles <path>` - open the floating browser rooted at `<path>` (absolute, relative, or `~`-prefixed)
55
+
56
+ The overlay is centered at 95% of terminal width with a one-cell margin. Its framed header separates the browser from the agent transcript; `q` or `Esc` closes it and returns focus to Pi.
57
+ Diff viewing is built into the file viewer: open a changed tracked file and press `d` to toggle the git diff view.
58
+
59
+ ## Browser Keybindings
60
+
61
+ - `j/k` or `↑/↓`: move
62
+ - `Enter`: open file / expand folder
63
+ - `h/l` or `←/→`: collapse/expand folder
64
+ - `PgUp/PgDn`: page up/down
65
+ - `c`: toggle changed-only view
66
+ - `C`: toggle the expanded changed view; enabling it expands every directory containing changes
67
+ - `]` / `[`: next/prev changed file
68
+ - `/`: search (type to filter, `Esc` to exit)
69
+ - `u`: go up one directory (re-root to parent)
70
+ - `.`: jump back to the starting directory
71
+ - `+` / `-`: increase/decrease browser height
72
+ - `q`: close
73
+
74
+ ## Viewer Keybindings
75
+
76
+ - `j/k` or `↑/↓`: move the line cursor (the viewport follows it)
77
+ - `PgUp/PgDn`: page up/down
78
+ - `g/G`: top/bottom
79
+ - `d`: toggle diff (tracked files only)
80
+ - `m`: toggle rendered/raw view for Markdown files
81
+ - `w`: toggle word wrap (disabled by default)
82
+ - `/`: search (type to search)
83
+ - `n` / `N`: next/prev match
84
+ - `v`: select mode (line selection)
85
+ - `c`: comment on selected lines (inline prompt)
86
+ - `Enter`: new line in the comment editor
87
+ - `Ctrl+Enter` or `Ctrl+D`: send the comment (`Alt+Enter` also works when supported)
88
+ - `]` / `[`: next/prev changed file
89
+ - `+` / `-`: increase/decrease viewer height
90
+ - `q`, `Esc`, or `←`: back to browser
91
+
92
+ ## Notes
93
+
94
+ - The overlay maximum height is 95% of the terminal; browser and viewer panels start at 85%, and `+` / `-` adjust within that available range.
95
+ - Hidden project files and directories such as `.pi/` and `.github/` are visible; `.git/` and common dependency/build caches remain hidden.
96
+ - Untracked files show as `[UNTRACKED]` and open in normal view.
97
+ - Searching in rendered Markdown switches to raw mode first, and selecting from rendered Markdown first switches you back to raw so line-based matches and comments stay aligned with the source file.
98
+ - When you browse outside the current project directory, inline comments on those files use absolute paths so the agent can still locate them. Files inside the project continue to use project-relative paths.
99
+ - Folder LOCs are shown only when the folder is collapsed (expanded folders would duplicate counts).
100
+ - Line counts load asynchronously; the header shows activity while counts are computed.
101
+ - Large non-git folders load progressively and may show `[partial]` while loading in safe mode.
102
+ - Git status refreshes every 3 seconds while `/readfiles` is open.
package/demo.png ADDED
Binary file
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "pi-files-widget-overlay",
3
+ "version": "0.3.0",
4
+ "description": "In-terminal file browser, viewer, and diff overlay for Pi.",
5
+ "license": "MIT",
6
+ "author": "tallshort",
7
+ "keywords": [
8
+ "pi-package"
9
+ ],
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/tallshort/pi-files-widget-overlay.git"
13
+ },
14
+ "bugs": "https://github.com/tallshort/pi-files-widget-overlay/issues",
15
+ "homepage": "https://github.com/tallshort/pi-files-widget-overlay#readme",
16
+ "peerDependencies": {
17
+ "@earendil-works/pi-coding-agent": "*",
18
+ "@earendil-works/pi-tui": "*"
19
+ },
20
+ "scripts": {
21
+ "typecheck": "tsc --noEmit",
22
+ "test": "vitest run",
23
+ "benchmark:readfiles": "vite-node benchmarks/readfiles.ts"
24
+ },
25
+ "pi": {
26
+ "extensions": [
27
+ "src/index.ts"
28
+ ],
29
+ "image": "https://raw.githubusercontent.com/tallshort/pi-files-widget-overlay/main/demo.png"
30
+ },
31
+ "devDependencies": {
32
+ "@earendil-works/pi-coding-agent": "^0.80.3",
33
+ "@types/node": "^22.0.0",
34
+ "@earendil-works/pi-tui": "^0.80.3",
35
+ "typescript": "^5.7.3",
36
+ "vitest": "^3.0.0"
37
+ }
38
+ }
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # A wizard walks a human through a manual procedure, step by step.
4
+ # Generated by the /wizard skill.
5
+ #
6
+ # Everything above the "STAGES" marker is the wizard library: do not hand-edit
7
+ # it. Author the per-step stages below the marker.
8
+
9
+ set -euo pipefail
10
+
11
+ # ──────────────────────────────────────────────────────────────────────────
12
+ # Wizard library: delightful, consistent UX, identical across every wizard.
13
+ # ──────────────────────────────────────────────────────────────────────────
14
+
15
+ if [[ -t 1 ]] && command -v tput >/dev/null 2>&1 && [[ "$(tput colors 2>/dev/null || echo 0)" -ge 8 ]]; then
16
+ BOLD=$(tput bold); DIM=$(tput dim); RESET=$(tput sgr0)
17
+ BLUE=$(tput setaf 4); GREEN=$(tput setaf 2); YELLOW=$(tput setaf 3); RED=$(tput setaf 1)
18
+ else
19
+ BOLD=""; DIM=""; RESET=""; BLUE=""; GREEN=""; YELLOW=""; RED=""
20
+ fi
21
+
22
+ # Author sets this at the top of the stages section.
23
+ TOTAL_STAGES=0
24
+
25
+ _STAGE_INDEX=0
26
+ ENV_FILE="${ENV_FILE:-.env}"
27
+ WRITTEN_ENV=() # KEYs written to ENV_FILE this run
28
+ WRITTEN_SECRET=() # secret NAMEs set this run
29
+ SKIPPED=() # things we couldn't do (e.g. gh missing)
30
+
31
+ # _clear wipes the terminal so only the current step is on screen. No-op when
32
+ # output isn't a terminal, so piped logs stay readable.
33
+ _clear() {
34
+ [[ -t 1 ]] || return 0
35
+ if command -v tput >/dev/null 2>&1; then tput clear; else printf '\033[2J\033[3J\033[H'; fi
36
+ }
37
+
38
+ # banner "Title" shows the opening frame: what this wizard does.
39
+ banner() {
40
+ _clear
41
+ printf '\n%s%s %s%s\n' "$BOLD" "$BLUE" "$1" "$RESET"
42
+ printf '%s %s stages%s\n\n' "$DIM" "$TOTAL_STAGES" "$RESET"
43
+ printf '%s You drive the browser; this wizard tells you exactly what to do and\n' "$DIM"
44
+ printf ' captures the values you copy back. Stop any time with Ctrl-C and re-run\n'
45
+ printf ' later, since it remembers values already saved.%s\n' "$RESET"
46
+ pause "Ready to start?"
47
+ }
48
+
49
+ # stage "Name" clears the screen, then announces a stage and shows progress.
50
+ # Clearing keeps only the current step on screen.
51
+ stage() {
52
+ _clear
53
+ _STAGE_INDEX=$((_STAGE_INDEX + 1))
54
+ printf '\n%s%s▸ Stage %s/%s · %s%s\n' \
55
+ "$BOLD" "$BLUE" "$_STAGE_INDEX" "$TOTAL_STAGES" "$1" "$RESET"
56
+ }
57
+
58
+ # say "..." prints a plain instruction line.
59
+ say() { printf ' %s\n' "$1"; }
60
+ # step "..." is a numbered-feeling action the human takes in the browser.
61
+ step() { printf ' %s•%s %s\n' "$BLUE" "$RESET" "$1"; }
62
+ note() { printf ' %s%s%s\n' "$DIM" "$1" "$RESET"; }
63
+ warn() { printf ' %s⚠ %s%s\n' "$YELLOW" "$1" "$RESET"; }
64
+
65
+ # open_url URL opens it in the human's browser, cross-platform incl. WSL.
66
+ open_url() {
67
+ local url="$1"
68
+ printf ' %s↗ opening%s %s\n' "$GREEN" "$RESET" "$url"
69
+ { if command -v wslview >/dev/null 2>&1; then wslview "$url"
70
+ elif command -v explorer.exe >/dev/null 2>&1; then explorer.exe "$url"
71
+ elif command -v xdg-open >/dev/null 2>&1; then xdg-open "$url"
72
+ elif command -v open >/dev/null 2>&1; then open "$url"
73
+ else warn "couldn't open a browser; visit it manually: $url"; fi
74
+ } >/dev/null 2>&1 || warn "couldn't open a browser, so visit it manually: $url"
75
+ }
76
+
77
+ # pause "msg" waits for the human to confirm they've done the manual part.
78
+ pause() {
79
+ printf ' %s%s%s ' "$DIM" "${1:-Press Enter to continue}" "$RESET"
80
+ read -r _ || true
81
+ }
82
+
83
+ # confirm "question" is a y/N gate; returns success on yes.
84
+ confirm() {
85
+ local reply=""
86
+ printf ' %s? %s [y/N] ' "$YELLOW" "$1"
87
+ read -r reply || true
88
+ [[ "$reply" =~ ^[Yy] ]]
89
+ }
90
+
91
+ # _existing KEY: current value of KEY in ENV_FILE, if any.
92
+ _existing() {
93
+ [[ -f "$ENV_FILE" ]] || return 1
94
+ local line; line=$(grep -E "^${1}=" "$ENV_FILE" | tail -n1) || return 1
95
+ printf '%s' "${line#*=}"
96
+ }
97
+
98
+ # ask KEY "Prompt" reads a value into $KEY. Offers the existing .env value as
99
+ # a default on re-runs (Enter keeps it). Visible input (non-secret).
100
+ ask() {
101
+ local key="$1" prompt="$2" current input
102
+ current=$(_existing "$key" || true)
103
+ if [[ -n "$current" ]]; then
104
+ printf ' %s%s%s %s[Enter keeps current]%s ' "$BOLD" "$prompt" "$RESET" "$DIM" "$RESET"
105
+ else
106
+ printf ' %s%s%s ' "$BOLD" "$prompt" "$RESET"
107
+ fi
108
+ read -r input || true
109
+ [[ -z "$input" && -n "$current" ]] && input="$current"
110
+ printf -v "$key" '%s' "$input"
111
+ }
112
+
113
+ # ask_secret KEY "Prompt" is like ask, but input is hidden.
114
+ ask_secret() {
115
+ local key="$1" prompt="$2" current input
116
+ current=$(_existing "$key" || true)
117
+ if [[ -n "$current" ]]; then
118
+ printf ' %s%s%s %s[Enter keeps current]%s ' "$BOLD" "$prompt" "$RESET" "$DIM" "$RESET"
119
+ else
120
+ printf ' %s%s%s ' "$BOLD" "$prompt" "$RESET"
121
+ fi
122
+ read -rs input || true
123
+ printf '\n'
124
+ [[ -z "$input" && -n "$current" ]] && input="$current"
125
+ printf -v "$key" '%s' "$input"
126
+ }
127
+
128
+ # write_env KEY VALUE upserts KEY=VALUE into ENV_FILE (creates it; replaces
129
+ # any existing line). Idempotent.
130
+ write_env() {
131
+ local key="$1" value="$2" tmp
132
+ touch "$ENV_FILE"
133
+ tmp=$(mktemp)
134
+ grep -vE "^${key}=" "$ENV_FILE" > "$tmp" || true
135
+ printf '%s=%s\n' "$key" "$value" >> "$tmp"
136
+ mv "$tmp" "$ENV_FILE"
137
+ WRITTEN_ENV+=("$key")
138
+ printf ' %s✓ wrote%s %s → %s\n' "$GREEN" "$RESET" "$key" "$ENV_FILE"
139
+ }
140
+
141
+ # set_secret NAME VALUE sets a GitHub Actions repo secret via gh. Falls back
142
+ # to a warning (and records it) if gh is unavailable or unauthenticated.
143
+ set_secret() {
144
+ local name="$1" value="$2"
145
+ if command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1; then
146
+ if printf '%s' "$value" | gh secret set "$name" >/dev/null 2>&1; then
147
+ WRITTEN_SECRET+=("$name")
148
+ printf ' %s✓ set%s GitHub secret %s\n' "$GREEN" "$RESET" "$name"
149
+ return
150
+ fi
151
+ fi
152
+ SKIPPED+=("GitHub secret $name (set it manually: gh secret set $name)")
153
+ warn "skipped GitHub secret $name: gh not ready; set it later"
154
+ }
155
+
156
+ # set_var NAME VALUE sets a GitHub Actions repo variable (non-secret).
157
+ set_var() {
158
+ local name="$1" value="$2"
159
+ if command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1; then
160
+ if gh variable set "$name" --body "$value" >/dev/null 2>&1; then
161
+ printf ' %s✓ set%s GitHub variable %s\n' "$GREEN" "$RESET" "$name"
162
+ return
163
+ fi
164
+ fi
165
+ SKIPPED+=("GitHub variable $name")
166
+ warn "skipped GitHub variable $name, gh not ready; set it later"
167
+ }
168
+
169
+ # finish clears, then shows a closing summary of everything configured.
170
+ finish() {
171
+ _clear
172
+ printf '\n%s%s ✓ Setup complete%s\n' "$BOLD" "$GREEN" "$RESET"
173
+ (( ${#WRITTEN_ENV[@]} )) && note "wrote ${#WRITTEN_ENV[@]} value(s) to $ENV_FILE: ${WRITTEN_ENV[*]}"
174
+ (( ${#WRITTEN_SECRET[@]} )) && note "set ${#WRITTEN_SECRET[@]} GitHub secret(s): ${WRITTEN_SECRET[*]}"
175
+ if (( ${#SKIPPED[@]} )); then
176
+ printf '\n'; warn "still to do by hand:"
177
+ for s in "${SKIPPED[@]}"; do note " - $s"; done
178
+ fi
179
+ printf '\n'
180
+ }
181
+
182
+ # ──────────────────────────────────────────────────────────────────────────
183
+ # STAGES: author this section. One stage() per step the human takes.
184
+ # Replace the example below. Set TOTAL_STAGES to match the stages you write.
185
+ # ──────────────────────────────────────────────────────────────────────────
186
+
187
+ TOTAL_STAGES=5
188
+
189
+ banner "Publish pi-files-widget-overlay"
190
+
191
+ stage "Create the GitHub repository"
192
+ open_url "https://github.com/new"
193
+ step "Owner: tallshort. Repository name: pi-files-widget-overlay."
194
+ step "Choose Public, and leave README, .gitignore, and license initialization unchecked."
195
+ step "Create the repository; it must be empty because this checkout already has history."
196
+ pause "Press Enter after the repository exists."
197
+
198
+ stage "Push the existing main branch"
199
+ say "This checkout already uses: https://github.com/tallshort/pi-files-widget-overlay.git"
200
+ step "Run: git ls-remote origin"
201
+ step "Run: git push -u origin main"
202
+ pause "Press Enter after the push succeeds."
203
+
204
+ stage "Verify the GitHub project"
205
+ open_url "https://github.com/tallshort/pi-files-widget-overlay"
206
+ step "Confirm the default branch is main and the repository shows src/, test/, docs/, README.md, and package.json."
207
+ pause "Press Enter after verification."
208
+
209
+ stage "Prepare the v0.3.0 Git release"
210
+ step "From the checkout run: npm test && npm run typecheck && npm pack --dry-run"
211
+ step "Review git status --short; it must be empty before tagging."
212
+ step "Run: git tag -a v0.3.0 -m 'Release 0.3.0'"
213
+ step "Run: git push origin main --tags"
214
+ pause "Press Enter after the tag is visible on GitHub."
215
+
216
+ stage "Publish to npm"
217
+ say "package.json already links the package page to the GitHub repository through its repository field."
218
+ step "Run: npm login"
219
+ step "Run: npm whoami"
220
+ step "Optional availability check: npm view pi-files-widget-overlay version"
221
+ if confirm "Publish version 0.3.0 to npm now?"; then
222
+ step "Run: npm publish"
223
+ step "Verify: npm view pi-files-widget-overlay version"
224
+ else
225
+ note "Skipped npm publish. Re-run this wizard when you are ready."
226
+ fi
227
+
228
+ finish
@@ -0,0 +1,10 @@
1
+ import { resolve } from "node:path";
2
+
3
+ export function getObservedToolActivityPath(toolName: string, input: unknown, cwd: string): string | undefined {
4
+ if (toolName !== "write" && toolName !== "edit") return undefined;
5
+ if (!input || typeof input !== "object") return undefined;
6
+
7
+ const field = toolName === "write" ? "path" : "file";
8
+ const path = (input as Record<string, unknown>)[field];
9
+ return typeof path === "string" && path.trim() ? resolve(cwd, path) : undefined;
10
+ }