@syndicalt/snow-cli 1.1.0 → 1.5.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 +380 -9
  2. package/dist/index.js +1376 -29
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # snow-cli
2
2
 
3
- A portable CLI for ServiceNow. Query tables, inspect schemas, edit script fields, and generate complete applications using AI — all from your terminal.
3
+ A portable CLI for ServiceNow. Query tables, inspect schemas, edit and search script fields, bulk-update records, manage users and groups, handle attachments, promote update sets across environments, and generate complete applications using AI — all from your terminal.
4
4
 
5
5
  - [Installation](#installation)
6
6
  - [Quick Start](#quick-start)
@@ -10,6 +10,11 @@ A portable CLI for ServiceNow. Query tables, inspect schemas, edit script fields
10
10
  - [snow schema](#snow-schema)
11
11
  - [snow schema map](#snow-schema-map)
12
12
  - [snow script](#snow-script)
13
+ - [snow bulk](#snow-bulk)
14
+ - [snow user](#snow-user)
15
+ - [snow attachment](#snow-attachment)
16
+ - [snow updateset](#snow-updateset)
17
+ - [snow status](#snow-status)
13
18
  - [snow provider](#snow-provider)
14
19
  - [snow ai](#snow-ai)
15
20
  - [Configuration File](#configuration-file)
@@ -46,16 +51,32 @@ snow instance add
46
51
  # 2. Query a table
47
52
  snow table get incident -q "active=true" -l 10 -f "number,short_description,state,assigned_to"
48
53
 
49
- # 3. Configure an AI provider
50
- snow provider set openai
54
+ # 3. Bulk-update records matching a query
55
+ snow bulk update incident -q "active=true^priority=1" --set assigned_to=admin --dry-run
51
56
 
52
- # 4. Generate a simple feature
53
- snow ai build "Create a script include that auto-routes incidents by category and urgency"
57
+ # 4. Pull a script field, edit it locally, push it back
58
+ snow script pull sys_script_include <sys_id> script
59
+
60
+ # 5. Search for a pattern across all scripts in an app scope
61
+ snow script search x_myapp --contains "GlideRecord('old_table')"
62
+
63
+ # 6. Manage update sets — list, export, and promote to another instance
64
+ snow updateset list
65
+ snow updateset export "Sprint 42" --out ./updatesets
66
+ snow updateset apply ./sprint-42.xml --target prod
67
+
68
+ # 7. Add a user to a group or assign a role
69
+ snow user add-to-group john.doe "Network Support"
70
+ snow user assign-role john.doe itil
54
71
 
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"
72
+ # 8. Download all attachments from a record
73
+ snow attachment pull incident <sys_id> --all --out ./downloads
57
74
 
58
- # 6. Start an interactive session to build iteratively
75
+ # 9. Configure an AI provider and generate a feature
76
+ snow provider set openai
77
+ snow ai build "Create a script include that auto-routes incidents by category and urgency"
78
+
79
+ # 10. Start an interactive session to build iteratively
59
80
  snow ai chat
60
81
  ```
61
82
 
@@ -331,6 +352,351 @@ snow script list
331
352
 
332
353
  Cached scripts are stored in `~/.snow/scripts/`.
333
354
 
355
+ #### `snow script search`
356
+
357
+ Search for a text pattern across script fields in a given app scope. Searches Script Includes, Business Rules, Client Scripts, UI Actions, UI Pages (HTML, client, and server scripts), and Scheduled Jobs.
358
+
359
+ ```bash
360
+ # Find all scripts containing a string
361
+ snow script search x_myapp --contains "GlideRecord('incident')"
362
+
363
+ # Search only specific tables
364
+ snow script search x_myapp --contains "oldMethod" --tables sys_script_include,sys_script
365
+
366
+ # Use a JavaScript regex
367
+ snow script search x_myapp --contains "gs\.(log|warn)" --regex
368
+ ```
369
+
370
+ Results show the record name, sys_id, and matching lines with line numbers (up to 5 preview lines per record).
371
+
372
+ **Options:**
373
+
374
+ | Flag | Description |
375
+ |---|---|
376
+ | `-c, --contains <pattern>` | Text or regex pattern to search for (required) |
377
+ | `-t, --tables <tables>` | Comma-separated table list (default: all 8 script tables) |
378
+ | `--regex` | Treat `--contains` as a JavaScript regex |
379
+ | `-l, --limit <n>` | Max records per table (default: `500`) |
380
+
381
+ #### `snow script replace`
382
+
383
+ Find and replace text across script fields in an app scope. Supports dry-run preview before committing changes.
384
+
385
+ ```bash
386
+ # Preview what would change
387
+ snow script replace x_myapp --find "gs.log" --replace "gs.info" --dry-run
388
+
389
+ # Replace with confirmation prompt
390
+ snow script replace x_myapp --find "gs.log" --replace "gs.info"
391
+
392
+ # Replace with regex and skip confirmation
393
+ snow script replace x_myapp --find "GlideRecord\('old_table'\)" --replace "GlideRecord('new_table')" --regex --yes
394
+
395
+ # Target only specific tables
396
+ snow script replace x_myapp --find "deprecated.util" --replace "NewUtils" --tables sys_script_include
397
+ ```
398
+
399
+ **Options:**
400
+
401
+ | Flag | Description |
402
+ |---|---|
403
+ | `-f, --find <pattern>` | Text to find (required) |
404
+ | `-r, --replace <text>` | Replacement text (required) |
405
+ | `-t, --tables <tables>` | Comma-separated table list (default: all 8 script tables) |
406
+ | `--regex` | Treat `--find` as a JavaScript regex |
407
+ | `-l, --limit <n>` | Max records per table (default: `500`) |
408
+ | `--dry-run` | Show matches without writing any changes |
409
+ | `--yes` | Skip confirmation prompt |
410
+
411
+ ---
412
+
413
+ ### `snow bulk`
414
+
415
+ Bulk update multiple records in one command. Fetches matching records, shows a preview, asks for confirmation, then patches each record.
416
+
417
+ ```bash
418
+ # Preview affected records without making changes
419
+ snow bulk update incident -q "active=true^priority=1" --set state=2 --dry-run
420
+
421
+ # Update with confirmation prompt
422
+ snow bulk update incident -q "active=true^priority=1" --set state=2 --set assigned_to=admin
423
+
424
+ # Skip confirmation (useful in scripts)
425
+ snow bulk update sys_user -q "department=IT^active=true" --set location=NYC --yes
426
+
427
+ # Cap the number of records updated
428
+ snow bulk update incident -q "active=true" --set impact=2 --limit 50
429
+ ```
430
+
431
+ **Options:**
432
+
433
+ | Flag | Description |
434
+ |---|---|
435
+ | `-q, --query <query>` | ServiceNow encoded query to select records (required) |
436
+ | `-s, --set <field=value>` | Field assignment — repeat for multiple fields (required) |
437
+ | `-l, --limit <n>` | Max records to update (default: `200`) |
438
+ | `--dry-run` | Show preview without making changes |
439
+ | `--yes` | Skip confirmation prompt |
440
+
441
+ The preview table shows the sys_id, display name, and new values for every record that will be updated.
442
+
443
+ ---
444
+
445
+ ### `snow user`
446
+
447
+ Manage group membership and role assignments for ServiceNow users. Users can be specified by `user_name`, email, display name, or sys_id.
448
+
449
+ ```bash
450
+ # Add a user to a group
451
+ snow user add-to-group john.doe "Network Support"
452
+ snow user add-to-group john.doe@example.com "IT Operations" --yes
453
+
454
+ # Remove a user from a group
455
+ snow user remove-from-group john.doe "Network Support"
456
+
457
+ # Assign a role to a user
458
+ snow user assign-role john.doe itil
459
+
460
+ # Remove a role from a user
461
+ snow user remove-role john.doe itil --yes
462
+ ```
463
+
464
+ Each command resolves the user and target, checks for existing membership/role to prevent duplicates, then prompts for confirmation before making any change.
465
+
466
+ | Command | Description |
467
+ |---|---|
468
+ | `snow user add-to-group <user> <group>` | Add user to a `sys_user_group` |
469
+ | `snow user remove-from-group <user> <group>` | Remove user from a `sys_user_group` |
470
+ | `snow user assign-role <user> <role>` | Grant a `sys_user_role` to a user |
471
+ | `snow user remove-role <user> <role>` | Revoke a `sys_user_role` from a user |
472
+
473
+ All subcommands accept `--yes` to skip the confirmation prompt.
474
+
475
+ ---
476
+
477
+ ### `snow attachment`
478
+
479
+ Download and upload file attachments on ServiceNow records via the Attachment API. Also available as `snow att`.
480
+
481
+ ```bash
482
+ # List attachments on a record
483
+ snow attachment list incident <sys_id>
484
+ snow att ls incident <sys_id>
485
+
486
+ # Download all attachments to a directory
487
+ snow attachment pull incident <sys_id> --all --out ./downloads
488
+
489
+ # Download a specific attachment by file name
490
+ snow attachment pull incident <sys_id> --name report.pdf
491
+
492
+ # Upload a file as an attachment
493
+ snow attachment push incident <sys_id> ./fix-notes.pdf
494
+
495
+ # Override the auto-detected Content-Type
496
+ snow attachment push incident <sys_id> ./data.bin --type application/octet-stream
497
+ ```
498
+
499
+ **`snow attachment pull` options:**
500
+
501
+ | Flag | Description |
502
+ |---|---|
503
+ | `-a, --all` | Download all attachments on the record |
504
+ | `-n, --name <file_name>` | Download a specific attachment by its file name |
505
+ | `-o, --out <dir>` | Output directory (default: current directory) |
506
+
507
+ **`snow attachment push` options:**
508
+
509
+ | Flag | Description |
510
+ |---|---|
511
+ | `-t, --type <content-type>` | Override the Content-Type header (auto-detected from extension by default) |
512
+
513
+ Content-Type is inferred from the file extension for common formats (PDF, PNG, JPG, CSV, XML, JSON, ZIP, DOCX, XLSX, etc.). Defaults to `application/octet-stream` for unknown types.
514
+
515
+ ---
516
+
517
+ ### `snow updateset`
518
+
519
+ Manage ServiceNow update sets from the CLI — list, inspect, export, import, and diff. Also available as `snow us`.
520
+
521
+ | Command | Description |
522
+ |---|---|
523
+ | `snow updateset list` | List update sets on the instance |
524
+ | `snow updateset current` | Show the currently active update set |
525
+ | `snow updateset set <name>` | Set the active update set |
526
+ | `snow updateset show <name>` | Show details and all captured items |
527
+ | `snow updateset capture <name> --add <table:sys_id>` | Add specific records to an update set |
528
+ | `snow updateset export <name>` | Download the update set as an XML file |
529
+ | `snow updateset apply <xml-file>` | Upload an XML file to another instance |
530
+ | `snow updateset diff <set1> <set2>` | Compare captured items between two update sets |
531
+
532
+ Names or sys_ids are accepted wherever `<name>` appears.
533
+
534
+ #### `snow updateset list`
535
+
536
+ ```bash
537
+ # All in-progress and complete update sets (default: excludes "ignore")
538
+ snow updateset list
539
+
540
+ # Filter by state
541
+ snow updateset list --state "in progress"
542
+ snow updateset list --state complete --limit 20
543
+ ```
544
+
545
+ **Options:**
546
+
547
+ | Flag | Description |
548
+ |---|---|
549
+ | `-s, --state <state>` | Filter by state: `in progress`, `complete`, `ignore` (default: all except `ignore`) |
550
+ | `-l, --limit <n>` | Max results (default: `50`) |
551
+
552
+ Output columns: **Name**, **State**, **Application** (scope), **Created by**, **Created on**. In-progress sets are highlighted in green; the active set is marked with a ★.
553
+
554
+ #### `snow updateset current`
555
+
556
+ ```bash
557
+ snow updateset current
558
+ ```
559
+
560
+ Shows the update set that is currently active for the authenticated user (read from `sys_user_preference`). REST API writes go to this update set.
561
+
562
+ #### `snow updateset set <name>`
563
+
564
+ ```bash
565
+ snow updateset set "Sprint 42 - Incident fixes"
566
+ snow updateset set a1b2c3d4e5f6... # sys_id also accepted
567
+ ```
568
+
569
+ Stores the selection in `sys_user_preference` so subsequent REST API operations (table updates, script pushes, etc.) are captured into the selected update set.
570
+
571
+ #### `snow updateset show <name>`
572
+
573
+ ```bash
574
+ snow updateset show "Sprint 42 - Incident fixes"
575
+ snow updateset show "Sprint 42 - Incident fixes" --limit 200
576
+ ```
577
+
578
+ Displays update set metadata followed by a table of every captured item (`sys_update_xml`) with type, action, and target name.
579
+
580
+ #### `snow updateset capture <name> --add <table:sys_id>`
581
+
582
+ Force-captures specific records into an update set without modifying them:
583
+
584
+ ```bash
585
+ # Capture a single record
586
+ snow updateset capture "My Update Set" --add sys_script_include:abc123...
587
+
588
+ # Capture multiple records at once
589
+ snow updateset capture "My Update Set" \
590
+ --add sys_script_include:abc123... \
591
+ --add sys_script:def456... \
592
+ --yes
593
+ ```
594
+
595
+ **How it works:** temporarily activates the target update set for the authenticated user, performs a no-op PATCH on each record to trigger ServiceNow's capture mechanism, then restores the previously active update set. The records themselves are not changed.
596
+
597
+ #### `snow updateset export <name>`
598
+
599
+ ```bash
600
+ # Export to current directory
601
+ snow updateset export "Sprint 42 - Incident fixes"
602
+
603
+ # Export to a specific directory
604
+ snow updateset export "Sprint 42 - Incident fixes" --out ./updatesets
605
+ ```
606
+
607
+ Calls `/export_update_set.do` and saves the XML to `<safe-name>.xml`. The file can be imported into any ServiceNow instance using `snow updateset apply` or via the ServiceNow UI.
608
+
609
+ #### `snow updateset apply <xml-file>`
610
+
611
+ Import an update set XML into an instance. Creates a **Retrieved Update Set** record that you then load, preview, and commit.
612
+
613
+ ```bash
614
+ # Apply to the active instance
615
+ snow updateset apply ./sprint-42-incident-fixes.xml
616
+
617
+ # Apply to a different instance by alias
618
+ snow updateset apply ./sprint-42-incident-fixes.xml --target prod
619
+
620
+ # Skip confirmation
621
+ snow updateset apply ./sprint-42-incident-fixes.xml --target prod --yes
622
+ ```
623
+
624
+ After uploading, the CLI prints the direct link to the Retrieved Update Set record and instructions for the load → preview → commit steps, which must be completed in the ServiceNow UI (or scripted separately).
625
+
626
+ #### `snow updateset diff <set1> <set2>`
627
+
628
+ Compare the captured items of two update sets side by side:
629
+
630
+ ```bash
631
+ snow updateset diff "Sprint 42" "Sprint 43"
632
+ snow updateset diff a1b2c3... b4c5d6... # sys_ids
633
+ ```
634
+
635
+ Output shows:
636
+ - Items only in the first set (removed in second) — in red
637
+ - Items only in the second set (added in second) — in green
638
+ - Items in both sets, flagged if the action changed (e.g. `INSERT_OR_UPDATE` → `DELETE`) — in yellow
639
+ - A summary line: `3 removed 5 added 1 changed 42 unchanged`
640
+
641
+ ---
642
+
643
+ ### `snow status`
644
+
645
+ Print a dashboard-style health and stats overview of the active instance. All sections run in parallel and degrade gracefully to `N/A` when the authenticated user lacks access.
646
+
647
+ ```bash
648
+ snow status
649
+
650
+ # Omit syslog sections (faster for non-admin users, or when syslog is restricted)
651
+ snow status --no-errors
652
+ ```
653
+
654
+ **Sections:**
655
+
656
+ | Section | What it shows |
657
+ |---|---|
658
+ | **Instance** | ServiceNow version (`glide.version`), cluster node count and status |
659
+ | **Users** | Total active user count |
660
+ | **Development** | Custom scoped app count, custom table count (`x_` prefix), in-progress update sets (up to 5, with author) |
661
+ | **Syslog errors** | Error count in the last hour + last 3 error messages with timestamps |
662
+ | **Scheduler errors** | Failed scheduled job count in the last 24h + last 3 messages |
663
+
664
+ **Example output:**
665
+ ```
666
+ ────────────────────────────────────────────────────
667
+ snow-cli · dev (https://dev12345.service-now.com)
668
+ ────────────────────────────────────────────────────
669
+
670
+ Instance
671
+ ────────
672
+ Version Utah Patch 7
673
+ Cluster nodes 3 active / 3 total
674
+
675
+ Users
676
+ ─────
677
+ Active users 1,234
678
+
679
+ Development
680
+ ───────────
681
+ Custom apps 5
682
+ Custom tables 34
683
+ Update sets 2 in progress
684
+ • My Feature Branch admin
685
+ • Hotfix-001 dev.user
686
+
687
+ Syslog errors (last hour)
688
+ ──────────────────────────
689
+ Error count 3
690
+ [10:34:01] Script error in BusinessRule 'Assign P...
691
+ [10:22:45] Invalid GlideRecord field: assigne_to
692
+
693
+ Scheduler errors (last 24h)
694
+ ────────────────────────────
695
+ Failed jobs 0
696
+ ```
697
+
698
+ > **Note:** Version and cluster node stats require admin access to `sys_properties` and `sys_cluster_state`. Syslog sections require read access to the `syslog` table. Sections that can't be read are shown as `N/A` rather than failing the command.
699
+
334
700
  ---
335
701
 
336
702
  ### `snow provider`
@@ -677,7 +1043,12 @@ src/
677
1043
  instance.ts snow instance
678
1044
  table.ts snow table
679
1045
  schema.ts snow schema
680
- script.ts snow script
1046
+ script.ts snow script (pull/push/list/search/replace)
1047
+ bulk.ts snow bulk (update)
1048
+ user.ts snow user (add-to-group/remove-from-group/assign-role/remove-role)
1049
+ attachment.ts snow attachment (list/pull/push)
1050
+ updateset.ts snow updateset (list/current/set/show/capture/export/apply/diff)
1051
+ status.ts snow status
681
1052
  provider.ts snow provider
682
1053
  ai.ts snow ai (build, chat, review, push)
683
1054
  lib/