@notis_ai/cli 0.2.14 → 0.2.16

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 (299) hide show
  1. package/README.md +83 -21
  2. package/dist/agent-hooks/notis-agent-hook.mjs +20168 -0
  3. package/{skills → dist/base-skills}/notis-apps/SKILL.md +167 -72
  4. package/{skills → dist/base-skills}/notis-cli/SKILL.md +86 -28
  5. package/dist/base-skills/notis-query/SKILL.md +705 -0
  6. package/dist/skill-sync/index.js +1528 -0
  7. package/dist/skill-sync/index.js.map +7 -0
  8. package/package.json +5 -2
  9. package/skills/notis-apps/cli.md +39 -18
  10. package/skills/notis-cli/AGENT_INSTRUCTIONS.md +39 -0
  11. package/skills/notis-onboarding/BRIEF.md +16 -0
  12. package/src/agent-hook-entry.js +5 -0
  13. package/src/cli.js +23 -14
  14. package/src/command-specs/agents.js +392 -0
  15. package/src/command-specs/apps.js +1021 -424
  16. package/src/command-specs/auth.js +63 -10
  17. package/src/command-specs/index.js +6 -0
  18. package/src/command-specs/onboarding.js +69 -5
  19. package/src/command-specs/skills.js +56 -0
  20. package/src/runtime/agent-memory-state.js +126 -0
  21. package/src/runtime/agent-setup.js +383 -0
  22. package/src/runtime/app-dev-consumers.js +154 -0
  23. package/src/runtime/app-dev-host-lock.js +80 -0
  24. package/src/runtime/app-dev-process-identity.js +111 -0
  25. package/src/runtime/app-dev-roots.js +284 -0
  26. package/src/runtime/app-dev-server.js +447 -29
  27. package/src/runtime/app-dev-sessions.js +105 -145
  28. package/src/runtime/app-platform.js +1314 -166
  29. package/src/runtime/app-registry-scaffolds.js +367 -0
  30. package/src/runtime/base-skills.d.ts +20 -0
  31. package/src/runtime/base-skills.js +167 -0
  32. package/src/runtime/login-listener.js +15 -0
  33. package/src/runtime/oauth.js +1506 -141
  34. package/src/runtime/output.js +7 -0
  35. package/src/runtime/ports.js +16 -0
  36. package/src/runtime/profiles.js +19 -16
  37. package/src/runtime/skill-sync/cloud-client.ts +96 -0
  38. package/src/runtime/skill-sync/index.ts +644 -0
  39. package/src/runtime/skill-sync/local-scanner.ts +1046 -0
  40. package/src/runtime/skill-sync/symlink-manager.ts +383 -0
  41. package/src/runtime/skill-sync/sync-plan.ts +22 -0
  42. package/src/runtime/skill-sync/types.ts +103 -0
  43. package/src/runtime/skill-sync/write-cloud-skill.ts +50 -0
  44. package/src/runtime/store-screenshot.js +6 -1
  45. package/src/runtime/sync-skills.d.ts +37 -0
  46. package/src/runtime/sync-skills.js +231 -0
  47. package/template/app/layout.tsx +5 -1
  48. package/template/notis.config.ts +1 -0
  49. package/template/packages/sdk/package.json +2 -1
  50. package/template/packages/sdk/src/components/DocumentEditor.tsx +13 -3
  51. package/template/packages/sdk/src/components/MarkdownEditor.tsx +121 -0
  52. package/template/packages/sdk/src/components/MultiSelectActionBar.tsx +43 -119
  53. package/template/packages/sdk/src/components/MultiSelectCheckbox.tsx +5 -1
  54. package/template/packages/sdk/src/components/MultiSelectDragOverlay.tsx +1 -1
  55. package/template/packages/sdk/src/components/NotisSelectionBoundary.tsx +55 -0
  56. package/template/packages/sdk/src/components/ShortcutHints.tsx +56 -0
  57. package/template/packages/sdk/src/config.ts +25 -0
  58. package/template/packages/sdk/src/documents.ts +7 -1
  59. package/template/packages/sdk/src/hooks/useActiveResource.ts +19 -0
  60. package/template/packages/sdk/src/hooks/useCollectionInteractions.ts +726 -0
  61. package/template/packages/sdk/src/hooks/useHandover.ts +3 -0
  62. package/template/packages/sdk/src/hooks/useMultiSelect.ts +44 -482
  63. package/template/packages/sdk/src/hooks/useNotis.ts +3 -0
  64. package/template/packages/sdk/src/hooks/useNotisNavigation.ts +7 -4
  65. package/template/packages/sdk/src/hooks/useTool.ts +5 -4
  66. package/template/packages/sdk/src/index.ts +47 -2
  67. package/template/packages/sdk/src/interactions/actions.ts +46 -0
  68. package/template/packages/sdk/src/interactions/shortcuts.tsx +634 -0
  69. package/template/packages/sdk/src/interactions.ts +41 -0
  70. package/template/packages/sdk/src/provider.tsx +2 -1
  71. package/template/packages/sdk/src/runtime.ts +92 -4
  72. package/dist/scaffolds/notis-database/CHANGELOG.md +0 -5
  73. package/dist/scaffolds/notis-database/app/globals.css +0 -44
  74. package/dist/scaffolds/notis-database/app/layout.tsx +0 -6
  75. package/dist/scaffolds/notis-database/app/page.tsx +0 -1088
  76. package/dist/scaffolds/notis-database/components/ui/badge.tsx +0 -28
  77. package/dist/scaffolds/notis-database/components/ui/button.tsx +0 -53
  78. package/dist/scaffolds/notis-database/components/ui/card.tsx +0 -56
  79. package/dist/scaffolds/notis-database/components/ui/table.tsx +0 -120
  80. package/dist/scaffolds/notis-database/components.json +0 -20
  81. package/dist/scaffolds/notis-database/index.html +0 -12
  82. package/dist/scaffolds/notis-database/lib/types.ts +0 -132
  83. package/dist/scaffolds/notis-database/lib/utils.ts +0 -6
  84. package/dist/scaffolds/notis-database/metadata/screenshot-1.png +0 -0
  85. package/dist/scaffolds/notis-database/metadata/screenshot-2.png +0 -0
  86. package/dist/scaffolds/notis-database/metadata/screenshot-3.png +0 -0
  87. package/dist/scaffolds/notis-database/metadata/screenshot-4.png +0 -0
  88. package/dist/scaffolds/notis-database/metadata/screenshot-5.png +0 -0
  89. package/dist/scaffolds/notis-database/metadata/screenshot-fixtures.json +0 -1839
  90. package/dist/scaffolds/notis-database/notis.config.ts +0 -73
  91. package/dist/scaffolds/notis-database/package-lock.json +0 -3935
  92. package/dist/scaffolds/notis-database/package.json +0 -32
  93. package/dist/scaffolds/notis-database/packages/sdk/package.json +0 -36
  94. package/dist/scaffolds/notis-database/packages/sdk/src/components/DocumentEditor.tsx +0 -93
  95. package/dist/scaffolds/notis-database/packages/sdk/src/components/Markdown.tsx +0 -60
  96. package/dist/scaffolds/notis-database/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
  97. package/dist/scaffolds/notis-database/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
  98. package/dist/scaffolds/notis-database/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
  99. package/dist/scaffolds/notis-database/packages/sdk/src/config.ts +0 -234
  100. package/dist/scaffolds/notis-database/packages/sdk/src/documents.ts +0 -250
  101. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useBackend.ts +0 -41
  102. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  103. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  104. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDatabaseSubscription.ts +0 -76
  105. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDocument.ts +0 -78
  106. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDocuments.ts +0 -121
  107. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useHandover.ts +0 -75
  108. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
  109. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useNotis.ts +0 -34
  110. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
  111. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useTool.ts +0 -64
  112. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useTools.ts +0 -56
  113. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  114. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
  115. package/dist/scaffolds/notis-database/packages/sdk/src/index.ts +0 -100
  116. package/dist/scaffolds/notis-database/packages/sdk/src/provider.tsx +0 -43
  117. package/dist/scaffolds/notis-database/packages/sdk/src/runtime.ts +0 -351
  118. package/dist/scaffolds/notis-database/packages/sdk/src/styles.css +0 -186
  119. package/dist/scaffolds/notis-database/packages/sdk/src/ui.ts +0 -15
  120. package/dist/scaffolds/notis-database/packages/sdk/src/vite.ts +0 -56
  121. package/dist/scaffolds/notis-database/packages/sdk/tsconfig.json +0 -15
  122. package/dist/scaffolds/notis-database/postcss.config.mjs +0 -8
  123. package/dist/scaffolds/notis-database/src/dev-main.tsx +0 -23
  124. package/dist/scaffolds/notis-database/src/mock-runtime.ts +0 -561
  125. package/dist/scaffolds/notis-database/tailwind.config.ts +0 -59
  126. package/dist/scaffolds/notis-database/tsconfig.json +0 -23
  127. package/dist/scaffolds/notis-database/vite.config.ts +0 -22
  128. package/dist/scaffolds/notis-journal/CHANGELOG.md +0 -29
  129. package/dist/scaffolds/notis-journal/app/globals.css +0 -37
  130. package/dist/scaffolds/notis-journal/app/insights/page.tsx +0 -513
  131. package/dist/scaffolds/notis-journal/app/journal-core.tsx +0 -362
  132. package/dist/scaffolds/notis-journal/app/journal-ui.tsx +0 -337
  133. package/dist/scaffolds/notis-journal/app/layout.tsx +0 -6
  134. package/dist/scaffolds/notis-journal/app/page.tsx +0 -486
  135. package/dist/scaffolds/notis-journal/components/ui/badge.tsx +0 -28
  136. package/dist/scaffolds/notis-journal/components/ui/button.tsx +0 -53
  137. package/dist/scaffolds/notis-journal/components/ui/card.tsx +0 -56
  138. package/dist/scaffolds/notis-journal/components.json +0 -20
  139. package/dist/scaffolds/notis-journal/index.html +0 -12
  140. package/dist/scaffolds/notis-journal/lib/utils.ts +0 -6
  141. package/dist/scaffolds/notis-journal/metadata/screenshot-1.png +0 -0
  142. package/dist/scaffolds/notis-journal/metadata/screenshot-2.png +0 -0
  143. package/dist/scaffolds/notis-journal/metadata/screenshot-3.png +0 -0
  144. package/dist/scaffolds/notis-journal/metadata/screenshot-4.png +0 -0
  145. package/dist/scaffolds/notis-journal/metadata/screenshot-5.png +0 -0
  146. package/dist/scaffolds/notis-journal/metadata/screenshot-6.png +0 -0
  147. package/dist/scaffolds/notis-journal/metadata/screenshot-fixtures.json +0 -132
  148. package/dist/scaffolds/notis-journal/notis.config.ts +0 -93
  149. package/dist/scaffolds/notis-journal/package-lock.json +0 -4615
  150. package/dist/scaffolds/notis-journal/package.json +0 -34
  151. package/dist/scaffolds/notis-journal/packages/sdk/package.json +0 -36
  152. package/dist/scaffolds/notis-journal/packages/sdk/src/components/DocumentEditor.tsx +0 -93
  153. package/dist/scaffolds/notis-journal/packages/sdk/src/components/Markdown.tsx +0 -60
  154. package/dist/scaffolds/notis-journal/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
  155. package/dist/scaffolds/notis-journal/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
  156. package/dist/scaffolds/notis-journal/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
  157. package/dist/scaffolds/notis-journal/packages/sdk/src/config.ts +0 -234
  158. package/dist/scaffolds/notis-journal/packages/sdk/src/documents.ts +0 -250
  159. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useBackend.ts +0 -41
  160. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  161. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  162. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDatabaseSubscription.ts +0 -76
  163. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDocument.ts +0 -78
  164. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDocuments.ts +0 -121
  165. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useHandover.ts +0 -75
  166. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
  167. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useNotis.ts +0 -34
  168. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
  169. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useTool.ts +0 -64
  170. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useTools.ts +0 -56
  171. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  172. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
  173. package/dist/scaffolds/notis-journal/packages/sdk/src/index.ts +0 -100
  174. package/dist/scaffolds/notis-journal/packages/sdk/src/provider.tsx +0 -43
  175. package/dist/scaffolds/notis-journal/packages/sdk/src/runtime.ts +0 -351
  176. package/dist/scaffolds/notis-journal/packages/sdk/src/styles.css +0 -186
  177. package/dist/scaffolds/notis-journal/packages/sdk/src/ui.ts +0 -15
  178. package/dist/scaffolds/notis-journal/packages/sdk/src/vite.ts +0 -56
  179. package/dist/scaffolds/notis-journal/packages/sdk/tsconfig.json +0 -15
  180. package/dist/scaffolds/notis-journal/postcss.config.mjs +0 -8
  181. package/dist/scaffolds/notis-journal/skills/journal-onboarding/SKILL.md +0 -120
  182. package/dist/scaffolds/notis-journal/src/dev-main.tsx +0 -58
  183. package/dist/scaffolds/notis-journal/src/mock-runtime.ts +0 -199
  184. package/dist/scaffolds/notis-journal/tailwind.config.ts +0 -58
  185. package/dist/scaffolds/notis-journal/tsconfig.json +0 -23
  186. package/dist/scaffolds/notis-journal/vite.config.ts +0 -10
  187. package/dist/scaffolds/notis-notes/CHANGELOG.md +0 -5
  188. package/dist/scaffolds/notis-notes/app/globals.css +0 -3
  189. package/dist/scaffolds/notis-notes/app/layout.tsx +0 -6
  190. package/dist/scaffolds/notis-notes/app/page.tsx +0 -1943
  191. package/dist/scaffolds/notis-notes/app/phosphor-icons.ts +0 -596
  192. package/dist/scaffolds/notis-notes/components/ui/badge.tsx +0 -28
  193. package/dist/scaffolds/notis-notes/components/ui/button.tsx +0 -53
  194. package/dist/scaffolds/notis-notes/components/ui/card.tsx +0 -56
  195. package/dist/scaffolds/notis-notes/components.json +0 -20
  196. package/dist/scaffolds/notis-notes/lib/utils.ts +0 -6
  197. package/dist/scaffolds/notis-notes/lib/visible-properties.ts +0 -144
  198. package/dist/scaffolds/notis-notes/metadata/screenshot-1.png +0 -0
  199. package/dist/scaffolds/notis-notes/metadata/screenshot-2.png +0 -0
  200. package/dist/scaffolds/notis-notes/metadata/screenshot-3.png +0 -0
  201. package/dist/scaffolds/notis-notes/metadata/screenshot-4.png +0 -0
  202. package/dist/scaffolds/notis-notes/metadata/screenshot-5.png +0 -0
  203. package/dist/scaffolds/notis-notes/metadata/screenshot-fixtures.json +0 -752
  204. package/dist/scaffolds/notis-notes/notis.config.ts +0 -80
  205. package/dist/scaffolds/notis-notes/package-lock.json +0 -4636
  206. package/dist/scaffolds/notis-notes/package.json +0 -35
  207. package/dist/scaffolds/notis-notes/packages/sdk/package.json +0 -36
  208. package/dist/scaffolds/notis-notes/packages/sdk/src/components/DocumentEditor.tsx +0 -93
  209. package/dist/scaffolds/notis-notes/packages/sdk/src/components/Markdown.tsx +0 -60
  210. package/dist/scaffolds/notis-notes/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
  211. package/dist/scaffolds/notis-notes/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
  212. package/dist/scaffolds/notis-notes/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
  213. package/dist/scaffolds/notis-notes/packages/sdk/src/config.ts +0 -234
  214. package/dist/scaffolds/notis-notes/packages/sdk/src/documents.ts +0 -250
  215. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useBackend.ts +0 -41
  216. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  217. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  218. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDatabaseSubscription.ts +0 -76
  219. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDocument.ts +0 -78
  220. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDocuments.ts +0 -121
  221. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useHandover.ts +0 -75
  222. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
  223. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useNotis.ts +0 -34
  224. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
  225. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useTool.ts +0 -64
  226. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useTools.ts +0 -56
  227. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  228. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
  229. package/dist/scaffolds/notis-notes/packages/sdk/src/index.ts +0 -100
  230. package/dist/scaffolds/notis-notes/packages/sdk/src/provider.tsx +0 -43
  231. package/dist/scaffolds/notis-notes/packages/sdk/src/runtime.ts +0 -351
  232. package/dist/scaffolds/notis-notes/packages/sdk/src/styles.css +0 -186
  233. package/dist/scaffolds/notis-notes/packages/sdk/src/ui.ts +0 -15
  234. package/dist/scaffolds/notis-notes/packages/sdk/src/vite.ts +0 -56
  235. package/dist/scaffolds/notis-notes/packages/sdk/tsconfig.json +0 -15
  236. package/dist/scaffolds/notis-notes/postcss.config.mjs +0 -8
  237. package/dist/scaffolds/notis-notes/tailwind.config.ts +0 -58
  238. package/dist/scaffolds/notis-notes/tsconfig.json +0 -23
  239. package/dist/scaffolds/notis-notes/vite.config.ts +0 -10
  240. package/dist/scaffolds/notis-random/CHANGELOG.md +0 -15
  241. package/dist/scaffolds/notis-random/README.md +0 -33
  242. package/dist/scaffolds/notis-random/app/globals.css +0 -11
  243. package/dist/scaffolds/notis-random/app/history/page.tsx +0 -67
  244. package/dist/scaffolds/notis-random/app/layout.tsx +0 -7
  245. package/dist/scaffolds/notis-random/app/page.tsx +0 -289
  246. package/dist/scaffolds/notis-random/components/ui/button.tsx +0 -50
  247. package/dist/scaffolds/notis-random/components/ui/card.tsx +0 -16
  248. package/dist/scaffolds/notis-random/components/ui/input.tsx +0 -23
  249. package/dist/scaffolds/notis-random/components.json +0 -20
  250. package/dist/scaffolds/notis-random/index.html +0 -12
  251. package/dist/scaffolds/notis-random/lib/notis-tools.ts +0 -128
  252. package/dist/scaffolds/notis-random/lib/rng.ts +0 -202
  253. package/dist/scaffolds/notis-random/lib/roll-record.ts +0 -189
  254. package/dist/scaffolds/notis-random/lib/utils.ts +0 -25
  255. package/dist/scaffolds/notis-random/metadata/screenshot-1.png +0 -0
  256. package/dist/scaffolds/notis-random/metadata/screenshot-2.png +0 -0
  257. package/dist/scaffolds/notis-random/metadata/screenshot-3.png +0 -0
  258. package/dist/scaffolds/notis-random/metadata/screenshot-4.png +0 -0
  259. package/dist/scaffolds/notis-random/metadata/screenshot-5.png +0 -0
  260. package/dist/scaffolds/notis-random/metadata/screenshot-fixtures.json +0 -753
  261. package/dist/scaffolds/notis-random/notis.config.ts +0 -86
  262. package/dist/scaffolds/notis-random/package-lock.json +0 -4513
  263. package/dist/scaffolds/notis-random/package.json +0 -36
  264. package/dist/scaffolds/notis-random/packages/sdk/package.json +0 -36
  265. package/dist/scaffolds/notis-random/packages/sdk/src/components/DocumentEditor.tsx +0 -93
  266. package/dist/scaffolds/notis-random/packages/sdk/src/components/Markdown.tsx +0 -60
  267. package/dist/scaffolds/notis-random/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
  268. package/dist/scaffolds/notis-random/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
  269. package/dist/scaffolds/notis-random/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
  270. package/dist/scaffolds/notis-random/packages/sdk/src/config.ts +0 -234
  271. package/dist/scaffolds/notis-random/packages/sdk/src/documents.ts +0 -250
  272. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useBackend.ts +0 -41
  273. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  274. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  275. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDatabaseSubscription.ts +0 -76
  276. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDocument.ts +0 -78
  277. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDocuments.ts +0 -121
  278. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useHandover.ts +0 -75
  279. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
  280. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useNotis.ts +0 -34
  281. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
  282. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useTool.ts +0 -64
  283. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useTools.ts +0 -56
  284. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  285. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
  286. package/dist/scaffolds/notis-random/packages/sdk/src/index.ts +0 -100
  287. package/dist/scaffolds/notis-random/packages/sdk/src/provider.tsx +0 -43
  288. package/dist/scaffolds/notis-random/packages/sdk/src/runtime.ts +0 -351
  289. package/dist/scaffolds/notis-random/packages/sdk/src/styles.css +0 -186
  290. package/dist/scaffolds/notis-random/packages/sdk/src/ui.ts +0 -15
  291. package/dist/scaffolds/notis-random/packages/sdk/src/vite.ts +0 -56
  292. package/dist/scaffolds/notis-random/packages/sdk/tsconfig.json +0 -15
  293. package/dist/scaffolds/notis-random/postcss.config.mjs +0 -6
  294. package/dist/scaffolds/notis-random/src/dev-main.tsx +0 -70
  295. package/dist/scaffolds/notis-random/src/mock-runtime.ts +0 -129
  296. package/dist/scaffolds/notis-random/tailwind.config.ts +0 -50
  297. package/dist/scaffolds/notis-random/tsconfig.json +0 -23
  298. package/dist/scaffolds/notis-random/vite.config.ts +0 -11
  299. package/dist/scaffolds.json +0 -49
@@ -1,13 +1,16 @@
1
1
  ---
2
2
  name: notis-apps
3
3
  description: Design and package Notis apps. Use when users want an app that groups databases, routes, documents, automations, and skills into one installable Notis product.
4
+ feature_flag: store
5
+ mcp_resource: true
6
+ mcp_tool_patterns: ["LOCAL_NOTIS_INSTALL_APP"]
4
7
  ---
5
8
 
6
9
  # Notis Apps Skill
7
10
 
8
11
  Use this skill when the user wants a packaged Notis app -- task manager, CRM, dashboard, internal tool, etc. Notis apps are **Vite + React projects** that deploy into the Notis portal as installed apps for the current user or team.
9
12
 
10
- Run the Notis CLI through NPX, for example `npx --package @notis_ai/cli@latest -- notis apps list`. Sign the CLI in once with `notis login`; each account you authorize is a profile you can switch between with `notis profile use`. This `notis-apps` skill is delivered through normal Notis skill sync for the signed-in user, alongside other curated skills.
13
+ Run the Notis CLI through NPX, for example `npx --package @notis_ai/cli@latest -- notis apps list`. Sign the CLI in once with `notis login`; each account you authorize is a profile you can switch between with `notis profile use`. The CLI bundles this `notis-apps` base skill and refreshes its canonical copy under `~/.notis/skills/base/` on every launch. It is independent of account-skill sync, feature flags, target selection, and cloud deletion.
11
14
 
12
15
  ## How Apps Are Built
13
16
 
@@ -20,12 +23,38 @@ All Notis apps are built using the Notis CLI, either locally in a repo workspace
20
23
  ## App Workspace Tool Rules
21
24
 
22
25
  - Apps are the top-level packaging unit in Notis.
23
- - Use `LOCAL_NOTIS_CREATE_APP` to register a new app, then use the Notis CLI in the shell to build and deploy it.
26
+ - Choose the execution path before changing an app. A prompt that says the
27
+ shell is a hosted/Vercel sandbox, or a shell rooted at `/vercel/sandbox`, is
28
+ the **hosted sandbox** path. A shell on the user's computer with Notis
29
+ Desktop available is the **local Desktop** path.
30
+ - In a hosted sandbox, do not run `apps dev`: the user's Desktop cannot mount
31
+ that sandbox filesystem. Unless the user explicitly requests preview-only,
32
+ read-only, or no deployment, a request to create or edit an app authorizes
33
+ deploying that app to the user's Workspace after `apps build` and automated
34
+ `apps verify` pass. An opt-out stops after those tests with no remote app
35
+ create/link, database mutation, deploy, or post-deploy checks. Pulling an existing app provides its exact link. For a new
36
+ app, test first, then reconcile profile state and `apps list --json` against
37
+ the canonical `notis.config.ts` `name` and intended personal/team scope: link
38
+ one exact editable non-development match after a metadata-only
39
+ (`include_documents: false`) detail read proves scope, fail on ambiguity or
40
+ scope mismatch, or create only when none exists. New CLI-created apps default
41
+ to personal scope. Before creation, prove that canonicalizing the config
42
+ `title` yields the config `name`. For personal scope, run `apps create
43
+ "<canonical-config-title>" . --json` exactly once. For explicitly requested
44
+ team scope, discover and inspect `LOCAL_NOTIS_CREATE_APP`, dry-run it, execute
45
+ it exactly once with team visibility and the verified current team scope,
46
+ verify the returned id/slug/team scope/edit permission, then `apps link` that
47
+ exact id. Stop for read-only
48
+ reconciliation if creation is ambiguous or outcome-unknown. In the local
49
+ Desktop path, use `apps dev [folder]`, let the user test the DEV app, and deploy
50
+ that development identity directly only after an explicit request. Use
51
+ `LOCAL_NOTIS_CREATE_APP` only for a hosted team-scoped creation or another
52
+ non-CLI administrative flow that explicitly requires a server-side app row.
24
53
  - Use `LOCAL_NOTIS_UPDATE_APP` to update app metadata.
25
54
  - Use `LOCAL_NOTIS_LIST_APPS` to discover the user's apps.
26
55
  - The full app lifecycle uses the CLI in the shell. Always run it through the registry-resolved package, for example `npx --package @notis_ai/cli@latest -- notis apps init`; use the same prefix for `build` and `deploy`. In hosted shells, the CLI is pre-authenticated through `NOTIS_JWT`.
27
56
  - There are no `save_app` or `load_app` tools. Do not attempt to call them. Use only the CLI for app file operations.
28
- - Use `npx --package @notis_ai/cli@latest -- notis apps scaffolds list` to discover bundled starting points before scaffolding.
57
+ - Use `npx --package @notis_ai/cli@latest -- notis apps scaffolds list` (optionally with `--search <term>`) to discover starting points before scaffolding. Every published Store app is a scaffold; the catalog is served from the public registry, not bundled inside the CLI.
29
58
  - Use `LOCAL_NOTIS_LIST_PUBLIC_APP_STORE` only to help users choose apps to install, not as a source-clone workflow.
30
59
  - Use `LOCAL_NOTIS_INSTALL_APP` only when the user explicitly wants to install from a listing.
31
60
  - Before installing, inspect the listing's `required_capabilities`. Explain each
@@ -49,7 +78,8 @@ Notis CLI (local workspace or Vercel Sandbox)
49
78
  ### Key Components
50
79
 
51
80
  1. **@notis/sdk** (`packages/sdk/`) -- SDK for app developers
52
- - `@notis/sdk` -- NotisProvider and generic runtime hooks such as useTool and useTools
81
+ - `@notis/sdk` -- NotisProvider, runtime hooks, editors, selection helpers, and shortcut primitives
82
+ - `@notis/sdk/interactions` -- headless collection actions and interaction types
53
83
  - `@notis/sdk/config` -- `defineNotisApp()` for notis.config.ts
54
84
  - `@notis/sdk/vite` -- `notisViteConfig()` for vite.config.ts
55
85
  - `@notis/sdk/styles.css` -- shadow-safe app shell styles and base app-surface classes
@@ -90,15 +120,17 @@ App code never accesses the runtime directly -- it uses SDK hooks (`useTool`, `u
90
120
  12. **Portal-owned sidebars stay portal-owned** -- If a route uses `collection.sidebar`, treat that sidebar as platform chrome. Do not remove it, recreate it inside app JSX, or replace it with a custom in-app folder rail.
91
121
  13. **Portal globals are off-limits** -- Never use `window.__NOTIS_RUNTIME__`, query portal-owned DOM hooks, or create global DOM portals.
92
122
  14. **Prefer inline optimistic edits** -- Rename-like edits for collections, app-owned rows, and sidebar-backed entities should use inline editing with an optimistic UI update, then roll back on backend failure. Use modals only when the edit requires multiple fields or destructive confirmation.
93
- 15. **Local development first; deploy is user-gated** -- Iterate with `apps dev` and let the **user** test the app in the desktop **Local development** sidebar group. Do NOT run `apps create` or `apps deploy` on your own initiative, even after a clean build and verify. `deploy` installs the app onto the user's account and is a one-directional, outward-facing action treat it like publishing: only run it when the user has tested the local build and **explicitly asks you to deploy**. Building a new app end-to-end without deploying is the expected, complete outcome. (See the **Local-development-first handoff** in the Workflow.)
94
- 16. **Installed app links are explicit** -- A mounted dev session updates an installed workspace app only when the local checkout is linked by app id in `.notis/state.json` and the dev-session registry mirrors that id. Name or slug matches may be suggestions, never update targets. After first install, keep that link so Portal and CLI show/update the same app instead of creating duplicates.
95
- 17. **Development identities stay separate** -- `.notis/state.json` uses `dev_app_id` for the hidden development-runtime row and `app_id` only for an accessible installed workspace app. The Electron registry mirrors the installed id as `targetAppId`. Never pass a runtime app whose manifest has `is_dev: true` to `notis apps link`; it is not an install/update target. Current CLIs reject that link and repair stale hidden, deleted, or inaccessible targets on the next `apps dev` without erasing valid state on transport or authentication failures.
96
- 18. **Mounted means Portal-acknowledged** -- A running process or HTTP 200 proves only that the app is serving. Before telling the user an app is mounted, require the current `apps dev` process to report `Mounted in <target desktop>`. The CLI selects the target from the active Notis profile: normal CLI runs target the signed-in Notis or Notis Beta desktop, while a CLI running inside an active Notis source workspace targets that workspace's matching desktop instance. The exact session/app/slug/nonce acknowledgment is accepted only from the visible target window after the app enters its final **Local development** sidebar model. Route rendering is a separate proof: when UI verification is required, also open the app and require `Rendered in <target desktop>`.
123
+ 15. **The execution environment determines the deploy gate** -- In the local Desktop path, run `apps dev [folder]`, let the **user** test the automatically mounted DEV app, and do not deploy until the user asks; first deploy promotes that `dev_app_id` directly, so never create a second app first. In a hosted sandbox, `apps dev` cannot reach the user's Desktop; bootstrap `agent-browser`, build and verify first, then resolve exact identity/resources and deploy to the user's Workspace, verify the remote version and live runtime, and return the exact Portal URL. Automatic deployment is the default for create/edit requests only; an explicit preview-only, read-only, or no-deploy request wins. This standing sandbox authorization does not authorize Store submission.
124
+ 16. **Installed app identity is exact, editable, and scope-proven** -- Validate an explicit persisted link for this API/user profile before using it. Otherwise inspect every accessible exact-canonical-slug row, including development rows; link only one editable non-development candidate whose exact detail proves the intended personal/team scope. Fail closed on a development collision, multiple matches, missing scope proof, or scope mismatch, and never infer identity from display name. After first install, keep the validated profile-scoped link so Portal and CLI update the same app instead of creating duplicates.
125
+ 17. **Development identities stay separate** -- `.notis/state.json` uses `dev_app_id` for the hidden development-runtime row and `app_id` only for an accessible installed workspace app, scoped under the authenticated environment. Never pass a runtime app whose manifest has `is_dev: true` to `notis apps link`.
126
+ 18. **Automatic mounts are multi-instance and least-authority** -- Prod, Beta, and source-development Desktop instances may mount the same source simultaneously with independent authenticated runtimes. Automatic mounting never grants capabilities: reuse existing grants and leave restricted capabilities denied until approved. Consumer leases expire after crashes so the shared host exits after the last live instance. There are no offline rows or manual start/stop controls.
97
127
  19. **Store submission is user-gated** -- Run `apps publish --confirm-ready` only after the user explicitly confirms the current App Details page and Store listing are ready. Deploy the exact approved local state first. The command must reject missing confirmation, incomplete listing media, a local/deployed version mismatch, private visibility, or an existing pending review.
98
- 20. **Bump `notisAppVersion` for every Store update** -- `package.json` must contain a semver `notisAppVersion`. For an existing Store app, increment it beyond the currently published registry version before deploy and submission; registry CI rejects equal or lower versions.
128
+ 20. **Bump `notisAppVersion` before linked development and every Store update** -- `package.json` must contain a semver `notisAppVersion`. A linked local source substitutes its installed Workspace app only when the local version is strictly greater than the installed manifest's `release_version`; equal, lower, missing, or invalid versions keep serving the online bundle. `apps pull` retrieves the online version, so increment `notisAppVersion` before `apps dev` when continuing development. For an existing Store app, also increment it beyond the currently published registry version before deploy and submission; registry CI rejects equal or lower versions.
99
129
  21. **`CHANGELOG.md` owns release history** -- Keep the complete release history in one root `CHANGELOG.md`, newest entry first. Do not add new `versionNotes` values to `notis.config.ts`. Use `## [Release title] - YYYY-MM-DD`, or `{PR_MERGE_DATE}` for an unpublished entry. App Details reads **What’s New** and **Version History** from the deployed package manifest, while the Store reads them from the latest published snapshot; unpublished workspace edits must never change the Store page. The manifest also exposes `package.json` `notisAppVersion` as the package version shown in App Details.
100
130
  22. **Database rows are private unless explicitly seeded** -- A string declaration such as `databases: ['notes']` publishes schema only and never includes the developer's rows. Use `{ slug: 'templates', seedDocuments: true }` only for small, intentional starter content that every installer should receive. Never enable it for user-created notes, history, leads, or other personal data.
101
131
  23. **Public submissions are complete, reviewable packages** -- The registry PR must contain the full editable source tree, Store assets, exact source-declared database schemas, and only explicitly seeded starter rows. Registry CI validates those boundaries before merge; do not hand-edit `notis-listing.json` or strip source files to make a check pass. Fix the app locally, redeploy, and resubmit.
132
+ 24. **New projects default to `~/.notis/apps/<slug>`, and `[dir]` overrides it** -- `apps init` and `apps pull` use this stable, predictable home unless the app belongs in a specific repository, monorepo, or user-chosen location. In those cases, pass `[dir]` and report the resulting path. Do not nest an app inside a directory whose local workspace metadata selects an unrelated Notis runtime or profile: later CLI calls inherit that routing and may target the wrong environment.
133
+ 25. **Machine names and display titles use different casing** -- In `notis.config.ts`, `name` is the stable machine identity and must be lowercase kebab-case (`name: 'link-building'`). `title` is the human-facing app name and must use deliberate display casing (`title: 'Link Building'`), preserving product spelling and acronyms such as `Notis` and `SEO`. Never put a title-cased phrase in `name`, never show a raw slug as the title, and never change an existing canonical `name` or remote slug merely to repair display casing. The persisted `apps.name`, Workspace sidebar, App Details, and Store listing must use `title`.
102
134
 
103
135
  ## Anti-patterns -- NEVER do these
104
136
 
@@ -106,8 +138,8 @@ These are the most common mistakes agents make. Each one wastes time and produce
106
138
 
107
139
  - **NEVER assume app deploys create databases for you** -- Create or update databases through native Notis database tools or the assistant first, then reference them by slug in `notis.config.ts`. Database creation requires the owning app to exist: pass its slug or id in the `app` argument of `LOCAL_NOTIS_DATABASE_UPSERT_DATABASE` (create the app first with `LOCAL_NOTIS_CREATE_APP` if needed). A database can only be referenced by the app that owns it.
108
140
  - **NEVER bypass the supported workflow by manually stitching together low-level save or lint calls from a local workspace** -- Local agents should go through the NPX Notis CLI for `apps pull`, `apps dev`, `apps build`, `apps verify`, `apps create`, `apps link`, and `apps deploy`.
109
- - **NEVER invent a Store clone path** -- `npx --package @notis_ai/cli@latest -- notis apps pull` only pulls source for an app the user can already access as an installed app. Pulling source directly from arbitrary Store listings is not supported yet.
110
- - **NEVER deploy on your own initiative** -- A clean `apps build` + `apps verify` is NOT a signal to deploy. `apps create` / `apps deploy` install the app onto the user's account; run them only after the user has tested the local (`apps dev`) build and explicitly asked you to deploy. When you finish building, hand off for local testing and stop do not create or deploy unprompted.
141
+ - **NEVER use `apps pull` to clone a Store listing** -- `npx --package @notis_ai/cli@latest -- notis apps pull` only pulls source for an app the user can already access as an installed app. To fork a published Store app, run `npx --package @notis_ai/cli@latest -- notis apps init "My App" --from <slug>` instead: it downloads that app's source from the public registry, and installing the app first is not required.
142
+ - **NEVER apply the local deploy gate to a hosted sandbox** -- On the user's local computer, a clean `apps build` + `apps verify` is not deploy consent: hand off the DEV app and wait. In a hosted sandbox, the user's create or edit request is deploy consent for that app because `apps dev` cannot reach their Desktop; deploy only after both commands pass, then verify the remote version. Neither path authorizes Store submission.
111
143
  - **NEVER submit without explicit approval** -- A deploy request alone does not authorize Store submission. Run `npx --package @notis_ai/cli@latest -- notis apps publish --confirm-ready` only when the user confirms App Details is ready for Store review.
112
144
  - **NEVER write raw `views/<slug>/index.js` files** -- Write standard React pages in `app/`.
113
145
  - **NEVER invent `npx --package @notis_ai/cli@latest -- notis apps push` or bypass the review flow** -- Source moves through `apps pull` and `apps deploy`; `apps publish --confirm-ready` submits the deployed snapshot through the same authenticated review endpoint as App Details.
@@ -119,80 +151,112 @@ These are the most common mistakes agents make. Each one wastes time and produce
119
151
 
120
152
  ## Workflow
121
153
 
122
- **Default to the bundled scaffold catalog, not a blank project.** Most user requests overlap with one of the scaffolds shipped inside the CLI. Starting from a bundled scaffold is faster than a bare app and does not require backend Store access.
154
+ **Default to the Store scaffold catalog, not a blank project.** Every published Store app is a scaffold: `notis apps scaffolds list` reads the catalog from the public registry, and `notis apps init --from <slug>` downloads that app's source. Most user requests overlap with a published app, and starting from one is faster than a bare app.
123
155
 
124
- 1. **Find a starting point.** Run `npx --package @notis_ai/cli@latest -- notis apps scaffolds list`. If something close matches, run `npx --package @notis_ai/cli@latest -- notis apps init "My App" --from <slug>`. Only run plain `npx --package @notis_ai/cli@latest -- notis apps init "My App"` when no scaffold fits.
125
- 2. **Pull only installed apps.** If the user explicitly wants to fork an app they already installed, run `npx --package @notis_ai/cli@latest -- notis apps list`, then `npx --package @notis_ai/cli@latest -- notis apps pull <app-id> ./<dir>`. To fork a Store app that is not installed, tell the user to install it from `/store` first.
126
- 3. **Edit the listing source.** Update `name` (slug), `title`, description, icon, accent, author, categories, tagline, databases, routes, and tools in `notis.config.ts`. Declare a database as a string for schema-only Store packaging; use `{ slug: 'templates', seedDocuments: true }` only when its rows are deliberate starter content for every installer. Keep the complete Store release history in the root `CHANGELOG.md`, newest entry first, using `## [Release title] - YYYY-MM-DD` (or `{PR_MERGE_DATE}` before publication). The first entry powers **What’s New** and the same file powers **Version History**. `icon` is a `phosphor:<name>` value or `metadata/icon.png`; when unset the app shows its **two-letter initials** everywhere (store, sidebar, app details). `accent` optionally pins the avatar color to one of `blue|violet|emerald|amber|rose|sky|fuchsia|teal` (default derived from the app id). Icon/accent flow through deploy onto the app row + listing and can also be set later via the `update_app` tool.
156
+ 1. **Find a starting point.** Run `npx --package @notis_ai/cli@latest -- notis apps scaffolds list` (add `--search <term>` to filter) to list the published Store apps. If something close matches, run `npx --package @notis_ai/cli@latest -- notis apps init "My App" --from <slug>` to download that app's source from the registry. Only run plain `notis apps init "My App"` when no published app fits. Either way the project lands in `~/.notis/apps/<slug>`; add a `[dir]` argument when the user wants it somewhere else (a tracked git repo, an existing monorepo), and report the path you used.
157
+ 2. **Pull your own apps; fork Store apps with `--from`.** `apps pull` is for apps the user already has installed or deployed: run `npx --package @notis_ai/cli@latest -- notis apps list`, preserve any local edits in the target directory, then run `npx --package @notis_ai/cli@latest -- notis apps pull <app-id>` (lands in `~/.notis/apps/<app-slug>`; pass a `[dir]` argument to place it elsewhere). A pull reproduces the installed release, so increment `package.json` `notisAppVersion` above that release before `apps dev`; until then the online bundle remains active. To fork a published Store app, use `apps init --from <slug>` instead -- it downloads the source from the registry and does not require installing the app first.
158
+ 3. **Edit the listing source.** In `notis.config.ts`, set `name` to the stable lowercase kebab-case identity and set `title` to the correctly cased human-facing name; for example, `name: 'link-building'` with `title: 'Link Building'`. Treat acronym and brand casing as editorial input, not something to derive mechanically from the slug. Then update description, icon, accent, author, categories, tagline, databases, routes, and tools. Declare a database as a string for schema-only Store packaging; use `{ slug: 'templates', seedDocuments: true }` only when its rows are deliberate starter content for every installer. Keep the complete Store release history in the root `CHANGELOG.md`, newest entry first, using `## [Release title] - YYYY-MM-DD` (or `{PR_MERGE_DATE}` before publication). The first entry powers **What’s New** and the same file powers **Version History**. `icon` is a `phosphor:<name>` value or `metadata/icon.png`; when unset the app shows its **two-letter initials** everywhere (store, sidebar, app details). `accent` optionally pins the avatar color to one of `blue|violet|emerald|amber|rose|sky|fuchsia|teal` (default derived from the app id). Icon/accent flow through deploy onto the app row + listing and can also be set later via the `update_app` tool.
127
159
  4. **Build pages in `app/`.** Reuse scaffold code wherever it fits.
128
- 5. **Iterate live.** Run `npx --package @notis_ai/cli@latest -- notis apps dev` so the target desktop's **Local development** sidebar group discovers the app and renders the local bundle. Keep this command running for as long as the user is testing; stopping it removes the temporary Local development entry. Read the command's `Target desktop` line instead of guessing between Notis, Notis Beta, or a source-workspace desktop. Add `--live-data` to point the session at the installed app's real databases instead of its own empty dev copies -- it applies to that session only, and warns and falls back when the app has not been deployed yet.
129
- 6. **Capture listing screenshots.** Declare 3–6 screenshots in `notis.config.ts`, each with a stable `path`, descriptive `alt`, and optional `route`/`scenario`/`focus`/`theme`, then run `npx --package @notis_ai/cli@latest -- notis apps screenshot`. Use `focus` to frame a real app root without empty browser canvas; use `theme: 'light'` or `theme: 'dark'` to match both the Portal render and Store backdrop, and pair both modes when that best represents the app. It renders the configured states in a headless harness and writes exact 2000x1250 PNGs under `metadata/`, using the deterministic Store presentation by default (`--raw` is diagnostic only). Apps are icon-led like Raycast — the icon set in `notis.config.ts` represents the app, so there is no cover image, only these screenshots. Never hand-author the PNGs; regenerate them when routes or UI change. A `scenario` names an entry in `metadata/screenshot-fixtures.json`; besides `actions` it may carry its own `tools` and `requests`, shallow-merged per key over the file-level ones for that capture, which is how the same route is shown both populated and in its first-run empty state.
130
- 7. **Verify locally.** Run `npm install`, then `npx --package @notis_ai/cli@latest -- notis apps build` and `npx --package @notis_ai/cli@latest -- notis apps verify`. Surface the verify report and fix failures. Incomplete listing media is only a `Store readiness:` warning there; run `notis apps verify --listing` before publish to make it a failure.
131
- 8. **Local-development-first handoff STOP HERE.** Keep `apps dev` running and hand off to the user: tell them the app is live in the target desktop's **Local development** sidebar group (green `DEV` badge) and ask them to test it there. Building a new app to this point, without deploying, is a **complete and expected** result. Do NOT proceed to `apps create` / `apps deploy` yet — wait for the user to test and explicitly ask to deploy. (`apps dev` is what puts the app in Local development; without a running session the app never appears there.) **Before handing off, complete all three acceptance checks:**
132
- 1. Target: capture the CLI's `Target desktop: <name>` line and make sure that exact desktop app is running and signed in.
133
- 2. Bundle: the reported loopback `/snapshot` URL responds successfully and contains the expected manifest/routes.
134
- 3. Mount and render: require `Mounted in <target desktop>: <app name>`. If the task includes UI or runtime behavior, open the default route and also require `Rendered in <target desktop>: <app name>`. If the CLI says only `Serving locally`, do not claim the app is mounted.
135
- See Troubleshooting *App is missing from Local development* if any check fails.
136
- 9. **Deploy only when the user asks.** Once the user has tested locally and explicitly requests a deploy, run `npx --package @notis_ai/cli@latest -- notis apps create "<name>" .` (first time) then `npx --package @notis_ai/cli@latest -- notis apps deploy --direct`, or link first with `npx --package @notis_ai/cli@latest -- notis apps link <id> .` / pass `--app-id <id>` for an existing app. Deploy installs or updates the app on the user's account (it appears under **Workspace**, not Local development). After first install, `.notis/state.json` must point at the installed app id so future local-dev actions become **Update**, not another **Install**.
160
+ 5. **Test the source before remote mutation.** Before changing a linked installed app, increment `package.json` `notisAppVersion` above the installed release. In a fresh hosted sandbox, bootstrap Agent Browser with `npm exec --yes --package agent-browser@latest -- agent-browser install`. Generate configured screenshots; use `theme: 'dark'` or `theme: 'light'` where appropriate and reserve screenshot `--raw` for diagnostics. Run `npm install`, run `npx --package @notis_ai/cli@latest -- notis apps build`, then run `npx --yes --package @notis_ai/cli@latest --package agent-browser@latest -- notis apps verify` in the sandbox (or the normal NPX verification command locally). Fix every failure. Do not create an app, mutate a database, or deploy before both checks pass. `--no-browser` is manual triage, not a passing automated gate.
161
+ 6. **Finish the local Desktop path at the DEV handoff.** Run `npx --package @notis_ai/cli@latest -- notis apps dev [folder]`; it creates the development identity and materializes available scaffold database snapshots without requiring a hosted app id. Hand off after the user can see and test the app in its DEV-badged Workspace row. Do not deploy until the user asks, and then run `apps deploy` directly so the existing `dev_app_id` is promoted in place; never run `apps create` after `apps dev`. **Before handing off, complete all three acceptance checks:**
162
+ 1. Root: `apps roots list` contains the intended folder (or the app is under the implicit default root).
163
+ 2. Bundle: the loopback `/snapshot` responds successfully and contains the expected manifest/routes.
164
+ 3. Mount and render: the app appears exactly once with a compact `DEV` badge and its default route renders. For multi-instance work, verify each requested Desktop independently.
165
+ See Troubleshooting *App is missing from the sidebar* if any check fails.
166
+ 7. **Gate and resolve one hosted identity after tests pass.** If the request is preview-only, read-only, or no-deploy, stop after step 5: do not create or link an app, mutate a database, deploy, or run post-deploy checks. Otherwise, existing edits keep the exact profile-scoped id linked by `apps pull`, after a metadata-only (`include_documents: false`) app-detail read validates its edit permission and scope without materializing databases. For a new hosted app, default the intended scope to personal unless the user explicitly requests team scope, inspect `.notis/state.json`, and run `apps list --json`. Consider every accessible exact canonical-slug row, including development rows. Link only one editable, non-development candidate whose metadata-only exact app-detail read proves the intended scope; fail on multiple matches, development-row collisions, missing scope proof, or scope mismatch. Create only when there are zero exact-slug rows. First prove that lowercasing the config `title`, replacing non-alphanumeric runs with `-`, and trimming hyphens yields the config `name`. For personal scope, run `npx --package @notis_ai/cli@latest -- notis apps create "<canonical-config-title>" . --json` exactly once and verify the returned id, remote slug, edit permission, and personal scope. For explicitly requested team scope, use `notis tools search` to discover the team-capable app-creation tool, inspect its schema, dry-run it, then execute `LOCAL_NOTIS_CREATE_APP` exactly once with the canonical display title, `visibility: "team"`, and the exact current `team_id` when resolved. Verify the result's id, canonical slug, `team_id`, team visibility, and edit permission, then run `notis apps link <returned-id> .` before database reconciliation. Never retry an outcome-unknown create; reconcile read-only and stop on ambiguity or any returned identity/scope mismatch.
167
+ 8. **Reconcile hosted database schemas safely.** Read the exact app detail and current schemas first; mutate only missing or changed declarations. For creation, pass the exact app id in the database tool's `app` argument. For an update, resolve the exact `database_id`, verify its `owner_app_id` equals the linked app id, update by that `database_id`, then read back slug, owner, and schema. Apply only backward-compatible schema expansion before deployment. Stage breaking or destructive changes through an expand-contract sequence and obtain the required destructive approval; never make the currently deployed bundle incompatible before its replacement is live.
168
+ 9. **Deploy and prove the hosted sandbox result.** Use only the exact id established in step 7. Run `npx --package @notis_ai/cli@latest -- notis apps deploy`, read the matching row back with `npx --package @notis_ai/cli@latest -- notis apps list --json`, confirm its id and deployed version, then run `npx --yes --package @notis_ai/cli@latest --package agent-browser@latest -- notis apps verify --mode live`. Return that row's exact profile-appropriate `portal_url` only after every proof passes. Report state precisely: a definite pre-commit rejection is **tested but not deployed**; a timeout/network/incomplete mutation response is **tested, deployment outcome unknown**; a confirmed deploy followed by failed readback is **deployed but not remotely verified**; a failed live check is **deployed but live verification failed**. Never retry an outcome-unknown mutation.
137
169
  10. **Submit only after confirmation.** When the user explicitly confirms the current App Details page is ready, ensure the approved state is deployed, then run `npx --package @notis_ai/cli@latest -- notis apps publish --confirm-ready`. The command submits Team apps immediately or opens the Public Store registry review PR. Without that confirmation, stop after deploy.
138
170
 
139
171
  ### Quick start
140
172
 
141
- Steps 1–3 are the agent's job on a build request. Step 4 is **user-gated** — do not run it until the user has tested the local build and asked you to deploy.
173
+ Choose the local or hosted finish after verification. Local deployment is
174
+ user-gated; hosted-sandbox deployment is the default for app create or edit
175
+ tasks unless the user explicitly requests preview-only, read-only, or no deploy.
142
176
 
143
177
  ```bash
144
- # 1. Pick a scaffold and scaffold
178
+ # 1. Pick a published Store app as the scaffold (catalog comes from the public registry)
179
+ # The project lands in ~/.notis/apps/<slug>; append a directory argument when
180
+ # the user wants the app in a repo they track.
145
181
  npx --package @notis_ai/cli@latest -- notis apps scaffolds list
146
- npx --package @notis_ai/cli@latest -- notis apps init "My App" --from <scaffold-slug>
147
- cd my-app
182
+ npx --package @notis_ai/cli@latest -- notis apps init "My App" --from <slug>
183
+ cd ~/.notis/apps/my-app
148
184
  npm install
149
185
 
150
- # 2. Develop against the Electron Portal, then HAND OFF for the user to test.
151
- # Keep this running it is what surfaces the app in the Local development
152
- # sidebar group. This is the finish line for a build request.
186
+ # 2. LOCAL COMPUTER: register with Desktop and iterate. After the user approves
187
+ # deployment, run deploy directly to promote the existing dev_app_id.
153
188
  npx --package @notis_ai/cli@latest -- notis apps dev
154
- # ... iterate until the app looks right in the Local development sidebar group ...
155
-
156
- # 3. Build, capture listing screenshots, and verify (still local — no deploy)
189
+ # ... user tests the DEV-badged app ...
157
190
  npx --package @notis_ai/cli@latest -- notis apps build
158
191
  npx --package @notis_ai/cli@latest -- notis apps screenshot
159
192
  npx --package @notis_ai/cli@latest -- notis apps verify
193
+ npx --package @notis_ai/cli@latest -- notis apps deploy
194
+ ```
160
195
 
161
- # 4. ONLY after the user tested locally and asked to deploy: create + deploy.
162
- # This writes .notis/state.json so future deploys update this app.
163
- npx --package @notis_ai/cli@latest -- notis apps create "My App" .
164
- npx --package @notis_ai/cli@latest -- notis apps deploy --direct
196
+ Hosted sandbox finish never run `apps dev`. Test first, then reconcile the
197
+ exact app identity and changed databases before deployment:
165
198
 
166
- # 5. ONLY after the user explicitly confirms App Details is ready for Store review
199
+ ```bash
200
+ npm exec --yes --package agent-browser@latest -- agent-browser install
201
+ npx --yes --package @notis_ai/cli@latest --package agent-browser@latest -- notis apps screenshot
202
+ npx --package @notis_ai/cli@latest -- notis apps build
203
+ npx --yes --package @notis_ai/cli@latest --package agent-browser@latest -- notis apps verify
204
+ # New unlinked app only: reconcile exact canonical slug with apps list. If no
205
+ # match exists, create once with the config title and verify the returned slug.
206
+ npx --package @notis_ai/cli@latest -- notis apps list --json
207
+ # Before create, prove canonicalize(config.title) == config.name.
208
+ npx --package @notis_ai/cli@latest -- notis apps create "<canonical-config-title>" . --json
209
+ # Compare schemas, then create only missing databases or update changed ones by
210
+ # verified database_id and read back owner/schema before continuing.
211
+ npx --package @notis_ai/cli@latest -- notis apps deploy
212
+ npx --package @notis_ai/cli@latest -- notis apps list --json
213
+ npx --yes --package @notis_ai/cli@latest --package agent-browser@latest -- notis apps verify --mode live
214
+ ```
215
+
216
+ Store submission on either path remains a separate approval-gated action:
217
+
218
+ ```bash
167
219
  npx --package @notis_ai/cli@latest -- notis apps publish --confirm-ready
168
220
  ```
169
221
 
170
- If deploying to an existing app without linking first, pass `--app-id` directly. Prefer linking when this checkout will keep being used for development:
222
+ For an existing app, link the checkout first so every later command uses the
223
+ same profile-scoped installed identity:
171
224
 
172
225
  ```bash
173
226
  npx --package @notis_ai/cli@latest -- notis apps link <app-id> .
174
- npx --package @notis_ai/cli@latest -- notis apps deploy --direct --app-id <app-id>
227
+ npx --package @notis_ai/cli@latest -- notis apps deploy
175
228
  ```
176
229
 
177
- Or if editing an installed app:
230
+ Or if editing an installed app locally:
178
231
 
179
232
  ```bash
180
233
  npx --package @notis_ai/cli@latest -- notis apps list
181
- npx --package @notis_ai/cli@latest -- notis apps pull <installed-app-id> ./my-app
182
- cd my-app
234
+ npx --package @notis_ai/cli@latest -- notis apps pull <installed-app-id>
235
+ cd ~/.notis/apps/my-app
183
236
  npm install
237
+ # Increment package.json notisAppVersion above the pulled online release.
184
238
  npx --package @notis_ai/cli@latest -- notis apps dev
185
239
  npx --package @notis_ai/cli@latest -- notis apps build
186
240
  npx --package @notis_ai/cli@latest -- notis apps verify
187
- npx --package @notis_ai/cli@latest -- notis apps deploy --direct --app-id <existing-app-id>
241
+ npx --package @notis_ai/cli@latest -- notis apps link <installed-app-id> .
242
+ # Only after the user explicitly asks to deploy:
243
+ npx --package @notis_ai/cli@latest -- notis apps deploy
188
244
  ```
189
245
 
246
+ In a hosted sandbox, use the same pull/build/verify sequence but omit `apps
247
+ dev`; bootstrap `agent-browser`, materialize any new or changed database schemas
248
+ against the exact linked id, deploy automatically after verification, read back
249
+ the exact app id/version and `portal_url` with `apps list --json`, run live verification, and return that
250
+ exact Portal URL. Never run `apps publish --confirm-ready` without separate
251
+ Store approval.
252
+
190
253
  ## Building an App
191
254
 
192
255
  ### Step 1: Define the config
193
256
 
194
257
  Create `notis.config.ts` with:
195
- - **name** -- Display name
258
+ - **name** -- Stable machine identity in lowercase kebab-case, such as `link-building`; do not use display casing here
259
+ - **title** -- Human-facing app name with deliberate casing, such as `Link Building`; preserve brands and acronyms exactly
196
260
  - **databases** -- Slug references to existing Notis databases
197
261
  - **routes** -- Route-first sidebar entries with explicit `slug`, optional `parentSlug`, and optional `collection.sidebar` tree config
198
262
  - **tools** -- Final tool names the app can call at runtime. Use the shared discovery flow (`COMPOSIO_SEARCH_TOOLS`, then `COMPOSIO_GET_TOOL_SCHEMAS`) while building the app, and copy the returned final names into this list. Examples include `LOCAL_NOTIS_DATABASE_QUERY`, `LOCAL_NOTIS_MONID_RUN`, `GMAIL_SEND_EMAIL`, `LOCAL_POSTFORME_CREATE_POST`, and `LOCAL_MCP_<SERVER>_<TOOL>`. App code calls each declared name directly through `useTool`; it does not wrap provider or MCP calls in `COMPOSIO_MULTI_EXECUTE_TOOL`. Access stays scoped to the signed-in user's own connections, native database tools stay scoped to the app's databases unless `capabilities.workspaceDatabases: 'read'` is granted, and metered tools use the CLI-equivalent credit-cap and fail-closed usage-billing path.
@@ -222,6 +286,8 @@ routes: [
222
286
 
223
287
  Use the same page template for the root Notes route and collection/sub-collection detail states. The portal sidebar injects live collection items under the static route row when `collection.sidebar.mode === 'tree'`.
224
288
 
289
+ For arbitrary app-owned resources that are not Notis collection rows, set `resourceDeepLinks: true` on the route. Read the decoded `?resource=` identifier from `useNotis().resourceId`, and link between routes with `toRoute('/inbox', { resourceId })`. Keep collection links on `?item=`. Publish external preview/source links as the resource `url`; the host separately supplies the exact Notis review link as `active_resource.view_url` for opted-in routes. Handle missing or deleted identifiers with a safe view-level fallback.
290
+
225
291
  ### Step 2: Build pages
226
292
 
227
293
  Standard React pages in `app/`. Use generic SDK tool hooks for data and build on top of the scaffolded shadcn components and portal shell classes (`notis-app-shell`, `notis-app-surface`):
@@ -307,7 +373,7 @@ Do NOT pass Notion-style wrappers (`{select: {name: "Todo"}}`) when upserting.
307
373
 
308
374
  - When a user asks for folders, sections, or hierarchy in the app sidebar, express that through `routes` and `collection.sidebar` in `notis.config.ts`.
309
375
  - Treat an existing collection-tree sidebar as a locked structural requirement unless the user explicitly asks to change navigation architecture.
310
- - If the sidebar appears missing in the Local development sidebar group or deployed portal build, do not silently redesign around it. Preserve the manifest contract, call out the discrepancy, and treat it as a portal/runtime bug.
376
+ - If the sidebar appears missing for the substituted DEV entry or deployed portal build, do not silently redesign around it. Preserve the manifest contract, call out the discrepancy, and treat it as a portal/runtime bug.
311
377
 
312
378
  ### Step 3: Root layout
313
379
 
@@ -329,7 +395,7 @@ Generated by `npx --package @notis_ai/cli@latest -- notis apps build` at `.notis
329
395
  {
330
396
  "version": 1,
331
397
  "spec_version": 4,
332
- "app": { "name": "My App", "description": "...", "icon": "phosphor:..." },
398
+ "app": { "name": "My App", "slug": "my-app", "title": "My App", "description": "...", "icon": "phosphor:..." },
333
399
  "routes": [
334
400
  {
335
401
  "path": "/",
@@ -427,19 +493,46 @@ the public `app-listing-assets` bucket before submission.
427
493
 
428
494
  ## SDK Hook Reference
429
495
 
430
- All hooks are imported from `@notis/sdk`:
496
+ All hooks and components below are imported from `@notis/sdk`. `NotisProvider`
497
+ already installs `ShortcutProvider`; app code should not add a second provider.
431
498
 
432
- | Hook | Signature | Description |
433
- |------|-----------|-------------|
434
- | `useNotis()` | `() => { app, route, context, ready }` | App metadata, current route, generic portal context, ready state |
435
- | `useTool<TArgs, TResult>(name)` | `(name: string) => { call, loading, error }` | Call a specific tool by name with app-defined argument and result types |
499
+ | API | Signature | Description |
500
+ |-----|-----------|-------------|
501
+ | `useNotis()` | `() => { app, route, databases, collectionItem, resourceId, ready }` | App metadata, current route, selected collection item, decoded exact-resource id, ready state |
502
+ | `useTool<TArgs, TResult>(name)` | `(name: string) => { call, loading, error }` | Call a declared tool with app-defined argument/result types. Identical idempotent reads may use `call(args, { dedupe: true })`; never dedupe writes |
436
503
  | `useTools()` | `() => { tools, loading }` | List available tools |
437
- | `useNotisNavigation()` | `() => { toRoute, toDocument, toApp }` | Navigate between routes, documents, or the app root |
504
+ | `useNotisNavigation()` | `() => { toRoute, toDocument, toApp }` | Navigate between routes (including `toRoute(path, { resourceId })`), documents, or the app root |
438
505
  | `useTopBarSearch(opts)` | `({ value, onChange, placeholder?, onSubmit? }) => { setLoading }` | Bind the current view to the Portal-owned top-bar search input |
439
506
  | `useBackend()` | `() => { request }` | Raw backend request proxy with JWT auth |
440
507
  | `useDatabaseSubscription(slug, opts?)` | `(slug: string, opts?) => { rows, documents, loading, error, refetch, live }` | Query a database and refetch it when its rows change. `live` is false on hosts without a change feed (dev harness, vite preview) -- keep a manual refresh for those |
441
- | `useHandover()` | `() => { handover, pending, error, available }` | Hand a prompt (optionally bound to a declared skill) to the Notis manager chat, which owns progress, billing and cancellation. `available` is false on hosts with no chat -- fall back to a copyable prompt |
508
+ | `useHandover()` | `() => { handover, pending, error, available }` | Open manager chat with app/resource context plus an optional starter prompt or declared skill. Omit `prompt` for a context-only composer. `available` is false on hosts with no chat -- fall back to a copyable prompt |
442
509
  | `useCloudComputer()` | `() => { facts, loading, error, refresh }` | Read-only cloud computer facts: sandbox existence/status and whether the GitHub CLI is signed in. Requires `capabilities.cloudComputer: 'read'` plus the user's approval; `facts.available === false` means answer from the app's own fallback |
510
+ | `useActiveResource(resource)` | `(ContextResource \| null) => void` | Publish the record currently open in the app so manager handover and context menus stay grounded |
511
+ | `useCollectionInteractions(opts)` | `(opts) => CollectionInteractionController` | Keyboard navigation, active-row state, range/toggle selection, marquee selection, and action dispatch for collection UIs |
512
+ | `useShortcuts(definitions, opts?)` | `(definitions, opts?) => void` | Register scoped keyboard shortcuts. Editable targets are ignored unless explicitly allowed; use `ShortcutHints` to display them |
513
+ | `MarkdownEditor` | `(NotisMarkdownEditorProps) => ReactElement` | Use the host editor with app-owned persistence, stable `resourceKey`, revision-aware `onSave`, and optional `onUploadFile` returning a durable URL |
514
+ | `NotisSelectionBoundary` | `(NotisSelectionBoundaryProps) => ReactElement` | Attach structured, explicitly untrusted app/resource/selection context to selected content and copy operations |
515
+ | `SelectionCheckbox` / `SelectionMarquee` | components | Standard selection controls backed by `useCollectionInteractions` |
516
+ | `MultiSelectActionBar` | component | Standard bulk actions with pending/disabled state and shortcut support |
517
+
518
+ Import headless collection action types and helpers from
519
+ `@notis/sdk/interactions`. Keep an open detail view synchronized with
520
+ `useActiveResource`, and wrap its selectable content in
521
+ `NotisSelectionBoundary` so the manager receives both the active record and the
522
+ user's exact selection. For `MarkdownEditor`, keep `resourceKey` stable per
523
+ record, pass the latest revision back from `onSave`, reject revision conflicts
524
+ instead of overwriting newer data, and implement `onUploadFile` whenever the
525
+ editor should accept media or file blocks.
526
+
527
+ ### App configuration additions
528
+
529
+ - `devSlug` is the stable local-development identity. Set it when a display
530
+ rename must not create a second DEV app; otherwise the CLI derives it from
531
+ `name`.
532
+ - `toolBindings` is only for provider-generated public tool names whose upstream
533
+ action cannot be reconstructed. Keep the exact final public `name` in
534
+ `tools`, then bind it to `providerToolName`; the public name remains the
535
+ permission boundary.
443
536
 
444
537
  ### Typed tool calls
445
538
 
@@ -464,34 +557,34 @@ const result = await queryTasks.call({ database_id: 'tasks-db-id', query: { page
464
557
 
465
558
  ## Development Modes
466
559
 
467
- ### Canonical local development
560
+ ### Hosted sandbox development
468
561
 
469
- ```bash
470
- npx --package @notis_ai/cli@latest -- notis apps dev
471
- ```
562
+ Do not run `apps dev` in a hosted sandbox. The sandbox filesystem is not on the
563
+ user's computer, so Desktop cannot mount it. Bootstrap sandbox `agent-browser`,
564
+ then build and verify before any remote mutation. For a create or edit request,
565
+ unless the user explicitly says preview-only, read-only, or no-deploy, resolve
566
+ one exact identity, safely materialize only missing or changed database schemas,
567
+ deploy, read back the exact app id/version, run live verification, and return
568
+ the exact Portal URL. Inspection, review, and diagnosis remain read-only.
472
569
 
473
- Runs the real desktop-local development workflow. The CLI should discover all apps in the target workspace, serve their bundles from loopback, and surface them in the Electron Portal's Local development sidebar group through the local desktop session registry.
474
-
475
- ## Deploy Without Backend Server
476
-
477
- If the live API is unreachable, use `--direct`:
570
+ ### Canonical local development
478
571
 
479
572
  ```bash
480
- npx --package @notis_ai/cli@latest -- notis apps deploy --direct
573
+ npx --package @notis_ai/cli@latest -- notis apps dev
481
574
  ```
482
575
 
483
- This uploads the bundle and editable source snapshot directly to Supabase storage and updates the app manifest in the database, bypassing the API server. The CLI auto-falls back to direct mode on network errors. Localhost backends are reserved for `/notis-tests` via `./dev.sh`; do not retarget the personal CLI lane at loopback from this skill.
576
+ Runs the real desktop-local development workflow. The CLI should discover all apps in the target workspace and serve their bundles from loopback. Unpublished apps appear in the Electron Portal's Workspace group; linked apps substitute their installed entry only when the local `notisAppVersion` is strictly greater than the installed `release_version`.
484
577
 
485
578
  ## Testing
486
579
 
487
580
  1. **Build validation**: `npx --package @notis_ai/cli@latest -- notis apps build` must succeed without errors. Vite surfaces TypeScript and bundling errors during this step.
488
- 2. **Headless render verification** (recommended after every build): run `npx --package @notis_ai/cli@latest -- notis apps verify`. It builds unless `--skip-build` is passed, spins up a loopback harness, drives `agent-browser` against every route, and reports per-route pass/fail with captured render errors and runtime calls.
489
- 3. **Local development acceptance**: Require the running CLI to name the intended desktop and report `Mounted in <target desktop>`, which proves the exact nonce-backed session entered that visible desktop's final `Local development` sidebar model. Bundle HTTP health alone proves only `Serving locally`. When the task includes UI, runtime behavior, or visual acceptance, open the default route and also require `Rendered in <target desktop>` before claiming the app works.
490
- 4. **Post-deploy**: Verify the deployed bundle via `/portal_views/get` -> `runtime_descriptor.bundle.js_url`, then verify the app renders in the portal. The portal renders app bundles directly as React components, so the fastest verification is navigating to the app page in the portal.
581
+ 2. **Headless render verification** (recommended after every build): run `npx --package @notis_ai/cli@latest -- notis apps verify` locally. In a hosted sandbox, first run `npm exec --yes --package agent-browser@latest -- agent-browser install`, then run `npx --yes --package @notis_ai/cli@latest --package agent-browser@latest -- notis apps verify`. It builds unless `--skip-build` is passed, spins up a loopback harness, drives `agent-browser` against every route, and reports per-route pass/fail with captured render errors and runtime calls.
582
+ 3. **Local development acceptance**: Run `notis apps dev [folder]` once to register the root, then verify each signed-in Desktop instance independently. For an unpublished app, expect one DEV-badged Workspace row. For a linked app, first confirm local `notisAppVersion` is strictly greater than installed `release_version`, then expect one substituted DEV-badged row; equal or lower must keep the online row and bundle. Verify the default route renders and live edits appear without restarting the CLI or Desktop. Use `notis apps roots list` as the persistence proof. Loopback bundle health alone does not prove that an authenticated instance mounted or rendered the app.
583
+ 4. **Post-deploy**: Read back the exact app id, version, and `portal_url` with `apps list --json`, run `apps verify --mode live`, verify the deployed bundle via `/portal_views/get` -> `runtime_descriptor.bundle.js_url`, and return that profile-appropriate exact Portal URL. A confirmed deploy followed by failed readback is deployed but not remotely verified; a failed live check is deployed but live verification failed. The portal renders app bundles directly as React components, so navigate to the app page when an authenticated browser is available.
491
584
 
492
585
  ### Headless harness verification
493
586
 
494
- Run `npx --package @notis_ai/cli@latest -- notis apps verify` after `npx --package @notis_ai/cli@latest -- notis apps build`. Use `--mode live` after deploy to exercise the real `/portal_views/runtime_query` with the CLI JWT instead of stub data; live mode also fails a route whose runtime calls all errored, which a well-behaved error state would otherwise hide. If `agent-browser` is unavailable, pass `--no-browser` to print URLs and use `--keep-open` for interactive triage with `notis-browser-control`.
587
+ Run `npx --package @notis_ai/cli@latest -- notis apps verify` after `npx --package @notis_ai/cli@latest -- notis apps build`. Use `--mode live` after deploy to exercise the real `/portal_views/runtime_query` with the CLI JWT instead of stub data; live mode also fails a route whose runtime calls all errored, which a well-behaved error state would otherwise hide. In a hosted sandbox, put `agent-browser` on the verification process's `PATH` with the combined-package command above. `--no-browser` only prints URLs for manual triage and does not satisfy the automated deployment gate.
495
588
 
496
589
  #### What the harness catches that `npx --package @notis_ai/cli@latest -- notis apps build` does not
497
590
 
@@ -511,8 +604,10 @@ Run `npx --package @notis_ai/cli@latest -- notis apps verify` after `npx --packa
511
604
 
512
605
  ### Common issues
513
606
 
514
- - **Deploy fails with network error**: Backend server not running. Use `npx --package @notis_ai/cli@latest -- notis apps deploy --direct` or start the server.
607
+ - **Deploy fails with network error**: Run `notis doctor`, then retry with the
608
+ authenticated API available. Do not bypass DEV-app promotion or installed-app
609
+ identity with a direct database/storage write.
515
610
  - **App shows old code after deploy**: Bundle cache is stale. Hard refresh (Cmd+Shift+R) or clear site data in DevTools.
516
- - **App is missing from Local development**: Read the `Target desktop` line from `apps dev`, then bring that exact Notis app forward and confirm it is signed into the same account reported by `npx --package @notis_ai/cli@latest -- notis whoami`. Keep `apps dev` running. If it still says only `Serving locally`, run `npx --package @notis_ai/cli@latest -- notis doctor`, restart the target desktop, and retry `apps dev`. Do not redirect internal registry files manually: the CLI selects the normal Notis/Notis Beta target from the active profile and selects a source-workspace desktop only when an active workspace runtime identifies it. Wait for `Mounted in <target desktop>` before claiming success; when validating UI or runtime behavior, open the route and wait for `Rendered in <target desktop>` too.
611
+ - **App is missing from the sidebar**: Run `apps roots list`, confirm the app is at the root, one direct child, or `apps/*`, and confirm its first build succeeds. For a linked app, compare `package.json` `notisAppVersion` with the installed manifest's `release_version`: equal, lower, missing, or invalid intentionally keeps the online app without a DEV badge. If source is stale, preserve any local edits, run `apps pull <app-id> <dir> --force` to refresh it, then increment `notisAppVersion` before continuing development. Restarting Desktop reattaches the same persistent roots; no terminal process or manual sidebar action is required.
517
612
  - **`LOCAL_NOTIS_DATABASE_QUERY` returns empty documents**: Check that the database ID passed to the tool matches the intended database. Use `npx --package @notis_ai/cli@latest -- notis tools exec LOCAL_NOTIS_DATABASE_LIST_DATABASES --arguments '{}'` to verify the ID; use the database slug only as a fallback.
518
613
  - **Properties are `undefined`**: Keep app-local result types for `useTool<TArgs, TResult>` and guard optional nested properties when reading live data.