pi-superwhisper-paste 0.1.20 → 0.1.23

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 CHANGED
@@ -1,160 +1,154 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- This project follows semantic versioning.
6
-
7
- ## Unreleased
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ This project follows semantic versioning.
6
+
7
+ ## [0.1.23] - 2026-09-27
8
+
9
+ - chore: periodic patch bump after 7+ days without npm publish
10
+
11
+
12
+
13
+ All notable changes to this project will be documented in this file.
14
+
15
+ This project follows semantic versioning.
16
+ ## [0.1.22] - 2026-09-28
8
17
 
18
+ - chore: periodic patch bump after 7+ days without npm publish
19
+ ## [0.1.21] - 2026-09-28
20
+
21
+ - chore: periodic patch bump after 7+ days without npm publish
9
22
  ## [0.1.20] - 2026-08-22
10
23
 
11
24
  ### Changed
12
25
 
13
26
  - Support the TypeScript 7 compiler package by using Node's built-in type stripping in runtime-loading regression tests.
14
-
15
27
  ## [0.1.19] - 2026-08-04
16
-
17
- ### Changed
18
-
19
- - Bump package version for the Discord release webhook verification.
20
- - Align README pinned npm install example with `package.json` (#38).
21
- - Add dotfield.xyz Discord community badge to README.
22
-
23
- ## [0.1.18] - 2026-07-21
24
-
25
- ### Changed
26
-
27
- - Bump package version and align extension status version constant with `package.json`.
28
-
29
- ## [0.1.17] - 2026-07-04
30
-
31
- ### Changed
32
-
33
- - Add Buy Me a Coffee sponsor button to README and native GitHub funding link via `.github/FUNDING.yml`.
34
-
35
- ### Fixed
36
-
37
- - Align `EXTENSION_VERSION` in the extension with `package.json` so Pi status text no longer reports a stale build during debugging (#35).
38
-
39
- ## [0.1.16] - 2026-06-27
40
-
41
- ### Changed
42
-
43
- - Align README with the current Pi extension template structure while preserving Windows install guidance and behavior notes.
44
-
45
- ## [0.1.15] - 2026-06-05
46
-
47
- ### Changed
48
-
49
- - Remove stale template-maintenance docs (`github-template.md`, `repository-settings.md`, `typescript.md`) from the published package.
50
-
51
- ## [0.1.14] - 2026-06-05
52
-
53
- ### Changed
54
-
55
- - Re-add `Code` / `Cursor` host processes to the clipboard-owner denylist so editor-hosted clipboard updates are blocked again during debugging.
56
-
57
- ## [0.1.13] - 2026-06-05
58
-
59
- ### Fixed
60
-
61
- - Remove `Code.exe` / `Cursor.exe` from the terminal-owner denylist so editor-hosted Superwhisper clipboard updates are not blocked just because Pi is running inside Code/Cursor.
62
-
63
- ## [0.1.12] - 2026-06-05
64
-
65
- ### Changed
66
-
67
- - Add an explicit `v0.1.12` marker to the status text so stale package loads are visible during live debugging.
68
-
69
- ## [0.1.11] - 2026-06-05
70
-
71
- ### Fixed
72
-
73
- - Broaden the terminal clipboard-owner denylist with `OpenConsole` / explicit `.exe` variants.
74
- - Surface the last clipboard decision in the Pi status text (`blocked ...`, `... via ...`) so real-machine owner mismatches can be diagnosed quickly.
75
-
76
- ## [0.1.10] - 2026-06-05
77
-
78
- ### Fixed
79
-
80
- - Fix the Windows PowerShell clipboard-owner probe script so the owner-aware bridge works in real Pi sessions instead of failing on multiline `Add-Type` syntax.
81
-
82
- ## [0.1.9] - 2026-06-05
83
-
84
- ### Fixed
85
-
86
- - Replace the strict Superwhisper owner allowlist with a terminal-owner denylist so unknown Superwhisper owner names still auto-paste while terminal/CLI clipboard owners stay blocked.
87
-
88
- ## [0.1.8] - 2026-06-05
89
-
90
- ### Fixed
91
-
92
- - Filter clipboard updates by clipboard-owner process so Pi auto-pastes only when the clipboard owner looks like Superwhisper.
93
- - Keep local terminal copy suppression as a fallback for forwarded copy shortcuts while blocking mouse/right-click terminal copies via owner filtering.
94
-
95
- ## [0.1.7] - 2026-06-05
96
-
97
- ### Fixed
98
-
99
- - Suppress auto-paste for a short window after local terminal copy shortcuts so copying inside the active CLI no longer pastes into Pi.
100
- - Refresh the clipboard baseline after local copy intent so the bridge keeps waiting for the next Superwhisper clipboard update.
101
-
102
- ## [0.1.6] - 2026-06-04
103
-
104
- ### Changed
105
-
106
- - Added `version:check` PR guard support: package script + `scripts/check-version-bump.mjs`.
107
- - Added CI verification that publishable changes must bump `package.json` and update `CHANGELOG.md` in the same PR.
108
-
109
- ### Fixed
110
-
111
- - Truncate clipboard text in PowerShell before writing stdout so huge clipboards no longer exceed Node `maxBuffer` on extension load.
112
- - Treat clipboard read failures (including `maxBuffer`) as empty reads so `session_start` never surfaces as an extension error.
113
-
114
- ## [0.1.5] - 2026-06-03
115
-
116
- ## [0.1.4] - 2026-06-03
117
-
118
- ### Changed
119
-
120
- - Clarify that `pi-superwhisper-paste` is the Windows clipboard-based package.
121
- - Point users to `@superwhisper/pi` only for the official deeplink/macOS flow.
122
- - Update npm package metadata to match the revived Windows-focused positioning.
123
-
124
- ## [0.1.3] - 2026-06-03
125
-
126
- ### Changed
127
-
128
- - Mark the package as archived in README and `package.json` description.
129
- - Point new installs to the official Superwhisper Pi extension: `pi install npm:@superwhisper/pi`.
130
-
131
- ## [0.1.2] - 2026-06-01
132
-
133
- ### Fixed
134
-
135
- - Register `/sw-paste:on` and `/sw-paste:off` as Pi slash commands so they appear in command autocomplete.
136
-
137
- ### Changed
138
-
139
- - Clarify that the Superwhisper paste controls are slash-autocomplete commands.
140
-
141
- ## [0.1.1] - 2026-05-31
142
-
143
- ### Added
144
-
145
- - Add automatic GitHub release creation for version bumps on `main`.
146
- - Add manual and release-published npm publish entrypoints for Trusted Publishing.
147
-
148
- ### Changed
149
-
150
- - Align CI and publish workflows with the maintained Pi OSS release pattern.
151
- - Skip npm publish when the exact package version is already published.
152
-
153
- ## [0.1.0] - 2026-05-30
154
-
155
- ### Added
156
-
157
- - Initial Superwhisper paste bridge extension for Pi on Windows.
158
- - Default-on clipboard watcher with `/sw-paste:on` and `/sw-paste:off` controls.
159
- - CI and npm Trusted Publishing workflow from the Pi extension template.
160
-
28
+
29
+ ### Changed
30
+
31
+ - Bump package version for the Discord release webhook verification.
32
+ - Align README pinned npm install example with `package.json` (#38).
33
+ - Add dotfield.xyz Discord community badge to README.
34
+ ## [0.1.18] - 2026-07-21
35
+
36
+ ### Changed
37
+
38
+ - Bump package version and align extension status version constant with `package.json`.
39
+ ## [0.1.17] - 2026-07-04
40
+
41
+ ### Changed
42
+
43
+ - Add Buy Me a Coffee sponsor button to README and native GitHub funding link via `.github/FUNDING.yml`.
44
+
45
+ ### Fixed
46
+
47
+ - Align `EXTENSION_VERSION` in the extension with `package.json` so Pi status text no longer reports a stale build during debugging (#35).
48
+ ## [0.1.16] - 2026-06-27
49
+
50
+ ### Changed
51
+
52
+ - Align README with the current Pi extension template structure while preserving Windows install guidance and behavior notes.
53
+ ## [0.1.15] - 2026-06-05
54
+
55
+ ### Changed
56
+
57
+ - Remove stale template-maintenance docs (`github-template.md`, `repository-settings.md`, `typescript.md`) from the published package.
58
+ ## [0.1.14] - 2026-06-05
59
+
60
+ ### Changed
61
+
62
+ - Re-add `Code` / `Cursor` host processes to the clipboard-owner denylist so editor-hosted clipboard updates are blocked again during debugging.
63
+ ## [0.1.13] - 2026-06-05
64
+
65
+ ### Fixed
66
+
67
+ - Remove `Code.exe` / `Cursor.exe` from the terminal-owner denylist so editor-hosted Superwhisper clipboard updates are not blocked just because Pi is running inside Code/Cursor.
68
+ ## [0.1.12] - 2026-06-05
69
+
70
+ ### Changed
71
+
72
+ - Add an explicit `v0.1.12` marker to the status text so stale package loads are visible during live debugging.
73
+ ## [0.1.11] - 2026-06-05
74
+
75
+ ### Fixed
76
+
77
+ - Broaden the terminal clipboard-owner denylist with `OpenConsole` / explicit `.exe` variants.
78
+ - Surface the last clipboard decision in the Pi status text (`blocked ...`, `... via ...`) so real-machine owner mismatches can be diagnosed quickly.
79
+ ## [0.1.10] - 2026-06-05
80
+
81
+ ### Fixed
82
+
83
+ - Fix the Windows PowerShell clipboard-owner probe script so the owner-aware bridge works in real Pi sessions instead of failing on multiline `Add-Type` syntax.
84
+ ## [0.1.9] - 2026-06-05
85
+
86
+ ### Fixed
87
+
88
+ - Replace the strict Superwhisper owner allowlist with a terminal-owner denylist so unknown Superwhisper owner names still auto-paste while terminal/CLI clipboard owners stay blocked.
89
+ ## [0.1.8] - 2026-06-05
90
+
91
+ ### Fixed
92
+
93
+ - Filter clipboard updates by clipboard-owner process so Pi auto-pastes only when the clipboard owner looks like Superwhisper.
94
+ - Keep local terminal copy suppression as a fallback for forwarded copy shortcuts while blocking mouse/right-click terminal copies via owner filtering.
95
+ ## [0.1.7] - 2026-06-05
96
+
97
+ ### Fixed
98
+
99
+ - Suppress auto-paste for a short window after local terminal copy shortcuts so copying inside the active CLI no longer pastes into Pi.
100
+ - Refresh the clipboard baseline after local copy intent so the bridge keeps waiting for the next Superwhisper clipboard update.
101
+ ## [0.1.6] - 2026-06-04
102
+
103
+ ### Changed
104
+
105
+ - Added `version:check` PR guard support: package script + `scripts/check-version-bump.mjs`.
106
+ - Added CI verification that publishable changes must bump `package.json` and update `CHANGELOG.md` in the same PR.
107
+
108
+ ### Fixed
109
+
110
+ - Truncate clipboard text in PowerShell before writing stdout so huge clipboards no longer exceed Node `maxBuffer` on extension load.
111
+ - Treat clipboard read failures (including `maxBuffer`) as empty reads so `session_start` never surfaces as an extension error.
112
+ ## [0.1.5] - 2026-06-03
113
+ ## [0.1.4] - 2026-06-03
114
+
115
+ ### Changed
116
+
117
+ - Clarify that `pi-superwhisper-paste` is the Windows clipboard-based package.
118
+ - Point users to `@superwhisper/pi` only for the official deeplink/macOS flow.
119
+ - Update npm package metadata to match the revived Windows-focused positioning.
120
+ ## [0.1.3] - 2026-06-03
121
+
122
+ ### Changed
123
+
124
+ - Mark the package as archived in README and `package.json` description.
125
+ - Point new installs to the official Superwhisper Pi extension: `pi install npm:@superwhisper/pi`.
126
+ ## [0.1.2] - 2026-06-01
127
+
128
+ ### Fixed
129
+
130
+ - Register `/sw-paste:on` and `/sw-paste:off` as Pi slash commands so they appear in command autocomplete.
131
+
132
+ ### Changed
133
+
134
+ - Clarify that the Superwhisper paste controls are slash-autocomplete commands.
135
+ ## [0.1.1] - 2026-05-31
136
+
137
+ ### Added
138
+
139
+ - Add automatic GitHub release creation for version bumps on `main`.
140
+ - Add manual and release-published npm publish entrypoints for Trusted Publishing.
141
+
142
+ ### Changed
143
+
144
+ - Align CI and publish workflows with the maintained Pi OSS release pattern.
145
+ - Skip npm publish when the exact package version is already published.
146
+ ## [0.1.0] - 2026-05-30
147
+
148
+ ### Added
149
+
150
+ - Initial Superwhisper paste bridge extension for Pi on Windows.
151
+ - Default-on clipboard watcher with `/sw-paste:on` and `/sw-paste:off` controls.
152
+ - CI and npm Trusted Publishing workflow from the Pi extension template.
153
+ ## Unreleased
154
+
package/README.md CHANGED
@@ -1,135 +1,135 @@
1
- # Pi Superwhisper Paste
2
-
3
- [![Join dotfield.xyz on Discord](https://img.shields.io/badge/Join%20dotfield.xyz%20on%20Discord-5865F2?logo=discord&logoColor=white)](https://discord.gg/4945dXZVW5)
4
-
5
- [![CI](https://github.com/eiei114/pi-superwhisper-paste/actions/workflows/ci.yml/badge.svg)](https://github.com/eiei114/pi-superwhisper-paste/actions/workflows/ci.yml)
6
- [![Publish](https://github.com/eiei114/pi-superwhisper-paste/actions/workflows/publish.yml/badge.svg)](https://github.com/eiei114/pi-superwhisper-paste/actions/workflows/publish.yml)
7
- [![npm version](https://img.shields.io/npm/v/pi-superwhisper-paste.svg)](https://www.npmjs.com/package/pi-superwhisper-paste)
8
- [![npm downloads](https://img.shields.io/npm/dm/pi-superwhisper-paste.svg)](https://www.npmjs.com/package/pi-superwhisper-paste)
9
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
10
- [![Pi package](https://img.shields.io/badge/pi-package-purple.svg)](https://pi.dev/packages)
11
- [![Trusted Publishing](https://img.shields.io/badge/npm-Trusted%20Publishing-blue.svg)](docs/release.md)
12
- <a href="https://buymeacoffee.com/ekawano114m"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" width="217" height="60"></a>
13
-
14
- > Windows-focused Pi bridge that pastes Superwhisper clipboard output into Pi's TUI editor.
15
-
16
- ## What this is
17
-
18
- Superwhisper can paste dictated text into normal Windows apps, but terminal TUIs can be a rough edge. In the original case, dictation worked in Notepad and PowerShell, and Typeless worked in Pi, but Superwhisper's automatic paste did not reliably reach Pi's TUI editor without a manual `Ctrl+V`.
19
-
20
- This package bridges that gap from the Pi side: it watches the Windows clipboard, detects new Superwhisper output, and inserts it into the active Pi editor with Pi's extension API.
21
-
22
- The official Superwhisper Pi package (`@superwhisper/pi`) targets the deeplink/macOS flow. If you need the clipboard-based Windows workaround, use this package.
23
-
24
- ## Features
25
-
26
- - Default-on after the extension loads on Windows.
27
- - Slash commands: `/sw-paste:on` and `/sw-paste:off`.
28
- - Windows clipboard polling with active-tab gating.
29
- - Brief copy-suppression window so local terminal copy actions do not get auto-pasted back into Pi.
30
- - Clipboard-owner filtering so terminal/CLI-owned clipboard updates stay blocked by default.
31
-
32
- ## Install
33
-
34
- Install the published npm package with Pi:
35
-
36
- ```bash
37
- pi install npm:pi-superwhisper-paste
38
- ```
39
-
40
- Pin a specific version when you want reproducible installs:
41
-
42
- ```bash
43
- pi install npm:pi-superwhisper-paste@0.1.20
44
- ```
45
-
46
- Install into the current project instead of your user Pi settings:
47
-
48
- ```bash
49
- pi install npm:pi-superwhisper-paste -l
50
- ```
51
-
52
- Or install from GitHub:
53
-
54
- ```bash
55
- pi install git:github.com/eiei114/pi-superwhisper-paste
56
- ```
57
-
58
- Try it without permanently installing:
59
-
60
- ```bash
61
- pi -e npm:pi-superwhisper-paste
62
- ```
63
-
64
- ### Official Superwhisper package
65
-
66
- If you are using the official Superwhisper Pi integration instead:
67
-
68
- ```bash
69
- pi install npm:@superwhisper/pi
70
- ```
71
-
72
- Docs: https://superwhisper.com/pi
73
-
74
- ## Quick start
75
-
76
- After install, start Pi and dictate with Superwhisper. New Superwhisper clipboard output should auto-paste into the active Pi editor when the bridge is on.
77
-
78
- Toggle the bridge at runtime:
79
-
80
- ```txt
81
- /sw-paste:off
82
- /sw-paste:on
83
- ```
84
-
85
- Try this package locally from a clone:
86
-
87
- ```bash
88
- pi -e .
89
- ```
90
-
91
- ## Package contents
92
-
93
- | Path | Purpose |
94
- |---|---|
95
- | `extensions/index.ts` | Pi TypeScript extension entrypoint |
96
- | `docs/examples.md` | Usage examples |
97
- | `docs/release.md` | Trusted Publishing release flow |
98
- | `docs/template-checklist.md` | Maintainer template checklist |
99
- | `CHANGELOG.md` | Version history |
100
- | `LICENSE` | MIT license |
101
-
102
- ## Development
103
-
104
- ```bash
105
- npm install
106
- npm run ci
107
- ```
108
-
109
- ## Release
110
-
111
- This package is set up for npm Trusted Publishing, so no `NPM_TOKEN` is required.
112
-
113
- ```bash
114
- npm version patch
115
- git push
116
- ```
117
-
118
- See [`docs/release.md`](docs/release.md) for setup details.
119
-
120
- ## Security
121
-
122
- Pi packages can execute code with your local permissions. Review extensions before installing third-party packages.
123
-
124
- For vulnerability reporting, see [`SECURITY.md`](SECURITY.md).
125
-
126
- ## Links
127
-
128
- - npm: https://www.npmjs.com/package/pi-superwhisper-paste
129
- - GitHub: https://github.com/eiei114/pi-superwhisper-paste
130
- - Issues: https://github.com/eiei114/pi-superwhisper-paste/issues
131
- - Official Superwhisper Pi package: https://superwhisper.com/pi — `@superwhisper/pi` on npm (`pi install npm:@superwhisper/pi`)
132
-
133
- ## License
134
-
135
- MIT
1
+ # Pi Superwhisper Paste
2
+
3
+ [![Join dotfield.xyz on Discord](https://img.shields.io/badge/Join%20dotfield.xyz%20on%20Discord-5865F2?logo=discord&logoColor=white)](https://discord.gg/4945dXZVW5)
4
+
5
+ [![CI](https://github.com/eiei114/pi-superwhisper-paste/actions/workflows/ci.yml/badge.svg)](https://github.com/eiei114/pi-superwhisper-paste/actions/workflows/ci.yml)
6
+ [![Publish](https://github.com/eiei114/pi-superwhisper-paste/actions/workflows/publish.yml/badge.svg)](https://github.com/eiei114/pi-superwhisper-paste/actions/workflows/publish.yml)
7
+ [![npm version](https://img.shields.io/npm/v/pi-superwhisper-paste.svg)](https://www.npmjs.com/package/pi-superwhisper-paste)
8
+ [![npm downloads](https://img.shields.io/npm/dm/pi-superwhisper-paste.svg)](https://www.npmjs.com/package/pi-superwhisper-paste)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
10
+ [![Pi package](https://img.shields.io/badge/pi-package-purple.svg)](https://pi.dev/packages)
11
+ [![Trusted Publishing](https://img.shields.io/badge/npm-Trusted%20Publishing-blue.svg)](docs/release.md)
12
+ <a href="https://buymeacoffee.com/ekawano114m"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" width="217" height="60"></a>
13
+
14
+ > Windows-focused Pi bridge that pastes Superwhisper clipboard output into Pi's TUI editor.
15
+
16
+ ## What this is
17
+
18
+ Superwhisper can paste dictated text into normal Windows apps, but terminal TUIs can be a rough edge. In the original case, dictation worked in Notepad and PowerShell, and Typeless worked in Pi, but Superwhisper's automatic paste did not reliably reach Pi's TUI editor without a manual `Ctrl+V`.
19
+
20
+ This package bridges that gap from the Pi side: it watches the Windows clipboard, detects new Superwhisper output, and inserts it into the active Pi editor with Pi's extension API.
21
+
22
+ The official Superwhisper Pi package (`@superwhisper/pi`) targets the deeplink/macOS flow. If you need the clipboard-based Windows workaround, use this package.
23
+
24
+ ## Features
25
+
26
+ - Default-on after the extension loads on Windows.
27
+ - Slash commands: `/sw-paste:on` and `/sw-paste:off`.
28
+ - Windows clipboard polling with active-tab gating.
29
+ - Brief copy-suppression window so local terminal copy actions do not get auto-pasted back into Pi.
30
+ - Clipboard-owner filtering so terminal/CLI-owned clipboard updates stay blocked by default.
31
+
32
+ ## Install
33
+
34
+ Install the published npm package with Pi:
35
+
36
+ ```bash
37
+ pi install npm:pi-superwhisper-paste
38
+ ```
39
+
40
+ Pin a specific version when you want reproducible installs:
41
+
42
+ ```bash
43
+ pi install npm:pi-superwhisper-paste@0.1.23
44
+ ```
45
+
46
+ Install into the current project instead of your user Pi settings:
47
+
48
+ ```bash
49
+ pi install npm:pi-superwhisper-paste -l
50
+ ```
51
+
52
+ Or install from GitHub:
53
+
54
+ ```bash
55
+ pi install git:github.com/eiei114/pi-superwhisper-paste
56
+ ```
57
+
58
+ Try it without permanently installing:
59
+
60
+ ```bash
61
+ pi -e npm:pi-superwhisper-paste
62
+ ```
63
+
64
+ ### Official Superwhisper package
65
+
66
+ If you are using the official Superwhisper Pi integration instead:
67
+
68
+ ```bash
69
+ pi install npm:@superwhisper/pi
70
+ ```
71
+
72
+ Docs: https://superwhisper.com/pi
73
+
74
+ ## Quick start
75
+
76
+ After install, start Pi and dictate with Superwhisper. New Superwhisper clipboard output should auto-paste into the active Pi editor when the bridge is on.
77
+
78
+ Toggle the bridge at runtime:
79
+
80
+ ```txt
81
+ /sw-paste:off
82
+ /sw-paste:on
83
+ ```
84
+
85
+ Try this package locally from a clone:
86
+
87
+ ```bash
88
+ pi -e .
89
+ ```
90
+
91
+ ## Package contents
92
+
93
+ | Path | Purpose |
94
+ |---|---|
95
+ | `extensions/index.ts` | Pi TypeScript extension entrypoint |
96
+ | `docs/examples.md` | Usage examples |
97
+ | `docs/release.md` | Trusted Publishing release flow |
98
+ | `docs/template-checklist.md` | Maintainer template checklist |
99
+ | `CHANGELOG.md` | Version history |
100
+ | `LICENSE` | MIT license |
101
+
102
+ ## Development
103
+
104
+ ```bash
105
+ npm install
106
+ npm run ci
107
+ ```
108
+
109
+ ## Release
110
+
111
+ This package is set up for npm Trusted Publishing, so no `NPM_TOKEN` is required.
112
+
113
+ ```bash
114
+ npm version patch
115
+ git push
116
+ ```
117
+
118
+ See [`docs/release.md`](docs/release.md) for setup details.
119
+
120
+ ## Security
121
+
122
+ Pi packages can execute code with your local permissions. Review extensions before installing third-party packages.
123
+
124
+ For vulnerability reporting, see [`SECURITY.md`](SECURITY.md).
125
+
126
+ ## Links
127
+
128
+ - npm: https://www.npmjs.com/package/pi-superwhisper-paste
129
+ - GitHub: https://github.com/eiei114/pi-superwhisper-paste
130
+ - Issues: https://github.com/eiei114/pi-superwhisper-paste/issues
131
+ - Official Superwhisper Pi package: https://superwhisper.com/pi — `@superwhisper/pi` on npm (`pi install npm:@superwhisper/pi`)
132
+
133
+ ## License
134
+
135
+ MIT
package/docs/examples.md CHANGED
@@ -29,7 +29,7 @@ Run these commands inside Pi's input box:
29
29
  | `PI_SUPERWHISPER_PASTE_INTERVAL_MS` | `800` | Clipboard polling interval. |
30
30
  | `PI_SUPERWHISPER_PASTE_MAX_CHARS` | `8000` | Maximum clipboard text length to paste. |
31
31
  | `PI_SUPERWHISPER_PASTE_IGNORE_COPY_MS` | `1500` | Ignore clipboard changes briefly after local terminal copy shortcuts. |
32
- | `PI_SUPERWHISPER_PASTE_OWNER_DENYLIST` | `windowsterminal,...` | Comma-separated clipboard owner process/path substrings blocked from auto-paste. |
32
+ | `PI_SUPERWHISPER_PASTE_OWNER_DENYLIST` | `windowsterminal, windows terminal, openconsole, wezterm, alacritty, mintty, conhost, cmd.exe, code, powershell, pwsh, bash, cursor, wsl (and .exe variants)` | Comma-separated clipboard owner process/path substrings blocked from auto-paste. |
33
33
 
34
34
  ## Expected workflow
35
35
 
@@ -6,7 +6,7 @@ import { join } from "node:path";
6
6
  import { promisify } from "node:util";
7
7
 
8
8
  const execFileAsync = promisify(execFile);
9
- const EXTENSION_VERSION = "0.1.20";
9
+ const EXTENSION_VERSION = "0.1.23";
10
10
 
11
11
  const STATUS_KEY = "superwhisper-paste";
12
12
  const DEFAULT_INTERVAL_MS = 800;
@@ -34,6 +34,7 @@ const DEFAULT_OWNER_DENYLIST = [
34
34
  "wsl",
35
35
  ];
36
36
  const ACTIVE_STATE_FILE = "pi-superwhisper-paste-active.json";
37
+ const ACTIVE_STATE_PATH = join(tmpdir(), ACTIVE_STATE_FILE);
37
38
  const FOCUS_IN = "\x1b[I";
38
39
  const FOCUS_OUT = "\x1b[O";
39
40
  const ENABLE_FOCUS_REPORTING = "\x1b[?1004h";
@@ -87,8 +88,21 @@ type BridgeState = {
87
88
  lastClipboard?: string;
88
89
  lastPasted?: string;
89
90
  lastPasteSummary?: string;
91
+ activeTabCache?: { ok: boolean; checkedAt: number };
90
92
  };
91
93
 
94
+ let cachedOwnerDenylistEnv: string | undefined;
95
+ let cachedOwnerDenylist: readonly string[] | undefined;
96
+ let cachedClipboardScript: { limit: number; script: string } | undefined;
97
+
98
+ type RuntimeConfig = {
99
+ intervalMs: number;
100
+ maxChars: number;
101
+ ignoreCopyMs: number;
102
+ };
103
+
104
+ let cachedRuntimeConfig: RuntimeConfig | undefined;
105
+
92
106
  const state: BridgeState = {
93
107
  mode: defaultMode(),
94
108
  generation: 0,
@@ -101,35 +115,60 @@ function defaultMode(): BridgeMode {
101
115
  return ["0", "false", "no", "off"].includes(raw) ? "off" : "on";
102
116
  }
103
117
 
118
+ /** Cached poll/copy limits parsed from env (hot path on every interval tick). */
119
+ function runtimeConfig(): RuntimeConfig {
120
+ if (cachedRuntimeConfig) return cachedRuntimeConfig;
121
+
122
+ const parsedInterval = Number(process.env.PI_SUPERWHISPER_PASTE_INTERVAL_MS);
123
+ const parsedMaxChars = Number(process.env.PI_SUPERWHISPER_PASTE_MAX_CHARS);
124
+ const parsedIgnoreCopy = Number(process.env.PI_SUPERWHISPER_PASTE_IGNORE_COPY_MS);
125
+
126
+ cachedRuntimeConfig = {
127
+ intervalMs:
128
+ Number.isFinite(parsedInterval) && parsedInterval > 0 ? parsedInterval : DEFAULT_INTERVAL_MS,
129
+ maxChars:
130
+ Number.isFinite(parsedMaxChars) && parsedMaxChars > 0 ? parsedMaxChars : DEFAULT_MAX_CHARS,
131
+ ignoreCopyMs:
132
+ Number.isFinite(parsedIgnoreCopy) && parsedIgnoreCopy >= 0
133
+ ? parsedIgnoreCopy
134
+ : DEFAULT_IGNORE_COPY_MS,
135
+ };
136
+ return cachedRuntimeConfig;
137
+ }
138
+
104
139
  /** Poll interval from env or default. */
105
140
  function intervalMs(): number {
106
- const parsed = Number(process.env.PI_SUPERWHISPER_PASTE_INTERVAL_MS);
107
- return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_INTERVAL_MS;
141
+ return runtimeConfig().intervalMs;
108
142
  }
109
143
 
110
144
  /** Max pasted characters from env or default. */
111
145
  function maxChars(): number {
112
- const parsed = Number(process.env.PI_SUPERWHISPER_PASTE_MAX_CHARS);
113
- return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_MAX_CHARS;
146
+ return runtimeConfig().maxChars;
114
147
  }
115
148
 
116
149
  /** Ignore clipboard changes briefly after local copy shortcuts. */
117
150
  function ignoreCopyMs(): number {
118
- const parsed = Number(process.env.PI_SUPERWHISPER_PASTE_IGNORE_COPY_MS);
119
- return Number.isFinite(parsed) && parsed >= 0 ? parsed : DEFAULT_IGNORE_COPY_MS;
151
+ return runtimeConfig().ignoreCopyMs;
120
152
  }
121
153
 
122
154
  /** Process-name/path substrings denied from triggering auto-paste. */
123
- function ownerDenylist(): string[] {
124
- const raw = process.env.PI_SUPERWHISPER_PASTE_OWNER_DENYLIST;
125
- if (!raw) return DEFAULT_OWNER_DENYLIST;
155
+ function ownerDenylist(): readonly string[] {
156
+ const raw = process.env.PI_SUPERWHISPER_PASTE_OWNER_DENYLIST ?? "";
157
+ if (cachedOwnerDenylist && cachedOwnerDenylistEnv === raw) return cachedOwnerDenylist;
158
+
159
+ cachedOwnerDenylistEnv = raw;
160
+ if (!raw) {
161
+ cachedOwnerDenylist = DEFAULT_OWNER_DENYLIST;
162
+ return cachedOwnerDenylist;
163
+ }
126
164
 
127
165
  const tokens = raw
128
166
  .split(",")
129
167
  .map((token) => token.trim().toLowerCase())
130
168
  .filter(Boolean);
131
169
 
132
- return tokens.length > 0 ? tokens : DEFAULT_OWNER_DENYLIST;
170
+ cachedOwnerDenylist = tokens.length > 0 ? tokens : DEFAULT_OWNER_DENYLIST;
171
+ return cachedOwnerDenylist;
133
172
  }
134
173
 
135
174
  /** Status bar label for the paste bridge. */
@@ -227,8 +266,17 @@ function markPasted(ctx: PiRuntimeContext, generation: number, text: string): vo
227
266
  setStatus(ctx, generation);
228
267
  }
229
268
 
269
+ /** Returns a cached PowerShell clipboard script for the current char limit. */
270
+ function clipboardPowerShellCommand(limit: number): string {
271
+ if (cachedClipboardScript?.limit === limit) return cachedClipboardScript.script;
272
+
273
+ const script = buildClipboardPowerShellScript(limit);
274
+ cachedClipboardScript = { limit, script };
275
+ return script;
276
+ }
277
+
230
278
  /** Builds a PowerShell command that reads clipboard text truncated to `limit` characters. */
231
- function clipboardPowerShellScript(limit: number): string {
279
+ function buildClipboardPowerShellScript(limit: number): string {
232
280
  return [
233
281
  "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8",
234
282
  "$signature = @\"",
@@ -273,7 +321,7 @@ async function readClipboardSnapshot(): Promise<ClipboardSnapshot | undefined> {
273
321
  try {
274
322
  const result = await execFileAsync(
275
323
  "powershell.exe",
276
- ["-NoProfile", "-Command", clipboardPowerShellScript(limit)],
324
+ ["-NoProfile", "-Command", clipboardPowerShellCommand(limit)],
277
325
  {
278
326
  encoding: "utf8",
279
327
  maxBuffer: limit * 4 + 1024,
@@ -300,9 +348,9 @@ async function readClipboardSnapshot(): Promise<ClipboardSnapshot | undefined> {
300
348
  }
301
349
  }
302
350
 
303
- /** Temp file path for cross-tab active-instance claim. */
304
- function activeStatePath(): string {
305
- return join(tmpdir(), ACTIVE_STATE_FILE);
351
+ /** Clears cached active-tab ownership between focus or session changes. */
352
+ function invalidateActiveTabCache(): void {
353
+ state.activeTabCache = undefined;
306
354
  }
307
355
 
308
356
  /** Writes this Pi instance as the active tab for paste gating. */
@@ -314,8 +362,11 @@ async function claimActiveTab(): Promise<void> {
314
362
  };
315
363
 
316
364
  try {
317
- await writeFile(activeStatePath(), JSON.stringify(claim), "utf8");
365
+ await writeFile(ACTIVE_STATE_PATH, JSON.stringify(claim), "utf8");
366
+ // Cache only negative ownership: a cached positive claim could let another
367
+ // instance's overwrite go unnoticed and paste into an inactive tab.
318
368
  } catch {
369
+ invalidateActiveTabCache();
319
370
  // Focus tracking is best-effort; clipboard safety still falls back to local focus state.
320
371
  }
321
372
  }
@@ -324,10 +375,16 @@ async function claimActiveTab(): Promise<void> {
324
375
  async function isActiveTab(): Promise<boolean> {
325
376
  if (!state.terminalFocused) return false;
326
377
 
378
+ const now = Date.now();
379
+ const cache = state.activeTabCache;
380
+ if (cache?.ok === false && now - cache.checkedAt < intervalMs()) return false;
381
+
327
382
  try {
328
- const raw = await readFile(activeStatePath(), "utf8");
383
+ const raw = await readFile(ACTIVE_STATE_PATH, "utf8");
329
384
  const claim = JSON.parse(raw) as { instanceId?: string };
330
- return claim.instanceId === INSTANCE_ID;
385
+ const ok = claim.instanceId === INSTANCE_ID;
386
+ state.activeTabCache = ok ? undefined : { ok: false, checkedAt: now };
387
+ return ok;
331
388
  } catch {
332
389
  await claimActiveTab();
333
390
  return true;
@@ -506,6 +563,7 @@ function setupTerminalFocusTracking(ctx: PiRuntimeContext, generation: number):
506
563
 
507
564
  if (data === FOCUS_OUT) {
508
565
  state.terminalFocused = false;
566
+ invalidateActiveTabCache();
509
567
  setStatus(ctx, generation);
510
568
  return { consume: true };
511
569
  }
@@ -551,6 +609,7 @@ function teardownSessionResources(): void {
551
609
  state.baselineRefreshTimeout = undefined;
552
610
  }
553
611
  teardownTerminalFocusTracking();
612
+ invalidateActiveTabCache();
554
613
  state.inFlightGeneration = undefined;
555
614
  state.activatingGeneration = undefined;
556
615
  state.suppressPasteUntil = undefined;
package/package.json CHANGED
@@ -1,63 +1,63 @@
1
- {
2
- "name": "pi-superwhisper-paste",
3
- "version": "0.1.20",
4
- "description": "Superwhisper clipboard bridge for Pi on Windows.",
5
- "type": "module",
6
- "license": "MIT",
7
- "author": "Keisu",
8
- "keywords": [
9
- "pi",
10
- "pi-package",
11
- "pi-extension",
12
- "superwhisper",
13
- "clipboard",
14
- "windows",
15
- "typescript"
16
- ],
17
- "repository": {
18
- "type": "git",
19
- "url": "git+https://github.com/eiei114/pi-superwhisper-paste.git"
20
- },
21
- "bugs": {
22
- "url": "https://github.com/eiei114/pi-superwhisper-paste/issues"
23
- },
24
- "homepage": "https://github.com/eiei114/pi-superwhisper-paste#readme",
25
- "files": [
26
- "extensions/",
27
- "lib/",
28
- "skills/",
29
- "prompts/",
30
- "themes/",
31
- "docs/",
32
- "README.md",
33
- "LICENSE",
34
- "CHANGELOG.md"
35
- ],
36
- "scripts": {
37
- "typecheck": "tsc --noEmit",
38
- "test": "node --test tests/*.test.mjs",
39
- "ci": "npm run typecheck && npm test && npm run pack:check",
40
- "pack:check": "npm pack --dry-run",
41
- "version:check": "node scripts/check-version-bump.mjs"
42
- },
43
- "pi": {
44
- "extensions": [
45
- "./extensions"
46
- ]
47
- },
48
- "publishConfig": {
49
- "access": "public"
50
- },
51
- "peerDependencies": {
52
- "@earendil-works/pi-ai": "*",
53
- "@earendil-works/pi-coding-agent": "*",
54
- "@earendil-works/pi-tui": "*"
55
- },
56
- "devDependencies": {
57
- "@earendil-works/pi-ai": "latest",
58
- "@earendil-works/pi-coding-agent": "latest",
59
- "@earendil-works/pi-tui": "latest",
60
- "@types/node": "^26.0.1",
61
- "typescript": "^7.0.2"
62
- }
63
- }
1
+ {
2
+ "name": "pi-superwhisper-paste",
3
+ "version": "0.1.23",
4
+ "description": "Superwhisper clipboard bridge for Pi on Windows.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Keisu",
8
+ "keywords": [
9
+ "pi",
10
+ "pi-package",
11
+ "pi-extension",
12
+ "superwhisper",
13
+ "clipboard",
14
+ "windows",
15
+ "typescript"
16
+ ],
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/eiei114/pi-superwhisper-paste.git"
20
+ },
21
+ "bugs": {
22
+ "url": "https://github.com/eiei114/pi-superwhisper-paste/issues"
23
+ },
24
+ "homepage": "https://github.com/eiei114/pi-superwhisper-paste#readme",
25
+ "files": [
26
+ "extensions/",
27
+ "lib/",
28
+ "skills/",
29
+ "prompts/",
30
+ "themes/",
31
+ "docs/",
32
+ "README.md",
33
+ "LICENSE",
34
+ "CHANGELOG.md"
35
+ ],
36
+ "scripts": {
37
+ "typecheck": "tsc --noEmit",
38
+ "test": "node --test tests/*.test.mjs",
39
+ "ci": "npm run typecheck && npm test && npm run pack:check",
40
+ "pack:check": "npm pack --dry-run",
41
+ "version:check": "node scripts/check-version-bump.mjs"
42
+ },
43
+ "pi": {
44
+ "extensions": [
45
+ "./extensions"
46
+ ]
47
+ },
48
+ "publishConfig": {
49
+ "access": "public"
50
+ },
51
+ "peerDependencies": {
52
+ "@earendil-works/pi-ai": "*",
53
+ "@earendil-works/pi-coding-agent": "*",
54
+ "@earendil-works/pi-tui": "*"
55
+ },
56
+ "devDependencies": {
57
+ "@earendil-works/pi-ai": "latest",
58
+ "@earendil-works/pi-coding-agent": "latest",
59
+ "@earendil-works/pi-tui": "latest",
60
+ "@types/node": "^26.0.1",
61
+ "typescript": "^7.0.2"
62
+ }
63
+ }