multi-agent-prompt 0.1.0__tar.gz

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,47 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - main
10
+
11
+ env:
12
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
13
+
14
+ jobs:
15
+ lint:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ # https://github.com/actions/checkout
19
+ - uses: actions/checkout@v6
20
+ with:
21
+ fetch-depth: 0
22
+
23
+ # The autosave/keymap/fold-on-paste integration tests drive a real
24
+ # Neovim (headless, and over a pseudo-terminal for anything that needs
25
+ # actual UI attachment — TextChanged and startinsert! don't fire
26
+ # without one). They skip gracefully if nvim is missing, but that
27
+ # would silently stop covering the thing this project mostly is.
28
+ - name: Install Neovim
29
+ run: sudo apt-get update && sudo apt-get install -y neovim
30
+
31
+ # https://github.com/astral-sh/setup-uv
32
+ - name: Install uv
33
+ uses: astral-sh/setup-uv@v7
34
+ with:
35
+ enable-cache: true
36
+
37
+ - name: Set up Python
38
+ run: uv python install
39
+
40
+ - name: Run ruff
41
+ run: uv run ruff check .
42
+
43
+ - name: Run mypy
44
+ run: uv run mypy src
45
+
46
+ - name: Run pytest
47
+ run: uv run pytest
@@ -0,0 +1,52 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ env:
9
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
10
+
11
+ jobs:
12
+ publish:
13
+ name: Build and publish
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ id-token: write
17
+ contents: write
18
+ attestations: write
19
+
20
+ steps:
21
+ # https://github.com/actions/checkout
22
+ - uses: actions/checkout@v6
23
+ with:
24
+ fetch-depth: 0
25
+
26
+ # See ci.yml: the integration tests need a real Neovim to run at all
27
+ # rather than skip.
28
+ - name: Install Neovim
29
+ run: sudo apt-get update && sudo apt-get install -y neovim
30
+
31
+ # https://github.com/astral-sh/setup-uv
32
+ - name: Install uv
33
+ uses: astral-sh/setup-uv@v7
34
+ with:
35
+ enable-cache: true
36
+
37
+ - name: Set up Python
38
+ run: uv python install
39
+
40
+ - name: Install dependencies
41
+ run: uv sync
42
+
43
+ - name: Run test suite
44
+ run: uv run pytest
45
+
46
+ - name: Build package
47
+ run: uv build
48
+
49
+ - name: Publish to PyPI
50
+ uses: pypa/gh-action-pypi-publish@release/v1
51
+ with:
52
+ verbose: true
@@ -0,0 +1,17 @@
1
+ .venv
2
+ __pycache__/
3
+ *.pyc
4
+ dist/
5
+ *.egg-info/
6
+ .pytest_cache/
7
+ .ruff_cache/
8
+ .mypy_cache/
9
+ .ma/prompt/
10
+
11
+ # task-agent auto-registers any git repo it finds under ~/repos/ as one of
12
+ # its own task stores — unrelated to this project, not ours to track.
13
+ # docs/tasks is a symlink it manages, pointing at a machine-specific
14
+ # absolute path — must never be committed as a real symlink.
15
+ .env
16
+ .ta-config.json
17
+ docs/tasks
@@ -0,0 +1,231 @@
1
+ Metadata-Version: 2.5
2
+ Name: multi-agent-prompt
3
+ Version: 0.1.0
4
+ Summary: A crash-proof, autosaving prompt editor for AI coding agent CLIs — compose in your real editor, hand off with a slash command
5
+ Author-email: Mark Stouffer <1802850+InTEGr8or@users.noreply.github.com>
6
+ License: MIT
7
+ Requires-Python: >=3.12
8
+ Requires-Dist: rich>=13.9.4
9
+ Requires-Dist: verkit>=0.1.4
10
+ Description-Content-Type: text/markdown
11
+
12
+ # Multi-Agent Prompt ✍️
13
+
14
+ A crash-proof, autosaving prompt editor for AI coding agent CLIs.
15
+
16
+ Chat text boxes lose long, carefully-composed prompts to a single wrong
17
+ keystroke, and give you almost no editing power while you write. `multi-agent-prompt`
18
+ moves composition out of the chat box entirely: write in a real Neovim, in a
19
+ split pane next to your agent session, autosaved to disk every couple of
20
+ seconds so a crash or a fat-fingered shortcut can never cost you more than a
21
+ moment of typing. When you're ready, hand it to the agent with `/prompt` —
22
+ which reads it, archives it, and clears the file in one step, so there's no
23
+ separate "now go clear it" to remember.
24
+
25
+ ---
26
+
27
+ ## Install
28
+
29
+ ```bash
30
+ pip install multi-agent-prompt
31
+ # or
32
+ uv tool install multi-agent-prompt
33
+ ```
34
+
35
+ Requires [Neovim](https://neovim.io/) — the autosave hook is Lua, so plain
36
+ Vim isn't supported.
37
+
38
+ ## Usage
39
+
40
+ Open a split pane next to your agent CLI (Windows Terminal: `Alt+Shift+-`;
41
+ tmux: `<prefix> "`) in the **same working directory**, then run:
42
+
43
+ ```bash
44
+ map
45
+ ```
46
+
47
+ This opens `.ma/prompt/current.md` — resolved to the current project's git
48
+ root, so every pane in the same repo shares one scratch file — in your actual
49
+ `nvim`, your actual `init.lua`, your actual keymaps and plugins. No config
50
+ import step, no reimplemented Vim subset: it's just Neovim. You land in
51
+ **insert mode already**, cursor at the end of the buffer, so there's no `i`
52
+ to press before you start typing (`--no-insert` if you'd rather open in
53
+ normal mode). A buffer-local autocmd (scoped only to this one buffer — it
54
+ never touches how you edit anything else) autosaves ~2 seconds after you stop
55
+ typing, and immediately when you switch away from the pane
56
+ (`FocusLost`/`BufLeave`), so the save always beats you to the chat window.
57
+
58
+ When you're done, switch back to the agent pane and either:
59
+
60
+ - Type `/prompt` (if the agent's install includes the skill — see below) —
61
+ reads the draft, archives it, and clears the file, all in one step, or
62
+ - Reference `@prompt.md` / `@.ma/prompt/current.md` directly, if your agent
63
+ supports file mentions and can see gitignored files — this is a plain
64
+ read, so unlike `/prompt` it doesn't archive or clear anything.
65
+
66
+ Pasting a long CLI transcript or diff in? Anything **6 lines or more**
67
+ (bracketed paste, `"+p`, `"*p` — any paste source) auto-folds, closed, so it
68
+ doesn't bury the rest of what you're writing — `za`/`zo`/`zc` (standard Vim)
69
+ toggle it open.
70
+
71
+ Also want to browse past drafts without leaving the editor? A buffer-local
72
+ keymap — `<leader>ph` by default — lists archived drafts (newest first) in a
73
+ split; `<CR>` opens one, read-only. Forgot what any of this is bound to?
74
+ Press `g?` — it shows exactly the keymaps active for *this* session
75
+ (respecting any `--clear-key`/`--history-key` overrides, and omitting
76
+ whichever ones you disabled):
77
+
78
+ ```
79
+ map # open the scratch file (same as `map edit`)
80
+ map where # print the resolved file path
81
+ map show # print its current content to stdout (does not clear it)
82
+ map pop # print it, archive it, and clear it — what /prompt uses
83
+ map clear # archive the current draft, then empty it, without printing it
84
+ map --clean # skip your init.lua entirely (-u NONE) for faster startup
85
+ ```
86
+
87
+ ```
88
+ map edit --clear-key '<F5>' # rebind the in-editor clear keymap
89
+ map edit --no-clear-key # don't register it at all
90
+ map edit --history-key '<F6>' # rebind the in-editor history-browse keymap
91
+ map edit --no-history-key # don't register it at all
92
+ map edit --help-key '<F1>' # rebind the in-editor g? cheatsheet keymap
93
+ map edit --no-help-key # don't register it at all
94
+ map edit --fold-threshold 3 # auto-fold pastes of 3+ lines instead of 6
95
+ map edit --no-fold-paste # don't auto-fold pastes at all
96
+ map edit --no-insert # open in normal mode instead of insert mode
97
+ map clear --keep 20 # override how many archived drafts to retain
98
+ map clear --no-archive # discard instead of archiving (e.g. it had a secret in it)
99
+ ```
100
+
101
+ `map pop` accepts the same `--keep`/`--no-archive` as `map clear`.
102
+
103
+ ### The archive
104
+
105
+ `map pop`/`map clear` — from the CLI or the in-editor keymap, which shells
106
+ out to `map clear` — never actually discard a non-empty draft; they move it
107
+ to `.ma/prompt/archive/<timestamp>-<seq>.md` first, then prune that archive
108
+ down to the most recent entries. Pruning is by **count**, not age (`--keep` /
109
+ `MAP_ARCHIVE_KEEP` env var, default **10**) — simpler to reason about than a
110
+ retention window, and it doesn't depend on the clock. Use `--no-archive` for
111
+ the one case that shouldn't be kept anywhere: you pasted a secret and want it
112
+ actually gone.
113
+
114
+ ## Performance
115
+
116
+ A `map` session opens your *entire* Neovim config, which is exactly the
117
+ point — but if that config is large, startup isn't free. Two things worth
118
+ knowing, from actually measuring it (not guessing):
119
+
120
+ - **It's not a one-time thing.** Whatever makes your first `map` slow will
121
+ make every subsequent one about equally slow, unless something changes
122
+ (lazy.nvim itself finishes installing/compiling once; LSP servers and
123
+ large plugin trees generally don't get meaningfully faster after that).
124
+ - **On WSL specifically, check for `vim.opt.clipboard = 'unnamedplus'` (or
125
+ similar) in your own init.lua.** Setting that option makes Neovim probe for
126
+ a clipboard provider immediately, and on WSL that probe walks every `PATH`
127
+ entry checking `executable()` — including everything under `/mnt/c/...`,
128
+ which is slow cross-filesystem interop. Measured on this project's own dev
129
+ machine: ~900ms startup with that line in play, ~160ms with the Windows
130
+ `PATH` entries stripped, ~4ms with `-u NONE`. That's not multi-agent-prompt
131
+ overhead; it's one line in a personal init.lua interacting badly with WSL,
132
+ and fixing it (or guarding it — see `MAP_SESSION` below) speeds up *every*
133
+ Neovim session, not just `map`.
134
+ - **`map --clean` (`-u NONE`)** sidesteps all of it by skipping your config
135
+ entirely — the built-in fast path when you don't need your plugins for a
136
+ quick edit.
137
+ - **`MAP_SESSION=1`** is set in the environment of every nvim `map` launches.
138
+ Nothing in this package reads it — it's there so you can guard an
139
+ expensive line in your *own* init.lua behind
140
+ `if not vim.env.MAP_SESSION then ... end`, if you want full-config speed
141
+ back without giving up faster `map` startup. That's your config to edit,
142
+ not something this tool does for you. This isn't just for the clipboard
143
+ line above — a scratch prompt buffer has no use for a file-tree sidebar or
144
+ git tooling either, and with [lazy.nvim](https://github.com/folke/lazy.nvim)
145
+ you can skip those specific plugins the same way, with `cond` on the spec:
146
+
147
+ ```lua
148
+ return {
149
+ 'nvim-neo-tree/neo-tree.nvim',
150
+ cond = not vim.env.MAP_SESSION,
151
+ -- ...
152
+ }
153
+ ```
154
+
155
+ Confirmed on this project's own dev config: with `neo-tree.nvim` and
156
+ `gitsigns.nvim` guarded this way, `<leader>e` (NeoTree's toggle) becomes a
157
+ no-op in a `map` session, and their entire module trees (dozens of
158
+ individual `require()` calls each) simply don't load — real startup
159
+ savings, not just fewer keymaps to trip over. `cond` is evaluated on every
160
+ start, so this takes effect immediately; no `:Lazy sync`/restart needed.
161
+ - **It's specifically a startup cost, not a per-save one.** The clipboard
162
+ probe runs once, while your init.lua is sourced, not again on autosave, on
163
+ `FocusLost`, or when you switch panes and type `/prompt` — that last step
164
+ never touches nvim at all (`map pop`/reading the file is a separate,
165
+ plain filesystem read and write). If a session still feels slow at the
166
+ hand-off moment specifically, that's terminal pane-switching or the
167
+ agent's own slash-command overhead, not this tool or Neovim.
168
+ - **`/prompt`'s own overhead is small, and it isn't Neovim's.** Measured on
169
+ this project's own dev machine: `map pop` runs in ~60-85ms end to end —
170
+ bare `python3 -c pass` alone is ~30ms of that, this package's own imports
171
+ add maybe another ~20ms, and the rest is the file read/archive/write. If
172
+ `/prompt` still feels slow, that latency lives in the *agent host's* own
173
+ tool-call round trip (spawning/sandboxing the shell command), not in
174
+ anything this package does — there's no nvim process in this path at all.
175
+ The one thing the `prompt` skill itself controls: it runs `map pop`
176
+ directly rather than checking `which map` first, since that check is a
177
+ second subprocess spawn that's a wasted round trip almost every time.
178
+
179
+ ## Agent integration
180
+
181
+ `skills/prompt/` is a portable [Agent Skill](https://code.claude.com/docs/en/skills)
182
+ that teaches a host to read `.ma/prompt/current.md` and treat its content as
183
+ the user's message when they type `/prompt`. See
184
+ [`skills/README.md`](./skills/README.md) for install paths.
185
+
186
+ ## Why not tmux `send-keys` / auto-injection?
187
+
188
+ That's the obvious next step — save, close the pane, and have the tool type
189
+ `/prompt` into the neighboring agent pane for you — but it needs a reliable
190
+ way to identify *which* pane is running the agent, which varies by terminal
191
+ (tmux panes, Windows Terminal panes, and OS-level input injection like
192
+ `xdotool`/`wtype` all solve a different half of that problem). The manual
193
+ handoff above works everywhere today; auto-injection is being explored as a
194
+ follow-up, potentially building on [`multi-agent-registry`](https://github.com/InTEGr8or/multi-agent-registry)'s
195
+ chat discovery to identify a live agent session (not just a recent one) in
196
+ the same directory.
197
+
198
+ If/when that lands: prefer sending a widely-supported "submit" keystroke —
199
+ `Ctrl+Enter` is the closest thing to a universal convention across chat
200
+ input boxes — into the target pane after typing `/prompt`, over anything
201
+ input-method-specific, so the same injection code has a chance of working
202
+ across agents rather than being re-tuned per host.
203
+
204
+ ## Design notes
205
+
206
+ - **The prompt file is per-project, not global.** `.ma/prompt/current.md`
207
+ resolves against the nearest `.git` root, so working on two projects in two
208
+ terminal tabs never mixes up their scratch files.
209
+ - **`.ma/` is a shared root, not this tool's alone.** It's the umbrella
210
+ directory for the whole multi-agent-* line (`map`'s CLI alias is the shared
211
+ `ma` prefix of `map`/`mar`/`maa`) — one dotfolder instead of one per
212
+ product. Only `.ma/prompt/` is this tool's; a sibling product could use
213
+ `.ma/registry/`, etc., without colliding. Note that `task-agent`'s existing
214
+ `.task-agent/` convention predates this and stays as-is — migrating an
215
+ already-shipped tool's config layout is a separate, larger decision.
216
+ - **`.gitignore` is managed for you.** The first time `map edit` runs in a
217
+ git repo, it appends `.ma/prompt/` to `.gitignore` if it isn't already
218
+ covered — including by a broader pre-existing `.ma/` entry.
219
+ - **Reading is non-destructive; handing off isn't, but it never discards
220
+ either.** `map show` and `@prompt.md` (file mention) just print/read — the
221
+ file is untouched either way. `/prompt` (`map pop`) clears it, because the
222
+ whole point is not needing a separate "now go clear it" step — but it
223
+ archives first, so "cleared" never means "gone". `--no-archive` is the
224
+ explicit opt-out for content that shouldn't be kept anywhere at all.
225
+ - **The editor notices when the file changes out from under it.** `/prompt`
226
+ runs `map pop` from the *agent's* process, not from inside the running
227
+ nvim session — so if you're still looking at that buffer when you hand a
228
+ draft off, it auto-reloads (`autoread` + `checktime` on
229
+ `FocusGained`/`BufEnter`) the next time you focus it, rather than keep
230
+ showing the text you already submitted. It won't discard anything you've
231
+ since typed there unsaved.
@@ -0,0 +1,220 @@
1
+ # Multi-Agent Prompt ✍️
2
+
3
+ A crash-proof, autosaving prompt editor for AI coding agent CLIs.
4
+
5
+ Chat text boxes lose long, carefully-composed prompts to a single wrong
6
+ keystroke, and give you almost no editing power while you write. `multi-agent-prompt`
7
+ moves composition out of the chat box entirely: write in a real Neovim, in a
8
+ split pane next to your agent session, autosaved to disk every couple of
9
+ seconds so a crash or a fat-fingered shortcut can never cost you more than a
10
+ moment of typing. When you're ready, hand it to the agent with `/prompt` —
11
+ which reads it, archives it, and clears the file in one step, so there's no
12
+ separate "now go clear it" to remember.
13
+
14
+ ---
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ pip install multi-agent-prompt
20
+ # or
21
+ uv tool install multi-agent-prompt
22
+ ```
23
+
24
+ Requires [Neovim](https://neovim.io/) — the autosave hook is Lua, so plain
25
+ Vim isn't supported.
26
+
27
+ ## Usage
28
+
29
+ Open a split pane next to your agent CLI (Windows Terminal: `Alt+Shift+-`;
30
+ tmux: `<prefix> "`) in the **same working directory**, then run:
31
+
32
+ ```bash
33
+ map
34
+ ```
35
+
36
+ This opens `.ma/prompt/current.md` — resolved to the current project's git
37
+ root, so every pane in the same repo shares one scratch file — in your actual
38
+ `nvim`, your actual `init.lua`, your actual keymaps and plugins. No config
39
+ import step, no reimplemented Vim subset: it's just Neovim. You land in
40
+ **insert mode already**, cursor at the end of the buffer, so there's no `i`
41
+ to press before you start typing (`--no-insert` if you'd rather open in
42
+ normal mode). A buffer-local autocmd (scoped only to this one buffer — it
43
+ never touches how you edit anything else) autosaves ~2 seconds after you stop
44
+ typing, and immediately when you switch away from the pane
45
+ (`FocusLost`/`BufLeave`), so the save always beats you to the chat window.
46
+
47
+ When you're done, switch back to the agent pane and either:
48
+
49
+ - Type `/prompt` (if the agent's install includes the skill — see below) —
50
+ reads the draft, archives it, and clears the file, all in one step, or
51
+ - Reference `@prompt.md` / `@.ma/prompt/current.md` directly, if your agent
52
+ supports file mentions and can see gitignored files — this is a plain
53
+ read, so unlike `/prompt` it doesn't archive or clear anything.
54
+
55
+ Pasting a long CLI transcript or diff in? Anything **6 lines or more**
56
+ (bracketed paste, `"+p`, `"*p` — any paste source) auto-folds, closed, so it
57
+ doesn't bury the rest of what you're writing — `za`/`zo`/`zc` (standard Vim)
58
+ toggle it open.
59
+
60
+ Also want to browse past drafts without leaving the editor? A buffer-local
61
+ keymap — `<leader>ph` by default — lists archived drafts (newest first) in a
62
+ split; `<CR>` opens one, read-only. Forgot what any of this is bound to?
63
+ Press `g?` — it shows exactly the keymaps active for *this* session
64
+ (respecting any `--clear-key`/`--history-key` overrides, and omitting
65
+ whichever ones you disabled):
66
+
67
+ ```
68
+ map # open the scratch file (same as `map edit`)
69
+ map where # print the resolved file path
70
+ map show # print its current content to stdout (does not clear it)
71
+ map pop # print it, archive it, and clear it — what /prompt uses
72
+ map clear # archive the current draft, then empty it, without printing it
73
+ map --clean # skip your init.lua entirely (-u NONE) for faster startup
74
+ ```
75
+
76
+ ```
77
+ map edit --clear-key '<F5>' # rebind the in-editor clear keymap
78
+ map edit --no-clear-key # don't register it at all
79
+ map edit --history-key '<F6>' # rebind the in-editor history-browse keymap
80
+ map edit --no-history-key # don't register it at all
81
+ map edit --help-key '<F1>' # rebind the in-editor g? cheatsheet keymap
82
+ map edit --no-help-key # don't register it at all
83
+ map edit --fold-threshold 3 # auto-fold pastes of 3+ lines instead of 6
84
+ map edit --no-fold-paste # don't auto-fold pastes at all
85
+ map edit --no-insert # open in normal mode instead of insert mode
86
+ map clear --keep 20 # override how many archived drafts to retain
87
+ map clear --no-archive # discard instead of archiving (e.g. it had a secret in it)
88
+ ```
89
+
90
+ `map pop` accepts the same `--keep`/`--no-archive` as `map clear`.
91
+
92
+ ### The archive
93
+
94
+ `map pop`/`map clear` — from the CLI or the in-editor keymap, which shells
95
+ out to `map clear` — never actually discard a non-empty draft; they move it
96
+ to `.ma/prompt/archive/<timestamp>-<seq>.md` first, then prune that archive
97
+ down to the most recent entries. Pruning is by **count**, not age (`--keep` /
98
+ `MAP_ARCHIVE_KEEP` env var, default **10**) — simpler to reason about than a
99
+ retention window, and it doesn't depend on the clock. Use `--no-archive` for
100
+ the one case that shouldn't be kept anywhere: you pasted a secret and want it
101
+ actually gone.
102
+
103
+ ## Performance
104
+
105
+ A `map` session opens your *entire* Neovim config, which is exactly the
106
+ point — but if that config is large, startup isn't free. Two things worth
107
+ knowing, from actually measuring it (not guessing):
108
+
109
+ - **It's not a one-time thing.** Whatever makes your first `map` slow will
110
+ make every subsequent one about equally slow, unless something changes
111
+ (lazy.nvim itself finishes installing/compiling once; LSP servers and
112
+ large plugin trees generally don't get meaningfully faster after that).
113
+ - **On WSL specifically, check for `vim.opt.clipboard = 'unnamedplus'` (or
114
+ similar) in your own init.lua.** Setting that option makes Neovim probe for
115
+ a clipboard provider immediately, and on WSL that probe walks every `PATH`
116
+ entry checking `executable()` — including everything under `/mnt/c/...`,
117
+ which is slow cross-filesystem interop. Measured on this project's own dev
118
+ machine: ~900ms startup with that line in play, ~160ms with the Windows
119
+ `PATH` entries stripped, ~4ms with `-u NONE`. That's not multi-agent-prompt
120
+ overhead; it's one line in a personal init.lua interacting badly with WSL,
121
+ and fixing it (or guarding it — see `MAP_SESSION` below) speeds up *every*
122
+ Neovim session, not just `map`.
123
+ - **`map --clean` (`-u NONE`)** sidesteps all of it by skipping your config
124
+ entirely — the built-in fast path when you don't need your plugins for a
125
+ quick edit.
126
+ - **`MAP_SESSION=1`** is set in the environment of every nvim `map` launches.
127
+ Nothing in this package reads it — it's there so you can guard an
128
+ expensive line in your *own* init.lua behind
129
+ `if not vim.env.MAP_SESSION then ... end`, if you want full-config speed
130
+ back without giving up faster `map` startup. That's your config to edit,
131
+ not something this tool does for you. This isn't just for the clipboard
132
+ line above — a scratch prompt buffer has no use for a file-tree sidebar or
133
+ git tooling either, and with [lazy.nvim](https://github.com/folke/lazy.nvim)
134
+ you can skip those specific plugins the same way, with `cond` on the spec:
135
+
136
+ ```lua
137
+ return {
138
+ 'nvim-neo-tree/neo-tree.nvim',
139
+ cond = not vim.env.MAP_SESSION,
140
+ -- ...
141
+ }
142
+ ```
143
+
144
+ Confirmed on this project's own dev config: with `neo-tree.nvim` and
145
+ `gitsigns.nvim` guarded this way, `<leader>e` (NeoTree's toggle) becomes a
146
+ no-op in a `map` session, and their entire module trees (dozens of
147
+ individual `require()` calls each) simply don't load — real startup
148
+ savings, not just fewer keymaps to trip over. `cond` is evaluated on every
149
+ start, so this takes effect immediately; no `:Lazy sync`/restart needed.
150
+ - **It's specifically a startup cost, not a per-save one.** The clipboard
151
+ probe runs once, while your init.lua is sourced, not again on autosave, on
152
+ `FocusLost`, or when you switch panes and type `/prompt` — that last step
153
+ never touches nvim at all (`map pop`/reading the file is a separate,
154
+ plain filesystem read and write). If a session still feels slow at the
155
+ hand-off moment specifically, that's terminal pane-switching or the
156
+ agent's own slash-command overhead, not this tool or Neovim.
157
+ - **`/prompt`'s own overhead is small, and it isn't Neovim's.** Measured on
158
+ this project's own dev machine: `map pop` runs in ~60-85ms end to end —
159
+ bare `python3 -c pass` alone is ~30ms of that, this package's own imports
160
+ add maybe another ~20ms, and the rest is the file read/archive/write. If
161
+ `/prompt` still feels slow, that latency lives in the *agent host's* own
162
+ tool-call round trip (spawning/sandboxing the shell command), not in
163
+ anything this package does — there's no nvim process in this path at all.
164
+ The one thing the `prompt` skill itself controls: it runs `map pop`
165
+ directly rather than checking `which map` first, since that check is a
166
+ second subprocess spawn that's a wasted round trip almost every time.
167
+
168
+ ## Agent integration
169
+
170
+ `skills/prompt/` is a portable [Agent Skill](https://code.claude.com/docs/en/skills)
171
+ that teaches a host to read `.ma/prompt/current.md` and treat its content as
172
+ the user's message when they type `/prompt`. See
173
+ [`skills/README.md`](./skills/README.md) for install paths.
174
+
175
+ ## Why not tmux `send-keys` / auto-injection?
176
+
177
+ That's the obvious next step — save, close the pane, and have the tool type
178
+ `/prompt` into the neighboring agent pane for you — but it needs a reliable
179
+ way to identify *which* pane is running the agent, which varies by terminal
180
+ (tmux panes, Windows Terminal panes, and OS-level input injection like
181
+ `xdotool`/`wtype` all solve a different half of that problem). The manual
182
+ handoff above works everywhere today; auto-injection is being explored as a
183
+ follow-up, potentially building on [`multi-agent-registry`](https://github.com/InTEGr8or/multi-agent-registry)'s
184
+ chat discovery to identify a live agent session (not just a recent one) in
185
+ the same directory.
186
+
187
+ If/when that lands: prefer sending a widely-supported "submit" keystroke —
188
+ `Ctrl+Enter` is the closest thing to a universal convention across chat
189
+ input boxes — into the target pane after typing `/prompt`, over anything
190
+ input-method-specific, so the same injection code has a chance of working
191
+ across agents rather than being re-tuned per host.
192
+
193
+ ## Design notes
194
+
195
+ - **The prompt file is per-project, not global.** `.ma/prompt/current.md`
196
+ resolves against the nearest `.git` root, so working on two projects in two
197
+ terminal tabs never mixes up their scratch files.
198
+ - **`.ma/` is a shared root, not this tool's alone.** It's the umbrella
199
+ directory for the whole multi-agent-* line (`map`'s CLI alias is the shared
200
+ `ma` prefix of `map`/`mar`/`maa`) — one dotfolder instead of one per
201
+ product. Only `.ma/prompt/` is this tool's; a sibling product could use
202
+ `.ma/registry/`, etc., without colliding. Note that `task-agent`'s existing
203
+ `.task-agent/` convention predates this and stays as-is — migrating an
204
+ already-shipped tool's config layout is a separate, larger decision.
205
+ - **`.gitignore` is managed for you.** The first time `map edit` runs in a
206
+ git repo, it appends `.ma/prompt/` to `.gitignore` if it isn't already
207
+ covered — including by a broader pre-existing `.ma/` entry.
208
+ - **Reading is non-destructive; handing off isn't, but it never discards
209
+ either.** `map show` and `@prompt.md` (file mention) just print/read — the
210
+ file is untouched either way. `/prompt` (`map pop`) clears it, because the
211
+ whole point is not needing a separate "now go clear it" step — but it
212
+ archives first, so "cleared" never means "gone". `--no-archive` is the
213
+ explicit opt-out for content that shouldn't be kept anywhere at all.
214
+ - **The editor notices when the file changes out from under it.** `/prompt`
215
+ runs `map pop` from the *agent's* process, not from inside the running
216
+ nvim session — so if you're still looking at that buffer when you hand a
217
+ draft off, it auto-reloads (`autoread` + `checktime` on
218
+ `FocusGained`/`BufEnter`) the next time you focus it, rather than keep
219
+ showing the text you already submitted. It won't discard anything you've
220
+ since typed there unsaved.
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "multi-agent-prompt"
7
+ version = "0.1.0"
8
+ description = "A crash-proof, autosaving prompt editor for AI coding agent CLIs — compose in your real editor, hand off with a slash command"
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "Mark Stouffer", email = "1802850+InTEGr8or@users.noreply.github.com" }
14
+ ]
15
+ dependencies = [
16
+ "verkit>=0.1.4",
17
+ "rich>=13.9.4",
18
+ ]
19
+
20
+ [project.scripts]
21
+ multi-agent-prompt = "multi_agent_prompt.cli:main"
22
+ map = "multi_agent_prompt.cli:main"
23
+
24
+ [tool.hatch.build.targets.wheel]
25
+ packages = ["src/multi_agent_prompt"]
26
+
27
+ [tool.hatch.metadata]
28
+ allow-direct-references = true
29
+
30
+ [tool.pytest.ini_options]
31
+ testpaths = ["tests"]
32
+ pythonpath = ["src"]
33
+
34
+ [dependency-groups]
35
+ dev = [
36
+ "pytest>=8.0.0",
37
+ "ruff>=0.8.0",
38
+ "mypy>=1.13.0",
39
+ ]
@@ -0,0 +1,41 @@
1
+ # Multi-Agent Prompt portable skill
2
+
3
+ One skill (`prompt`) that teaches a host to read the user's draft from
4
+ `.ma/prompt/current.md` — the scratch file `map` edits — treat it as their
5
+ next message, and clear it for the next one (via `map pop`, which archives
6
+ before it clears) when they type `/prompt`.
7
+
8
+ ## Manual install
9
+
10
+ Skills are a plain directory. Copy or symlink it into the host's skills path.
11
+
12
+ ### Claude Code
13
+
14
+ Project-local (recommended):
15
+
16
+ ```bash
17
+ mkdir -p .claude/skills
18
+ ln -sfn ../../skills/prompt .claude/skills/prompt
19
+ ```
20
+
21
+ User-global:
22
+
23
+ ```bash
24
+ mkdir -p ~/.claude/skills
25
+ cp -a skills/prompt ~/.claude/skills/
26
+ ```
27
+
28
+ ### Antigravity CLI (`agy`)
29
+
30
+ ```bash
31
+ mkdir -p .agents/skills
32
+ cp -a skills/prompt .agents/skills/
33
+ ```
34
+
35
+ ### Other hosts (Cursor, Copilot, Grok, OpenCode)
36
+
37
+ Copy `skills/prompt` into that host's skills location. If the host doesn't
38
+ support skills at all, `@prompt.md` / `@.ma/prompt/current.md` (file mention)
39
+ works anywhere the host can see the file — including gitignored files, in
40
+ most hosts. Note that a file mention just reads the content; it doesn't run
41
+ `map pop`, so unlike `/prompt` it won't archive or clear the draft.