@syndicalt/snow-cli 1.0.0 → 1.1.0

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 (3) hide show
  1. package/README.md +691 -545
  2. package/dist/index.js +666 -203
  3. package/package.json +52 -52
package/README.md CHANGED
@@ -1,545 +1,691 @@
1
- # snow-cli
2
-
3
- A portable CLI for ServiceNow. Query tables, inspect schemas, edit script fields, and generate complete applications using AI — all from your terminal.
4
-
5
- - [Installation](#installation)
6
- - [Quick Start](#quick-start)
7
- - [Commands](#commands)
8
- - [snow instance](#snow-instance)
9
- - [snow table](#snow-table)
10
- - [snow schema](#snow-schema)
11
- - [snow script](#snow-script)
12
- - [snow provider](#snow-provider)
13
- - [snow ai](#snow-ai)
14
- - [Configuration File](#configuration-file)
15
- - [Development](#development)
16
-
17
- ---
18
-
19
- ## Installation
20
-
21
- **From npm (when published):**
22
- ```bash
23
- npm install -g snow-cli
24
- ```
25
-
26
- **From source:**
27
- ```bash
28
- git clone <repo>
29
- cd snow-cli
30
- npm install
31
- npm run build
32
- npm link
33
- ```
34
-
35
- Requires Node.js 18+.
36
-
37
- ---
38
-
39
- ## Quick Start
40
-
41
- ```bash
42
- # 1. Add a ServiceNow instance
43
- snow instance add
44
-
45
- # 2. Query a table
46
- snow table get incident -q "active=true" -l 10 -f "number,short_description,state,assigned_to"
47
-
48
- # 3. Configure an AI provider
49
- snow provider set openai
50
-
51
- # 4. Generate a simple feature
52
- snow ai build "Create a script include that auto-routes incidents by category and urgency"
53
-
54
- # 5. Generate a full scoped application (AI decides scope automatically)
55
- snow ai build "Build a hardware asset request application with a custom table, approval script include, and assignment business rule"
56
-
57
- # 6. Start an interactive session to build iteratively
58
- snow ai chat
59
- ```
60
-
61
- ---
62
-
63
- ## Commands
64
-
65
- ### `snow instance`
66
-
67
- Manage ServiceNow instance connections. Credentials are stored in `~/.snow/config.json` (mode `0600`).
68
-
69
- | Command | Description |
70
- |---|---|
71
- | `snow instance add` | Interactively add an instance (prompts for alias, URL, auth type) |
72
- | `snow instance list` | List all configured instances, showing the active one |
73
- | `snow instance use <alias>` | Switch the active instance |
74
- | `snow instance remove <alias>` | Remove an instance |
75
- | `snow instance test` | Test the active instance connection |
76
-
77
- **Adding an instance:**
78
- ```bash
79
- # Interactive (recommended)
80
- snow instance add
81
-
82
- # Basic auth — non-interactive
83
- snow instance add --alias dev --url https://dev12345.service-now.com --auth basic
84
-
85
- # OAuth (password grant) — prompts for client ID and secret
86
- snow instance add --alias prod --url https://prod.service-now.com --auth oauth
87
- ```
88
-
89
- OAuth access tokens are fetched automatically using the password grant flow and cached in the config file with their expiry time. They are refreshed transparently when they expire.
90
-
91
- ---
92
-
93
- ### `snow table`
94
-
95
- Table API CRUD operations. Output defaults to a terminal-friendly table; use `--json` for raw JSON.
96
-
97
- ```bash
98
- # Query records (table format by default)
99
- snow table get incident -q "active=true^priority=1" -l 20
100
- snow table get incident -q "active=true" -f "number,short_description,assigned_to" -l 50
101
-
102
- # Output as JSON array
103
- snow table get incident -q "active=true" -l 5 --json
104
-
105
- # Fetch a single record by sys_id
106
- snow table fetch incident <sys_id>
107
- snow table fetch incident <sys_id> -f "number,state,short_description"
108
-
109
- # Create a record
110
- snow table create incident -d '{"short_description":"VPN issue","urgency":"2","category":"network"}'
111
-
112
- # Update a record
113
- snow table update incident <sys_id> -d '{"state":"6","close_notes":"Resolved"}'
114
-
115
- # Delete a record (prompts for confirmation)
116
- snow table delete incident <sys_id>
117
- snow table delete incident <sys_id> --yes # skip confirmation
118
- ```
119
-
120
- **`snow table get` flags:**
121
-
122
- | Flag | Description |
123
- |---|---|
124
- | `-q, --query <sysparm_query>` | ServiceNow encoded query string |
125
- | `-f, --fields <fields>` | Comma-separated field list to return |
126
- | `-l, --limit <n>` | Max records (default: `20`) |
127
- | `-o, --offset <n>` | Pagination offset (default: `0`) |
128
- | `--display-value` | Return display values instead of raw values |
129
- | `--json` | Output as a JSON array instead of a table |
130
-
131
- **Output behaviour:** When a query returns more fields than can fit in the terminal, the CLI automatically switches to a **card layout** (one record per block) rather than trying to squash too many columns. Use `-f` to select specific fields for tabular output.
132
-
133
- ---
134
-
135
- ### `snow schema`
136
-
137
- Inspect field definitions for any table by querying `sys_dictionary`.
138
-
139
- ```bash
140
- snow schema incident
141
- snow schema sys_user --filter email # filter fields by name or label
142
- snow schema cmdb_ci_server --format json # JSON output
143
- ```
144
-
145
- Output columns: field name, label, type, max length, and flags (`M` = mandatory, `R` = read-only, `ref=<table>` for reference fields).
146
-
147
- ---
148
-
149
- ### `snow script`
150
-
151
- Pull a script field to disk, open it in your editor, then push the edited version back — all in one workflow.
152
-
153
- ```bash
154
- # Pull → edit → push (interactive)
155
- snow script pull sys_script_include <sys_id> script
156
-
157
- # Pull to a specific file path without opening an editor
158
- snow script pull sys_script_include <sys_id> script --no-open -o ./my-script.js
159
-
160
- # Push a local file to a script field
161
- snow script push sys_script_include <sys_id> script ./my-script.js
162
-
163
- # Push the last-pulled file for a record (no file path needed)
164
- snow script push sys_script_include <sys_id> script
165
-
166
- # List locally cached scripts
167
- snow script list
168
- ```
169
-
170
- **Supported field types and file extensions:**
171
-
172
- | Field type | Extension |
173
- |---|---|
174
- | Script (default) | `.js` |
175
- | HTML | `.html` |
176
- | CSS | `.css` |
177
- | XML | `.xml` |
178
- | JSON | `.json` |
179
-
180
- **Editor resolution order:**
181
- 1. `--editor <cmd>` flag
182
- 2. `$VISUAL` environment variable
183
- 3. `$EDITOR` environment variable
184
- 4. First found: `code`, `notepad++`, `notepad` (Windows) / `code`, `nvim`, `vim`, `nano`, `vi` (Unix)
185
-
186
- Cached scripts are stored in `~/.snow/scripts/`.
187
-
188
- ---
189
-
190
- ### `snow provider`
191
-
192
- Configure LLM providers used by `snow ai`. API keys and model preferences are stored in `~/.snow/config.json`.
193
-
194
- | Command | Description |
195
- |---|---|
196
- | `snow provider set <name>` | Add or update a provider (prompts for key and model) |
197
- | `snow provider list` | List all configured providers |
198
- | `snow provider use <name>` | Set the active provider |
199
- | `snow provider show` | Show the active provider details |
200
- | `snow provider test [name]` | Send a test message to verify connectivity |
201
- | `snow provider remove <name>` | Remove a provider configuration |
202
-
203
- **Supported providers:**
204
-
205
- | Name | Models | Notes |
206
- |---|---|---|
207
- | `openai` | `gpt-4o`, `gpt-4-turbo`, `gpt-4o-mini`, | Requires OpenAI API key |
208
- | `anthropic` | `claude-opus-4-6`, `claude-sonnet-4-6`, | Requires Anthropic API key |
209
- | `xai` | `grok-3`, `grok-2`, … | Requires xAI API key; uses OpenAI-compatible API |
210
- | `ollama` | `llama3`, `mistral`, `codellama`, | Local inference; no API key needed |
211
-
212
- **Setup examples:**
213
-
214
- ```bash
215
- # OpenAI (prompts interactively for key and model)
216
- snow provider set openai
217
-
218
- # Anthropic
219
- snow provider set anthropic
220
-
221
- # xAI / Grok
222
- snow provider set xai
223
-
224
- # Ollama (local — no key required)
225
- snow provider set ollama --model llama3
226
- snow provider set ollama --model codellama --url http://localhost:11434
227
-
228
- # Non-interactive with flags
229
- snow provider set openai --key sk-... --model gpt-4o
230
-
231
- # Switch between configured providers
232
- snow provider use anthropic
233
- snow provider use openai
234
-
235
- # Verify a provider is working
236
- snow provider test
237
- snow provider test anthropic
238
- ```
239
-
240
- ---
241
-
242
- ### `snow ai`
243
-
244
- Generate ServiceNow applications using an LLM. The AI produces structured artifacts that are exported as an importable **update set XML** file and optionally pushed directly to your instance via the Table API. When a request warrants it, the AI automatically creates a **scoped application** to namespace the artifacts.
245
-
246
- #### Supported artifact types
247
-
248
- | Type | ServiceNow table(s) | Description |
249
- |---|---|---|
250
- | `script_include` | `sys_script_include` | Reusable server-side JavaScript class |
251
- | `business_rule` | `sys_script` | Auto-triggers on table insert/update/delete/query |
252
- | `client_script` | `sys_client_script` | Browser-side form script (onLoad, onChange, onSubmit) |
253
- | `ui_action` | `sys_ui_action` | Form button or context menu item |
254
- | `ui_page` | `sys_ui_page` | Custom HTML page with Jelly templating |
255
- | `scheduled_job` | `sys_trigger` | Script that runs on a schedule |
256
- | `table` | `sys_db_object` + `sys_dictionary` + `sys_choice` | Custom database table with typed columns and choice lists |
257
- | `decision_table` | `sys_decision` + children | Ordered rule set mapping input conditions to an output value |
258
- | `flow_action` | `sys_hub_action_type_definition` + children | Reusable custom action for Flow Designer |
259
-
260
- #### Scoped applications
261
-
262
- The AI automatically determines whether a build warrants its own application scope. Scope is added when:
263
- - The request creates two or more custom tables
264
- - The request is described as an "application" or "module"
265
- - A distinct namespace is needed to avoid naming conflicts
266
-
267
- When a scope is generated, the build includes a `sys_app` record and every artifact is stamped with `sys_scope`/`sys_package`. All custom table names and script include API names are automatically prefixed (e.g. `x_myco_myapp_tablename`). The scope is shown in the build summary:
268
-
269
- ```
270
- My Incident App
271
- scope: x_myco_incapp v1.0.0
272
-
273
- + table x_myco_incapp_request
274
- + script_include x_myco_incapp.RequestUtils
275
- + business_rule Auto-Assign on Insert
276
- ```
277
-
278
- For Table API push, the CLI resolves or creates the scoped application on the target instance before pushing artifacts.
279
-
280
- #### `snow ai build <prompt>`
281
-
282
- Generate a ServiceNow application from a text description. The AI may ask clarifying questions before generating — answer them interactively and the build proceeds once the AI has enough information. Saves output to a directory named after the update set.
283
-
284
- ```bash
285
- snow ai build "Create a script include that routes incidents based on category and urgency"
286
-
287
- snow ai build "Add a before business rule on the incident table that sets priority = urgency + impact when a record is inserted"
288
-
289
- # Save to a custom directory
290
- snow ai build "Create a client script that hides the CI field when category is Software" --output my-feature
291
-
292
- # Push artifacts directly to the active instance after generating
293
- snow ai build "Create a scheduled job that closes resolved incidents older than 30 days" --push
294
-
295
- # Use a specific provider for this request only
296
- snow ai build "..." --provider anthropic
297
-
298
- # Debug mode — prints raw LLM response and full error traces
299
- snow ai build "..." --debug
300
- ```
301
-
302
- **Interactive clarification:** If your prompt is vague or the AI needs more detail, it will ask targeted questions before generating. You answer in the terminal and the conversation continues until the AI produces the final build.
303
-
304
- ```
305
- AI > To generate the right artifacts, a few questions:
306
- 1. Which table should the business rule operate on?
307
- 2. Should it fire on insert, update, or both?
308
-
309
- You > incident table, on insert only
310
-
311
- [AI generates the build]
312
- ```
313
-
314
- **Post-build flow:** After generating, the CLI presents two optional prompts:
315
-
316
- 1. **Review artifacts** opens an interactive selector to inspect and edit any code field in your preferred editor before deploying
317
- 2. **Push to instance** — confirm to deploy directly, or decline to deploy later with `snow ai push`
318
-
319
- **Output structure:**
320
- ```
321
- incident-priority-router/
322
- incident-priority-router.xml ← importable update set XML
323
- incident-priority-router.manifest.json ← artifact manifest for snow ai push/review
324
- ```
325
-
326
- **Importing the update set in ServiceNow:**
327
- 1. Navigate to **System Update Sets → Retrieved Update Sets**
328
- 2. Click **Import Update Set from XML**
329
- 3. Upload the `.xml` file
330
- 4. Click **Load Update Set**, then **Preview**, then **Commit**
331
-
332
- **Generating tables:**
333
- ```
334
- snow ai build "Create a custom table for tracking hardware asset requests with fields for requester, asset type, urgency, and status"
335
- ```
336
- The AI generates `sys_db_object` + `sys_dictionary` entries for each column, plus `sys_choice` records for any choice fields. If the table extends `task`, inherited fields (number, state, assigned_to, etc.) are not re-declared.
337
-
338
- **Generating decision tables:**
339
- ```
340
- snow ai build "Create a decision table that maps urgency and impact values to a priority level"
341
- ```
342
- Produces a `sys_decision` record with input columns, ordered rules, and per-rule conditions. Decision tables are evaluated top-down — the first matching rule wins.
343
-
344
- **Generating flow actions:**
345
- ```
346
- snow ai build "Create a Flow Designer action that creates an incident from an email subject and body and returns the sys_id"
347
- ```
348
- Produces a `sys_hub_action_type_definition` with typed input and output variables. The action appears in the Flow Designer action picker under the specified category and can be used in any flow or subflow.
349
-
350
- **Generating a scoped application:**
351
- ```
352
- snow ai build "Build a full hardware asset request application with a custom table, approval workflow script include, and email notification business rule"
353
- ```
354
- When the AI determines a scope is appropriate it generates the `sys_app` record and prefixes all custom artifacts automatically. You can also explicitly ask for a scope:
355
- ```
356
- snow ai build "Create a scoped application called 'HR Onboarding' with scope prefix x_myco_hronboard ..."
357
- ```
358
-
359
- #### `snow ai chat`
360
-
361
- Interactive multi-turn session. The AI can ask clarifying questions before generating, and refines artifacts as the conversation continues. The update set is re-saved to disk automatically after each generation.
362
-
363
- ```bash
364
- snow ai chat
365
- snow ai chat --push # auto-push to instance on each generation
366
- snow ai chat --debug # show raw LLM responses
367
- snow ai chat --output ./my-app # save all builds to a specific directory
368
- ```
369
-
370
- **In-session commands:**
371
-
372
- | Command | Action |
373
- |---|---|
374
- | `/status` | Show the current build summary and artifact list |
375
- | `/save` | Write the current XML and manifest to disk |
376
- | `/push` | Push the current build to the active ServiceNow instance |
377
- | `/clear` | Reset the session (clears history and current build) |
378
- | `/exit` | Quit |
379
-
380
- After each generation, the CLI prompts whether to push to the active instance (unless `--push` is set, in which case it pushes automatically).
381
-
382
- **Example session:**
383
- ```
384
- You > I want to build an incident auto-assignment feature
385
-
386
- AI > To generate the right artifacts, a few questions:
387
- 1. Which teams/groups should incidents be routed to?
388
- 2. What fields determine the routing — category, urgency, location, or something else?
389
- 3. Should assignment happen on insert only, or also on update?
390
-
391
- You > Route by category: Network → Network Ops, Software → App Support.
392
- Assignment on insert only.
393
-
394
- AI > [generates script include + business rule]
395
-
396
- + script_include IncidentRouter
397
- + business_rule Auto-Assign Incident on Insert
398
-
399
- incident-auto-assignment/
400
- incident-auto-assignment.xml
401
- incident-auto-assignment.manifest.json
402
-
403
- Push 2 artifact(s) to dev (https://dev12345.service-now.com)? (y/N)
404
-
405
- You > Also add a UI action button to manually re-trigger the routing
406
-
407
- AI > [generates updated build with all three artifacts]
408
-
409
- + script_include IncidentRouter (unchanged)
410
- + business_rule Auto-Assign ... (unchanged)
411
- + ui_action Re-Route Incident ← new
412
- ```
413
-
414
- #### `snow ai review <path>`
415
-
416
- Review and edit a previously generated build. Opens an interactive artifact selector, shows code with line numbers, and lets you open any field in your editor. Changes are saved back to the XML and manifest immediately. After reviewing, you can optionally push the (modified) build to the active instance.
417
-
418
- ```bash
419
- # Review from a build directory
420
- snow ai review ./incident-auto-assignment/
421
-
422
- # Review from a manifest file
423
- snow ai review ./incident-auto-assignment/incident-auto-assignment.manifest.json
424
-
425
- # Review from the XML file (locates the sibling .manifest.json automatically)
426
- snow ai review ./incident-auto-assignment/incident-auto-assignment.xml
427
- ```
428
-
429
- **Review workflow:**
430
- 1. Select an artifact from the list
431
- 2. The code is printed with line numbers
432
- 3. Confirm to open in your editor (uses `$VISUAL`, `$EDITOR`, or auto-detected editor)
433
- 4. Save and close the editor changes are written back to disk immediately
434
- 5. Select another artifact or choose **Done reviewing**
435
- 6. Confirm whether to push the build to the active instance
436
-
437
- #### `snow ai push <path>`
438
-
439
- Push a previously generated build to the active instance via Table API.
440
-
441
- ```bash
442
- # Push from a build directory
443
- snow ai push ./incident-auto-assignment/
444
-
445
- # Push from a manifest file
446
- snow ai push ./incident-auto-assignment/incident-auto-assignment.manifest.json
447
- ```
448
-
449
- **Push behaviour per artifact type:**
450
-
451
- | Artifact | Strategy |
452
- |---|---|
453
- | script_include, business_rule, etc. | Looks up by name creates or updates the single record |
454
- | `table` | Upserts `sys_db_object`; upserts each `sys_dictionary` column by table+element; upserts `sys_choice` rows by table+element+value |
455
- | `decision_table` | Upserts `sys_decision`; deletes and recreates all input columns and rules on update |
456
- | `flow_action` | Upserts `sys_hub_action_type_definition`; deletes and recreates all input/output variables on update |
457
- | Scoped build | Resolves or creates the `sys_app` record first; stamps `sys_scope`/`sys_package` on every record |
458
-
459
- ---
460
-
461
- ## Configuration File
462
-
463
- All settings are stored in `~/.snow/config.json`. The directory is created with mode `0700` and the file with `0600`.
464
-
465
- ```json
466
- {
467
- "activeInstance": "dev",
468
- "instances": {
469
- "dev": {
470
- "alias": "dev",
471
- "url": "https://dev12345.service-now.com",
472
- "auth": {
473
- "type": "basic",
474
- "username": "admin",
475
- "password": "your-password"
476
- }
477
- },
478
- "prod": {
479
- "alias": "prod",
480
- "url": "https://prod.service-now.com",
481
- "auth": {
482
- "type": "oauth",
483
- "clientId": "...",
484
- "clientSecret": "...",
485
- "accessToken": "...",
486
- "tokenExpiry": 1700000000000
487
- }
488
- }
489
- },
490
- "ai": {
491
- "activeProvider": "openai",
492
- "providers": {
493
- "openai": {
494
- "model": "gpt-4o",
495
- "apiKey": "sk-..."
496
- },
497
- "anthropic": {
498
- "model": "claude-opus-4-6",
499
- "apiKey": "sk-ant-..."
500
- },
501
- "xai": {
502
- "model": "grok-3",
503
- "apiKey": "xai-...",
504
- "baseUrl": "https://api.x.ai/v1"
505
- },
506
- "ollama": {
507
- "model": "llama3",
508
- "baseUrl": "http://localhost:11434"
509
- }
510
- }
511
- }
512
- }
513
- ```
514
-
515
- ---
516
-
517
- ## Development
518
-
519
- ```bash
520
- npm run dev # Watch mode rebuilds on every file change
521
- npm run build # One-time production build to dist/
522
- ```
523
-
524
- The entry point is `src/index.ts`. Commands live in `src/commands/`, shared utilities in `src/lib/`.
525
-
526
- **Project structure:**
527
- ```
528
- src/
529
- index.ts CLI entry point and command registration
530
- commands/
531
- instance.ts snow instance
532
- table.ts snow table
533
- schema.ts snow schema
534
- script.ts snow script
535
- provider.ts snow provider
536
- ai.ts snow ai (build, chat, review, push)
537
- lib/
538
- config.ts Config file read/write + instance and provider helpers
539
- client.ts ServiceNow HTTP client (axios, basic + OAuth auth)
540
- llm.ts LLM provider abstraction (OpenAI, Anthropic, xAI, Ollama)
541
- sn-context.ts ServiceNow system prompt and artifact type definitions
542
- update-set.ts XML update set generation and Table API push
543
- types/
544
- index.ts Shared TypeScript interfaces
545
- ```
1
+ # snow-cli
2
+
3
+ A portable CLI for ServiceNow. Query tables, inspect schemas, edit script fields, and generate complete applications using AI — all from your terminal.
4
+
5
+ - [Installation](#installation)
6
+ - [Quick Start](#quick-start)
7
+ - [Commands](#commands)
8
+ - [snow instance](#snow-instance)
9
+ - [snow table](#snow-table)
10
+ - [snow schema](#snow-schema)
11
+ - [snow schema map](#snow-schema-map)
12
+ - [snow script](#snow-script)
13
+ - [snow provider](#snow-provider)
14
+ - [snow ai](#snow-ai)
15
+ - [Configuration File](#configuration-file)
16
+ - [Development](#development)
17
+
18
+ ---
19
+
20
+ ## Installation
21
+
22
+ **From npm (when published):**
23
+ ```bash
24
+ npm install -g snow-cli
25
+ ```
26
+
27
+ **From source:**
28
+ ```bash
29
+ git clone <repo>
30
+ cd snow-cli
31
+ npm install
32
+ npm run build
33
+ npm link
34
+ ```
35
+
36
+ Requires Node.js 18+.
37
+
38
+ ---
39
+
40
+ ## Quick Start
41
+
42
+ ```bash
43
+ # 1. Add a ServiceNow instance
44
+ snow instance add
45
+
46
+ # 2. Query a table
47
+ snow table get incident -q "active=true" -l 10 -f "number,short_description,state,assigned_to"
48
+
49
+ # 3. Configure an AI provider
50
+ snow provider set openai
51
+
52
+ # 4. Generate a simple feature
53
+ snow ai build "Create a script include that auto-routes incidents by category and urgency"
54
+
55
+ # 5. Generate a full scoped application (AI decides scope automatically)
56
+ snow ai build "Build a hardware asset request application with a custom table, approval script include, and assignment business rule"
57
+
58
+ # 6. Start an interactive session to build iteratively
59
+ snow ai chat
60
+ ```
61
+
62
+ ---
63
+
64
+ ## Commands
65
+
66
+ ### `snow instance`
67
+
68
+ Manage ServiceNow instance connections. Credentials are stored in `~/.snow/config.json` (mode `0600`).
69
+
70
+ | Command | Description |
71
+ |---|---|
72
+ | `snow instance add` | Interactively add an instance (prompts for alias, URL, auth type) |
73
+ | `snow instance list` | List all configured instances, showing the active one |
74
+ | `snow instance use <alias>` | Switch the active instance |
75
+ | `snow instance remove <alias>` | Remove an instance |
76
+ | `snow instance test` | Test the active instance connection |
77
+
78
+ **Adding an instance:**
79
+ ```bash
80
+ # Interactive (recommended)
81
+ snow instance add
82
+
83
+ # Basic auth non-interactive
84
+ snow instance add --alias dev --url https://dev12345.service-now.com --auth basic
85
+
86
+ # OAuth (password grant) prompts for client ID and secret
87
+ snow instance add --alias prod --url https://prod.service-now.com --auth oauth
88
+ ```
89
+
90
+ OAuth access tokens are fetched automatically using the password grant flow and cached in the config file with their expiry time. They are refreshed transparently when they expire.
91
+
92
+ ---
93
+
94
+ ### `snow table`
95
+
96
+ Table API CRUD operations. Output defaults to a terminal-friendly table; use `--json` for raw JSON.
97
+
98
+ ```bash
99
+ # Query records (table format by default)
100
+ snow table get incident -q "active=true^priority=1" -l 20
101
+ snow table get incident -q "active=true" -f "number,short_description,assigned_to" -l 50
102
+
103
+ # Output as JSON array
104
+ snow table get incident -q "active=true" -l 5 --json
105
+
106
+ # Fetch a single record by sys_id
107
+ snow table fetch incident <sys_id>
108
+ snow table fetch incident <sys_id> -f "number,state,short_description"
109
+
110
+ # Create a record
111
+ snow table create incident -d '{"short_description":"VPN issue","urgency":"2","category":"network"}'
112
+
113
+ # Update a record
114
+ snow table update incident <sys_id> -d '{"state":"6","close_notes":"Resolved"}'
115
+
116
+ # Delete a record (prompts for confirmation)
117
+ snow table delete incident <sys_id>
118
+ snow table delete incident <sys_id> --yes # skip confirmation
119
+ ```
120
+
121
+ **`snow table get` flags:**
122
+
123
+ | Flag | Description |
124
+ |---|---|
125
+ | `-q, --query <sysparm_query>` | ServiceNow encoded query string |
126
+ | `-f, --fields <fields>` | Comma-separated field list to return |
127
+ | `-l, --limit <n>` | Max records (default: `20`) |
128
+ | `-o, --offset <n>` | Pagination offset (default: `0`) |
129
+ | `--display-value` | Return display values instead of raw values |
130
+ | `--json` | Output as a JSON array instead of a table |
131
+
132
+ **Output behaviour:** When a query returns more fields than can fit in the terminal, the CLI automatically switches to a **card layout** (one record per block) rather than trying to squash too many columns. Use `-f` to select specific fields for tabular output.
133
+
134
+ ---
135
+
136
+ ### `snow schema`
137
+
138
+ Inspect field definitions for any table, or generate a full cross-table schema map.
139
+
140
+ #### Field inspection
141
+
142
+ ```bash
143
+ snow schema incident
144
+ snow schema sys_user --filter email # filter fields by name or label
145
+ snow schema cmdb_ci_server --format json # JSON output
146
+ ```
147
+
148
+ Output columns: field name, label, type, max length, and flags (`M` = mandatory, `R` = read-only, `ref=<table>` for reference fields).
149
+
150
+ #### `snow schema map`
151
+
152
+ Crawl a table's reference and M2M fields to generate a complete relational schema diagram. The crawl follows references to the specified depth, building a graph of all connected tables including their scope information. Outputs Mermaid (`.mmd`) or DBML (`.dbml`) to disk.
153
+
154
+ ```bash
155
+ # Mermaid diagram, depth 2 (default)
156
+ snow schema map incident
157
+
158
+ # DBML format, custom filename, saved to a directory
159
+ snow schema map incident --format dbml --out ./diagrams --name incident-full
160
+
161
+ # Follow 3 levels of references
162
+ snow schema map incident --depth 3
163
+
164
+ # Include glide_list (M2M) relationships
165
+ snow schema map incident --show-m2m
166
+
167
+ # Also crawl tables that reference incident (inbound — keep depth low)
168
+ snow schema map incident --inbound --depth 1
169
+
170
+ # Include choice field enum blocks in DBML output
171
+ snow schema map incident --format dbml --enums
172
+
173
+ # Generate the diagram then have the AI explain the data model
174
+ snow schema map incident --explain
175
+
176
+ # All options combined
177
+ snow schema map x_myco_myapp_request --depth 2 --format dbml --enums --explain --name myapp-schema
178
+ ```
179
+
180
+ **Options:**
181
+
182
+ | Flag | Default | Description |
183
+ |---|---|---|
184
+ | `-d, --depth <n>` | `2` | How many levels of reference fields to follow |
185
+ | `--show-m2m` | off | Include `glide_list` fields as many-to-many relationships |
186
+ | `--format <fmt>` | `mermaid` | Output format: `mermaid` or `dbml` |
187
+ | `--out <dir>` | `.` | Directory to write the output file(s) |
188
+ | `--name <name>` | `<table>-schema` | Base filename — extension added automatically |
189
+ | `--inbound` | off | Also crawl tables that have reference fields pointing *to* this table |
190
+ | `--enums` | off | Fetch `sys_choice` values and emit Enum blocks (DBML) or `%%` comments (Mermaid) |
191
+ | `--explain` | off | Use the active AI provider to generate a plain-English explanation of the schema |
192
+
193
+ **Output files:**
194
+
195
+ | Format | File | Open with |
196
+ |---|---|---|
197
+ | Mermaid | `<name>.mmd` | VS Code Mermaid Preview, GitHub, mermaid.live |
198
+ | DBML | `<name>.dbml` | dbdiagram.io, any DBML-compatible tool |
199
+ | Explanation | `<name>.explanation.md` | Any Markdown viewer (`--explain` only) |
200
+
201
+ **How the crawl works:**
202
+
203
+ 1. Fetches all fields for the root table from `sys_dictionary`, plus label and `sys_scope` via `sys_db_object`
204
+ 2. For every `reference`-type field, records the relationship and queues the target table
205
+ 3. Repeats for each discovered table until `--depth` is reached
206
+ 4. With `--show-m2m`: also follows `glide_list` fields, shown as many-to-many edges
207
+ 5. With `--inbound`: additionally queues tables that have reference fields pointing *to* the current table
208
+ 6. Tables referenced by fields that fall outside the crawl depth are rendered as **stub placeholders** (marked `not crawled`) so all references in the diagram resolve without broken links
209
+
210
+ > **Tip:** `--inbound` with depth > 1 can produce very large graphs for highly-referenced tables like `sys_user` or `task`. Use `--depth 1` when combining these flags. A warning is also printed when the crawl discovers more than 50 tables.
211
+
212
+ **Scope annotations:**
213
+
214
+ Each table's application scope is fetched alongside its label. Both output formats include a scope summary header. In DBML, non-Global tables are annotated directly:
215
+
216
+ ```dbml
217
+ // Scopes: Global (12), ITSM (3)
218
+ // Warning: tables from 2 scopes — cross-scope references present
219
+
220
+ Table incident [note: 'Incident | scope: ITSM'] { ... }
221
+ ```
222
+
223
+ In Mermaid, scope information appears as `%%` comments at the top of the file.
224
+
225
+ **Choice enums (`--enums`):**
226
+
227
+ Queries `sys_choice` for every `choice`-type field across all crawled tables. In DBML, each set of choices becomes a named `Enum` block and the field type references it:
228
+
229
+ ```dbml
230
+ Table incident {
231
+ state incident__state [not null]
232
+ }
233
+
234
+ Enum incident__state {
235
+ "1" [note: 'New']
236
+ "2" [note: 'In Progress']
237
+ "6" [note: 'Resolved']
238
+ }
239
+ ```
240
+
241
+ In Mermaid, choice values are emitted as `%%` comments since `erDiagram` has no enum syntax.
242
+
243
+ **AI explanation (`--explain`):**
244
+
245
+ Requires a configured AI provider (`snow provider set`). After writing the schema file, the CLI sends the schema content to the active LLM and saves the Markdown response to `<name>.explanation.md`. The explanation is also printed to the terminal. It covers the business domain, key tables, notable relationships, and any cross-scope dependencies.
246
+
247
+ ```bash
248
+ snow provider set anthropic # configure a provider first
249
+ snow schema map incident --format dbml --explain
250
+ ```
251
+
252
+ **Example output (Mermaid):**
253
+ ```
254
+ %% Scopes: Global (8), ITSM (2)
255
+ incident }o--|| sys_user : "Caller"
256
+ incident }o--|| problem : "Problem"
257
+ incident }o--|| change_request : "RFC"
258
+ sys_user }o--|| cmn_department : "Department"
259
+ ...
260
+ cmn_location { string sys_id } %% stub: referenced but not crawled
261
+ ```
262
+
263
+ **Example output (DBML):**
264
+ ```dbml
265
+ // Scopes: Global (8), ITSM (2)
266
+
267
+ Table incident [note: 'Incident | scope: ITSM'] {
268
+ caller_id varchar(32) [ref: > sys_user.sys_id]
269
+ problem_id varchar(32) [ref: > problem.sys_id]
270
+ state incident__state [not null]
271
+ }
272
+
273
+ // Placeholder tables — referenced but not crawled (increase --depth to explore)
274
+ Table cmn_schedule [note: 'not crawled'] {
275
+ sys_id varchar(32) [pk]
276
+ }
277
+
278
+ // Choice field enums
279
+ Enum incident__state {
280
+ "1" [note: 'New']
281
+ "2" [note: 'In Progress']
282
+ "6" [note: 'Resolved']
283
+ }
284
+ ```
285
+
286
+ **Cardinality notation:**
287
+
288
+ | Relationship | Mermaid | Meaning |
289
+ |---|---|---|
290
+ | Reference field | `}o--\|\|` | Many records one target |
291
+ | Glide list (M2M) | `}o--o{` | Many records ↔ many targets |
292
+
293
+ ---
294
+
295
+ ### `snow script`
296
+
297
+ Pull a script field to disk, open it in your editor, then push the edited version back — all in one workflow.
298
+
299
+ ```bash
300
+ # Pull → edit → push (interactive)
301
+ snow script pull sys_script_include <sys_id> script
302
+
303
+ # Pull to a specific file path without opening an editor
304
+ snow script pull sys_script_include <sys_id> script --no-open -o ./my-script.js
305
+
306
+ # Push a local file to a script field
307
+ snow script push sys_script_include <sys_id> script ./my-script.js
308
+
309
+ # Push the last-pulled file for a record (no file path needed)
310
+ snow script push sys_script_include <sys_id> script
311
+
312
+ # List locally cached scripts
313
+ snow script list
314
+ ```
315
+
316
+ **Supported field types and file extensions:**
317
+
318
+ | Field type | Extension |
319
+ |---|---|
320
+ | Script (default) | `.js` |
321
+ | HTML | `.html` |
322
+ | CSS | `.css` |
323
+ | XML | `.xml` |
324
+ | JSON | `.json` |
325
+
326
+ **Editor resolution order:**
327
+ 1. `--editor <cmd>` flag
328
+ 2. `$VISUAL` environment variable
329
+ 3. `$EDITOR` environment variable
330
+ 4. First found: `code`, `notepad++`, `notepad` (Windows) / `code`, `nvim`, `vim`, `nano`, `vi` (Unix)
331
+
332
+ Cached scripts are stored in `~/.snow/scripts/`.
333
+
334
+ ---
335
+
336
+ ### `snow provider`
337
+
338
+ Configure LLM providers used by `snow ai`. API keys and model preferences are stored in `~/.snow/config.json`.
339
+
340
+ | Command | Description |
341
+ |---|---|
342
+ | `snow provider set <name>` | Add or update a provider (prompts for key and model) |
343
+ | `snow provider list` | List all configured providers |
344
+ | `snow provider use <name>` | Set the active provider |
345
+ | `snow provider show` | Show the active provider details |
346
+ | `snow provider test [name]` | Send a test message to verify connectivity |
347
+ | `snow provider remove <name>` | Remove a provider configuration |
348
+
349
+ **Supported providers:**
350
+
351
+ | Name | Models | Notes |
352
+ |---|---|---|
353
+ | `openai` | `gpt-4o`, `gpt-4-turbo`, `gpt-4o-mini`, … | Requires OpenAI API key |
354
+ | `anthropic` | `claude-opus-4-6`, `claude-sonnet-4-6`, | Requires Anthropic API key |
355
+ | `xai` | `grok-3`, `grok-2`, … | Requires xAI API key; uses OpenAI-compatible API |
356
+ | `ollama` | `llama3`, `mistral`, `codellama`, | Local inference; no API key needed |
357
+
358
+ **Setup examples:**
359
+
360
+ ```bash
361
+ # OpenAI (prompts interactively for key and model)
362
+ snow provider set openai
363
+
364
+ # Anthropic
365
+ snow provider set anthropic
366
+
367
+ # xAI / Grok
368
+ snow provider set xai
369
+
370
+ # Ollama (local — no key required)
371
+ snow provider set ollama --model llama3
372
+ snow provider set ollama --model codellama --url http://localhost:11434
373
+
374
+ # Non-interactive with flags
375
+ snow provider set openai --key sk-... --model gpt-4o
376
+
377
+ # Switch between configured providers
378
+ snow provider use anthropic
379
+ snow provider use openai
380
+
381
+ # Verify a provider is working
382
+ snow provider test
383
+ snow provider test anthropic
384
+ ```
385
+
386
+ ---
387
+
388
+ ### `snow ai`
389
+
390
+ Generate ServiceNow applications using an LLM. The AI produces structured artifacts that are exported as an importable **update set XML** file and optionally pushed directly to your instance via the Table API. When a request warrants it, the AI automatically creates a **scoped application** to namespace the artifacts.
391
+
392
+ #### Supported artifact types
393
+
394
+ | Type | ServiceNow table(s) | Description |
395
+ |---|---|---|
396
+ | `script_include` | `sys_script_include` | Reusable server-side JavaScript class |
397
+ | `business_rule` | `sys_script` | Auto-triggers on table insert/update/delete/query |
398
+ | `client_script` | `sys_client_script` | Browser-side form script (onLoad, onChange, onSubmit) |
399
+ | `ui_action` | `sys_ui_action` | Form button or context menu item |
400
+ | `ui_page` | `sys_ui_page` | Custom HTML page with Jelly templating |
401
+ | `scheduled_job` | `sys_trigger` | Script that runs on a schedule |
402
+ | `table` | `sys_db_object` + `sys_dictionary` + `sys_choice` | Custom database table with typed columns and choice lists |
403
+ | `decision_table` | `sys_decision` + children | Ordered rule set mapping input conditions to an output value |
404
+ | `flow_action` | `sys_hub_action_type_definition` + children | Reusable custom action for Flow Designer |
405
+
406
+ #### Scoped applications
407
+
408
+ The AI automatically determines whether a build warrants its own application scope. Scope is added when:
409
+ - The request creates two or more custom tables
410
+ - The request is described as an "application" or "module"
411
+ - A distinct namespace is needed to avoid naming conflicts
412
+
413
+ When a scope is generated, the build includes a `sys_app` record and every artifact is stamped with `sys_scope`/`sys_package`. All custom table names and script include API names are automatically prefixed (e.g. `x_myco_myapp_tablename`). The scope is shown in the build summary:
414
+
415
+ ```
416
+ My Incident App
417
+ scope: x_myco_incapp v1.0.0
418
+
419
+ + table x_myco_incapp_request
420
+ + script_include x_myco_incapp.RequestUtils
421
+ + business_rule Auto-Assign on Insert
422
+ ```
423
+
424
+ For Table API push, the CLI resolves or creates the scoped application on the target instance before pushing artifacts.
425
+
426
+ #### `snow ai build <prompt>`
427
+
428
+ Generate a ServiceNow application from a text description. The AI may ask clarifying questions before generating — answer them interactively and the build proceeds once the AI has enough information. Saves output to a directory named after the update set.
429
+
430
+ ```bash
431
+ snow ai build "Create a script include that routes incidents based on category and urgency"
432
+
433
+ snow ai build "Add a before business rule on the incident table that sets priority = urgency + impact when a record is inserted"
434
+
435
+ # Save to a custom directory
436
+ snow ai build "Create a client script that hides the CI field when category is Software" --output my-feature
437
+
438
+ # Push artifacts directly to the active instance after generating
439
+ snow ai build "Create a scheduled job that closes resolved incidents older than 30 days" --push
440
+
441
+ # Use a specific provider for this request only
442
+ snow ai build "..." --provider anthropic
443
+
444
+ # Debug mode — prints raw LLM response and full error traces
445
+ snow ai build "..." --debug
446
+ ```
447
+
448
+ **Interactive clarification:** If your prompt is vague or the AI needs more detail, it will ask targeted questions before generating. You answer in the terminal and the conversation continues until the AI produces the final build.
449
+
450
+ ```
451
+ AI > To generate the right artifacts, a few questions:
452
+ 1. Which table should the business rule operate on?
453
+ 2. Should it fire on insert, update, or both?
454
+
455
+ You > incident table, on insert only
456
+
457
+ [AI generates the build]
458
+ ```
459
+
460
+ **Post-build flow:** After generating, the CLI presents two optional prompts:
461
+
462
+ 1. **Review artifacts** — opens an interactive selector to inspect and edit any code field in your preferred editor before deploying
463
+ 2. **Push to instance** confirm to deploy directly, or decline to deploy later with `snow ai push`
464
+
465
+ **Output structure:**
466
+ ```
467
+ incident-priority-router/
468
+ incident-priority-router.xml ← importable update set XML
469
+ incident-priority-router.manifest.json ← artifact manifest for snow ai push/review
470
+ ```
471
+
472
+ **Importing the update set in ServiceNow:**
473
+ 1. Navigate to **System Update Sets → Retrieved Update Sets**
474
+ 2. Click **Import Update Set from XML**
475
+ 3. Upload the `.xml` file
476
+ 4. Click **Load Update Set**, then **Preview**, then **Commit**
477
+
478
+ **Generating tables:**
479
+ ```
480
+ snow ai build "Create a custom table for tracking hardware asset requests with fields for requester, asset type, urgency, and status"
481
+ ```
482
+ The AI generates `sys_db_object` + `sys_dictionary` entries for each column, plus `sys_choice` records for any choice fields. If the table extends `task`, inherited fields (number, state, assigned_to, etc.) are not re-declared.
483
+
484
+ **Generating decision tables:**
485
+ ```
486
+ snow ai build "Create a decision table that maps urgency and impact values to a priority level"
487
+ ```
488
+ Produces a `sys_decision` record with input columns, ordered rules, and per-rule conditions. Decision tables are evaluated top-down — the first matching rule wins.
489
+
490
+ **Generating flow actions:**
491
+ ```
492
+ snow ai build "Create a Flow Designer action that creates an incident from an email subject and body and returns the sys_id"
493
+ ```
494
+ Produces a `sys_hub_action_type_definition` with typed input and output variables. The action appears in the Flow Designer action picker under the specified category and can be used in any flow or subflow.
495
+
496
+ **Generating a scoped application:**
497
+ ```
498
+ snow ai build "Build a full hardware asset request application with a custom table, approval workflow script include, and email notification business rule"
499
+ ```
500
+ When the AI determines a scope is appropriate it generates the `sys_app` record and prefixes all custom artifacts automatically. You can also explicitly ask for a scope:
501
+ ```
502
+ snow ai build "Create a scoped application called 'HR Onboarding' with scope prefix x_myco_hronboard ..."
503
+ ```
504
+
505
+ #### `snow ai chat`
506
+
507
+ Interactive multi-turn session. The AI can ask clarifying questions before generating, and refines artifacts as the conversation continues. The update set is re-saved to disk automatically after each generation.
508
+
509
+ ```bash
510
+ snow ai chat
511
+ snow ai chat --push # auto-push to instance on each generation
512
+ snow ai chat --debug # show raw LLM responses
513
+ snow ai chat --output ./my-app # save all builds to a specific directory
514
+ ```
515
+
516
+ **In-session commands:**
517
+
518
+ | Command | Action |
519
+ |---|---|
520
+ | `/status` | Show the current build summary and artifact list |
521
+ | `/save` | Write the current XML and manifest to disk |
522
+ | `/push` | Push the current build to the active ServiceNow instance |
523
+ | `/clear` | Reset the session (clears history and current build) |
524
+ | `/exit` | Quit |
525
+
526
+ After each generation, the CLI prompts whether to push to the active instance (unless `--push` is set, in which case it pushes automatically).
527
+
528
+ **Example session:**
529
+ ```
530
+ You > I want to build an incident auto-assignment feature
531
+
532
+ AI > To generate the right artifacts, a few questions:
533
+ 1. Which teams/groups should incidents be routed to?
534
+ 2. What fields determine the routing — category, urgency, location, or something else?
535
+ 3. Should assignment happen on insert only, or also on update?
536
+
537
+ You > Route by category: Network → Network Ops, Software → App Support.
538
+ Assignment on insert only.
539
+
540
+ AI > [generates script include + business rule]
541
+
542
+ + script_include IncidentRouter
543
+ + business_rule Auto-Assign Incident on Insert
544
+
545
+ ✔ incident-auto-assignment/
546
+ incident-auto-assignment.xml
547
+ incident-auto-assignment.manifest.json
548
+
549
+ Push 2 artifact(s) to dev (https://dev12345.service-now.com)? (y/N)
550
+
551
+ You > Also add a UI action button to manually re-trigger the routing
552
+
553
+ AI > [generates updated build with all three artifacts]
554
+
555
+ + script_include IncidentRouter (unchanged)
556
+ + business_rule Auto-Assign ... (unchanged)
557
+ + ui_action Re-Route Incident ← new
558
+ ```
559
+
560
+ #### `snow ai review <path>`
561
+
562
+ Review and edit a previously generated build. Opens an interactive artifact selector, shows code with line numbers, and lets you open any field in your editor. Changes are saved back to the XML and manifest immediately. After reviewing, you can optionally push the (modified) build to the active instance.
563
+
564
+ ```bash
565
+ # Review from a build directory
566
+ snow ai review ./incident-auto-assignment/
567
+
568
+ # Review from a manifest file
569
+ snow ai review ./incident-auto-assignment/incident-auto-assignment.manifest.json
570
+
571
+ # Review from the XML file (locates the sibling .manifest.json automatically)
572
+ snow ai review ./incident-auto-assignment/incident-auto-assignment.xml
573
+ ```
574
+
575
+ **Review workflow:**
576
+ 1. Select an artifact from the list
577
+ 2. The code is printed with line numbers
578
+ 3. Confirm to open in your editor (uses `$VISUAL`, `$EDITOR`, or auto-detected editor)
579
+ 4. Save and close the editor — changes are written back to disk immediately
580
+ 5. Select another artifact or choose **Done reviewing**
581
+ 6. Confirm whether to push the build to the active instance
582
+
583
+ #### `snow ai push <path>`
584
+
585
+ Push a previously generated build to the active instance via Table API.
586
+
587
+ ```bash
588
+ # Push from a build directory
589
+ snow ai push ./incident-auto-assignment/
590
+
591
+ # Push from a manifest file
592
+ snow ai push ./incident-auto-assignment/incident-auto-assignment.manifest.json
593
+ ```
594
+
595
+ **Push behaviour per artifact type:**
596
+
597
+ | Artifact | Strategy |
598
+ |---|---|
599
+ | script_include, business_rule, etc. | Looks up by name — creates or updates the single record |
600
+ | `table` | Upserts `sys_db_object`; upserts each `sys_dictionary` column by table+element; upserts `sys_choice` rows by table+element+value |
601
+ | `decision_table` | Upserts `sys_decision`; deletes and recreates all input columns and rules on update |
602
+ | `flow_action` | Upserts `sys_hub_action_type_definition`; deletes and recreates all input/output variables on update |
603
+ | Scoped build | Resolves or creates the `sys_app` record first; stamps `sys_scope`/`sys_package` on every record |
604
+
605
+ ---
606
+
607
+ ## Configuration File
608
+
609
+ All settings are stored in `~/.snow/config.json`. The directory is created with mode `0700` and the file with `0600`.
610
+
611
+ ```json
612
+ {
613
+ "activeInstance": "dev",
614
+ "instances": {
615
+ "dev": {
616
+ "alias": "dev",
617
+ "url": "https://dev12345.service-now.com",
618
+ "auth": {
619
+ "type": "basic",
620
+ "username": "admin",
621
+ "password": "your-password"
622
+ }
623
+ },
624
+ "prod": {
625
+ "alias": "prod",
626
+ "url": "https://prod.service-now.com",
627
+ "auth": {
628
+ "type": "oauth",
629
+ "clientId": "...",
630
+ "clientSecret": "...",
631
+ "accessToken": "...",
632
+ "tokenExpiry": 1700000000000
633
+ }
634
+ }
635
+ },
636
+ "ai": {
637
+ "activeProvider": "openai",
638
+ "providers": {
639
+ "openai": {
640
+ "model": "gpt-4o",
641
+ "apiKey": "sk-..."
642
+ },
643
+ "anthropic": {
644
+ "model": "claude-opus-4-6",
645
+ "apiKey": "sk-ant-..."
646
+ },
647
+ "xai": {
648
+ "model": "grok-3",
649
+ "apiKey": "xai-...",
650
+ "baseUrl": "https://api.x.ai/v1"
651
+ },
652
+ "ollama": {
653
+ "model": "llama3",
654
+ "baseUrl": "http://localhost:11434"
655
+ }
656
+ }
657
+ }
658
+ }
659
+ ```
660
+
661
+ ---
662
+
663
+ ## Development
664
+
665
+ ```bash
666
+ npm run dev # Watch mode — rebuilds on every file change
667
+ npm run build # One-time production build to dist/
668
+ ```
669
+
670
+ The entry point is `src/index.ts`. Commands live in `src/commands/`, shared utilities in `src/lib/`.
671
+
672
+ **Project structure:**
673
+ ```
674
+ src/
675
+ index.ts CLI entry point and command registration
676
+ commands/
677
+ instance.ts snow instance
678
+ table.ts snow table
679
+ schema.ts snow schema
680
+ script.ts snow script
681
+ provider.ts snow provider
682
+ ai.ts snow ai (build, chat, review, push)
683
+ lib/
684
+ config.ts Config file read/write + instance and provider helpers
685
+ client.ts ServiceNow HTTP client (axios, basic + OAuth auth)
686
+ llm.ts LLM provider abstraction (OpenAI, Anthropic, xAI, Ollama)
687
+ sn-context.ts ServiceNow system prompt and artifact type definitions
688
+ update-set.ts XML update set generation and Table API push
689
+ types/
690
+ index.ts Shared TypeScript interfaces
691
+ ```