@notis_ai/cli 0.2.0-beta.35.1 → 0.2.0-beta.48.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -83
- package/dist/scaffolds/notis-database/app/globals.css +44 -0
- package/dist/scaffolds/notis-database/app/page.tsx +1091 -0
- package/dist/scaffolds/notis-database/components/ui/table.tsx +120 -0
- package/dist/scaffolds/notis-database/index.html +12 -0
- package/dist/scaffolds/notis-database/lib/types.ts +134 -0
- package/dist/scaffolds/notis-database/metadata/cover.png +0 -0
- package/dist/scaffolds/notis-database/metadata/screenshot-1.png +0 -0
- package/dist/scaffolds/notis-database/metadata/screenshot-2.png +0 -0
- package/dist/scaffolds/notis-database/metadata/screenshot-3.png +0 -0
- package/dist/scaffolds/notis-database/notis.config.ts +27 -0
- package/dist/scaffolds/notis-database/package.json +31 -0
- package/dist/scaffolds/notis-database/src/dev-main.tsx +23 -0
- package/dist/scaffolds/notis-database/src/mock-runtime.ts +557 -0
- package/dist/scaffolds/notis-database/tailwind.config.ts +59 -0
- package/dist/scaffolds/{notes → notis-database}/tsconfig.json +2 -1
- package/dist/scaffolds/notis-database/vite.config.ts +22 -0
- package/dist/scaffolds/notis-notes/app/layout.tsx +6 -0
- package/dist/scaffolds/{notes → notis-notes}/app/page.tsx +783 -80
- package/dist/scaffolds/notis-notes/components/ui/badge.tsx +28 -0
- package/dist/scaffolds/notis-notes/components/ui/button.tsx +53 -0
- package/dist/scaffolds/notis-notes/components/ui/card.tsx +56 -0
- package/dist/scaffolds/notis-notes/components.json +20 -0
- package/dist/scaffolds/notis-notes/lib/utils.ts +6 -0
- package/dist/scaffolds/notis-notes/metadata/cover.png +0 -0
- package/dist/scaffolds/notis-notes/metadata/screenshot-1.png +0 -0
- package/dist/scaffolds/notis-notes/metadata/screenshot-2.png +0 -0
- package/dist/scaffolds/notis-notes/metadata/screenshot-3.png +0 -0
- package/dist/scaffolds/{notes → notis-notes}/notis.config.ts +12 -7
- package/dist/scaffolds/{notes → notis-notes}/package.json +3 -3
- package/dist/scaffolds/notis-notes/postcss.config.mjs +8 -0
- package/dist/scaffolds/notis-notes/tsconfig.json +23 -0
- package/dist/scaffolds/notis-random/README.md +33 -0
- package/dist/scaffolds/notis-random/app/globals.css +11 -0
- package/dist/scaffolds/notis-random/app/history/page.tsx +66 -0
- package/dist/scaffolds/notis-random/app/layout.tsx +7 -0
- package/dist/scaffolds/notis-random/app/page.tsx +222 -0
- package/dist/scaffolds/notis-random/index.html +12 -0
- package/dist/scaffolds/notis-random/lib/notis-tools.ts +109 -0
- package/dist/scaffolds/notis-random/lib/rng.ts +42 -0
- package/dist/scaffolds/notis-random/lib/roll-record.ts +102 -0
- package/dist/scaffolds/notis-random/lib/utils.ts +25 -0
- package/dist/scaffolds/notis-random/metadata/cover.png +0 -0
- package/dist/scaffolds/notis-random/metadata/screenshot-1.png +0 -0
- package/dist/scaffolds/notis-random/metadata/screenshot-2.png +0 -0
- package/dist/scaffolds/notis-random/metadata/screenshot-3.png +0 -0
- package/dist/scaffolds/notis-random/notis.config.ts +43 -0
- package/dist/scaffolds/notis-random/package.json +32 -0
- package/dist/scaffolds/notis-random/postcss.config.mjs +6 -0
- package/dist/scaffolds/notis-random/src/dev-main.tsx +70 -0
- package/dist/scaffolds/notis-random/src/mock-runtime.ts +128 -0
- package/dist/scaffolds/notis-random/tailwind.config.ts +43 -0
- package/dist/scaffolds/notis-random/tsconfig.json +23 -0
- package/dist/scaffolds/notis-random/vite.config.ts +11 -0
- package/dist/scaffolds.json +27 -4
- package/package.json +1 -1
- package/skills/notis-apps/SKILL.md +27 -33
- package/skills/notis-apps/cli.md +51 -51
- package/skills/notis-cli/SKILL.md +66 -71
- package/skills/notis-query/cli.md +11 -11
- package/src/cli.js +10 -1
- package/src/command-specs/apps.js +9 -9
- package/src/command-specs/helpers.js +69 -46
- package/src/command-specs/meta.js +6 -6
- package/src/command-specs/tools.js +159 -50
- package/src/runtime/app-dev-server.js +2 -2
- package/src/runtime/app-platform.js +28 -0
- package/src/runtime/transport.js +122 -37
- package/template/packages/sdk/package.json +6 -0
- package/template/packages/sdk/src/hooks/useDatabase.ts +76 -0
- package/template/packages/sdk/src/hooks/useNotis.ts +10 -6
- package/template/packages/sdk/src/hooks/useUpsertDocument.ts +50 -0
- package/template/packages/sdk/src/index.ts +9 -1
- package/template/packages/sdk/src/runtime.ts +83 -2
- /package/dist/scaffolds/{notes → notis-database}/app/layout.tsx +0 -0
- /package/dist/scaffolds/{notes → notis-database}/components/ui/badge.tsx +0 -0
- /package/dist/scaffolds/{notes → notis-database}/components/ui/button.tsx +0 -0
- /package/dist/scaffolds/{notes → notis-database}/components/ui/card.tsx +0 -0
- /package/dist/scaffolds/{notes → notis-database}/components.json +0 -0
- /package/dist/scaffolds/{notes → notis-database}/lib/utils.ts +0 -0
- /package/dist/scaffolds/{notes → notis-database}/postcss.config.mjs +0 -0
- /package/dist/scaffolds/{notes → notis-notes}/app/globals.css +0 -0
- /package/dist/scaffolds/{notes → notis-notes}/tailwind.config.ts +0 -0
- /package/dist/scaffolds/{notes → notis-notes}/vite.config.ts +0 -0
|
@@ -22,18 +22,13 @@ Activate this skill when:
|
|
|
22
22
|
- the user wants to use an integration-backed capability through Notis rather than a first-class local tool
|
|
23
23
|
- the task mentions the `notis` CLI directly
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
Use the registry-resolved published npm package everywhere:
|
|
26
26
|
|
|
27
|
-
- `
|
|
27
|
+
- `npx --package @notis_ai/cli@latest -- notis ...`
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Always use this NPX command form so the agent runs the current published CLI. In hosted shells, the CLI is pre-authenticated through `NOTIS_JWT`; locally, Notis Desktop keeps the CLI auth profile current for NPX invocations.
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- from the repo root: `node packages/cli/bin/notis.js ...`
|
|
34
|
-
- from app workspaces under `.context/`: `node ../../packages/cli/bin/notis.js ...`
|
|
35
|
-
|
|
36
|
-
The Notis desktop app automatically installs and keeps this `notis-cli` skill updated alongside the `notis-apps` skill for local agents. No separate manual skill install is needed on desktop.
|
|
31
|
+
Notis Desktop keeps the CLI auth profile current for NPX runs. This `notis-cli` skill is delivered through normal Notis skill sync for the signed-in user, alongside other curated skills.
|
|
37
32
|
|
|
38
33
|
## Critical rule for missing tools
|
|
39
34
|
|
|
@@ -61,47 +56,47 @@ Important: `deploy` means updating the installed app artifact for the current us
|
|
|
61
56
|
### App development workflow
|
|
62
57
|
|
|
63
58
|
1. Scaffold a new app:
|
|
64
|
-
- `
|
|
59
|
+
- `npx --package @notis_ai/cli@latest -- notis apps init`
|
|
65
60
|
2. Or pull an existing app's source to edit it locally (the project is linked automatically):
|
|
66
|
-
- `
|
|
67
|
-
- then run `npm install`, `
|
|
61
|
+
- `npx --package @notis_ai/cli@latest -- notis apps pull <app-id>`
|
|
62
|
+
- then run `npm install`, `npx --package @notis_ai/cli@latest -- notis apps dev`, edit, build, and deploy
|
|
68
63
|
3. Develop locally with live reload:
|
|
69
|
-
- `
|
|
64
|
+
- `npx --package @notis_ai/cli@latest -- notis apps dev`
|
|
70
65
|
4. Build the production artifact:
|
|
71
|
-
- `
|
|
66
|
+
- `npx --package @notis_ai/cli@latest -- notis apps build`
|
|
72
67
|
5. Verify the built artifact headlessly:
|
|
73
|
-
- `
|
|
68
|
+
- `npx --package @notis_ai/cli@latest -- notis apps verify`
|
|
74
69
|
6. For a brand-new app, create the remote app and link the project in one step:
|
|
75
|
-
- `
|
|
70
|
+
- `npx --package @notis_ai/cli@latest -- notis apps create "My App" .`
|
|
76
71
|
7. Or link the project to an existing remote app (skip if you used `pull` or `create`):
|
|
77
|
-
- `
|
|
72
|
+
- `npx --package @notis_ai/cli@latest -- notis apps link`
|
|
78
73
|
8. Deploy the artifact to Notis:
|
|
79
|
-
- `
|
|
74
|
+
- `npx --package @notis_ai/cli@latest -- notis apps deploy`
|
|
80
75
|
9. Check project health:
|
|
81
|
-
- `
|
|
76
|
+
- `npx --package @notis_ai/cli@latest -- notis apps doctor`
|
|
82
77
|
|
|
83
78
|
### App development rules
|
|
84
79
|
|
|
85
80
|
- Always `build` before `deploy`; run `verify` before deploy when validating an app change.
|
|
86
|
-
- Prefer `
|
|
81
|
+
- Prefer `npx --package @notis_ai/cli@latest -- notis apps create "Name" .` for the first deploy of a new app.
|
|
87
82
|
- Link before `deploy`, or pass `--app-id <id>` when intentionally deploying without writing local link state.
|
|
88
|
-
- Use `
|
|
89
|
-
- Use `
|
|
83
|
+
- Use `npx --package @notis_ai/cli@latest -- notis apps doctor` to diagnose configuration or dependency issues.
|
|
84
|
+
- Use `npx --package @notis_ai/cli@latest -- notis apps list` to discover existing app IDs before linking.
|
|
90
85
|
- For App Store publishing, do not use the CLI. The user opens the app details page in the Notis Portal, sets visibility to Team or Public, then uses Publish/Update. The backend opens the registry PR on their behalf using a service token. Do not invent any CLI store-publish command.
|
|
91
86
|
|
|
92
87
|
### App development command reference
|
|
93
88
|
|
|
94
|
-
- `
|
|
95
|
-
- `
|
|
96
|
-
- `
|
|
97
|
-
- `
|
|
98
|
-
- `
|
|
99
|
-
- `
|
|
100
|
-
- `
|
|
101
|
-
- `
|
|
102
|
-
- `
|
|
103
|
-
- `
|
|
104
|
-
- `
|
|
89
|
+
- `npx --package @notis_ai/cli@latest -- notis apps list` -- list accessible apps
|
|
90
|
+
- `npx --package @notis_ai/cli@latest -- notis apps init` -- scaffold a new Vite + React + `@notis/sdk` project
|
|
91
|
+
- `npx --package @notis_ai/cli@latest -- notis apps pull <app-id> [dir] [--force] [--version <n>]` -- download the persisted source snapshot for an installed app and link the local directory to that app/version; legacy apps must be redeployed once with the current CLI before they can be pulled
|
|
92
|
+
- `npx --package @notis_ai/cli@latest -- notis apps dev` -- discover local apps, register desktop-local dev sessions, and load them in the Electron Portal Local development sidebar group
|
|
93
|
+
- `npx --package @notis_ai/cli@latest -- notis apps build` -- compile the production artifact
|
|
94
|
+
- `npx --package @notis_ai/cli@latest -- notis apps verify` -- headless render-smoke packaged routes before deploy
|
|
95
|
+
- `npx --package @notis_ai/cli@latest -- notis apps create` -- create a fresh remote app and optionally link the local project
|
|
96
|
+
- `npx --package @notis_ai/cli@latest -- notis apps link` -- associate the project with a remote app
|
|
97
|
+
- `npx --package @notis_ai/cli@latest -- notis apps deploy` -- upload the artifact and editable source snapshot to the linked installed app in Notis
|
|
98
|
+
- `npx --package @notis_ai/cli@latest -- notis apps deploy --direct` -- deploy directly to Supabase storage, bypassing the backend server (auto-fallback when server is down)
|
|
99
|
+
- `npx --package @notis_ai/cli@latest -- notis apps doctor` -- run project diagnostics
|
|
105
100
|
|
|
106
101
|
App Store publishing is portal-only — there is no CLI publish command.
|
|
107
102
|
|
|
@@ -109,14 +104,14 @@ If the task is specifically about app structure, runtime behavior, or database/v
|
|
|
109
104
|
|
|
110
105
|
## IMPORTANT: When NOT to use tool access for app development
|
|
111
106
|
|
|
112
|
-
When building or deploying a Notis app, do NOT use `notis tools exec` for any of these operations:
|
|
107
|
+
When building or deploying a Notis app, do NOT use `npx --package @notis_ai/cli@latest -- notis tools exec` for any of these operations:
|
|
113
108
|
|
|
114
109
|
- Creating databases -- declare them in `notis.config.ts` instead
|
|
115
|
-
- Loading or saving app files -- use `notis apps build` and `notis apps deploy`
|
|
116
|
-
- Linting app files -- use `notis apps build` which validates automatically
|
|
110
|
+
- Loading or saving app files -- use `npx --package @notis_ai/cli@latest -- notis apps build` and `npx --package @notis_ai/cli@latest -- notis apps deploy`
|
|
111
|
+
- Linting app files -- use `npx --package @notis_ai/cli@latest -- notis apps build` which validates automatically
|
|
117
112
|
- Managing app routes -- write standard Vite + React pages in `app/`, not raw JS files
|
|
118
113
|
|
|
119
|
-
The only `notis tools exec` calls that are valid during app development are for testing the app's runtime behavior after deployment (e.g., querying a database to verify data was created).
|
|
114
|
+
The only `npx --package @notis_ai/cli@latest -- notis tools exec` calls that are valid during app development are for testing the app's runtime behavior after deployment (e.g., querying a database to verify data was created).
|
|
120
115
|
|
|
121
116
|
## Section 2: Accessing Tools Through the Notis CLI
|
|
122
117
|
|
|
@@ -132,29 +127,29 @@ This is the main escape hatch for:
|
|
|
132
127
|
### Tool access workflow
|
|
133
128
|
|
|
134
129
|
1. List available toolkit namespaces:
|
|
135
|
-
- `notis tools toolkits`
|
|
130
|
+
- `npx --package @notis_ai/cli@latest -- notis tools toolkits`
|
|
136
131
|
2. Search for the capability you need using natural language:
|
|
137
|
-
- `notis tools search "<query>"`
|
|
138
|
-
- optionally
|
|
132
|
+
- `npx --package @notis_ai/cli@latest -- notis tools search "<query>"`
|
|
133
|
+
- optionally add known field hints with `--known-fields "<key:value>"`
|
|
139
134
|
3. If needed, inspect the exact tool and parameter schema:
|
|
140
|
-
- `notis tools describe <tool-name>`
|
|
141
|
-
- `notis tools exec <tool-name> --get-schema`
|
|
135
|
+
- `npx --package @notis_ai/cli@latest -- notis tools describe <tool-name>`
|
|
136
|
+
- `npx --package @notis_ai/cli@latest -- notis tools exec <tool-name> --get-schema`
|
|
142
137
|
4. Validate arguments before execution when the tool is mutating or the schema is non-trivial:
|
|
143
|
-
- `notis tools exec <tool-name> --dry-run --arguments '<json>'`
|
|
138
|
+
- `npx --package @notis_ai/cli@latest -- notis tools exec <tool-name> --dry-run --arguments '<json>'`
|
|
144
139
|
5. Execute the tool:
|
|
145
|
-
- `notis tools exec <tool-name> --arguments '<json>'`
|
|
140
|
+
- `npx --package @notis_ai/cli@latest -- notis tools exec <tool-name> --arguments '<json>'`
|
|
146
141
|
6. If multiple independent calls are needed, use:
|
|
147
|
-
- `notis tools exec-parallel '<json-array>'`
|
|
142
|
+
- `npx --package @notis_ai/cli@latest -- notis tools exec-parallel '<json-array>'`
|
|
148
143
|
7. If the toolkit is not connected yet, generate the connection URL:
|
|
149
|
-
- `notis tools link <toolkit>`
|
|
144
|
+
- `npx --package @notis_ai/cli@latest -- notis tools link <toolkit>`
|
|
150
145
|
|
|
151
146
|
### Tool access rules
|
|
152
147
|
|
|
153
|
-
- Never guess tool names. Discover them with `notis tools search` first.
|
|
154
|
-
- Prefer first-class CLI commands when they exist, but use `notis tools ...` whenever the capability is not covered by a dedicated command.
|
|
155
|
-
- When you know the tool name but not the argument shape, use `notis tools describe` or `--get-schema` before execution.
|
|
148
|
+
- Never guess tool names. Discover them with `npx --package @notis_ai/cli@latest -- notis tools search` first.
|
|
149
|
+
- Prefer first-class CLI commands when they exist, but use `npx --package @notis_ai/cli@latest -- notis tools ...` whenever the capability is not covered by a dedicated command.
|
|
150
|
+
- When you know the tool name but not the argument shape, use `npx --package @notis_ai/cli@latest -- notis tools describe` or `--get-schema` before execution.
|
|
156
151
|
- Use `--dry-run` before mutating calls when you want schema validation without execution.
|
|
157
|
-
- If a toolkit is missing, use `notis tools link <toolkit>` to start the connection flow.
|
|
152
|
+
- If a toolkit is missing, use `npx --package @notis_ai/cli@latest -- notis tools link <toolkit>` to start the connection flow.
|
|
158
153
|
|
|
159
154
|
### Toolkit mental model
|
|
160
155
|
|
|
@@ -176,35 +171,35 @@ The pattern is:
|
|
|
176
171
|
Find a tool:
|
|
177
172
|
|
|
178
173
|
```bash
|
|
179
|
-
notis tools toolkits
|
|
180
|
-
notis tools search "list today's calendar events"
|
|
174
|
+
npx --package @notis_ai/cli@latest -- notis tools toolkits
|
|
175
|
+
npx --package @notis_ai/cli@latest -- notis tools search "list today's calendar events"
|
|
181
176
|
```
|
|
182
177
|
|
|
183
178
|
Inspect a tool before execution:
|
|
184
179
|
|
|
185
180
|
```bash
|
|
186
|
-
notis tools describe composio-googlecalendar-default-list_events
|
|
187
|
-
notis tools exec composio-googlecalendar-default-list_events --get-schema
|
|
181
|
+
npx --package @notis_ai/cli@latest -- notis tools describe composio-googlecalendar-default-list_events
|
|
182
|
+
npx --package @notis_ai/cli@latest -- notis tools exec composio-googlecalendar-default-list_events --get-schema
|
|
188
183
|
```
|
|
189
184
|
|
|
190
185
|
Dry-run a tool call:
|
|
191
186
|
|
|
192
187
|
```bash
|
|
193
|
-
notis tools exec notis-default-query --dry-run --arguments '{"database_slug":"tasks","query":{"page_size":10}}'
|
|
194
|
-
notis tools exec notis-default-get_database --dry-run --arguments '{"database_slug":"tasks"}'
|
|
188
|
+
npx --package @notis_ai/cli@latest -- notis tools exec notis-default-query --dry-run --arguments '{"database_slug":"tasks","query":{"page_size":10}}'
|
|
189
|
+
npx --package @notis_ai/cli@latest -- notis tools exec notis-default-get_database --dry-run --arguments '{"database_slug":"tasks"}'
|
|
195
190
|
```
|
|
196
191
|
|
|
197
192
|
Execute a tool call:
|
|
198
193
|
|
|
199
194
|
```bash
|
|
200
|
-
notis tools exec notis-default-query --arguments '{"database_slug":"tasks","query":{"page_size":10}}'
|
|
201
|
-
notis tools exec notis-default-get_database --arguments '{"database_slug":"tasks"}'
|
|
195
|
+
npx --package @notis_ai/cli@latest -- notis tools exec notis-default-query --arguments '{"database_slug":"tasks","query":{"page_size":10}}'
|
|
196
|
+
npx --package @notis_ai/cli@latest -- notis tools exec notis-default-get_database --arguments '{"database_slug":"tasks"}'
|
|
202
197
|
```
|
|
203
198
|
|
|
204
199
|
Connect a missing toolkit:
|
|
205
200
|
|
|
206
201
|
```bash
|
|
207
|
-
notis tools link github
|
|
202
|
+
npx --package @notis_ai/cli@latest -- notis tools link github
|
|
208
203
|
```
|
|
209
204
|
|
|
210
205
|
## Native database access
|
|
@@ -219,24 +214,24 @@ Native Notis databases are accessed through the generic tool workflow, not a fir
|
|
|
219
214
|
Example workflow before building an app:
|
|
220
215
|
|
|
221
216
|
```bash
|
|
222
|
-
notis tools search "list Notis databases"
|
|
223
|
-
notis tools exec notis-default-list_databases --arguments '{}'
|
|
224
|
-
notis tools exec notis-default-get_database --get-schema
|
|
225
|
-
notis tools exec notis-default-get_database --arguments '{"database_slug":"social_media_calendar"}'
|
|
226
|
-
notis tools exec notis-default-query --arguments '{"database_slug":"social_media_calendar","query":{"page_size":1}}'
|
|
217
|
+
npx --package @notis_ai/cli@latest -- notis tools search "list Notis databases"
|
|
218
|
+
npx --package @notis_ai/cli@latest -- notis tools exec notis-default-list_databases --arguments '{}'
|
|
219
|
+
npx --package @notis_ai/cli@latest -- notis tools exec notis-default-get_database --get-schema
|
|
220
|
+
npx --package @notis_ai/cli@latest -- notis tools exec notis-default-get_database --arguments '{"database_slug":"social_media_calendar"}'
|
|
221
|
+
npx --package @notis_ai/cli@latest -- notis tools exec notis-default-query --arguments '{"database_slug":"social_media_calendar","query":{"page_size":1}}'
|
|
227
222
|
```
|
|
228
223
|
|
|
229
224
|
## Supporting commands
|
|
230
225
|
|
|
231
|
-
- `notis doctor` — verify CLI config, auth, and API reachability before relying on the CLI
|
|
232
|
-
- `notis describe <command...>` — get the exact command contract for first-class CLI commands
|
|
226
|
+
- `npx --package @notis_ai/cli@latest -- notis doctor` — verify CLI config, auth, and API reachability before relying on the CLI
|
|
227
|
+
- `npx --package @notis_ai/cli@latest -- notis describe <command...>` — get the exact command contract for first-class CLI commands
|
|
233
228
|
|
|
234
229
|
## Summary
|
|
235
230
|
|
|
236
231
|
Use `notis-cli` for two things:
|
|
237
232
|
|
|
238
|
-
1. local app development through `notis apps ...`
|
|
239
|
-
2. tool discovery and execution through `notis tools ...`
|
|
233
|
+
1. local app development through `npx --package @notis_ai/cli@latest -- notis apps ...`
|
|
234
|
+
2. tool discovery and execution through `npx --package @notis_ai/cli@latest -- notis tools ...`
|
|
240
235
|
|
|
241
236
|
Most importantly: if you do not currently have the tool you need, especially for direct MCP or integration work, use the Notis CLI instead of treating the task as blocked.
|
|
242
237
|
|
|
@@ -246,11 +241,11 @@ Most importantly: if you do not currently have the tool you need, especially for
|
|
|
246
241
|
|
|
247
242
|
The backend server at `http://localhost:3001` is not running. Solutions:
|
|
248
243
|
|
|
249
|
-
1. Use `--direct` flag: `notis apps deploy --direct` uploads to Supabase storage directly
|
|
244
|
+
1. Use `--direct` flag: `npx --package @notis_ai/cli@latest -- notis apps deploy --direct` uploads to Supabase storage directly
|
|
250
245
|
2. Start the backend server: `cd server && python3 main.py`
|
|
251
|
-
3. Check the API base: `notis doctor` shows the configured `api_base`
|
|
246
|
+
3. Check the API base: `npx --package @notis_ai/cli@latest -- notis doctor` shows the configured `api_base`
|
|
252
247
|
|
|
253
|
-
### `notis doctor` shows health/tool_roundtrip errors
|
|
248
|
+
### `npx --package @notis_ai/cli@latest -- notis doctor` shows health/tool_roundtrip errors
|
|
254
249
|
|
|
255
250
|
The CLI health check pings the backend server. If it's not running, these checks fail. App development commands that are `backend_call: local` (`init`, `build`, `verify`, `link`, `doctor`) work without the server. `dev`, `pull`, `create`, `list`, and normal `deploy` need the backend; `deploy --direct` can bypass it when Supabase credentials are available.
|
|
256
251
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Notis CLI — Database Tool Workflow
|
|
2
2
|
|
|
3
|
-
Use the generic `notis tools` workflow for native Notis Database operations from the terminal. The dedicated database command group has been removed.
|
|
3
|
+
Use the generic `notis tools` workflow through NPX for native Notis Database operations from the terminal. The dedicated database command group has been removed.
|
|
4
4
|
|
|
5
5
|
## Setup
|
|
6
6
|
|
|
7
|
-
Install and sign into Notis Desktop
|
|
7
|
+
Install and sign into Notis Desktop to keep the CLI profile current. Run the CLI through NPX, for example `npx --package @notis_ai/cli@latest -- notis tools search "list Notis databases"`.
|
|
8
8
|
|
|
9
9
|
For CI, hosted agents, or internal scripts, pass a non-persisted token with `NOTIS_JWT=<token>` and use `--api-base <server-url>` when targeting a non-default server.
|
|
10
10
|
|
|
@@ -18,23 +18,23 @@ For CI, hosted agents, or internal scripts, pass a non-persisted token with `NOT
|
|
|
18
18
|
## Workflow
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
notis tools search "list Notis databases"
|
|
22
|
-
notis tools exec notis-default-list_databases --arguments '{}'
|
|
23
|
-
notis tools exec notis-default-get_database --get-schema
|
|
24
|
-
notis tools exec notis-default-get_database --arguments '{"database_slug":"tasks"}'
|
|
25
|
-
notis tools exec notis-default-query --dry-run --arguments '{"database_slug":"tasks","query":{"page_size":10}}'
|
|
26
|
-
notis tools exec notis-default-query --arguments '{"database_slug":"tasks","query":{"page_size":10}}'
|
|
21
|
+
npx --package @notis_ai/cli@latest -- notis tools search "list Notis databases"
|
|
22
|
+
npx --package @notis_ai/cli@latest -- notis tools exec notis-default-list_databases --arguments '{}'
|
|
23
|
+
npx --package @notis_ai/cli@latest -- notis tools exec notis-default-get_database --get-schema
|
|
24
|
+
npx --package @notis_ai/cli@latest -- notis tools exec notis-default-get_database --arguments '{"database_slug":"tasks"}'
|
|
25
|
+
npx --package @notis_ai/cli@latest -- notis tools exec notis-default-query --dry-run --arguments '{"database_slug":"tasks","query":{"page_size":10}}'
|
|
26
|
+
npx --package @notis_ai/cli@latest -- notis tools exec notis-default-query --arguments '{"database_slug":"tasks","query":{"page_size":10}}'
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
## Supporting command
|
|
30
30
|
|
|
31
|
-
### `notis doctor`
|
|
31
|
+
### `npx --package @notis_ai/cli@latest -- notis doctor`
|
|
32
32
|
|
|
33
33
|
Run a quick CLI health check for config, auth, and API reachability.
|
|
34
34
|
|
|
35
35
|
When to use: Use this before relying on the CLI in automation or after changing environments.
|
|
36
36
|
|
|
37
37
|
Examples:
|
|
38
|
-
- `notis doctor`
|
|
39
|
-
- `notis doctor --json`
|
|
38
|
+
- `npx --package @notis_ai/cli@latest -- notis doctor`
|
|
39
|
+
- `npx --package @notis_ai/cli@latest -- notis doctor --json`
|
|
40
40
|
|
package/src/cli.js
CHANGED
|
@@ -64,7 +64,16 @@ function attachSpec(program, parentMap, spec, specs) {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
for (const option of spec.args_schema?.options || []) {
|
|
67
|
-
|
|
67
|
+
if (option.collect) {
|
|
68
|
+
command.option(
|
|
69
|
+
option.flags,
|
|
70
|
+
option.description,
|
|
71
|
+
(value, previous) => [...(previous || []), value],
|
|
72
|
+
[],
|
|
73
|
+
);
|
|
74
|
+
} else {
|
|
75
|
+
command.option(option.flags, option.description);
|
|
76
|
+
}
|
|
68
77
|
}
|
|
69
78
|
|
|
70
79
|
command.action(async (...raw) => {
|
|
@@ -381,8 +381,8 @@ export function buildEnsureDevInstallArguments({ appConfig, manifest, linkedStat
|
|
|
381
381
|
name: appConfig.name,
|
|
382
382
|
manifest,
|
|
383
383
|
};
|
|
384
|
-
if (linkedState?.
|
|
385
|
-
arguments_.app_id = linkedState.
|
|
384
|
+
if (linkedState?.dev_app_id) {
|
|
385
|
+
arguments_.app_id = linkedState.dev_app_id;
|
|
386
386
|
}
|
|
387
387
|
return arguments_;
|
|
388
388
|
}
|
|
@@ -447,7 +447,7 @@ function databaseMaterializationWarnings(apps) {
|
|
|
447
447
|
async function assertDirectDeployAccess(runtime, appId) {
|
|
448
448
|
const result = await runToolCommand({
|
|
449
449
|
runtime,
|
|
450
|
-
toolName: '
|
|
450
|
+
toolName: 'notis-default-list_apps',
|
|
451
451
|
});
|
|
452
452
|
const apps = result.payload.apps || [];
|
|
453
453
|
const hasAccess = apps.some((app) => (app.app_id || app.id) === appId);
|
|
@@ -463,7 +463,7 @@ async function assertDirectDeployAccess(runtime, appId) {
|
|
|
463
463
|
async function appsListHandler(ctx) {
|
|
464
464
|
const result = await runToolCommand({
|
|
465
465
|
runtime: ctx.runtime,
|
|
466
|
-
toolName: '
|
|
466
|
+
toolName: 'notis-default-list_apps',
|
|
467
467
|
});
|
|
468
468
|
const apps = result.payload.apps || [];
|
|
469
469
|
return ctx.output.emitSuccess({
|
|
@@ -511,7 +511,7 @@ async function appsCreateHandler(ctx) {
|
|
|
511
511
|
const idempotencyKey = nextIdempotencyKey(ctx.globalOptions);
|
|
512
512
|
const result = await runToolCommand({
|
|
513
513
|
runtime: ctx.runtime,
|
|
514
|
-
toolName: '
|
|
514
|
+
toolName: 'notis-default-create_app',
|
|
515
515
|
arguments_: {
|
|
516
516
|
name: ctx.args.name,
|
|
517
517
|
description: appConfig?.description || undefined,
|
|
@@ -1073,7 +1073,7 @@ async function appsDeployHandler(ctx) {
|
|
|
1073
1073
|
try {
|
|
1074
1074
|
result = await runToolCommand({
|
|
1075
1075
|
runtime: ctx.runtime,
|
|
1076
|
-
toolName: '
|
|
1076
|
+
toolName: 'notis-default-save_app_files',
|
|
1077
1077
|
arguments_: {
|
|
1078
1078
|
app_id: appId,
|
|
1079
1079
|
files,
|
|
@@ -1185,7 +1185,7 @@ export const appsCommandSpecs = [
|
|
|
1185
1185
|
examples: ['notis apps list', 'notis apps list --json'],
|
|
1186
1186
|
mutates: false,
|
|
1187
1187
|
idempotent: true,
|
|
1188
|
-
backend_call: { type: 'tool', name: '
|
|
1188
|
+
backend_call: { type: 'tool', name: 'notis-default-list_apps' },
|
|
1189
1189
|
handler: appsListHandler,
|
|
1190
1190
|
},
|
|
1191
1191
|
{
|
|
@@ -1242,7 +1242,7 @@ export const appsCommandSpecs = [
|
|
|
1242
1242
|
],
|
|
1243
1243
|
mutates: true,
|
|
1244
1244
|
idempotent: false,
|
|
1245
|
-
backend_call: { type: 'tool', name: '
|
|
1245
|
+
backend_call: { type: 'tool', name: 'notis-default-create_app' },
|
|
1246
1246
|
handler: appsCreateHandler,
|
|
1247
1247
|
},
|
|
1248
1248
|
{
|
|
@@ -1376,7 +1376,7 @@ export const appsCommandSpecs = [
|
|
|
1376
1376
|
examples: ['notis apps deploy', 'notis apps deploy --skip-build', 'notis apps deploy --app-id abc123', 'notis apps deploy --direct'],
|
|
1377
1377
|
mutates: true,
|
|
1378
1378
|
idempotent: true,
|
|
1379
|
-
backend_call: { type: 'tool', name: '
|
|
1379
|
+
backend_call: { type: 'tool', name: 'notis-default-save_app_files' },
|
|
1380
1380
|
handler: appsDeployHandler,
|
|
1381
1381
|
},
|
|
1382
1382
|
{
|
|
@@ -17,23 +17,6 @@ export function parseMaybeJson(value, label) {
|
|
|
17
17
|
return parseJson(value, label);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export function normalizeToolkits(value) {
|
|
21
|
-
if (!value) {
|
|
22
|
-
return [];
|
|
23
|
-
}
|
|
24
|
-
if (value.startsWith('[')) {
|
|
25
|
-
const parsed = parseJson(value, 'toolkits');
|
|
26
|
-
if (!Array.isArray(parsed)) {
|
|
27
|
-
throw usageError('toolkits JSON must be an array of toolkit strings');
|
|
28
|
-
}
|
|
29
|
-
return parsed;
|
|
30
|
-
}
|
|
31
|
-
return value
|
|
32
|
-
.split(',')
|
|
33
|
-
.map((entry) => entry.trim())
|
|
34
|
-
.filter(Boolean);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
20
|
export function nextIdempotencyKey(globalOptions) {
|
|
38
21
|
return globalOptions.idempotencyKey || randomUUID();
|
|
39
22
|
}
|
|
@@ -44,39 +27,32 @@ export async function runToolCommand({
|
|
|
44
27
|
arguments_ = {},
|
|
45
28
|
mutating = false,
|
|
46
29
|
idempotencyKey,
|
|
30
|
+
fileBindings = [],
|
|
47
31
|
}) {
|
|
48
32
|
const result = await callTool({
|
|
49
33
|
runtime: { ...runtime, mutating },
|
|
50
34
|
toolName,
|
|
51
35
|
arguments_,
|
|
52
36
|
idempotencyKey: mutating ? idempotencyKey : null,
|
|
37
|
+
fileBindings,
|
|
53
38
|
});
|
|
54
39
|
return result;
|
|
55
40
|
}
|
|
56
41
|
|
|
57
42
|
export async function fetchToolkits(runtime) {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (toolkits.length) {
|
|
68
|
-
return toolkits;
|
|
69
|
-
}
|
|
70
|
-
const availableToolkits = await fetchToolkits(runtime);
|
|
71
|
-
return availableToolkits.map((entry) => entry.id);
|
|
43
|
+
const payload = await fetchToolDiscovery(runtime, 'List available toolkit namespaces and connection statuses');
|
|
44
|
+
return (payload.toolkit_connection_statuses || []).map((entry) => ({
|
|
45
|
+
id: entry.toolkit,
|
|
46
|
+
provider: typeof entry.toolkit === 'string' ? entry.toolkit.split('-', 1)[0] : undefined,
|
|
47
|
+
description: entry.description || entry.status_message || entry.toolkit,
|
|
48
|
+
has_active_connection: Boolean(entry.has_active_connection),
|
|
49
|
+
status_message: entry.status_message || '',
|
|
50
|
+
connection_details: entry.connection_details || {},
|
|
51
|
+
}));
|
|
72
52
|
}
|
|
73
53
|
|
|
74
54
|
export async function probeAuth(runtime) {
|
|
75
|
-
|
|
76
|
-
runtime,
|
|
77
|
-
toolName: 'notis_find_toolkits',
|
|
78
|
-
});
|
|
79
|
-
return result.payload;
|
|
55
|
+
return fetchToolDiscovery(runtime, 'List available toolkit namespaces and connection statuses');
|
|
80
56
|
}
|
|
81
57
|
|
|
82
58
|
export async function healthCheck(runtime) {
|
|
@@ -88,22 +64,69 @@ export async function healthCheck(runtime) {
|
|
|
88
64
|
});
|
|
89
65
|
}
|
|
90
66
|
|
|
91
|
-
export async function fetchToolSchema(runtime, toolName
|
|
92
|
-
const
|
|
67
|
+
export async function fetchToolSchema(runtime, toolName) {
|
|
68
|
+
const canonicalHints = canonicalToolHints(toolName);
|
|
69
|
+
const payload = await fetchToolDiscovery(
|
|
70
|
+
runtime,
|
|
71
|
+
canonicalHints.useCase,
|
|
72
|
+
canonicalHints.knownFields,
|
|
73
|
+
);
|
|
74
|
+
const schema = payload.tool_schemas?.[toolName];
|
|
75
|
+
if (!schema) {
|
|
76
|
+
throw usageError(`Tool "${toolName}" not found.`);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
name: toolName,
|
|
80
|
+
toolkit_id: schema.toolkit,
|
|
81
|
+
description: schema.description || '',
|
|
82
|
+
parameters: schema.input_schema || { type: 'object', properties: {} },
|
|
83
|
+
output_schema: schema.output_schema || {},
|
|
84
|
+
schema_available: Boolean(schema.hasFullSchema),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function canonicalToolHints(toolName) {
|
|
89
|
+
const rawName = String(toolName || '').trim();
|
|
90
|
+
const parts = rawName.split('-').filter(Boolean);
|
|
91
|
+
if (parts.length < 3) {
|
|
92
|
+
return {
|
|
93
|
+
useCase: `Describe the ${rawName} tool schema`,
|
|
94
|
+
knownFields: `tool_name:${rawName}`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const provider = parts[0];
|
|
99
|
+
const action = parts[parts.length - 1];
|
|
100
|
+
const toolkitParts = parts.slice(1, -1);
|
|
101
|
+
const toolkit = [provider, ...toolkitParts].join('-');
|
|
102
|
+
const providerToolkit = toolkitParts[0] || '';
|
|
103
|
+
const knownFields = [
|
|
104
|
+
`tool_name:${rawName}`,
|
|
105
|
+
`provider:${provider}`,
|
|
106
|
+
`toolkit:${toolkit}`,
|
|
107
|
+
providerToolkit ? `toolkit_slug:${providerToolkit}` : null,
|
|
108
|
+
`action:${action}`,
|
|
109
|
+
].filter(Boolean).join(' ');
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
useCase: `Describe the ${action} schema for ${toolkit}`,
|
|
113
|
+
knownFields,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function fetchToolDiscovery(runtime, useCase, knownFields = '') {
|
|
118
|
+
const query = { use_case: useCase };
|
|
119
|
+
if (knownFields) {
|
|
120
|
+
query.known_fields = knownFields;
|
|
121
|
+
}
|
|
93
122
|
const result = await runToolCommand({
|
|
94
123
|
runtime,
|
|
95
124
|
toolName: 'notis_find_tools',
|
|
96
125
|
arguments_: {
|
|
97
|
-
|
|
98
|
-
...(toolkits.length ? { toolkits } : {}),
|
|
126
|
+
queries: [query],
|
|
99
127
|
},
|
|
100
128
|
});
|
|
101
|
-
|
|
102
|
-
const match = tools.find((t) => t.name === toolName);
|
|
103
|
-
if (!match) {
|
|
104
|
-
throw usageError(`Tool "${toolName}" not found.`);
|
|
105
|
-
}
|
|
106
|
-
return match;
|
|
129
|
+
return result.payload || {};
|
|
107
130
|
}
|
|
108
131
|
|
|
109
132
|
export function validateArguments(schema, args) {
|
|
@@ -21,7 +21,7 @@ async function doctorHandler(ctx) {
|
|
|
21
21
|
if (ctx.runtime.jwt) {
|
|
22
22
|
try {
|
|
23
23
|
const payload = await probeAuth(ctx.runtime);
|
|
24
|
-
checks.tool_roundtrip = Array.isArray(payload.
|
|
24
|
+
checks.tool_roundtrip = Array.isArray(payload.toolkit_connection_statuses) ? 'ok' : 'error';
|
|
25
25
|
} catch {
|
|
26
26
|
checks.tool_roundtrip = 'error';
|
|
27
27
|
}
|
|
@@ -68,7 +68,7 @@ function decodeJwtUserId(jwt) {
|
|
|
68
68
|
|
|
69
69
|
async function whoamiHandler(ctx) {
|
|
70
70
|
const payload = await probeAuth(ctx.runtime);
|
|
71
|
-
const toolkits = payload.
|
|
71
|
+
const toolkits = payload.toolkit_connection_statuses || [];
|
|
72
72
|
const userId = decodeJwtUserId(ctx.runtime.jwt);
|
|
73
73
|
|
|
74
74
|
return ctx.output.emitSuccess({
|
|
@@ -78,7 +78,7 @@ async function whoamiHandler(ctx) {
|
|
|
78
78
|
api_base: ctx.runtime.apiBase,
|
|
79
79
|
user_id: userId,
|
|
80
80
|
toolkit_count: toolkits.length,
|
|
81
|
-
toolkits: toolkits.map((t) => t.
|
|
81
|
+
toolkits: toolkits.map((t) => t.toolkit),
|
|
82
82
|
cli_version: ctx.runtime.cliVersion,
|
|
83
83
|
},
|
|
84
84
|
humanSummary: `Logged in as ${userId || 'unknown'} via profile "${ctx.runtime.profileName}"`,
|
|
@@ -91,7 +91,7 @@ async function whoamiHandler(ctx) {
|
|
|
91
91
|
`Version: ${ctx.runtime.cliVersion}`,
|
|
92
92
|
].join('\n'),
|
|
93
93
|
hints: [
|
|
94
|
-
{ command: 'notis tools toolkits', reason: 'List available toolkit namespaces' },
|
|
94
|
+
{ command: 'notis tools toolkits', reason: 'List available toolkit namespaces and connection statuses' },
|
|
95
95
|
{ command: 'notis doctor', reason: 'Run a full health check' },
|
|
96
96
|
],
|
|
97
97
|
});
|
|
@@ -110,7 +110,7 @@ async function describeHandler(ctx) {
|
|
|
110
110
|
export const metaCommandSpecs = [
|
|
111
111
|
{
|
|
112
112
|
command_path: ['whoami'],
|
|
113
|
-
summary: 'Display the active profile, user, and available
|
|
113
|
+
summary: 'Display the active profile, user, and available toolkit connection statuses.',
|
|
114
114
|
when_to_use: 'Use this to quickly confirm which account and environment a command will target.',
|
|
115
115
|
args_schema: { arguments: [], options: [] },
|
|
116
116
|
examples: ['notis whoami', 'notis whoami --json'],
|
|
@@ -118,7 +118,7 @@ export const metaCommandSpecs = [
|
|
|
118
118
|
mutates: false,
|
|
119
119
|
idempotent: true,
|
|
120
120
|
related_commands: ['notis doctor'],
|
|
121
|
-
backend_call: { type: 'tool', name: '
|
|
121
|
+
backend_call: { type: 'tool', name: 'notis_find_tools' },
|
|
122
122
|
handler: whoamiHandler,
|
|
123
123
|
},
|
|
124
124
|
{
|