@nicknisi/pi-stash 0.1.3 → 0.1.5
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 +19 -9
- package/dist/index.d.ts +4 -4
- package/dist/index.js +6 -6
- package/dist/index.test.js +3 -3
- package/index.ts +6 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# @nicknisi/pi-stash
|
|
2
2
|
|
|
3
|
-
Replicates Claude Code's message stash using `ctrl+
|
|
3
|
+
Replicates Claude Code's message stash using `ctrl+s`. Rebind Pi's built-in `ctrl+s` actions as shown below to avoid shortcut conflicts. Press `ctrl+s` to stash whatever you've typed in the input editor, go do something else, then press `ctrl+s` again with an empty editor to pop the most recent stash back. Stashes live on a stack, so multiple drafts can be parked and restored LIFO.
|
|
4
4
|
|
|
5
5
|
## What it adds
|
|
6
6
|
|
|
7
|
-
- **Keybinding:** `ctrl+
|
|
8
|
-
- **Widget:** a single-line widget above the editor, visible whenever the stash stack is non-empty, showing a 60-char preview of the most recent stash, the count of additional stashes (`(+N more)`), and a `ctrl+
|
|
7
|
+
- **Keybinding:** `ctrl+s` toggles stash/restore. See the behavior table below.
|
|
8
|
+
- **Widget:** a single-line widget above the editor, visible whenever the stash stack is non-empty, showing a 60-char preview of the most recent stash, the count of additional stashes (`(+N more)`), and a `ctrl+s to restore` hint
|
|
9
9
|
- **Events hooked:** `before_agent_start` — after a message is submitted and the agent starts, the most recent stash is auto-restored into the now-empty editor (mirrors Claude Code)
|
|
10
10
|
- No slash commands, no tools, no custom entry types.
|
|
11
11
|
|
|
12
12
|
### Keybinding behavior
|
|
13
13
|
|
|
14
|
-
| Editor state on `ctrl+
|
|
14
|
+
| Editor state on `ctrl+s` | Action |
|
|
15
15
|
| ----------------------------------------- | ------------------------------------------ |
|
|
16
16
|
| Contains text | Push text onto the stack, clear the editor |
|
|
17
17
|
| Empty (or whitespace) and stack non-empty | Pop the most recent stash into the editor |
|
|
@@ -21,16 +21,26 @@ Replicates Claude Code's message stash using `ctrl+shift+s` to avoid conflicts w
|
|
|
21
21
|
|
|
22
22
|
```text
|
|
23
23
|
(type a long prompt, then need to ask something else first)
|
|
24
|
-
ctrl+
|
|
24
|
+
ctrl+s "⧉ stashed: Refactor the auth module to..." · editor cleared
|
|
25
25
|
(ask the other question; on submit, the stashed draft is restored automatically)
|
|
26
|
-
ctrl+
|
|
26
|
+
ctrl+s (with empty editor) pops the stash back manually
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
The stash is in-memory only (per session, per process). It is not persisted across restarts.
|
|
30
30
|
|
|
31
31
|
## Configuration
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
The stash shortcut is fixed at `ctrl+s`. Move Pi's built-in actions off that key in `~/.pi/agent/keybindings.json`:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"app.models.save": ["ctrl+shift+v"],
|
|
38
|
+
"app.thinking.save": ["ctrl+shift+v"],
|
|
39
|
+
"app.session.toggleSort": ["ctrl+shift+r"]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Merge these entries into your existing config, then run `/reload`. Model-save and thinking-save use separate selectors, so they can share a key. `pi-web-access` can keep its default `ctrl+shift+s` curator shortcut.
|
|
34
44
|
|
|
35
45
|
## Dependencies
|
|
36
46
|
|
|
@@ -41,9 +51,9 @@ None. No config files, no options, no environment variables.
|
|
|
41
51
|
|
|
42
52
|
- UI-gated: every handler checks `ctx.hasUI`; the extension is a no-op in headless/non-TUI mode.
|
|
43
53
|
- Depends on the editor text APIs (`ctx.ui.getEditorText` / `setEditorText`) and the widget system (`ctx.ui.setWidget`) — these are stable pi extension APIs, but a pi version that changes editor or widget semantics could affect it.
|
|
44
|
-
- The `before_agent_start` auto-restore pops a stash whenever a message is sent with an empty editor. If you intentionally sent a quick command and wanted the stash to stay parked, it will still be restored into the editor (you can `ctrl+
|
|
54
|
+
- The `before_agent_start` auto-restore pops a stash whenever a message is sent with an empty editor. If you intentionally sent a quick command and wanted the stash to stay parked, it will still be restored into the editor (you can `ctrl+s` it back). This matches Claude Code's behavior.
|
|
45
55
|
- Stash stack is module-local state; it does not survive session reload or extension reload.
|
|
46
|
-
- The terminal
|
|
56
|
+
- The shifted replacement shortcuts require a terminal that reports them distinctly, for example through the Kitty keyboard protocol. The widget preview uses the Unicode glyphs `⧉` and `…`.
|
|
47
57
|
|
|
48
58
|
## Install
|
|
49
59
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Message Stash Extension
|
|
3
3
|
*
|
|
4
|
-
* Replicates Claude Code's message stash: press ctrl+
|
|
4
|
+
* Replicates Claude Code's message stash: press ctrl+s to stash
|
|
5
5
|
* whatever you've typed in the input box, do something else, then press
|
|
6
|
-
* ctrl+
|
|
6
|
+
* ctrl+s again (with an empty input) to restore it.
|
|
7
7
|
*
|
|
8
|
-
* - ctrl+
|
|
9
|
-
* - ctrl+
|
|
8
|
+
* - ctrl+s with text in the editor → pushes it onto a stack and clears
|
|
9
|
+
* - ctrl+s with an empty editor → pops the most recent stash back
|
|
10
10
|
* - sending another message → auto-restores the most recent stash
|
|
11
11
|
*
|
|
12
12
|
* A widget above the editor shows how many messages are stashed with a
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Message Stash Extension
|
|
3
3
|
*
|
|
4
|
-
* Replicates Claude Code's message stash: press ctrl+
|
|
4
|
+
* Replicates Claude Code's message stash: press ctrl+s to stash
|
|
5
5
|
* whatever you've typed in the input box, do something else, then press
|
|
6
|
-
* ctrl+
|
|
6
|
+
* ctrl+s again (with an empty input) to restore it.
|
|
7
7
|
*
|
|
8
|
-
* - ctrl+
|
|
9
|
-
* - ctrl+
|
|
8
|
+
* - ctrl+s with text in the editor → pushes it onto a stack and clears
|
|
9
|
+
* - ctrl+s with an empty editor → pops the most recent stash back
|
|
10
10
|
* - sending another message → auto-restores the most recent stash
|
|
11
11
|
*
|
|
12
12
|
* A widget above the editor shows how many messages are stashed with a
|
|
@@ -28,10 +28,10 @@ export default function stash(pi) {
|
|
|
28
28
|
const preview = firstLine.length > 60 ? `${firstLine.slice(0, 60)}…` : firstLine;
|
|
29
29
|
const count = stack.length > 1 ? theme.fg('dim', ` (+${stack.length - 1} more)`) : '';
|
|
30
30
|
ctx.ui.setWidget(WIDGET_KEY, [
|
|
31
|
-
`${theme.fg('accent', '⧉ stashed:')} ${theme.fg('muted', preview)}${count} ${theme.fg('dim', '· ctrl+
|
|
31
|
+
`${theme.fg('accent', '⧉ stashed:')} ${theme.fg('muted', preview)}${count} ${theme.fg('dim', '· ctrl+s to restore')}`,
|
|
32
32
|
]);
|
|
33
33
|
};
|
|
34
|
-
pi.registerShortcut('ctrl+
|
|
34
|
+
pi.registerShortcut('ctrl+s', {
|
|
35
35
|
description: 'Stash / restore the typed message',
|
|
36
36
|
handler: async (ctx) => {
|
|
37
37
|
if (!ctx.hasUI)
|
package/dist/index.test.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { expect, it, vi } from 'vitest';
|
|
2
2
|
import stash from './index.js';
|
|
3
|
-
it('stashes and restores drafts with Ctrl+
|
|
3
|
+
it('stashes and restores drafts with Ctrl+S and shows the matching hint', async () => {
|
|
4
4
|
const registerShortcut = vi.fn();
|
|
5
5
|
stash({ registerShortcut, on: vi.fn() });
|
|
6
6
|
expect(registerShortcut).toHaveBeenCalledOnce();
|
|
7
7
|
const [key, { handler }] = registerShortcut.mock.calls[0];
|
|
8
|
-
expect(key).toBe('ctrl+
|
|
8
|
+
expect(key).toBe('ctrl+s');
|
|
9
9
|
let text = 'first draft';
|
|
10
10
|
const setWidget = vi.fn();
|
|
11
11
|
const ctx = {
|
|
@@ -21,7 +21,7 @@ it('stashes and restores drafts with Ctrl+Shift+S and shows the matching hint',
|
|
|
21
21
|
};
|
|
22
22
|
await handler(ctx);
|
|
23
23
|
expect(text).toBe('');
|
|
24
|
-
expect(setWidget).toHaveBeenLastCalledWith('message-stash', [expect.stringContaining('ctrl+
|
|
24
|
+
expect(setWidget).toHaveBeenLastCalledWith('message-stash', [expect.stringContaining('ctrl+s to restore')]);
|
|
25
25
|
text = 'second draft';
|
|
26
26
|
await handler(ctx);
|
|
27
27
|
expect(text).toBe('');
|
package/index.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Message Stash Extension
|
|
3
3
|
*
|
|
4
|
-
* Replicates Claude Code's message stash: press ctrl+
|
|
4
|
+
* Replicates Claude Code's message stash: press ctrl+s to stash
|
|
5
5
|
* whatever you've typed in the input box, do something else, then press
|
|
6
|
-
* ctrl+
|
|
6
|
+
* ctrl+s again (with an empty input) to restore it.
|
|
7
7
|
*
|
|
8
|
-
* - ctrl+
|
|
9
|
-
* - ctrl+
|
|
8
|
+
* - ctrl+s with text in the editor → pushes it onto a stack and clears
|
|
9
|
+
* - ctrl+s with an empty editor → pops the most recent stash back
|
|
10
10
|
* - sending another message → auto-restores the most recent stash
|
|
11
11
|
*
|
|
12
12
|
* A widget above the editor shows how many messages are stashed with a
|
|
@@ -32,11 +32,11 @@ export default function stash(pi: ExtensionAPI) {
|
|
|
32
32
|
const preview = firstLine.length > 60 ? `${firstLine.slice(0, 60)}…` : firstLine;
|
|
33
33
|
const count = stack.length > 1 ? theme.fg('dim', ` (+${stack.length - 1} more)`) : '';
|
|
34
34
|
ctx.ui.setWidget(WIDGET_KEY, [
|
|
35
|
-
`${theme.fg('accent', '⧉ stashed:')} ${theme.fg('muted', preview)}${count} ${theme.fg('dim', '· ctrl+
|
|
35
|
+
`${theme.fg('accent', '⧉ stashed:')} ${theme.fg('muted', preview)}${count} ${theme.fg('dim', '· ctrl+s to restore')}`,
|
|
36
36
|
]);
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
-
pi.registerShortcut('ctrl+
|
|
39
|
+
pi.registerShortcut('ctrl+s', {
|
|
40
40
|
description: 'Stash / restore the typed message',
|
|
41
41
|
handler: async (ctx) => {
|
|
42
42
|
if (!ctx.hasUI) return;
|