@symerian/symi 3.0.16 → 3.0.18

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.
Files changed (310) hide show
  1. package/dist/{audio-preflight-CBDFctZN.js → audio-preflight-BfmZbg4Y.js} +4 -4
  2. package/dist/{audio-preflight-gsZSpG-6.js → audio-preflight-DcuC-liM.js} +4 -4
  3. package/dist/build-info.json +3 -3
  4. package/dist/bundled/boot-md/handler.js +8 -8
  5. package/dist/bundled/session-memory/handler.js +7 -7
  6. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  7. package/dist/{chrome-nPMY1XTJ.js → chrome-Bo7cbvFK.js} +5 -5
  8. package/dist/{chrome-BjVab8gM.js → chrome-DYp18Q0t.js} +5 -5
  9. package/dist/{deliver-D-QFqm31.js → deliver-ChSIbiMM.js} +1 -1
  10. package/dist/{deliver-B4-bcot9.js → deliver-DEgRQM4J.js} +1 -1
  11. package/dist/extensionAPI.js +7 -7
  12. package/dist/{image-CDwtQjmt.js → image-Bx-hvoNJ.js} +1 -1
  13. package/dist/{image-CcS-vzTA.js → image-CQl_mjWk.js} +1 -1
  14. package/dist/llm-slug-generator.js +7 -7
  15. package/dist/{manager-BnEdHzmO.js → manager-D_pn0urG.js} +1 -1
  16. package/dist/{manager-09r0qPze.js → manager-YQxK2t0C.js} +1 -1
  17. package/dist/{pi-embedded-CWsY69-4.js → pi-embedded-CLw_ZzEZ.js} +16 -16
  18. package/dist/{pi-embedded-helpers-BBMy-lqr.js → pi-embedded-helpers-B5I53aw6.js} +4 -4
  19. package/dist/{pi-embedded-helpers-ChEYbgVj.js → pi-embedded-helpers-sUAEIC9X.js} +4 -4
  20. package/dist/plugin-sdk/{accounts-BfyWsC_i.js → accounts-CWFytwbR.js} +3 -3
  21. package/dist/plugin-sdk/{active-listener-DcJW7xAT.js → active-listener-BkZ4jHrL.js} +2 -2
  22. package/dist/plugin-sdk/{agent-scope-ChbGV6of.js → agent-scope-C9gfY_Gk.js} +2 -2
  23. package/dist/plugin-sdk/{audio-preflight-D3GtNLqW.js → audio-preflight-HKbdzXLZ.js} +21 -21
  24. package/dist/plugin-sdk/{bindings-CN2Qmefj.js → bindings-BaKIqPPy.js} +2 -2
  25. package/dist/plugin-sdk/{channel-web-DTyqujjA.js → channel-web-D5nWiTH1.js} +18 -18
  26. package/dist/plugin-sdk/{chrome-BKzAKr3K.js → chrome-klTSnz-9.js} +3 -3
  27. package/dist/plugin-sdk/{chunk-DhDkBujV.js → chunk-BbrYSny_.js} +1 -1
  28. package/dist/plugin-sdk/{command-format-CVrYFyZS.js → command-format-BN6tyZt6.js} +1 -1
  29. package/dist/plugin-sdk/{commands-registry-17yfZkHZ.js → commands-registry-CTzKKtY6.js} +4 -4
  30. package/dist/plugin-sdk/{config-7wk65zKC.js → config-Crv2qEdJ.js} +9 -9
  31. package/dist/plugin-sdk/{consolidate-exbAW0ml.js → consolidate-DT1QH65Q.js} +2 -2
  32. package/dist/plugin-sdk/{deliver-TxAcw7J5.js → deliver-7rOvAlrc.js} +12 -12
  33. package/dist/plugin-sdk/{diagnostic-Debx4frd.js → diagnostic-0nsxhWp7.js} +1 -1
  34. package/dist/plugin-sdk/{fs-safe-wBYbAkJF.js → fs-safe-DfWYBeWF.js} +1 -1
  35. package/dist/plugin-sdk/{gemini-auth-7U2pm2Ky.js → gemini-auth-C0N0_u49.js} +1 -1
  36. package/dist/plugin-sdk/{image-BtDVmYA5.js → image-WOSl2apK.js} +4 -4
  37. package/dist/plugin-sdk/index.js +43 -43
  38. package/dist/plugin-sdk/{ir-CKMvRrGW.js → ir-9J84MTls.js} +4 -4
  39. package/dist/plugin-sdk/{local-roots-c_gaPs01.js → local-roots-OLRDbvyY.js} +3 -3
  40. package/dist/plugin-sdk/{login-DUym1Jy0.js → login-C7x4q0i2.js} +7 -7
  41. package/dist/plugin-sdk/{login-qr-B-WBdvrX.js → login-qr-Dv5_MoAW.js} +9 -9
  42. package/dist/plugin-sdk/{manager-B71SCzos.js → manager-C83tK17x.js} +8 -8
  43. package/dist/plugin-sdk/{manifest-registry-Dnic6Chh.js → manifest-registry-CJMV-PI7.js} +1 -1
  44. package/dist/plugin-sdk/{markdown-tables-Dur7OTlM.js → markdown-tables-DXNKz5y_.js} +1 -1
  45. package/dist/plugin-sdk/{message-channel-BrAhJJV_.js → message-channel-aGy1HbQQ.js} +1 -1
  46. package/dist/plugin-sdk/{model-selection-B9qaVQSJ.js → model-selection-C-3-tpe7.js} +4 -4
  47. package/dist/plugin-sdk/{outbound-DB1wDM8b.js → outbound-DquCeSy5.js} +6 -6
  48. package/dist/plugin-sdk/{pi-auth-json-ZO118hoy.js → pi-auth-json-D9PDCXGn.js} +1 -1
  49. package/dist/plugin-sdk/{pi-embedded-helpers-s_U0Un7j.js → pi-embedded-helpers-D3ygfH7l.js} +16 -16
  50. package/dist/plugin-sdk/{plugins-DF81oSaI.js → plugins-DOwnSg9D.js} +4 -4
  51. package/dist/plugin-sdk/{pw-ai-CTwP02uv.js → pw-ai-rlengLjb.js} +8 -8
  52. package/dist/plugin-sdk/{qmd-manager-CBaSGant.js → qmd-manager-BzxFjRFa.js} +4 -4
  53. package/dist/plugin-sdk/{registry-CZVURNhF.js → registry-5iFfixlB.js} +2 -2
  54. package/dist/plugin-sdk/{replies-hwRbkU3z.js → replies-BXOzO_H5.js} +7 -7
  55. package/dist/plugin-sdk/{reply-prefix-CaXmzZlx.js → reply-prefix-INAKTqCU.js} +1 -1
  56. package/dist/plugin-sdk/{resolve-outbound-target-fxVSOBmk.js → resolve-outbound-target-DvbxHtqp.js} +2 -2
  57. package/dist/plugin-sdk/{resolve-route-ClCyiOeu.js → resolve-route-URXlY3AK.js} +3 -3
  58. package/dist/plugin-sdk/{runner-Cq5jvwQ7.js → runner-Bv0_DWoH.js} +9 -9
  59. package/dist/plugin-sdk/{session-B_TkB65Y.js → session-C3r8l7ou.js} +4 -4
  60. package/dist/plugin-sdk/{skill-commands-0LF9HTGr.js → skill-commands-KjLUGIdZ.js} +5 -5
  61. package/dist/plugin-sdk/{skills-BIT_O7J0.js → skills-BrsD4L5c.js} +7 -7
  62. package/dist/plugin-sdk/{sqlite-Bx5Y5U5X.js → sqlite-CjW7ME1H.js} +1 -1
  63. package/dist/plugin-sdk/{subsystem-CXqYeDy-.js → subsystem-DcOg1xJr.js} +1 -1
  64. package/dist/plugin-sdk/{synthesis-DtsYAj1E.js → synthesis-CY7YAasV.js} +38 -38
  65. package/dist/plugin-sdk/{target-errors-B8mokOeH.js → target-errors-BVWJGWFq.js} +2 -2
  66. package/dist/plugin-sdk/{thinking-Ca0DhqzO.js → thinking-CtsTDPOi.js} +3 -3
  67. package/dist/plugin-sdk/{tokens-CvlONEqh.js → tokens-8lqOTZCB.js} +1 -1
  68. package/dist/plugin-sdk/{tool-images-DpBaWEHT.js → tool-images-Cl_rGIUZ.js} +2 -2
  69. package/dist/plugin-sdk/{tool-loop-detection-BOvUFa0f.js → tool-loop-detection-Da4WUT_P.js} +2 -2
  70. package/dist/plugin-sdk/{unified-runner-CnM7lyNd.js → unified-runner-nwMnsZyj.js} +60 -60
  71. package/dist/plugin-sdk/web-BlweOZDp.js +54 -0
  72. package/dist/plugin-sdk/{whatsapp-actions-CvnfsFJm.js → whatsapp-actions-DpfaGYs7.js} +21 -21
  73. package/dist/{pw-ai-BW8_KeDf.js → pw-ai-BqxJG-Wh.js} +1 -1
  74. package/dist/{pw-ai-j9IE1K0-.js → pw-ai-C-NSGye0.js} +1 -1
  75. package/dist/{runner-8ALr2UII.js → runner-COGFTeDw.js} +1 -1
  76. package/dist/{runner-C4-9kFdR.js → runner-DhCi2lT1.js} +1 -1
  77. package/dist/{synthesis-Cph3LhA1.js → synthesis-CXZu24Vx.js} +7 -7
  78. package/dist/{synthesis-Cus0A2dL.js → synthesis-DrPxcMlQ.js} +7 -7
  79. package/dist/{unified-runner-CX80YMTk.js → unified-runner-iByUazvW.js} +16 -16
  80. package/dist/{web-ChozvJ7I.js → web-EsMQBIYf.js} +7 -7
  81. package/dist/{web-DFlsbXmQ.js → web-PPg5y6xI.js} +7 -7
  82. package/docs/.i18n/zh-CN.tm.jsonl +0 -20
  83. package/docs/automation/cron-jobs.md +0 -2
  84. package/docs/automation/hooks.md +0 -2
  85. package/docs/automation/poll.md +0 -8
  86. package/docs/automation/webhook.md +0 -2
  87. package/docs/capabilities.md +0 -2
  88. package/docs/channels/broadcast-groups.md +0 -1
  89. package/docs/channels/channel-routing.md +4 -10
  90. package/docs/channels/group-messages.md +0 -2
  91. package/docs/channels/groups.md +0 -10
  92. package/docs/channels/index.md +0 -1
  93. package/docs/channels/matrix.md +0 -2
  94. package/docs/channels/msteams.md +0 -2
  95. package/docs/channels/pairing.md +0 -3
  96. package/docs/channels/signal.md +0 -2
  97. package/docs/channels/troubleshooting.md +0 -7
  98. package/docs/cli/channels.md +0 -6
  99. package/docs/cli/configure.md +0 -1
  100. package/docs/cli/directory.md +0 -1
  101. package/docs/cli/index.md +0 -7
  102. package/docs/cli/message.md +1 -47
  103. package/docs/cli/status.md +0 -1
  104. package/docs/concepts/architecture.md +0 -1
  105. package/docs/concepts/features.md +0 -2
  106. package/docs/concepts/markdown-formatting.md +6 -8
  107. package/docs/concepts/memory.md +0 -4
  108. package/docs/concepts/messages.md +0 -1
  109. package/docs/concepts/models.md +0 -1
  110. package/docs/concepts/multi-agent.md +4 -19
  111. package/docs/concepts/queue.md +0 -3
  112. package/docs/concepts/retry.md +0 -5
  113. package/docs/concepts/session-tool.md +0 -2
  114. package/docs/concepts/session.md +2 -9
  115. package/docs/concepts/streaming.md +0 -2
  116. package/docs/concepts/system-prompt.md +0 -1
  117. package/docs/concepts/timezone.md +0 -1
  118. package/docs/date-time.md +0 -1
  119. package/docs/docs.json +2 -11
  120. package/docs/experiments/plans/cron-add-hardening.md +0 -1
  121. package/docs/experiments/plans/session-binding-channel-agnostic.md +2 -23
  122. package/docs/experiments/plans/thread-bound-subagents.md +7 -64
  123. package/docs/gateway/configuration-examples.md +0 -10
  124. package/docs/gateway/configuration-reference.md +22 -47
  125. package/docs/gateway/configuration.md +0 -3
  126. package/docs/gateway/heartbeat.md +0 -2
  127. package/docs/gateway/security/index.md +1 -6
  128. package/docs/gateway/troubleshooting.md +0 -1
  129. package/docs/help/faq.md +0 -13
  130. package/docs/help/troubleshooting.md +0 -1
  131. package/docs/index.md +0 -6
  132. package/docs/install/ansible.md +2 -3
  133. package/docs/install/docker.md +1 -7
  134. package/docs/install/fly.md +0 -14
  135. package/docs/install/northflank.mdx +7 -11
  136. package/docs/install/railway.mdx +6 -10
  137. package/docs/install/render.mdx +1 -2
  138. package/docs/ja-JP/index.md +0 -3
  139. package/docs/pi.md +3 -5
  140. package/docs/platforms/digitalocean.md +0 -1
  141. package/docs/platforms/mac/voicewake.md +0 -1
  142. package/docs/providers/index.md +0 -2
  143. package/docs/refactor/outbound-session-mirroring.md +0 -2
  144. package/docs/reference/AGENTS.default.md +0 -1
  145. package/docs/reference/RELEASING.md +0 -1
  146. package/docs/reference/session-management-compaction.md +0 -1
  147. package/docs/reference/templates/AGENTS.md +0 -7
  148. package/docs/reference/wizard.md +0 -4
  149. package/docs/security/CONTRIBUTING-THREAT-MODEL.md +0 -1
  150. package/docs/security/README.md +0 -1
  151. package/docs/security/THREAT-MODEL-ATLAS.md +7 -10
  152. package/docs/start/docs-directory.md +0 -1
  153. package/docs/start/hubs.md +0 -1
  154. package/docs/start/lore.md +0 -3
  155. package/docs/start/setup.md +0 -2
  156. package/docs/start/showcase.md +0 -2
  157. package/docs/start/symi.md +0 -4
  158. package/docs/start/wizard-cli-reference.md +0 -4
  159. package/docs/start/wizard.md +3 -4
  160. package/docs/tools/agent-send.md +0 -1
  161. package/docs/tools/elevated.md +0 -2
  162. package/docs/tools/exec-approvals.md +0 -1
  163. package/docs/tools/index.md +0 -7
  164. package/docs/tools/multi-agent-sandbox-tools.md +1 -2
  165. package/docs/tools/reactions.md +0 -1
  166. package/docs/tools/slash-commands.md +0 -14
  167. package/docs/tools/symihub.md +0 -1
  168. package/docs/tts.md +0 -1
  169. package/docs/web/control-ui.md +0 -1
  170. package/docs/zh-CN/automation/cron-jobs.md +0 -2
  171. package/docs/zh-CN/automation/poll.md +0 -8
  172. package/docs/zh-CN/automation/webhook.md +0 -2
  173. package/docs/zh-CN/channels/broadcast-groups.md +0 -1
  174. package/docs/zh-CN/channels/channel-routing.md +4 -9
  175. package/docs/zh-CN/channels/group-messages.md +0 -2
  176. package/docs/zh-CN/channels/groups.md +0 -10
  177. package/docs/zh-CN/channels/imessage.md +0 -2
  178. package/docs/zh-CN/channels/index.md +0 -1
  179. package/docs/zh-CN/channels/msteams.md +0 -2
  180. package/docs/zh-CN/channels/pairing.md +0 -3
  181. package/docs/zh-CN/channels/signal.md +0 -2
  182. package/docs/zh-CN/channels/slack.md +0 -2
  183. package/docs/zh-CN/channels/telegram.md +0 -3
  184. package/docs/zh-CN/channels/troubleshooting.md +0 -2
  185. package/docs/zh-CN/cli/channels.md +0 -6
  186. package/docs/zh-CN/cli/configure.md +0 -1
  187. package/docs/zh-CN/cli/directory.md +0 -1
  188. package/docs/zh-CN/cli/index.md +0 -7
  189. package/docs/zh-CN/cli/message.md +1 -42
  190. package/docs/zh-CN/cli/status.md +0 -1
  191. package/docs/zh-CN/concepts/architecture.md +0 -1
  192. package/docs/zh-CN/concepts/features.md +0 -2
  193. package/docs/zh-CN/concepts/markdown-formatting.md +6 -8
  194. package/docs/zh-CN/concepts/messages.md +0 -1
  195. package/docs/zh-CN/concepts/multi-agent.md +4 -5
  196. package/docs/zh-CN/concepts/queue.md +0 -3
  197. package/docs/zh-CN/concepts/retry.md +0 -5
  198. package/docs/zh-CN/concepts/session-tool.md +0 -2
  199. package/docs/zh-CN/concepts/session.md +3 -11
  200. package/docs/zh-CN/concepts/streaming.md +0 -2
  201. package/docs/zh-CN/concepts/system-prompt.md +0 -2
  202. package/docs/zh-CN/concepts/timezone.md +0 -2
  203. package/docs/zh-CN/date-time.md +0 -1
  204. package/docs/zh-CN/experiments/plans/cron-add-hardening.md +0 -1
  205. package/docs/zh-CN/gateway/configuration-examples.md +0 -7
  206. package/docs/zh-CN/gateway/configuration.md +2 -50
  207. package/docs/zh-CN/gateway/heartbeat.md +0 -2
  208. package/docs/zh-CN/gateway/security/index.md +1 -6
  209. package/docs/zh-CN/gateway/troubleshooting.md +1 -14
  210. package/docs/zh-CN/help/faq.md +0 -15
  211. package/docs/zh-CN/index.md +0 -3
  212. package/docs/zh-CN/install/ansible.md +2 -3
  213. package/docs/zh-CN/install/docker.md +1 -7
  214. package/docs/zh-CN/install/fly.md +0 -14
  215. package/docs/zh-CN/install/northflank.mdx +7 -11
  216. package/docs/zh-CN/install/railway.mdx +6 -10
  217. package/docs/zh-CN/install/render.mdx +1 -2
  218. package/docs/zh-CN/pi.md +3 -5
  219. package/docs/zh-CN/platforms/digitalocean.md +0 -1
  220. package/docs/zh-CN/platforms/mac/voicewake.md +0 -1
  221. package/docs/zh-CN/providers/index.md +0 -2
  222. package/docs/zh-CN/refactor/outbound-session-mirroring.md +0 -2
  223. package/docs/zh-CN/reference/AGENTS.default.md +0 -1
  224. package/docs/zh-CN/reference/RELEASING.md +0 -1
  225. package/docs/zh-CN/reference/session-management-compaction.md +0 -1
  226. package/docs/zh-CN/reference/templates/AGENTS.md +0 -5
  227. package/docs/zh-CN/start/docs-directory.md +0 -1
  228. package/docs/zh-CN/start/getting-started.md +0 -5
  229. package/docs/zh-CN/start/hubs.md +0 -1
  230. package/docs/zh-CN/start/lore.md +0 -3
  231. package/docs/zh-CN/start/setup.md +0 -2
  232. package/docs/zh-CN/start/showcase.md +0 -2
  233. package/docs/zh-CN/start/symi.md +0 -4
  234. package/docs/zh-CN/start/wizard.md +0 -5
  235. package/docs/zh-CN/tools/agent-send.md +0 -1
  236. package/docs/zh-CN/tools/elevated.md +0 -2
  237. package/docs/zh-CN/tools/exec-approvals.md +0 -1
  238. package/docs/zh-CN/tools/index.md +0 -7
  239. package/docs/zh-CN/tools/multi-agent-sandbox-tools.md +1 -2
  240. package/docs/zh-CN/tools/reactions.md +0 -1
  241. package/docs/zh-CN/tools/slash-commands.md +0 -9
  242. package/docs/zh-CN/tts.md +0 -2
  243. package/docs/zh-CN/web/control-ui.md +0 -1
  244. package/package.json +1 -1
  245. package/dist/plugin-sdk/web-CIPJBHAU.js +0 -54
  246. package/docs/channels/discord.md +0 -998
  247. package/docs/zh-CN/channels/discord.md +0 -468
  248. package/skills/1password/SKILL.md +0 -71
  249. package/skills/1password/references/cli-examples.md +0 -29
  250. package/skills/1password/references/get-started.md +0 -17
  251. package/skills/apple-notes/SKILL.md +0 -78
  252. package/skills/apple-reminders/SKILL.md +0 -119
  253. package/skills/bear-notes/SKILL.md +0 -108
  254. package/skills/blogwatcher/SKILL.md +0 -70
  255. package/skills/blucli/SKILL.md +0 -48
  256. package/skills/bluebubbles/SKILL.md +0 -132
  257. package/skills/camsnap/SKILL.md +0 -46
  258. package/skills/canvas/SKILL.md +0 -204
  259. package/skills/connect-email/SKILL.md +0 -142
  260. package/skills/document-generation/SKILL.md +0 -83
  261. package/skills/eightctl/SKILL.md +0 -51
  262. package/skills/food-order/SKILL.md +0 -49
  263. package/skills/gemini/SKILL.md +0 -44
  264. package/skills/gh-issues/SKILL.md +0 -865
  265. package/skills/gifgrep/SKILL.md +0 -80
  266. package/skills/github/SKILL.md +0 -164
  267. package/skills/gog/SKILL.md +0 -117
  268. package/skills/goplaces/SKILL.md +0 -53
  269. package/skills/healthcheck/SKILL.md +0 -246
  270. package/skills/himalaya/SKILL.md +0 -258
  271. package/skills/himalaya/references/configuration.md +0 -184
  272. package/skills/himalaya/references/message-composition.md +0 -199
  273. package/skills/imsg/SKILL.md +0 -122
  274. package/skills/long-task/SKILL.md +0 -58
  275. package/skills/long-task/scripts/detach-task.sh +0 -187
  276. package/skills/nano-banana-pro/SKILL.md +0 -59
  277. package/skills/nano-banana-pro/scripts/generate_image.py +0 -184
  278. package/skills/nano-pdf/SKILL.md +0 -39
  279. package/skills/notion/SKILL.md +0 -173
  280. package/skills/obsidian/SKILL.md +0 -82
  281. package/skills/openai-image-gen/SKILL.md +0 -90
  282. package/skills/openai-image-gen/scripts/gen.py +0 -240
  283. package/skills/openai-whisper/SKILL.md +0 -39
  284. package/skills/openai-whisper-api/SKILL.md +0 -53
  285. package/skills/openai-whisper-api/scripts/transcribe.sh +0 -85
  286. package/skills/openhue/SKILL.md +0 -113
  287. package/skills/oracle/SKILL.md +0 -126
  288. package/skills/ordercli/SKILL.md +0 -79
  289. package/skills/peekaboo/SKILL.md +0 -191
  290. package/skills/reactions-extensive/SKILL.md +0 -30
  291. package/skills/reactions-minimal/SKILL.md +0 -31
  292. package/skills/safe-edit/SKILL.md +0 -51
  293. package/skills/sag/SKILL.md +0 -88
  294. package/skills/sherpa-onnx-tts/SKILL.md +0 -104
  295. package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +0 -178
  296. package/skills/songsee/SKILL.md +0 -50
  297. package/skills/sonoscli/SKILL.md +0 -66
  298. package/skills/spotify-player/SKILL.md +0 -65
  299. package/skills/symihub/SKILL.md +0 -78
  300. package/skills/things-mac/SKILL.md +0 -87
  301. package/skills/tmux/SKILL.md +0 -153
  302. package/skills/tmux/scripts/find-sessions.sh +0 -112
  303. package/skills/tmux/scripts/wait-for-text.sh +0 -83
  304. package/skills/trello/SKILL.md +0 -96
  305. package/skills/video-frames/SKILL.md +0 -47
  306. package/skills/video-frames/scripts/frame.sh +0 -81
  307. package/skills/voice-call/SKILL.md +0 -46
  308. package/skills/wacli/SKILL.md +0 -73
  309. package/skills/weather/SKILL.md +0 -113
  310. package/skills/xurl/SKILL.md +0 -462
@@ -1,122 +0,0 @@
1
- ---
2
- name: imsg
3
- description: iMessage/SMS CLI for listing chats, history, and sending messages via Messages.app.
4
- homepage: https://imsg.to
5
- metadata:
6
- {
7
- "symi":
8
- {
9
- "emoji": "📨",
10
- "os": ["darwin"],
11
- "requires": { "bins": ["imsg"] },
12
- "install":
13
- [
14
- {
15
- "id": "brew",
16
- "kind": "brew",
17
- "formula": "steipete/tap/imsg",
18
- "bins": ["imsg"],
19
- "label": "Install imsg (brew)",
20
- },
21
- ],
22
- },
23
- }
24
- triggers: [imsg]
25
- ---
26
-
27
- # imsg
28
-
29
- Use `imsg` to read and send iMessage/SMS via macOS Messages.app.
30
-
31
- ## When to Use
32
-
33
- ✅ **USE this skill when:**
34
-
35
- - User explicitly asks to send iMessage or SMS
36
- - Reading iMessage conversation history
37
- - Checking recent Messages.app chats
38
- - Sending to phone numbers or Apple IDs
39
-
40
- ## When NOT to Use
41
-
42
- ❌ **DON'T use this skill when:**
43
-
44
- - Telegram messages → use `message` tool with `channel:telegram`
45
- - Signal messages → use Signal channel if configured
46
- - WhatsApp messages → use WhatsApp channel if configured
47
- - Slack messages → use `slack` skill
48
- - Group chat management (adding/removing members) → not supported
49
- - Bulk/mass messaging → always confirm with user first
50
- - Replying in current conversation → just reply normally (Symi routes automatically)
51
-
52
- ## Requirements
53
-
54
- - macOS with Messages.app signed in
55
- - Full Disk Access for terminal
56
- - Automation permission for Messages.app (for sending)
57
-
58
- ## Common Commands
59
-
60
- ### List Chats
61
-
62
- ```bash
63
- imsg chats --limit 10 --json
64
- ```
65
-
66
- ### View History
67
-
68
- ```bash
69
- # By chat ID
70
- imsg history --chat-id 1 --limit 20 --json
71
-
72
- # With attachments info
73
- imsg history --chat-id 1 --limit 20 --attachments --json
74
- ```
75
-
76
- ### Watch for New Messages
77
-
78
- ```bash
79
- imsg watch --chat-id 1 --attachments
80
- ```
81
-
82
- ### Send Messages
83
-
84
- ```bash
85
- # Text only
86
- imsg send --to "+14155551212" --text "Hello!"
87
-
88
- # With attachment
89
- imsg send --to "+14155551212" --text "Check this out" --file /path/to/image.jpg
90
-
91
- # Specify service
92
- imsg send --to "+14155551212" --text "Hi" --service imessage
93
- imsg send --to "+14155551212" --text "Hi" --service sms
94
- ```
95
-
96
- ## Service Options
97
-
98
- - `--service imessage` — Force iMessage (requires recipient has iMessage)
99
- - `--service sms` — Force SMS (green bubble)
100
- - `--service auto` — Let Messages.app decide (default)
101
-
102
- ## Safety Rules
103
-
104
- 1. **Always confirm recipient and message content** before sending
105
- 2. **Never send to unknown numbers** without explicit user approval
106
- 3. **Be careful with attachments** — confirm file path exists
107
- 4. **Rate limit yourself** — don't spam
108
-
109
- ## Example Workflow
110
-
111
- User: "Text mom that I'll be late"
112
-
113
- ```bash
114
- # 1. Find mom's chat
115
- imsg chats --limit 20 --json | jq '.[] | select(.displayName | contains("Mom"))'
116
-
117
- # 2. Confirm with user
118
- # "Found Mom at +1555123456. Send 'I'll be late' via iMessage?"
119
-
120
- # 3. Send after confirmation
121
- imsg send --to "+1555123456" --text "I'll be late"
122
- ```
@@ -1,58 +0,0 @@
1
- ---
2
- name: long-task
3
- description: Run long operations (deep scans, brute-forces, big builds, exhaustive enumeration) without hitting the agent-turn timeout. Detaches the command with setsid+nohup and schedules a cron monitor that polls status every 2-3 minutes. Use when a single exec call may exceed 15 minutes (deep nmap `-sS -sV -O` on /24 or larger, full hydra/gobuster/ffuf/masscan sweeps, multi-hour builds).
4
- triggers: [long-task, long, task]
5
- ---
6
-
7
- # Long-Running Task — detach + cron monitor pattern
8
-
9
- Deep scans (`nmap -sS -sV -O` on a /24, comprehensive `-sC` sweeps, full TCP/UDP, long brute-forces, big builds) routinely run 25–60 minutes. The agent-turn timeout (`agents.defaults.timeoutSeconds`, default 1800 = 30 min) is a hard ceiling, and a foreground-blocked exec tool call will SIGTERM the subprocess when the turn ends. **Do not foreground long tasks.** Use this two-part pattern instead.
10
-
11
- ## Part 1 — Detach the task
12
-
13
- Launch with the helper script bundled with this skill:
14
-
15
- <skill-dir>/scripts/detach-task.sh <task-id> <workdir> <command...>
16
-
17
- Where:
18
-
19
- - `<task-id>` is a short identifier you pick (e.g. `scan-192-168-10`)
20
- - `<workdir>` is a directory the state files will be written into (agent workspace is fine)
21
- - `<command...>` is the literal command you want to run
22
-
23
- The script creates in `<workdir>`:
24
-
25
- - `task-<id>.pid` — PID of the detached process
26
- - `task-<id>.cmd` — the literal command line
27
- - `task-<id>.started` — ISO-8601 start timestamp
28
- - `task-<id>.log` — merged stdout/stderr
29
- - `task-<id>.status` — `running` while alive, `complete rc=<N>` after exit
30
-
31
- After running, **return control to the user immediately** with: task id, PID, log path, your ETA, and a note that a cron monitor will be scheduled.
32
-
33
- ## Part 2 — Schedule the cron monitor
34
-
35
- Use the `cron` tool with `action: add`. Schedule every 2–3 minutes. The job prompt must be self-contained — include the task-id, PID, log path, and status path literally, since a future agent turn will receive only that prompt.
36
-
37
- Example job prompt:
38
-
39
- > Check if PID <pid> is alive (`kill -0 <pid> 2>/dev/null`).
40
- > If alive: tail -n 20 <log-path>, post one-sentence progress update.
41
- > If not alive: read <status-path> and tail <log-path>, post final summary, then call the cron tool with `action: remove, id: <this-cron-id>` to clean up.
42
-
43
- ## Part 3 — Cleanup
44
-
45
- The monitor cron job is responsible for removing itself when it detects `status=complete`. Do not leave stale monitors running.
46
-
47
- ## Why this works
48
-
49
- - `setsid` puts the subprocess in a new session — it survives SIGHUP.
50
- - `nohup` ignores SIGHUP directly as belt-and-braces.
51
- - The outer shell exits immediately, so the agent-turn abort (which kills the process tree of the shell the agent spawned) never reaches the detached task — it's no longer a descendant.
52
- - Each agent turn stays short (initial detach <1 min, each cron check <30 sec, final summary <1 min), so the default 1800s ceiling never fires.
53
-
54
- ## When NOT to use this pattern
55
-
56
- - Short scans (single host, small port range) that complete in under 10 minutes — foreground exec is simpler.
57
- - Interactive commands that need a TTY — the script closes stdin and redirects stdout/stderr.
58
- - Tasks where you need to stream output back to the user in real time — the cron-monitor pattern polls at 2–3 min intervals, not live.
@@ -1,187 +0,0 @@
1
- #!/usr/bin/env bash
2
- # detach-task.sh — launch a long-running command fully detached from the
3
- # calling agent turn, so it survives the agent-turn timeout (default 30 min).
4
- #
5
- # Usage:
6
- # detach-task.sh <task-id> <workdir> <command...>
7
- #
8
- # Creates in <workdir>:
9
- # task-<id>.pid — PID of the detached process
10
- # task-<id>.cmd — literal command line (for future agent turns to see)
11
- # task-<id>.started — ISO-8601 start timestamp
12
- # task-<id>.log — combined stdout + stderr (grows as task runs)
13
- # task-<id>.status — "running pid=<N> started=<ISO>"
14
- # → "complete rc=<N> ended=<ISO>" on clean exit
15
- # → "aborted rc=<N> signal=<NAME>" on SIGTERM/INT/HUP
16
- #
17
- # Exit code: 0 on successful spawn, 1 on missing args, 2 on invalid args,
18
- # 3 on workdir creation failure, 4 on task-id collision (a task
19
- # with the same id is already running).
20
- #
21
- # Hardening notes (2.7.0):
22
- # - task-id is validated against an allow-list ([a-zA-Z0-9._-], 1–60 chars,
23
- # must not start with '.' or '-'). Prevents path traversal via task-id.
24
- # - workdir must be an absolute path.
25
- # - Status file is written via tmp + mv so concurrent readers never see a
26
- # half-written file and the "stuck at running after SIGTERM" failure mode
27
- # is eliminated.
28
- # - Child shell has a TERM/INT/HUP trap that records an "aborted" status
29
- # before exiting, so external kill signals leave a deterministic record.
30
- #
31
- # Hardening notes (post-2.8.12):
32
- # - Pre-flight collision check: refuses to overwrite the state files of a
33
- # task-id whose recorded PID is still alive (exit code 4).
34
- # - Log file is bounded by LONG_TASK_LOG_MAX_BYTES (default 104857600 =
35
- # 100 MiB; override via env). Once exceeded, a single marker line is
36
- # written and further output is silently discarded — the producer keeps
37
- # running, never gets SIGPIPE.
38
- #
39
- # Design notes:
40
- # - setsid + nohup + disown: triple-armor against SIGHUP when the parent
41
- # shell exits. The subprocess gets its own session.
42
- # - stdin closed, stdout/stderr redirected to the log file. No terminal.
43
- # - The wrapper shell exits immediately after spawning; does NOT wait.
44
-
45
- set -euo pipefail
46
-
47
- if [[ $# -lt 3 ]]; then
48
- echo "usage: $0 <task-id> <workdir> <command...>" >&2
49
- exit 1
50
- fi
51
-
52
- raw_task_id="$1"
53
- workdir="$2"
54
- shift 2
55
-
56
- # --- task-id validation -----------------------------------------------------
57
- if [[ -z "$raw_task_id" ]]; then
58
- echo "detach-task: task-id must not be empty" >&2
59
- exit 2
60
- fi
61
- if [[ ${#raw_task_id} -gt 60 ]]; then
62
- echo "detach-task: task-id exceeds 60 chars" >&2
63
- exit 2
64
- fi
65
- if [[ "$raw_task_id" =~ [^a-zA-Z0-9._-] ]]; then
66
- echo "detach-task: task-id contains illegal chars (allowed: alphanumeric, dot, dash, underscore): $raw_task_id" >&2
67
- exit 2
68
- fi
69
- case "$raw_task_id" in
70
- .* | -*)
71
- echo "detach-task: task-id must not start with dot or dash: $raw_task_id" >&2
72
- exit 2
73
- ;;
74
- esac
75
- task_id="$raw_task_id"
76
-
77
- # --- workdir validation -----------------------------------------------------
78
- if [[ "$workdir" != /* ]]; then
79
- echo "detach-task: workdir must be an absolute path: $workdir" >&2
80
- exit 2
81
- fi
82
- if ! mkdir -p "$workdir"; then
83
- echo "detach-task: cannot create workdir: $workdir" >&2
84
- exit 3
85
- fi
86
-
87
- # --- log size cap -----------------------------------------------------------
88
- log_max_bytes="${LONG_TASK_LOG_MAX_BYTES:-104857600}"
89
- if ! [[ "$log_max_bytes" =~ ^[0-9]+$ ]] || (( log_max_bytes < 1 )); then
90
- echo "detach-task: LONG_TASK_LOG_MAX_BYTES must be a positive integer (got: $log_max_bytes)" >&2
91
- exit 2
92
- fi
93
-
94
- pid_file="$workdir/task-${task_id}.pid"
95
- cmd_file="$workdir/task-${task_id}.cmd"
96
- started_file="$workdir/task-${task_id}.started"
97
- log_file="$workdir/task-${task_id}.log"
98
- status_file="$workdir/task-${task_id}.status"
99
-
100
- # --- collision check --------------------------------------------------------
101
- # If a pid file exists and the recorded PID is still alive, a prior task with
102
- # this id is already running. Refuse to clobber its log/status files.
103
- # Stale pid files (process already dead) are silently overwritten below.
104
- if [[ -f "$pid_file" ]]; then
105
- prior_pid="$(tr -dc '0-9' < "$pid_file" 2>/dev/null || true)"
106
- if [[ -n "$prior_pid" ]] && kill -0 "$prior_pid" 2>/dev/null; then
107
- echo "detach-task: task-id '$task_id' is already running (pid=$prior_pid). Pick a different id or wait for it to finish." >&2
108
- exit 4
109
- fi
110
- fi
111
-
112
- # --- atomic status writer (parent) -----------------------------------------
113
- write_status_atomic() {
114
- local _payload="$1"
115
- local _tmp="${status_file}.$$.${RANDOM}.tmp"
116
- printf '%s\n' "$_payload" > "$_tmp"
117
- mv -f "$_tmp" "$status_file"
118
- }
119
-
120
- printf '%s\n' "$*" > "$cmd_file"
121
- started_at="$(date -u -Iseconds)"
122
- printf '%s\n' "$started_at" > "$started_file"
123
- write_status_atomic "running started=$started_at"
124
-
125
- # --- detached child --------------------------------------------------------
126
- # The inner `bash -c` inherits status/log paths as positional args so we
127
- # never string-interpolate paths into the script body. The inner script
128
- # re-implements the atomic writer (functions don't cross process boundaries
129
- # via `bash -c`). A TERM/INT/HUP trap catches external kill signals and
130
- # writes a terminal "aborted" status before exiting with the signal's code.
131
- setsid nohup bash -c '
132
- set -u
133
- _status="$1"
134
- _log="$2"
135
- _max="$3"
136
- shift 3
137
- _write() {
138
- local _tmp="${_status}.$$.${RANDOM}.tmp"
139
- printf "%s\n" "$1" > "$_tmp" && mv -f "$_tmp" "$_status"
140
- }
141
- _on_signal() {
142
- local _sig="$1"
143
- local _rc=$?
144
- _write "aborted rc=$_rc signal=$_sig ended=$(date -u -Iseconds)" 2>/dev/null || true
145
- exit "$_rc"
146
- }
147
- # Reads stdin line-by-line, prints to its stdout (which the caller
148
- # redirects to the log file) up to _max total bytes, then writes one
149
- # cap marker and silently discards the rest. Reading continues until
150
- # EOF so the producing pipe never receives SIGPIPE.
151
- _log_capper() {
152
- local _total=0
153
- local _capped=0
154
- local _line
155
- local _ls
156
- while IFS= read -r _line; do
157
- if (( _capped )); then
158
- continue
159
- fi
160
- _ls=$(( ${#_line} + 1 ))
161
- if (( _total + _ls > _max )); then
162
- printf "[long-task: log capped at %s bytes; further output discarded]\n" "$_max"
163
- _capped=1
164
- continue
165
- fi
166
- printf "%s\n" "$_line"
167
- _total=$(( _total + _ls ))
168
- done
169
- }
170
- trap "_on_signal TERM" TERM
171
- trap "_on_signal INT" INT
172
- trap "_on_signal HUP" HUP
173
- "$@" 2>&1 | _log_capper >> "$_log"
174
- rc=${PIPESTATUS[0]}
175
- _write "complete rc=$rc ended=$(date -u -Iseconds)"
176
- ' -- "$status_file" "$log_file" "$log_max_bytes" "$@" < /dev/null > /dev/null 2>&1 &
177
-
178
- pid=$!
179
- disown "$pid" 2>/dev/null || true
180
- printf '%d\n' "$pid" > "$pid_file"
181
-
182
- # Finalise the parent status with the PID once known. The child may race us
183
- # and overwrite with "complete" if the command was very fast — that's fine,
184
- # the mv is atomic and the final state wins.
185
- write_status_atomic "running pid=$pid started=$started_at"
186
-
187
- echo "spawned task=$task_id pid=$pid log=$log_file status=$status_file"
@@ -1,59 +0,0 @@
1
- ---
2
- name: nano-banana-pro
3
- description: Generate or edit images via Gemini 3 Pro Image (Nano Banana Pro).
4
- homepage: https://ai.google.dev/
5
- metadata:
6
- {
7
- "symi":
8
- {
9
- "emoji": "🍌",
10
- "requires": { "bins": ["uv"], "env": ["GEMINI_API_KEY"] },
11
- "primaryEnv": "GEMINI_API_KEY",
12
- "install":
13
- [
14
- {
15
- "id": "uv-brew",
16
- "kind": "brew",
17
- "formula": "uv",
18
- "bins": ["uv"],
19
- "label": "Install uv (brew)",
20
- },
21
- ],
22
- },
23
- }
24
- triggers: [nano-banana-pro, nano, banana, pro]
25
- ---
26
-
27
- # Nano Banana Pro (Gemini 3 Pro Image)
28
-
29
- Use the bundled script to generate or edit images.
30
-
31
- Generate
32
-
33
- ```bash
34
- uv run {baseDir}/scripts/generate_image.py --prompt "your image description" --filename "output.png" --resolution 1K
35
- ```
36
-
37
- Edit (single image)
38
-
39
- ```bash
40
- uv run {baseDir}/scripts/generate_image.py --prompt "edit instructions" --filename "output.png" -i "/path/in.png" --resolution 2K
41
- ```
42
-
43
- Multi-image composition (up to 14 images)
44
-
45
- ```bash
46
- uv run {baseDir}/scripts/generate_image.py --prompt "combine these into one scene" --filename "output.png" -i img1.png -i img2.png -i img3.png
47
- ```
48
-
49
- API key
50
-
51
- - `GEMINI_API_KEY` env var
52
- - Or set `skills."nano-banana-pro".apiKey` / `skills."nano-banana-pro".env.GEMINI_API_KEY` in `~/.symi/symi.json`
53
-
54
- Notes
55
-
56
- - Resolutions: `1K` (default), `2K`, `4K`.
57
- - Use timestamps in filenames: `yyyy-mm-dd-hh-mm-ss-name.png`.
58
- - The script prints a `MEDIA:` line for Symi to auto-attach on supported chat providers.
59
- - Do not read the image back; report the saved path only.
@@ -1,184 +0,0 @@
1
- #!/usr/bin/env python3
2
- # /// script
3
- # requires-python = ">=3.10"
4
- # dependencies = [
5
- # "google-genai>=1.0.0",
6
- # "pillow>=10.0.0",
7
- # ]
8
- # ///
9
- """
10
- Generate images using Google's Nano Banana Pro (Gemini 3 Pro Image) API.
11
-
12
- Usage:
13
- uv run generate_image.py --prompt "your image description" --filename "output.png" [--resolution 1K|2K|4K] [--api-key KEY]
14
-
15
- Multi-image editing (up to 14 images):
16
- uv run generate_image.py --prompt "combine these images" --filename "output.png" -i img1.png -i img2.png -i img3.png
17
- """
18
-
19
- import argparse
20
- import os
21
- import sys
22
- from pathlib import Path
23
-
24
-
25
- def get_api_key(provided_key: str | None) -> str | None:
26
- """Get API key from argument first, then environment."""
27
- if provided_key:
28
- return provided_key
29
- return os.environ.get("GEMINI_API_KEY")
30
-
31
-
32
- def main():
33
- parser = argparse.ArgumentParser(
34
- description="Generate images using Nano Banana Pro (Gemini 3 Pro Image)"
35
- )
36
- parser.add_argument(
37
- "--prompt", "-p",
38
- required=True,
39
- help="Image description/prompt"
40
- )
41
- parser.add_argument(
42
- "--filename", "-f",
43
- required=True,
44
- help="Output filename (e.g., sunset-mountains.png)"
45
- )
46
- parser.add_argument(
47
- "--input-image", "-i",
48
- action="append",
49
- dest="input_images",
50
- metavar="IMAGE",
51
- help="Input image path(s) for editing/composition. Can be specified multiple times (up to 14 images)."
52
- )
53
- parser.add_argument(
54
- "--resolution", "-r",
55
- choices=["1K", "2K", "4K"],
56
- default="1K",
57
- help="Output resolution: 1K (default), 2K, or 4K"
58
- )
59
- parser.add_argument(
60
- "--api-key", "-k",
61
- help="Gemini API key (overrides GEMINI_API_KEY env var)"
62
- )
63
-
64
- args = parser.parse_args()
65
-
66
- # Get API key
67
- api_key = get_api_key(args.api_key)
68
- if not api_key:
69
- print("Error: No API key provided.", file=sys.stderr)
70
- print("Please either:", file=sys.stderr)
71
- print(" 1. Provide --api-key argument", file=sys.stderr)
72
- print(" 2. Set GEMINI_API_KEY environment variable", file=sys.stderr)
73
- sys.exit(1)
74
-
75
- # Import here after checking API key to avoid slow import on error
76
- from google import genai
77
- from google.genai import types
78
- from PIL import Image as PILImage
79
-
80
- # Initialise client
81
- client = genai.Client(api_key=api_key)
82
-
83
- # Set up output path
84
- output_path = Path(args.filename)
85
- output_path.parent.mkdir(parents=True, exist_ok=True)
86
-
87
- # Load input images if provided (up to 14 supported by Nano Banana Pro)
88
- input_images = []
89
- output_resolution = args.resolution
90
- if args.input_images:
91
- if len(args.input_images) > 14:
92
- print(f"Error: Too many input images ({len(args.input_images)}). Maximum is 14.", file=sys.stderr)
93
- sys.exit(1)
94
-
95
- max_input_dim = 0
96
- for img_path in args.input_images:
97
- try:
98
- img = PILImage.open(img_path)
99
- input_images.append(img)
100
- print(f"Loaded input image: {img_path}")
101
-
102
- # Track largest dimension for auto-resolution
103
- width, height = img.size
104
- max_input_dim = max(max_input_dim, width, height)
105
- except Exception as e:
106
- print(f"Error loading input image '{img_path}': {e}", file=sys.stderr)
107
- sys.exit(1)
108
-
109
- # Auto-detect resolution from largest input if not explicitly set
110
- if args.resolution == "1K" and max_input_dim > 0: # Default value
111
- if max_input_dim >= 3000:
112
- output_resolution = "4K"
113
- elif max_input_dim >= 1500:
114
- output_resolution = "2K"
115
- else:
116
- output_resolution = "1K"
117
- print(f"Auto-detected resolution: {output_resolution} (from max input dimension {max_input_dim})")
118
-
119
- # Build contents (images first if editing, prompt only if generating)
120
- if input_images:
121
- contents = [*input_images, args.prompt]
122
- img_count = len(input_images)
123
- print(f"Processing {img_count} image{'s' if img_count > 1 else ''} with resolution {output_resolution}...")
124
- else:
125
- contents = args.prompt
126
- print(f"Generating image with resolution {output_resolution}...")
127
-
128
- try:
129
- response = client.models.generate_content(
130
- model="gemini-3-pro-image-preview",
131
- contents=contents,
132
- config=types.GenerateContentConfig(
133
- response_modalities=["TEXT", "IMAGE"],
134
- image_config=types.ImageConfig(
135
- image_size=output_resolution
136
- )
137
- )
138
- )
139
-
140
- # Process response and convert to PNG
141
- image_saved = False
142
- for part in response.parts:
143
- if part.text is not None:
144
- print(f"Model response: {part.text}")
145
- elif part.inline_data is not None:
146
- # Convert inline data to PIL Image and save as PNG
147
- from io import BytesIO
148
-
149
- # inline_data.data is already bytes, not base64
150
- image_data = part.inline_data.data
151
- if isinstance(image_data, str):
152
- # If it's a string, it might be base64
153
- import base64
154
- image_data = base64.b64decode(image_data)
155
-
156
- image = PILImage.open(BytesIO(image_data))
157
-
158
- # Ensure RGB mode for PNG (convert RGBA to RGB with white background if needed)
159
- if image.mode == 'RGBA':
160
- rgb_image = PILImage.new('RGB', image.size, (255, 255, 255))
161
- rgb_image.paste(image, mask=image.split()[3])
162
- rgb_image.save(str(output_path), 'PNG')
163
- elif image.mode == 'RGB':
164
- image.save(str(output_path), 'PNG')
165
- else:
166
- image.convert('RGB').save(str(output_path), 'PNG')
167
- image_saved = True
168
-
169
- if image_saved:
170
- full_path = output_path.resolve()
171
- print(f"\nImage saved: {full_path}")
172
- # Symi parses MEDIA tokens and will attach the file on supported providers.
173
- print(f"MEDIA: {full_path}")
174
- else:
175
- print("Error: No image was generated in the response.", file=sys.stderr)
176
- sys.exit(1)
177
-
178
- except Exception as e:
179
- print(f"Error generating image: {e}", file=sys.stderr)
180
- sys.exit(1)
181
-
182
-
183
- if __name__ == "__main__":
184
- main()
@@ -1,39 +0,0 @@
1
- ---
2
- name: nano-pdf
3
- description: Edit PDFs with natural-language instructions using the nano-pdf CLI.
4
- homepage: https://pypi.org/project/nano-pdf/
5
- metadata:
6
- {
7
- "symi":
8
- {
9
- "emoji": "📄",
10
- "requires": { "bins": ["nano-pdf"] },
11
- "install":
12
- [
13
- {
14
- "id": "uv",
15
- "kind": "uv",
16
- "package": "nano-pdf",
17
- "bins": ["nano-pdf"],
18
- "label": "Install nano-pdf (uv)",
19
- },
20
- ],
21
- },
22
- }
23
- triggers: [nano-pdf, nano, pdf]
24
- ---
25
-
26
- # nano-pdf
27
-
28
- Use `nano-pdf` to apply edits to a specific page in a PDF using a natural-language instruction.
29
-
30
- ## Quick start
31
-
32
- ```bash
33
- nano-pdf edit deck.pdf 1 "Change the title to 'Q3 Results' and fix the typo in the subtitle"
34
- ```
35
-
36
- Notes:
37
-
38
- - Page numbers are 0-based or 1-based depending on the tool’s version/config; if the result looks off by one, retry with the other.
39
- - Always sanity-check the output PDF before sending it out.