@pushary/agent-hooks 1.9.29 → 1.9.31
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 +22 -0
- package/data/SKILL.md +46 -12
- package/data/cursor-plugin/skills/pushary/SKILL.md +46 -12
- package/data/vscode-plugin/skills/pushary/SKILL.md +46 -12
- package/dist/bin/pushary-bell-hook.js +26 -26
- package/dist/bin/pushary-bell.js +9 -9
- package/dist/bin/pushary-claude.js +30 -27
- package/dist/bin/pushary-clean.js +29 -29
- package/dist/bin/pushary-codex-bridge.js +17 -17
- package/dist/bin/pushary-codex-hook.js +41 -40
- package/dist/bin/pushary-codex.js +12 -12
- package/dist/bin/pushary-connect.js +24 -24
- package/dist/bin/pushary-cowork.js +5 -5
- package/dist/bin/pushary-daemon.js +33 -33
- package/dist/bin/pushary-disconnect.js +24 -24
- package/dist/bin/pushary-doctor.js +33 -33
- package/dist/bin/pushary-elicitation-hook.js +26 -26
- package/dist/bin/pushary-gemini-bridge.js +13 -13
- package/dist/bin/pushary-gemini-hook.js +28 -28
- package/dist/bin/pushary-hook.js +30 -30
- package/dist/bin/pushary-login.js +12 -12
- package/dist/bin/pushary-logout.js +24 -24
- package/dist/bin/pushary-mcp.js +9 -9
- package/dist/bin/pushary-mode.js +12 -12
- package/dist/bin/pushary-notification-hook.js +25 -25
- package/dist/bin/pushary-opencode-hook.js +27 -27
- package/dist/bin/pushary-permission-denied-hook.js +30 -30
- package/dist/bin/pushary-permission-hook.js +29 -29
- package/dist/bin/pushary-post-hook.js +25 -25
- package/dist/bin/pushary-prompt-hook.js +25 -25
- package/dist/bin/pushary-session-end-hook.js +25 -25
- package/dist/bin/pushary-session-start-hook.js +29 -29
- package/dist/bin/pushary-setup.js +35 -35
- package/dist/bin/pushary-stats.js +5 -5
- package/dist/bin/pushary-status.js +26 -26
- package/dist/bin/pushary-stop-hook.js +25 -25
- package/dist/bin/pushary-stopfailure-hook.js +25 -25
- package/dist/bin/pushary-suggestions.js +12 -12
- package/dist/bin/pushary-transcript-register.js +18 -18
- package/dist/bin/pushary-transcripts.js +8 -8
- package/dist/bin/pushary-upgrade.js +30 -30
- package/dist/bin/pushary-wait.js +12 -12
- package/dist/bin/pushary.js +6 -6
- package/dist/{chunk-QOMUEL44.js → chunk-2ROXUEZV.js} +1 -1
- package/dist/{chunk-WJUYWTNT.js → chunk-35RJKPIC.js} +1 -1
- package/dist/{chunk-SLKVEJLM.js → chunk-3EIJDBVB.js} +5 -5
- package/dist/{chunk-Y3OZ3CT6.js → chunk-464FX6W5.js} +6 -5
- package/dist/{chunk-KMTSU366.js → chunk-4JOWKPUF.js} +1 -1
- package/dist/{chunk-35CMXPES.js → chunk-4WGKAGIU.js} +3 -3
- package/dist/{chunk-TXKAPRIA.js → chunk-5EX2SD5N.js} +1 -1
- package/dist/{chunk-WLDFMVRY.js → chunk-5F32ZTWD.js} +2 -2
- package/dist/{chunk-NRV5PIPA.js → chunk-5FNE6ZVV.js} +2 -2
- package/dist/{chunk-L7PGUSAU.js → chunk-5GDNIEL5.js} +1 -1
- package/dist/{chunk-OUWDJIJF.js → chunk-7447DYNW.js} +1 -1
- package/dist/{chunk-5L7H32JK.js → chunk-75UCMLT5.js} +1 -1
- package/dist/{chunk-7MYGOFVX.js → chunk-77J4RVB2.js} +4 -4
- package/dist/{chunk-CCI2UBYR.js → chunk-7S4Z36H7.js} +3 -3
- package/dist/{chunk-LSB66XQC.js → chunk-ALSIMOFS.js} +4 -4
- package/dist/{chunk-M2L4EHYW.js → chunk-AXANUGOV.js} +2 -2
- package/dist/{chunk-Z2WS466S.js → chunk-BMUTA66M.js} +15 -13
- package/dist/{chunk-XH7NMH3Q.js → chunk-CJCVPCOB.js} +2 -2
- package/dist/{chunk-PRVG3COH.js → chunk-D3TVRNZC.js} +2 -2
- package/dist/{chunk-CPZZTS4I.js → chunk-DP2FAIW6.js} +1 -1
- package/dist/{chunk-VTR4VRL2.js → chunk-DWQYCOPI.js} +2 -4
- package/dist/{chunk-LRLF6PZ2.js → chunk-EPVY3JU3.js} +1 -1
- package/dist/{chunk-GVIPEBEL.js → chunk-FEICGRNI.js} +3 -3
- package/dist/{chunk-C2ZIVQ6W.js → chunk-FGFFUCEL.js} +6 -6
- package/dist/{chunk-TJXCBTL4.js → chunk-FXJ5SEQT.js} +5 -5
- package/dist/{chunk-G4X3Z3YS.js → chunk-GROYT52D.js} +4 -4
- package/dist/{chunk-2FOAQ64R.js → chunk-GSBOLJZ4.js} +177 -56
- package/dist/{chunk-UW37WHVP.js → chunk-H2PQXK26.js} +2 -2
- package/dist/{chunk-BUOLA2AM.js → chunk-IDGESFKZ.js} +1 -1
- package/dist/{chunk-BAVNBGH4.js → chunk-IIP4LEO3.js} +7 -7
- package/dist/{chunk-GMVZYB3W.js → chunk-IKJJB4QG.js} +3 -3
- package/dist/{chunk-S3DP6DCZ.js → chunk-KBRKQMCI.js} +2 -2
- package/dist/{chunk-AZMHKUUU.js → chunk-MG523AVN.js} +1 -1
- package/dist/{chunk-AVQ6ETA7.js → chunk-MRR4NQ3H.js} +1 -1
- package/dist/{chunk-ETLVZHRG.js → chunk-N4LLBUU2.js} +2 -2
- package/dist/{chunk-YFEHKEGQ.js → chunk-NTWTU6FA.js} +1 -1
- package/dist/{chunk-UM2HNUJA.js → chunk-OS6AE2MR.js} +3 -3
- package/dist/{chunk-DQGM57ZW.js → chunk-OSUAY4SA.js} +1 -1
- package/dist/{chunk-IWPEAA2J.js → chunk-OTDRNEED.js} +1 -1
- package/dist/{chunk-BP3WMLXJ.js → chunk-OULHOX5C.js} +5 -5
- package/dist/{chunk-4DTKE3AS.js → chunk-Q2GSTQ3R.js} +2 -2
- package/dist/{chunk-DUVHHQEL.js → chunk-Q7H2IMJQ.js} +2 -2
- package/dist/{chunk-PX4RRHEB.js → chunk-QCOE42GO.js} +4 -4
- package/dist/{chunk-BKOWTW5P.js → chunk-QGCEQGH6.js} +4 -4
- package/dist/{chunk-JGDBHB6L.js → chunk-RN3KZDWP.js} +2 -2
- package/dist/{chunk-BJMVQ6D5.js → chunk-SAHD5DYW.js} +4 -4
- package/dist/{chunk-62LJB5U3.js → chunk-SJJA2GPD.js} +2 -2
- package/dist/{chunk-IM73P6JT.js → chunk-SQIZGUAN.js} +5 -5
- package/dist/{chunk-CBOHZ6NY.js → chunk-SRRJLA24.js} +4 -4
- package/dist/{chunk-TILXDMUR.js → chunk-SYUHM6V3.js} +3 -3
- package/dist/{chunk-H7QTZTIE.js → chunk-TDLEFGAM.js} +1641 -178
- package/dist/{chunk-CJQEJWLU.js → chunk-VFNYTVTJ.js} +5 -5
- package/dist/{chunk-OSVDGVLL.js → chunk-X427XA76.js} +12 -12
- package/dist/{chunk-2XM4TGIM.js → chunk-X5HK4XUN.js} +4 -4
- package/dist/{chunk-EO2GYHWH.js → chunk-ZYDSHR5P.js} +3 -3
- package/dist/{global-upgrade-ZPULZXOY.js → global-upgrade-YMBTZHDP.js} +6 -6
- package/dist/{paths-Y7ZWWCFK.js → paths-BPFRUWMB.js} +2 -2
- package/dist/{reapply-I4YMQP7F.js → reapply-ZC2LSUVZ.js} +20 -20
- package/dist/src/index.js +19 -19
- package/dist/{upgrade-lock-IDAAFSH2.js → upgrade-lock-TTZMLZPB.js} +3 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.31
|
|
4
|
+
|
|
5
|
+
- SQL sent through `psql`, `mysql` and `mariadb` is now read the way the database reads it. These used to run under an approve rule and now ask: a write after a dollar quote with a non-ASCII tag, such as `psql -c 'SELECT $é$ -- $é$; UPDATE users SET x=1'`; a write after a carriage return that ends a `--` comment; and a write inside a MySQL `/*! ... */` or MariaDB `/*M! ... */` comment, which those clients run.
|
|
6
|
+
- `SELECT ... INTO` and a `LOCK` statement now count as writes and ask, as do `EXECUTE IMMEDIATE` and `PREPARE ... FROM`.
|
|
7
|
+
- A command after `bash -c` and its options is now seen, so a `Bash(git push:*)` deny rule now refuses `bash -c -x 'git push'`, `bash -c -- 'git push'` and `zsh -c -x 'git push'`, which used to run.
|
|
8
|
+
- `env` options are read the way GNU and macOS `env` read them, abbreviations included, so the same deny rule now refuses `env --spl='git push'`. When the two versions of `env` would run different commands, Pushary asks.
|
|
9
|
+
- Codex: `gh api -iXDELETE` and `gh api -iX DELETE` are read as DELETE requests and ask, instead of being passed back to Codex.
|
|
10
|
+
- A tool name that is not one concrete tool, such as `*`, can no longer be saved as an Always allow rule.
|
|
11
|
+
- History capture works when Claude Code or Codex keeps its files under a custom `CLAUDE_CONFIG_DIR` or `CODEX_HOME`.
|
|
12
|
+
- `pushary-mcp` tells Pushary which computer is asking, so the phone's Try it step checks the computer you chose.
|
|
13
|
+
|
|
14
|
+
## 1.9.30
|
|
15
|
+
|
|
16
|
+
- "Always allow PowerShell" and "Always allow Monitor" now ask about the same consequences "Always allow Bash" does. A Monitor command is judged exactly as the same Bash command. In PowerShell that includes `Remove-Item -Recurse`, `irm ... | iex`, a downloaded script then run, `Set-Content .env`, `Stop-Service`, `Format-Volume` and a recursive `Get-ChildItem` piped to `Remove-Item`. A plain `Remove-Item file.txt`, `git push`, `Stop-Process`, `-WhatIf` and every read such as `Get-ChildItem` keep running.
|
|
17
|
+
- A `*` approve rule no longer runs a destructive PowerShell or Monitor command, such as `Remove-Item -Recurse -Force ~`, `cmd /c rd /s` or `rm -rf ~`, without asking. It asks, as it already did for Bash.
|
|
18
|
+
- Codex: a call nobody answers is now refused instead of passed back to Codex, which ran calls it does not ask about itself. Only a rule you set to approve on timeout lets it run.
|
|
19
|
+
- A call refused because your phone approvals for a session are paused now says so, and tells you to tap Approve on the notification to resume. It used to say "No response within timeout".
|
|
20
|
+
- Codex: a GitHub, Stripe, AWS or Twilio write behind `caffeinate`, `stdbuf` or `flock` now asks, and `gh` asks about anything that is not a known read, such as `gh extension install`, `gh ssh-key add` or `gh label clone`. `gh pr co` now runs like `gh pr checkout`.
|
|
21
|
+
- Codex: a patch to a GitHub workflow or secrets file now asks however its path is capitalised, so `.GitHub/Workflows/ci.yml` no longer runs unasked.
|
|
22
|
+
- When two of your rules hold a call equally, Pushary now uses the one that refuses it if nobody answers, whatever order the rules are in.
|
|
23
|
+
- Antigravity CLI: input to a running command that is not text is now refused instead of shown as blank input.
|
|
24
|
+
|
|
3
25
|
## 1.9.29
|
|
4
26
|
|
|
5
27
|
- Codex: answering "Handle on your machine" now always refuses the call, and tells you to ask Codex to run it again while you are at your computer, or to run it yourself. In Codex's default modes the call used to pass back to Codex, and a call Codex does not ask about itself, such as a remote API write or a file deletion, could run without anyone approving it.
|
package/data/SKILL.md
CHANGED
|
@@ -174,20 +174,46 @@ Put a boundary that is not a file path in `promises`, never in `allowedPaths`. R
|
|
|
174
174
|
|
|
175
175
|
**Look at the machine first. Do not guess the install path.** Run these. Each one is read-only and fast. Run them as separate commands.
|
|
176
176
|
|
|
177
|
+
Use `uname -s` in a Unix shell (`Darwin` is Mac, `Linux` is Linux). In
|
|
178
|
+
PowerShell, inspect `$env:OS` (`Windows_NT` is Windows). Platform discovery must
|
|
179
|
+
not depend on Node: the native Mac route does not require it.
|
|
180
|
+
|
|
181
|
+
In a Unix shell, run these separately:
|
|
182
|
+
|
|
177
183
|
```bash
|
|
178
|
-
|
|
184
|
+
uname -s
|
|
179
185
|
[ -n "${PUSHARY_API_KEY:+x}" ] && echo key-in-env
|
|
180
|
-
|
|
186
|
+
command -v node >/dev/null 2>&1 && echo node-available
|
|
187
|
+
command -v npm >/dev/null 2>&1 && echo npm-available
|
|
181
188
|
test -x ~/.pushary/bin/pushary-bridge && echo mac-app
|
|
182
189
|
```
|
|
183
190
|
|
|
184
|
-
|
|
191
|
+
On Mac, check the stored key without Node or printing its value:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
if pushary_key_check=$(/usr/bin/plutil -extract apiKey raw -expect string -o - ~/.pushary/config.json 2>/dev/null); then
|
|
195
|
+
printf '%s\n' "$pushary_key_check" | /usr/bin/awk 'NF { found=1 } END { exit !found }' && echo keyed
|
|
196
|
+
fi
|
|
197
|
+
unset pushary_key_check
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
When Node is available, other Unix platforms can check the stored key with:
|
|
185
201
|
|
|
186
|
-
|
|
202
|
+
```bash
|
|
203
|
+
node -e "try{process.exit(JSON.parse(require('fs').readFileSync(process.env.HOME+'/.pushary/config.json','utf8')).apiKey?.trim()?0:1)}catch{process.exit(1)}" && echo keyed
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
In PowerShell, check for a nonempty environment/stored key without printing it;
|
|
207
|
+
use `Get-Content` and `ConvertFrom-Json` for the config in `$env:USERPROFILE`.
|
|
208
|
+
Check `Get-Command node,npm` before choosing the terminal installer.
|
|
209
|
+
|
|
210
|
+
The stored-key and bridge tests answer different questions.
|
|
211
|
+
|
|
212
|
+
The stored-key test says a key is stored **and is not empty**. Test the value, not the file.
|
|
187
213
|
The file stays behind after a logout removes the key. A test for the file alone
|
|
188
214
|
tells a logged-out user they are ready.
|
|
189
215
|
|
|
190
|
-
The
|
|
216
|
+
The bridge test says the Mac app is installed here. Only the Mac app writes that file.
|
|
191
217
|
|
|
192
218
|
Check the environment before the stored key. An exported key wins over a stored
|
|
193
219
|
one. Never print the key itself.
|
|
@@ -196,14 +222,22 @@ Then take one branch.
|
|
|
196
222
|
|
|
197
223
|
### Branch 1. `key-in-env`, `keyed`, or `mac-app`
|
|
198
224
|
|
|
199
|
-
This machine
|
|
225
|
+
This machine has an existing installation or credential. Offer no new install.
|
|
226
|
+
Verify its readiness before reporting success. Do not run `setup` again.
|
|
200
227
|
|
|
201
228
|
`mac-app` counts on its own. The Mac app signs in for the user. It writes the key
|
|
202
229
|
into the agent configuration files it wires, not into `~/.pushary/config.json`. A
|
|
203
|
-
machine the app set up therefore prints `mac-app` and nothing else.
|
|
204
|
-
|
|
230
|
+
machine the app set up therefore prints `mac-app` and nothing else. The locator
|
|
231
|
+
proves installation, not sign-in, entitlement, current agent admission or delivery.
|
|
232
|
+
|
|
233
|
+
For `mac-app` without Node/npm, open Pushary and check the intended account,
|
|
234
|
+
subscription and Agents connection state there. Use the native app to connect or
|
|
235
|
+
repair the selected agents and phone. Then send a harmless question from the
|
|
236
|
+
current agent and confirm its returned answer. Do not install Node to inspect
|
|
237
|
+
the native setup and do not claim a CLI status exit code when no CLI ran.
|
|
205
238
|
|
|
206
|
-
|
|
239
|
+
When Node/npm are available, check it with `npx pushary@latest status --json`.
|
|
240
|
+
The exit code is the answer:
|
|
207
241
|
|
|
208
242
|
| Code | Meaning |
|
|
209
243
|
| --- | --- |
|
|
@@ -224,7 +258,7 @@ grep -lq pushary-bridge ~/.claude/settings.json ~/.gemini/settings.json ~/.curso
|
|
|
224
258
|
|
|
225
259
|
If the app owns them, `setup` would keep them and write almost nothing, so telling the user to re-run it is bad advice. Point them at the Pushary app instead.
|
|
226
260
|
|
|
227
|
-
### Branch 2. `
|
|
261
|
+
### Branch 2. `Darwin`, no key, no `mac-app`
|
|
228
262
|
|
|
229
263
|
Offer the Mac app first. It needs no Node and no terminal. It writes the agent configuration itself, and it answers questions in the notch at the desk.
|
|
230
264
|
|
|
@@ -236,7 +270,7 @@ They can also download it from https://pushary.com/download. It needs macOS 14 o
|
|
|
236
270
|
|
|
237
271
|
The command line works on macOS too. Offer it if the user prefers the terminal, or if the user runs Hermes, because Hermes needs a Python the app cannot install.
|
|
238
272
|
|
|
239
|
-
### Branch 3. `
|
|
273
|
+
### Branch 3. `Linux` or `Windows_NT`
|
|
240
274
|
|
|
241
275
|
There is no Mac app for these machines. Use the command line. It is fully supported.
|
|
242
276
|
|
|
@@ -251,7 +285,7 @@ Node 20.17+, 22.13+ or 23.5+ is necessary. Then the user needs a phone to answer
|
|
|
251
285
|
|
|
252
286
|
On Windows, setup writes no shell file, so `~/.pushary/config.json` is the only key store. On a Linux machine with no screen, browser login does not work, but the pairing QR does.
|
|
253
287
|
|
|
254
|
-
### Branch 4. `
|
|
288
|
+
### Branch 4. `Darwin`, `mac-app`, and the user asked for the command line
|
|
255
289
|
|
|
256
290
|
Run `setup`. It reads the key the app signed in with, so it mints no second key, and it keeps the hooks the app owns. Pass `--take-over-hooks` only when the user wants the command line to own them instead.
|
|
257
291
|
|
|
@@ -167,20 +167,46 @@ Put a boundary that is not a file path in `promises`, never in `allowedPaths`. R
|
|
|
167
167
|
|
|
168
168
|
**Look at the machine first. Do not guess the install path.** Run these. Each one is read-only and fast. Run them as separate commands.
|
|
169
169
|
|
|
170
|
+
Use `uname -s` in a Unix shell (`Darwin` is Mac, `Linux` is Linux). In
|
|
171
|
+
PowerShell, inspect `$env:OS` (`Windows_NT` is Windows). Platform discovery must
|
|
172
|
+
not depend on Node: the native Mac route does not require it.
|
|
173
|
+
|
|
174
|
+
In a Unix shell, run these separately:
|
|
175
|
+
|
|
170
176
|
```bash
|
|
171
|
-
|
|
177
|
+
uname -s
|
|
172
178
|
[ -n "${PUSHARY_API_KEY:+x}" ] && echo key-in-env
|
|
173
|
-
|
|
179
|
+
command -v node >/dev/null 2>&1 && echo node-available
|
|
180
|
+
command -v npm >/dev/null 2>&1 && echo npm-available
|
|
174
181
|
test -x ~/.pushary/bin/pushary-bridge && echo mac-app
|
|
175
182
|
```
|
|
176
183
|
|
|
177
|
-
|
|
184
|
+
On Mac, check the stored key without Node or printing its value:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
if pushary_key_check=$(/usr/bin/plutil -extract apiKey raw -expect string -o - ~/.pushary/config.json 2>/dev/null); then
|
|
188
|
+
printf '%s\n' "$pushary_key_check" | /usr/bin/awk 'NF { found=1 } END { exit !found }' && echo keyed
|
|
189
|
+
fi
|
|
190
|
+
unset pushary_key_check
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
When Node is available, other Unix platforms can check the stored key with:
|
|
178
194
|
|
|
179
|
-
|
|
195
|
+
```bash
|
|
196
|
+
node -e "try{process.exit(JSON.parse(require('fs').readFileSync(process.env.HOME+'/.pushary/config.json','utf8')).apiKey?.trim()?0:1)}catch{process.exit(1)}" && echo keyed
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
In PowerShell, check for a nonempty environment/stored key without printing it;
|
|
200
|
+
use `Get-Content` and `ConvertFrom-Json` for the config in `$env:USERPROFILE`.
|
|
201
|
+
Check `Get-Command node,npm` before choosing the terminal installer.
|
|
202
|
+
|
|
203
|
+
The stored-key and bridge tests answer different questions.
|
|
204
|
+
|
|
205
|
+
The stored-key test says a key is stored **and is not empty**. Test the value, not the file.
|
|
180
206
|
The file stays behind after a logout removes the key. A test for the file alone
|
|
181
207
|
tells a logged-out user they are ready.
|
|
182
208
|
|
|
183
|
-
The
|
|
209
|
+
The bridge test says the Mac app is installed here. Only the Mac app writes that file.
|
|
184
210
|
|
|
185
211
|
Check the environment before the stored key. An exported key wins over a stored
|
|
186
212
|
one. Never print the key itself.
|
|
@@ -189,14 +215,22 @@ Then take one branch.
|
|
|
189
215
|
|
|
190
216
|
### Branch 1. `key-in-env`, `keyed`, or `mac-app`
|
|
191
217
|
|
|
192
|
-
This machine
|
|
218
|
+
This machine has an existing installation or credential. Offer no new install.
|
|
219
|
+
Verify its readiness before reporting success. Do not run `setup` again.
|
|
193
220
|
|
|
194
221
|
`mac-app` counts on its own. The Mac app signs in for the user. It writes the key
|
|
195
222
|
into the agent configuration files it wires, not into `~/.pushary/config.json`. A
|
|
196
|
-
machine the app set up therefore prints `mac-app` and nothing else.
|
|
197
|
-
|
|
223
|
+
machine the app set up therefore prints `mac-app` and nothing else. The locator
|
|
224
|
+
proves installation, not sign-in, entitlement, current agent admission or delivery.
|
|
225
|
+
|
|
226
|
+
For `mac-app` without Node/npm, open Pushary and check the intended account,
|
|
227
|
+
subscription and Agents connection state there. Use the native app to connect or
|
|
228
|
+
repair the selected agents and phone. Then send a harmless question from the
|
|
229
|
+
current agent and confirm its returned answer. Do not install Node to inspect
|
|
230
|
+
the native setup and do not claim a CLI status exit code when no CLI ran.
|
|
198
231
|
|
|
199
|
-
|
|
232
|
+
When Node/npm are available, check it with `npx pushary@latest status --json`.
|
|
233
|
+
The exit code is the answer:
|
|
200
234
|
|
|
201
235
|
| Code | Meaning |
|
|
202
236
|
| --- | --- |
|
|
@@ -217,7 +251,7 @@ grep -lq pushary-bridge ~/.claude/settings.json ~/.gemini/settings.json ~/.curso
|
|
|
217
251
|
|
|
218
252
|
If the app owns them, `setup` would keep them and write almost nothing, so telling the user to re-run it is bad advice. Point them at the Pushary app instead.
|
|
219
253
|
|
|
220
|
-
### Branch 2. `
|
|
254
|
+
### Branch 2. `Darwin`, no key, no `mac-app`
|
|
221
255
|
|
|
222
256
|
Offer the Mac app first. It needs no Node and no terminal. It writes the agent configuration itself, and it answers questions in the notch at the desk.
|
|
223
257
|
|
|
@@ -229,7 +263,7 @@ They can also download it from https://pushary.com/download. It needs macOS 14 o
|
|
|
229
263
|
|
|
230
264
|
The command line works on macOS too. Offer it if the user prefers the terminal, or if the user runs Hermes, because Hermes needs a Python the app cannot install.
|
|
231
265
|
|
|
232
|
-
### Branch 3. `
|
|
266
|
+
### Branch 3. `Linux` or `Windows_NT`
|
|
233
267
|
|
|
234
268
|
There is no Mac app for these machines. Use the command line. It is fully supported.
|
|
235
269
|
|
|
@@ -244,7 +278,7 @@ Node 20.17+, 22.13+ or 23.5+ is necessary. Then the user needs a phone to answer
|
|
|
244
278
|
|
|
245
279
|
On Windows, setup writes no shell file, so `~/.pushary/config.json` is the only key store. On a Linux machine with no screen, browser login does not work, but the pairing QR does.
|
|
246
280
|
|
|
247
|
-
### Branch 4. `
|
|
281
|
+
### Branch 4. `Darwin`, `mac-app`, and the user asked for the command line
|
|
248
282
|
|
|
249
283
|
Run `setup`. It reads the key the app signed in with, so it mints no second key, and it keeps the hooks the app owns. Pass `--take-over-hooks` only when the user wants the command line to own them instead.
|
|
250
284
|
|
|
@@ -167,20 +167,46 @@ Put a boundary that is not a file path in `promises`, never in `allowedPaths`. R
|
|
|
167
167
|
|
|
168
168
|
**Look at the machine first. Do not guess the install path.** Run these. Each one is read-only and fast. Run them as separate commands.
|
|
169
169
|
|
|
170
|
+
Use `uname -s` in a Unix shell (`Darwin` is Mac, `Linux` is Linux). In
|
|
171
|
+
PowerShell, inspect `$env:OS` (`Windows_NT` is Windows). Platform discovery must
|
|
172
|
+
not depend on Node: the native Mac route does not require it.
|
|
173
|
+
|
|
174
|
+
In a Unix shell, run these separately:
|
|
175
|
+
|
|
170
176
|
```bash
|
|
171
|
-
|
|
177
|
+
uname -s
|
|
172
178
|
[ -n "${PUSHARY_API_KEY:+x}" ] && echo key-in-env
|
|
173
|
-
|
|
179
|
+
command -v node >/dev/null 2>&1 && echo node-available
|
|
180
|
+
command -v npm >/dev/null 2>&1 && echo npm-available
|
|
174
181
|
test -x ~/.pushary/bin/pushary-bridge && echo mac-app
|
|
175
182
|
```
|
|
176
183
|
|
|
177
|
-
|
|
184
|
+
On Mac, check the stored key without Node or printing its value:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
if pushary_key_check=$(/usr/bin/plutil -extract apiKey raw -expect string -o - ~/.pushary/config.json 2>/dev/null); then
|
|
188
|
+
printf '%s\n' "$pushary_key_check" | /usr/bin/awk 'NF { found=1 } END { exit !found }' && echo keyed
|
|
189
|
+
fi
|
|
190
|
+
unset pushary_key_check
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
When Node is available, other Unix platforms can check the stored key with:
|
|
178
194
|
|
|
179
|
-
|
|
195
|
+
```bash
|
|
196
|
+
node -e "try{process.exit(JSON.parse(require('fs').readFileSync(process.env.HOME+'/.pushary/config.json','utf8')).apiKey?.trim()?0:1)}catch{process.exit(1)}" && echo keyed
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
In PowerShell, check for a nonempty environment/stored key without printing it;
|
|
200
|
+
use `Get-Content` and `ConvertFrom-Json` for the config in `$env:USERPROFILE`.
|
|
201
|
+
Check `Get-Command node,npm` before choosing the terminal installer.
|
|
202
|
+
|
|
203
|
+
The stored-key and bridge tests answer different questions.
|
|
204
|
+
|
|
205
|
+
The stored-key test says a key is stored **and is not empty**. Test the value, not the file.
|
|
180
206
|
The file stays behind after a logout removes the key. A test for the file alone
|
|
181
207
|
tells a logged-out user they are ready.
|
|
182
208
|
|
|
183
|
-
The
|
|
209
|
+
The bridge test says the Mac app is installed here. Only the Mac app writes that file.
|
|
184
210
|
|
|
185
211
|
Check the environment before the stored key. An exported key wins over a stored
|
|
186
212
|
one. Never print the key itself.
|
|
@@ -189,14 +215,22 @@ Then take one branch.
|
|
|
189
215
|
|
|
190
216
|
### Branch 1. `key-in-env`, `keyed`, or `mac-app`
|
|
191
217
|
|
|
192
|
-
This machine
|
|
218
|
+
This machine has an existing installation or credential. Offer no new install.
|
|
219
|
+
Verify its readiness before reporting success. Do not run `setup` again.
|
|
193
220
|
|
|
194
221
|
`mac-app` counts on its own. The Mac app signs in for the user. It writes the key
|
|
195
222
|
into the agent configuration files it wires, not into `~/.pushary/config.json`. A
|
|
196
|
-
machine the app set up therefore prints `mac-app` and nothing else.
|
|
197
|
-
|
|
223
|
+
machine the app set up therefore prints `mac-app` and nothing else. The locator
|
|
224
|
+
proves installation, not sign-in, entitlement, current agent admission or delivery.
|
|
225
|
+
|
|
226
|
+
For `mac-app` without Node/npm, open Pushary and check the intended account,
|
|
227
|
+
subscription and Agents connection state there. Use the native app to connect or
|
|
228
|
+
repair the selected agents and phone. Then send a harmless question from the
|
|
229
|
+
current agent and confirm its returned answer. Do not install Node to inspect
|
|
230
|
+
the native setup and do not claim a CLI status exit code when no CLI ran.
|
|
198
231
|
|
|
199
|
-
|
|
232
|
+
When Node/npm are available, check it with `npx pushary@latest status --json`.
|
|
233
|
+
The exit code is the answer:
|
|
200
234
|
|
|
201
235
|
| Code | Meaning |
|
|
202
236
|
| --- | --- |
|
|
@@ -217,7 +251,7 @@ grep -lq pushary-bridge ~/.claude/settings.json ~/.gemini/settings.json ~/.curso
|
|
|
217
251
|
|
|
218
252
|
If the app owns them, `setup` would keep them and write almost nothing, so telling the user to re-run it is bad advice. Point them at the Pushary app instead.
|
|
219
253
|
|
|
220
|
-
### Branch 2. `
|
|
254
|
+
### Branch 2. `Darwin`, no key, no `mac-app`
|
|
221
255
|
|
|
222
256
|
Offer the Mac app first. It needs no Node and no terminal. It writes the agent configuration itself, and it answers questions in the notch at the desk.
|
|
223
257
|
|
|
@@ -229,7 +263,7 @@ They can also download it from https://pushary.com/download. It needs macOS 14 o
|
|
|
229
263
|
|
|
230
264
|
The command line works on macOS too. Offer it if the user prefers the terminal, or if the user runs Hermes, because Hermes needs a Python the app cannot install.
|
|
231
265
|
|
|
232
|
-
### Branch 3. `
|
|
266
|
+
### Branch 3. `Linux` or `Windows_NT`
|
|
233
267
|
|
|
234
268
|
There is no Mac app for these machines. Use the command line. It is fully supported.
|
|
235
269
|
|
|
@@ -244,7 +278,7 @@ Node 20.17+, 22.13+ or 23.5+ is necessary. Then the user needs a phone to answer
|
|
|
244
278
|
|
|
245
279
|
On Windows, setup writes no shell file, so `~/.pushary/config.json` is the only key store. On a Linux machine with no screen, browser login does not work, but the pairing QR does.
|
|
246
280
|
|
|
247
|
-
### Branch 4. `
|
|
281
|
+
### Branch 4. `Darwin`, `mac-app`, and the user asked for the command line
|
|
248
282
|
|
|
249
283
|
Run `setup`. It reads the key the app signed in with, so it mints no second key, and it keeps the hooks the app owns. Pass `--take-over-hooks` only when the user wants the command line to own them instead.
|
|
250
284
|
|
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
handleBell
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-75UCMLT5.js";
|
|
5
5
|
import {
|
|
6
6
|
readHookInput
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
11
|
-
import "../chunk-
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-ALSIMOFS.js";
|
|
8
|
+
import "../chunk-GSBOLJZ4.js";
|
|
9
|
+
import "../chunk-DWQYCOPI.js";
|
|
10
|
+
import "../chunk-VFNYTVTJ.js";
|
|
11
|
+
import "../chunk-7447DYNW.js";
|
|
12
|
+
import "../chunk-EPVY3JU3.js";
|
|
13
|
+
import "../chunk-MRR4NQ3H.js";
|
|
14
14
|
import "../chunk-XHKBHWLX.js";
|
|
15
|
-
import "../chunk-
|
|
16
|
-
import "../chunk-
|
|
17
|
-
import "../chunk-
|
|
18
|
-
import "../chunk-
|
|
19
|
-
import "../chunk-
|
|
15
|
+
import "../chunk-SAHD5DYW.js";
|
|
16
|
+
import "../chunk-FXJ5SEQT.js";
|
|
17
|
+
import "../chunk-OS6AE2MR.js";
|
|
18
|
+
import "../chunk-35RJKPIC.js";
|
|
19
|
+
import "../chunk-IDGESFKZ.js";
|
|
20
20
|
import "../chunk-GMXKITVA.js";
|
|
21
21
|
import "../chunk-6ICPEJY5.js";
|
|
22
|
-
import "../chunk-
|
|
23
|
-
import "../chunk-
|
|
24
|
-
import "../chunk-
|
|
25
|
-
import "../chunk-
|
|
22
|
+
import "../chunk-IKJJB4QG.js";
|
|
23
|
+
import "../chunk-X427XA76.js";
|
|
24
|
+
import "../chunk-4JOWKPUF.js";
|
|
25
|
+
import "../chunk-464FX6W5.js";
|
|
26
26
|
import "../chunk-POFBE6ZY.js";
|
|
27
|
-
import "../chunk-
|
|
28
|
-
import "../chunk-
|
|
29
|
-
import "../chunk-
|
|
30
|
-
import "../chunk-
|
|
27
|
+
import "../chunk-FEICGRNI.js";
|
|
28
|
+
import "../chunk-SYUHM6V3.js";
|
|
29
|
+
import "../chunk-4WGKAGIU.js";
|
|
30
|
+
import "../chunk-NTWTU6FA.js";
|
|
31
31
|
import "../chunk-7QLSKOSU.js";
|
|
32
32
|
import "../chunk-KZERVKTD.js";
|
|
33
|
-
import "../chunk-
|
|
34
|
-
import "../chunk-
|
|
33
|
+
import "../chunk-KBRKQMCI.js";
|
|
34
|
+
import "../chunk-SRRJLA24.js";
|
|
35
35
|
import "../chunk-AQFEP65J.js";
|
|
36
|
-
import "../chunk-
|
|
37
|
-
import "../chunk-
|
|
38
|
-
import "../chunk-
|
|
36
|
+
import "../chunk-5EX2SD5N.js";
|
|
37
|
+
import "../chunk-2ROXUEZV.js";
|
|
38
|
+
import "../chunk-TDLEFGAM.js";
|
|
39
39
|
|
|
40
40
|
// bin/pushary-bell-hook.ts
|
|
41
41
|
var main = async () => {
|
package/dist/bin/pushary-bell.js
CHANGED
|
@@ -5,39 +5,39 @@ import {
|
|
|
5
5
|
liveAgentCount,
|
|
6
6
|
ring,
|
|
7
7
|
upgradeThreshold
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-75UCMLT5.js";
|
|
9
9
|
import {
|
|
10
10
|
createIo
|
|
11
11
|
} from "../chunk-FO3MDD26.js";
|
|
12
12
|
import {
|
|
13
13
|
exitOnHelpFlag
|
|
14
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-CJCVPCOB.js";
|
|
15
15
|
import {
|
|
16
16
|
addBellHooks,
|
|
17
17
|
bellInstalled,
|
|
18
18
|
removeBellHooks
|
|
19
|
-
} from "../chunk-
|
|
19
|
+
} from "../chunk-IDGESFKZ.js";
|
|
20
20
|
import {
|
|
21
21
|
parseFlags
|
|
22
22
|
} from "../chunk-GMXKITVA.js";
|
|
23
|
-
import "../chunk-
|
|
23
|
+
import "../chunk-IKJJB4QG.js";
|
|
24
24
|
import "../chunk-7QLSKOSU.js";
|
|
25
25
|
import {
|
|
26
26
|
EXIT
|
|
27
27
|
} from "../chunk-KZERVKTD.js";
|
|
28
|
-
import "../chunk-
|
|
28
|
+
import "../chunk-KBRKQMCI.js";
|
|
29
29
|
import {
|
|
30
30
|
claudeSettings
|
|
31
|
-
} from "../chunk-
|
|
31
|
+
} from "../chunk-SRRJLA24.js";
|
|
32
32
|
import {
|
|
33
33
|
readJsonSafe,
|
|
34
34
|
writeJsonAtomic
|
|
35
35
|
} from "../chunk-AQFEP65J.js";
|
|
36
|
-
import "../chunk-
|
|
37
|
-
import "../chunk-
|
|
36
|
+
import "../chunk-5EX2SD5N.js";
|
|
37
|
+
import "../chunk-2ROXUEZV.js";
|
|
38
38
|
import {
|
|
39
39
|
isRecord
|
|
40
|
-
} from "../chunk-
|
|
40
|
+
} from "../chunk-TDLEFGAM.js";
|
|
41
41
|
|
|
42
42
|
// bin/pushary-bell.ts
|
|
43
43
|
exitOnHelpFlag("bell");
|
|
@@ -8,39 +8,39 @@ import {
|
|
|
8
8
|
describeIdleWindow,
|
|
9
9
|
startProcessOwnership,
|
|
10
10
|
withSpawnProcessOwnership
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-D3TVRNZC.js";
|
|
12
12
|
import {
|
|
13
13
|
announceSubscriptionRequired,
|
|
14
14
|
isDeferAnswer
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-MG523AVN.js";
|
|
16
16
|
import {
|
|
17
17
|
claudeTranscriptPath,
|
|
18
18
|
loadSessionKey,
|
|
19
19
|
registerTranscript,
|
|
20
20
|
registeredTranscriptEnabled
|
|
21
|
-
} from "../chunk-
|
|
22
|
-
import "../chunk-
|
|
21
|
+
} from "../chunk-GSBOLJZ4.js";
|
|
22
|
+
import "../chunk-DWQYCOPI.js";
|
|
23
23
|
import {
|
|
24
24
|
ensureDaemonRunning
|
|
25
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-VFNYTVTJ.js";
|
|
26
26
|
import {
|
|
27
27
|
encryptRecord
|
|
28
|
-
} from "../chunk-
|
|
29
|
-
import "../chunk-
|
|
28
|
+
} from "../chunk-7447DYNW.js";
|
|
29
|
+
import "../chunk-EPVY3JU3.js";
|
|
30
30
|
import {
|
|
31
31
|
transcriptsEnabled
|
|
32
|
-
} from "../chunk-
|
|
32
|
+
} from "../chunk-MRR4NQ3H.js";
|
|
33
33
|
import {
|
|
34
34
|
needsShell,
|
|
35
35
|
spawnClaude
|
|
36
36
|
} from "../chunk-XHKBHWLX.js";
|
|
37
|
-
import "../chunk-
|
|
38
|
-
import "../chunk-
|
|
39
|
-
import "../chunk-
|
|
40
|
-
import "../chunk-
|
|
37
|
+
import "../chunk-FXJ5SEQT.js";
|
|
38
|
+
import "../chunk-OS6AE2MR.js";
|
|
39
|
+
import "../chunk-35RJKPIC.js";
|
|
40
|
+
import "../chunk-IDGESFKZ.js";
|
|
41
41
|
import "../chunk-GMXKITVA.js";
|
|
42
42
|
import "../chunk-6ICPEJY5.js";
|
|
43
|
-
import "../chunk-
|
|
43
|
+
import "../chunk-IKJJB4QG.js";
|
|
44
44
|
import {
|
|
45
45
|
DEFAULT_SESSION,
|
|
46
46
|
UNNAMED_ACTION,
|
|
@@ -58,48 +58,50 @@ import {
|
|
|
58
58
|
reportEvent,
|
|
59
59
|
savePendingCommand,
|
|
60
60
|
scopePathFor
|
|
61
|
-
} from "../chunk-
|
|
62
|
-
import "../chunk-
|
|
61
|
+
} from "../chunk-X427XA76.js";
|
|
62
|
+
import "../chunk-4JOWKPUF.js";
|
|
63
63
|
import {
|
|
64
64
|
askUser,
|
|
65
65
|
cancelQuestion,
|
|
66
|
+
isAwayPaused,
|
|
66
67
|
isDecisionStopped,
|
|
67
68
|
isLocalQuestionHandoff,
|
|
68
69
|
nextLongPollMs,
|
|
69
70
|
waitForAnswer,
|
|
70
71
|
waitsForThePhone,
|
|
71
72
|
withdrawQuestion
|
|
72
|
-
} from "../chunk-
|
|
73
|
+
} from "../chunk-464FX6W5.js";
|
|
73
74
|
import "../chunk-POFBE6ZY.js";
|
|
74
75
|
import {
|
|
75
76
|
SubscriptionRequiredError
|
|
76
|
-
} from "../chunk-
|
|
77
|
-
import "../chunk-
|
|
78
|
-
import "../chunk-
|
|
77
|
+
} from "../chunk-FEICGRNI.js";
|
|
78
|
+
import "../chunk-SYUHM6V3.js";
|
|
79
|
+
import "../chunk-4WGKAGIU.js";
|
|
79
80
|
import {
|
|
80
81
|
getMachineId
|
|
81
|
-
} from "../chunk-
|
|
82
|
+
} from "../chunk-NTWTU6FA.js";
|
|
82
83
|
import "../chunk-7QLSKOSU.js";
|
|
83
84
|
import "../chunk-KZERVKTD.js";
|
|
84
|
-
import "../chunk-
|
|
85
|
-
import "../chunk-
|
|
85
|
+
import "../chunk-KBRKQMCI.js";
|
|
86
|
+
import "../chunk-SRRJLA24.js";
|
|
86
87
|
import "../chunk-AQFEP65J.js";
|
|
87
88
|
import {
|
|
88
89
|
getApiKey,
|
|
89
90
|
getBaseUrl
|
|
90
|
-
} from "../chunk-
|
|
91
|
+
} from "../chunk-5EX2SD5N.js";
|
|
91
92
|
import {
|
|
92
93
|
NPX_LATEST_COMMAND
|
|
93
|
-
} from "../chunk-
|
|
94
|
+
} from "../chunk-2ROXUEZV.js";
|
|
94
95
|
import {
|
|
95
96
|
DECISION_STOP_REASON,
|
|
96
97
|
HAND_BACK_WITHOUT_A_PROMPT,
|
|
97
98
|
KILL_REASON,
|
|
99
|
+
SESSION_PAUSED_REASON,
|
|
98
100
|
UNVERIFIABLE_APPROVAL_REASON,
|
|
99
101
|
redactSecretsFromContent,
|
|
100
102
|
resolveGate,
|
|
101
103
|
timeoutActionWithoutLocalPrompt
|
|
102
|
-
} from "../chunk-
|
|
104
|
+
} from "../chunk-TDLEFGAM.js";
|
|
103
105
|
|
|
104
106
|
// src/wrapper/localPassthrough.ts
|
|
105
107
|
var SIGNAL_NUMBERS = {
|
|
@@ -431,6 +433,7 @@ var BoundedInputQueue = class {
|
|
|
431
433
|
|
|
432
434
|
// src/wrapper/approver.ts
|
|
433
435
|
var DEFAULT_MAX_CONCURRENT = 16;
|
|
436
|
+
var NO_APPROVAL_IN_TIME = "No approval received in time";
|
|
434
437
|
var NO_LOCAL_APPROVAL_UI = "This remote session has no local approval UI. Continue in an interactive session or choose a mode that permits remote approval.";
|
|
435
438
|
var SUBSCRIPTION_REQUIRED_NO_LOCAL_APPROVAL_UI = "Your Pushary workspace has no active subscription, so approvals cannot reach your phone, and this remote session has no local approval UI. Continue in an interactive session.";
|
|
436
439
|
var DEFAULT_APPROVAL_WINDOW_MS = 5 * 6e4;
|
|
@@ -456,7 +459,7 @@ var createRemoteApprover = (deps) => {
|
|
|
456
459
|
const ceiling = policy.timeoutAction === "wait" ? MAX_APPROVAL_WINDOW_MS : base;
|
|
457
460
|
return Math.min(Math.max(base, 15e3), Math.max(ceiling, 15e3));
|
|
458
461
|
};
|
|
459
|
-
const applyTimeout = (policy, input) => timeoutActionWithoutLocalPrompt(policy) === "approve" ? allow(input) : deny(
|
|
462
|
+
const applyTimeout = (policy, input, paused) => timeoutActionWithoutLocalPrompt(policy) === "approve" ? allow(input) : deny(paused ? SESSION_PAUSED_REASON : NO_APPROVAL_IN_TIME);
|
|
460
463
|
const waitForPhone = async (entry, correlationId, windowMs) => {
|
|
461
464
|
const deadline = now() + windowMs;
|
|
462
465
|
while (now() < deadline && !entry.controller.signal.aborted) {
|
|
@@ -558,7 +561,7 @@ var createRemoteApprover = (deps) => {
|
|
|
558
561
|
return answer.value === "yes" ? allow(input) : deny("Denied from your phone");
|
|
559
562
|
}
|
|
560
563
|
if (localHandoff) return deny(NO_LOCAL_APPROVAL_UI);
|
|
561
|
-
return applyTimeout(policy, input);
|
|
564
|
+
return applyTimeout(policy, input, isAwayPaused(question));
|
|
562
565
|
} catch {
|
|
563
566
|
return deny("Approval unavailable; denied by default");
|
|
564
567
|
} finally {
|