@syndicalt/snow-cli 1.1.0 → 2.0.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 +901 -8
  2. package/dist/index.js +6237 -2853
  3. package/package.json +2 -2
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, browse the Service Catalog, inspect Flow Designer flows, manage scoped applications, tail system logs, 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,17 @@ 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)
18
+ - [snow diff](#snow-diff)
19
+ - [snow factory](#snow-factory)
20
+ - [snow catalog](#snow-catalog)
21
+ - [snow flow](#snow-flow)
22
+ - [snow app](#snow-app)
23
+ - [snow log](#snow-log)
13
24
  - [snow provider](#snow-provider)
14
25
  - [snow ai](#snow-ai)
15
26
  - [Configuration File](#configuration-file)
@@ -46,17 +57,60 @@ snow instance add
46
57
  # 2. Query a table
47
58
  snow table get incident -q "active=true" -l 10 -f "number,short_description,state,assigned_to"
48
59
 
49
- # 3. Configure an AI provider
50
- snow provider set openai
60
+ # 3. Bulk-update records matching a query
61
+ snow bulk update incident -q "active=true^priority=1" --set assigned_to=admin --dry-run
62
+
63
+ # 4. Pull a script field, edit it locally, push it back
64
+ snow script pull sys_script_include <sys_id> script
65
+
66
+ # 5. Search for a pattern across all scripts in an app scope
67
+ snow script search x_myapp --contains "GlideRecord('old_table')"
68
+
69
+ # 6. Manage update sets — list, export, and promote to another instance
70
+ snow updateset list
71
+ snow updateset export "Sprint 42" --out ./updatesets
72
+ snow updateset apply ./sprint-42.xml --target prod
73
+
74
+ # 7. Add a user to a group or assign a role
75
+ snow user add-to-group john.doe "Network Support"
76
+ snow user assign-role john.doe itil
51
77
 
52
- # 4. Generate a simple feature
78
+ # 8. Download all attachments from a record
79
+ snow attachment pull incident <sys_id> --all --out ./downloads
80
+
81
+ # 9. Configure an AI provider and generate a feature
82
+ snow provider set openai
53
83
  snow ai build "Create a script include that auto-routes incidents by category and urgency"
54
84
 
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"
85
+ # 10. Compare schema/scripts between instances to detect drift
86
+ snow diff incident --against prod --fields
87
+ snow diff all --against test --scripts --scope x_myco_myapp
88
+
89
+ # 11. Run the full factory pipeline: plan → build → test → promote
90
+ snow factory "Build a hardware asset request app with approval workflow" --envs test,prod
57
91
 
58
- # 6. Start an interactive session to build iteratively
92
+ # 12. Start an interactive session to build iteratively
59
93
  snow ai chat
94
+
95
+ # 13. Browse the Service Catalog
96
+ snow catalog list
97
+ snow catalog search "VPN"
98
+ snow catalog get "Request VPN Access"
99
+
100
+ # 14. Inspect Flow Designer flows and actions
101
+ snow flow list
102
+ snow flow list --subflows --scope x_myco_myapp
103
+ snow flow get "My Approval Flow"
104
+
105
+ # 15. List scoped applications
106
+ snow app list
107
+ snow app get x_myco_myapp
108
+
109
+ # 16. Tail system logs
110
+ snow log
111
+ snow log --level err --follow
112
+ snow log app --scope x_myco_myapp
113
+ snow log tx --slow 2000
60
114
  ```
61
115
 
62
116
  ---
@@ -331,6 +385,833 @@ snow script list
331
385
 
332
386
  Cached scripts are stored in `~/.snow/scripts/`.
333
387
 
388
+ #### `snow script search`
389
+
390
+ 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.
391
+
392
+ ```bash
393
+ # Find all scripts containing a string
394
+ snow script search x_myapp --contains "GlideRecord('incident')"
395
+
396
+ # Search only specific tables
397
+ snow script search x_myapp --contains "oldMethod" --tables sys_script_include,sys_script
398
+
399
+ # Use a JavaScript regex
400
+ snow script search x_myapp --contains "gs\.(log|warn)" --regex
401
+ ```
402
+
403
+ Results show the record name, sys_id, and matching lines with line numbers (up to 5 preview lines per record).
404
+
405
+ **Options:**
406
+
407
+ | Flag | Description |
408
+ |---|---|
409
+ | `-c, --contains <pattern>` | Text or regex pattern to search for (required) |
410
+ | `-t, --tables <tables>` | Comma-separated table list (default: all 8 script tables) |
411
+ | `--regex` | Treat `--contains` as a JavaScript regex |
412
+ | `-l, --limit <n>` | Max records per table (default: `500`) |
413
+
414
+ #### `snow script replace`
415
+
416
+ Find and replace text across script fields in an app scope. Supports dry-run preview before committing changes.
417
+
418
+ ```bash
419
+ # Preview what would change
420
+ snow script replace x_myapp --find "gs.log" --replace "gs.info" --dry-run
421
+
422
+ # Replace with confirmation prompt
423
+ snow script replace x_myapp --find "gs.log" --replace "gs.info"
424
+
425
+ # Replace with regex and skip confirmation
426
+ snow script replace x_myapp --find "GlideRecord\('old_table'\)" --replace "GlideRecord('new_table')" --regex --yes
427
+
428
+ # Target only specific tables
429
+ snow script replace x_myapp --find "deprecated.util" --replace "NewUtils" --tables sys_script_include
430
+ ```
431
+
432
+ **Options:**
433
+
434
+ | Flag | Description |
435
+ |---|---|
436
+ | `-f, --find <pattern>` | Text to find (required) |
437
+ | `-r, --replace <text>` | Replacement text (required) |
438
+ | `-t, --tables <tables>` | Comma-separated table list (default: all 8 script tables) |
439
+ | `--regex` | Treat `--find` as a JavaScript regex |
440
+ | `-l, --limit <n>` | Max records per table (default: `500`) |
441
+ | `--dry-run` | Show matches without writing any changes |
442
+ | `--yes` | Skip confirmation prompt |
443
+
444
+ ---
445
+
446
+ ### `snow bulk`
447
+
448
+ Bulk update multiple records in one command. Fetches matching records, shows a preview, asks for confirmation, then patches each record.
449
+
450
+ ```bash
451
+ # Preview affected records without making changes
452
+ snow bulk update incident -q "active=true^priority=1" --set state=2 --dry-run
453
+
454
+ # Update with confirmation prompt
455
+ snow bulk update incident -q "active=true^priority=1" --set state=2 --set assigned_to=admin
456
+
457
+ # Skip confirmation (useful in scripts)
458
+ snow bulk update sys_user -q "department=IT^active=true" --set location=NYC --yes
459
+
460
+ # Cap the number of records updated
461
+ snow bulk update incident -q "active=true" --set impact=2 --limit 50
462
+ ```
463
+
464
+ **Options:**
465
+
466
+ | Flag | Description |
467
+ |---|---|
468
+ | `-q, --query <query>` | ServiceNow encoded query to select records (required) |
469
+ | `-s, --set <field=value>` | Field assignment — repeat for multiple fields (required) |
470
+ | `-l, --limit <n>` | Max records to update (default: `200`) |
471
+ | `--dry-run` | Show preview without making changes |
472
+ | `--yes` | Skip confirmation prompt |
473
+
474
+ The preview table shows the sys_id, display name, and new values for every record that will be updated.
475
+
476
+ ---
477
+
478
+ ### `snow user`
479
+
480
+ Manage group membership and role assignments for ServiceNow users. Users can be specified by `user_name`, email, display name, or sys_id.
481
+
482
+ ```bash
483
+ # Add a user to a group
484
+ snow user add-to-group john.doe "Network Support"
485
+ snow user add-to-group john.doe@example.com "IT Operations" --yes
486
+
487
+ # Remove a user from a group
488
+ snow user remove-from-group john.doe "Network Support"
489
+
490
+ # Assign a role to a user
491
+ snow user assign-role john.doe itil
492
+
493
+ # Remove a role from a user
494
+ snow user remove-role john.doe itil --yes
495
+ ```
496
+
497
+ Each command resolves the user and target, checks for existing membership/role to prevent duplicates, then prompts for confirmation before making any change.
498
+
499
+ | Command | Description |
500
+ |---|---|
501
+ | `snow user add-to-group <user> <group>` | Add user to a `sys_user_group` |
502
+ | `snow user remove-from-group <user> <group>` | Remove user from a `sys_user_group` |
503
+ | `snow user assign-role <user> <role>` | Grant a `sys_user_role` to a user |
504
+ | `snow user remove-role <user> <role>` | Revoke a `sys_user_role` from a user |
505
+
506
+ All subcommands accept `--yes` to skip the confirmation prompt.
507
+
508
+ ---
509
+
510
+ ### `snow attachment`
511
+
512
+ Download and upload file attachments on ServiceNow records via the Attachment API. Also available as `snow att`.
513
+
514
+ ```bash
515
+ # List attachments on a record
516
+ snow attachment list incident <sys_id>
517
+ snow att ls incident <sys_id>
518
+
519
+ # Download all attachments to a directory
520
+ snow attachment pull incident <sys_id> --all --out ./downloads
521
+
522
+ # Download a specific attachment by file name
523
+ snow attachment pull incident <sys_id> --name report.pdf
524
+
525
+ # Upload a file as an attachment
526
+ snow attachment push incident <sys_id> ./fix-notes.pdf
527
+
528
+ # Override the auto-detected Content-Type
529
+ snow attachment push incident <sys_id> ./data.bin --type application/octet-stream
530
+ ```
531
+
532
+ **`snow attachment pull` options:**
533
+
534
+ | Flag | Description |
535
+ |---|---|
536
+ | `-a, --all` | Download all attachments on the record |
537
+ | `-n, --name <file_name>` | Download a specific attachment by its file name |
538
+ | `-o, --out <dir>` | Output directory (default: current directory) |
539
+
540
+ **`snow attachment push` options:**
541
+
542
+ | Flag | Description |
543
+ |---|---|
544
+ | `-t, --type <content-type>` | Override the Content-Type header (auto-detected from extension by default) |
545
+
546
+ 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.
547
+
548
+ ---
549
+
550
+ ### `snow updateset`
551
+
552
+ Manage ServiceNow update sets from the CLI — list, inspect, export, import, and diff. Also available as `snow us`.
553
+
554
+ | Command | Description |
555
+ |---|---|
556
+ | `snow updateset list` | List update sets on the instance |
557
+ | `snow updateset current` | Show the currently active update set |
558
+ | `snow updateset set <name>` | Set the active update set |
559
+ | `snow updateset show <name>` | Show details and all captured items |
560
+ | `snow updateset capture <name> --add <table:sys_id>` | Add specific records to an update set |
561
+ | `snow updateset export <name>` | Download the update set as an XML file |
562
+ | `snow updateset apply <xml-file>` | Upload an XML file to another instance |
563
+ | `snow updateset diff <set1> <set2>` | Compare captured items between two update sets |
564
+
565
+ Names or sys_ids are accepted wherever `<name>` appears.
566
+
567
+ #### `snow updateset list`
568
+
569
+ ```bash
570
+ # All in-progress and complete update sets (default: excludes "ignore")
571
+ snow updateset list
572
+
573
+ # Filter by state
574
+ snow updateset list --state "in progress"
575
+ snow updateset list --state complete --limit 20
576
+ ```
577
+
578
+ **Options:**
579
+
580
+ | Flag | Description |
581
+ |---|---|
582
+ | `-s, --state <state>` | Filter by state: `in progress`, `complete`, `ignore` (default: all except `ignore`) |
583
+ | `-l, --limit <n>` | Max results (default: `50`) |
584
+
585
+ Output columns: **Name**, **State**, **Application** (scope), **Created by**, **Created on**. In-progress sets are highlighted in green; the active set is marked with a ★.
586
+
587
+ #### `snow updateset current`
588
+
589
+ ```bash
590
+ snow updateset current
591
+ ```
592
+
593
+ 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.
594
+
595
+ #### `snow updateset set <name>`
596
+
597
+ ```bash
598
+ snow updateset set "Sprint 42 - Incident fixes"
599
+ snow updateset set a1b2c3d4e5f6... # sys_id also accepted
600
+ ```
601
+
602
+ Stores the selection in `sys_user_preference` so subsequent REST API operations (table updates, script pushes, etc.) are captured into the selected update set.
603
+
604
+ #### `snow updateset show <name>`
605
+
606
+ ```bash
607
+ snow updateset show "Sprint 42 - Incident fixes"
608
+ snow updateset show "Sprint 42 - Incident fixes" --limit 200
609
+ ```
610
+
611
+ Displays update set metadata followed by a table of every captured item (`sys_update_xml`) with type, action, and target name.
612
+
613
+ #### `snow updateset capture <name> --add <table:sys_id>`
614
+
615
+ Force-captures specific records into an update set without modifying them:
616
+
617
+ ```bash
618
+ # Capture a single record
619
+ snow updateset capture "My Update Set" --add sys_script_include:abc123...
620
+
621
+ # Capture multiple records at once
622
+ snow updateset capture "My Update Set" \
623
+ --add sys_script_include:abc123... \
624
+ --add sys_script:def456... \
625
+ --yes
626
+ ```
627
+
628
+ **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.
629
+
630
+ #### `snow updateset export <name>`
631
+
632
+ ```bash
633
+ # Export to current directory
634
+ snow updateset export "Sprint 42 - Incident fixes"
635
+
636
+ # Export to a specific directory
637
+ snow updateset export "Sprint 42 - Incident fixes" --out ./updatesets
638
+ ```
639
+
640
+ 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.
641
+
642
+ #### `snow updateset apply <xml-file>`
643
+
644
+ Import an update set XML into an instance. Creates a **Retrieved Update Set** record that you then load, preview, and commit.
645
+
646
+ ```bash
647
+ # Apply to the active instance
648
+ snow updateset apply ./sprint-42-incident-fixes.xml
649
+
650
+ # Apply to a different instance by alias
651
+ snow updateset apply ./sprint-42-incident-fixes.xml --target prod
652
+
653
+ # Skip confirmation
654
+ snow updateset apply ./sprint-42-incident-fixes.xml --target prod --yes
655
+ ```
656
+
657
+ 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).
658
+
659
+ #### `snow updateset diff <set1> <set2>`
660
+
661
+ Compare the captured items of two update sets side by side:
662
+
663
+ ```bash
664
+ snow updateset diff "Sprint 42" "Sprint 43"
665
+ snow updateset diff a1b2c3... b4c5d6... # sys_ids
666
+ ```
667
+
668
+ Output shows:
669
+ - Items only in the first set (removed in second) — in red
670
+ - Items only in the second set (added in second) — in green
671
+ - Items in both sets, flagged if the action changed (e.g. `INSERT_OR_UPDATE` → `DELETE`) — in yellow
672
+ - A summary line: `3 removed 5 added 1 changed 42 unchanged`
673
+
674
+ ---
675
+
676
+ ### `snow status`
677
+
678
+ 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.
679
+
680
+ ```bash
681
+ snow status
682
+
683
+ # Omit syslog sections (faster for non-admin users, or when syslog is restricted)
684
+ snow status --no-errors
685
+ ```
686
+
687
+ **Sections:**
688
+
689
+ | Section | What it shows |
690
+ |---|---|
691
+ | **Instance** | ServiceNow version (`glide.version`), cluster node count and status |
692
+ | **Users** | Total active user count |
693
+ | **Development** | Custom scoped app count, custom table count (`x_` prefix), in-progress update sets (up to 5, with author) |
694
+ | **Syslog errors** | Error count in the last hour + last 3 error messages with timestamps |
695
+ | **Scheduler errors** | Failed scheduled job count in the last 24h + last 3 messages |
696
+
697
+ **Example output:**
698
+ ```
699
+ ────────────────────────────────────────────────────
700
+ snow-cli · dev (https://dev12345.service-now.com)
701
+ ────────────────────────────────────────────────────
702
+
703
+ Instance
704
+ ────────
705
+ Version Utah Patch 7
706
+ Cluster nodes 3 active / 3 total
707
+
708
+ Users
709
+ ─────
710
+ Active users 1,234
711
+
712
+ Development
713
+ ───────────
714
+ Custom apps 5
715
+ Custom tables 34
716
+ Update sets 2 in progress
717
+ • My Feature Branch admin
718
+ • Hotfix-001 dev.user
719
+
720
+ Syslog errors (last hour)
721
+ ──────────────────────────
722
+ Error count 3
723
+ [10:34:01] Script error in BusinessRule 'Assign P...
724
+ [10:22:45] Invalid GlideRecord field: assigne_to
725
+
726
+ Scheduler errors (last 24h)
727
+ ────────────────────────────
728
+ Failed jobs 0
729
+ ```
730
+
731
+ > **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.
732
+
733
+ ---
734
+
735
+ ### `snow diff`
736
+
737
+ Compare schema field definitions and script content between two configured instances. Useful for detecting drift — fields added/removed/changed, or scripts that diverged between dev and test/prod.
738
+
739
+ ```bash
740
+ # Compare field definitions for a table
741
+ snow diff incident --against prod --fields
742
+
743
+ # Compare script content in an app scope between dev and test
744
+ snow diff all --against test --scripts --scope x_myco_myapp
745
+
746
+ # Compare both fields and scripts
747
+ snow diff sys_script_include --against prod --fields --scripts
748
+
749
+ # Output as Markdown (for pasting into docs or tickets)
750
+ snow diff incident --against prod --fields --markdown
751
+
752
+ # Output as JSON (for scripting or CI pipelines)
753
+ snow diff incident --against prod --fields --scripts --json
754
+
755
+ # Save the diff report to a file (ANSI stripped automatically)
756
+ snow diff all --against prod --scripts --scope x_myco_myapp --output ./diff-report.txt
757
+ ```
758
+
759
+ The source is always the **active instance** (`snow instance use <alias>` to set it). `--against` specifies the target instance alias.
760
+
761
+ **Arguments:**
762
+
763
+ | Argument | Description |
764
+ |---|---|
765
+ | `<table>` | Table to compare for `--fields`. Use `all` with `--scripts` to scan all script-bearing tables. |
766
+
767
+ **Options:**
768
+
769
+ | Flag | Description |
770
+ |---|---|
771
+ | `--against <alias>` | Target instance alias to compare against (required) |
772
+ | `--fields` | Compare `sys_dictionary` field definitions |
773
+ | `--scripts` | Compare script field content across script-bearing tables |
774
+ | `--scope <prefix>` | Filter scripts by application scope prefix (e.g. `x_myco_myapp`) |
775
+ | `--markdown` | Output as Markdown for docs/tickets |
776
+ | `--json` | Output structured JSON (fields rows + script hunks) |
777
+ | `--output <file>` | Write the diff to a file (ANSI color codes stripped automatically) |
778
+
779
+ At least one of `--fields` or `--scripts` is required.
780
+
781
+ #### Field diff output
782
+
783
+ Shows every field that was **added** (only in target), **removed** (only in source), or **changed** (type, max_length, mandatory, read_only, reference, or active flag differs):
784
+
785
+ ```
786
+ Schema diff: incident
787
+ ──────────────────────────────────────────────────
788
+ Field Status Detail
789
+ ──────────────────────────────────────────────────────────────────────────
790
+ x_myco_priority_code added type=string
791
+ x_myco_legacy_flag removed type=boolean
792
+ category changed max_length: 40 → 100
793
+ ```
794
+
795
+ #### Script diff output
796
+
797
+ For each script-bearing table, shows scripts **added** (only in target), **removed** (only in source), or **changed** (content differs), with a contextual line diff for changed scripts:
798
+
799
+ ```
800
+ Script diff: sys_script_include
801
+ ──────────────────────────────────────────────────
802
+ + NewUtils (only in prod)
803
+ - OldHelper (only in dev)
804
+ ~ IncidentRouter
805
+
806
+ IncidentRouter
807
+ --- dev
808
+ +++ prod
809
+ @@ lines 12–16 @@
810
+ var gr = new GlideRecord('incident');
811
+ - gr.addQuery('state', 1);
812
+ + gr.addQuery('state', 2);
813
+ gr.query();
814
+ ```
815
+
816
+ **Script tables scanned** (when using `--scripts`):
817
+
818
+ | Table | Description |
819
+ |---|---|
820
+ | `sys_script_include` | Script Includes |
821
+ | `sys_script` | Business Rules |
822
+ | `sys_script_client` | Client Scripts |
823
+ | `sys_ui_action` | UI Actions |
824
+ | `sysauto_script` | Scheduled Script Executions |
825
+
826
+ ---
827
+
828
+ ### `snow factory`
829
+
830
+ AI-orchestrated multi-component application pipeline. Takes a natural language description, breaks it into a dependency-ordered build plan, generates each component via LLM, pushes to the source instance, optionally generates and runs ATF tests, then promotes through additional environments.
831
+
832
+ ```bash
833
+ # Plan and build (deploys to active instance only)
834
+ snow factory "Build an employee onboarding app with custom tables, approval workflow, and email notifications"
835
+
836
+ # Full pipeline: dev → test → prod
837
+ snow factory "Build a hardware asset request app" --envs test,prod
838
+
839
+ # Force all artifacts into an existing application scope
840
+ snow factory "Add an approval business rule to the asset request app" --scope x_myco_assetreq
841
+
842
+ # Preview the plan without building
843
+ snow factory "Build an incident escalation app" --dry-run
844
+
845
+ # Generate and immediately run ATF tests
846
+ snow factory "Build a change approval workflow" --run-tests
847
+
848
+ # Skip ATF test generation (faster)
849
+ snow factory "Add a business rule to auto-assign P1 incidents" --skip-tests
850
+
851
+ # Resume a failed or interrupted run
852
+ snow factory "..." --resume abc12345
853
+
854
+ # List recent factory runs
855
+ snow factory "" --list
856
+ ```
857
+
858
+ **Options:**
859
+
860
+ | Flag | Description |
861
+ |---|---|
862
+ | `--envs <aliases>` | Comma-separated instance aliases to promote to after source, in order (e.g. `test,prod`) |
863
+ | `--scope <prefix>` | Override the application scope prefix for all artifacts (e.g. `x_myco_myapp`) |
864
+ | `--skip-tests` | Skip ATF test generation |
865
+ | `--run-tests` | Execute the generated ATF test suite immediately after pushing |
866
+ | `--dry-run` | Show the generated plan only — no builds, no deployments |
867
+ | `--resume <id>` | Resume a previous run from its checkpoint (see `--list`) |
868
+ | `--list` | Show recent factory runs and their component completion status |
869
+
870
+ #### Pipeline phases
871
+
872
+ ```
873
+ [1/N] Planning
874
+ LLM analyzes the prompt → structured plan with components, dependencies, risks
875
+ Displays plan for review → confirm before proceeding
876
+
877
+ [2/N] Building components
878
+ Each component is built sequentially in dependency order
879
+ Tables first, then script includes, then business rules / client scripts
880
+ Each component saved to ~/.snow/factory/<run-id>/<component>/
881
+
882
+ [3/N] Pushing to <source-instance>
883
+ All artifacts pushed to the active instance via Table API
884
+ Creates or updates existing records
885
+
886
+ [4/N] Generating ATF tests (unless --skip-tests)
887
+ LLM generates a test suite with server-side script assertions
888
+ Tests pushed to the instance as sys_atf_test + sys_atf_step records
889
+ Optionally executed if --run-tests is set
890
+
891
+ [5/N] Promoting to <env> (once per additional env in --envs)
892
+ Checks for pre-existing artifacts on the target
893
+ Confirms before applying
894
+ Uploads combined update set XML to sys_remote_update_set
895
+ Prints direct link → then Load → Preview → Commit in the UI
896
+ ```
897
+
898
+ #### Checkpointing and resume
899
+
900
+ Every factory run is checkpointed to `~/.snow/factory/<run-id>/state.json` after each completed phase. If a run is interrupted (network error, LLM failure, manual cancellation), resume it:
901
+
902
+ ```bash
903
+ snow factory "" --list # find the run ID
904
+ snow factory "" --resume abc12345 # resume from last successful phase
905
+ ```
906
+
907
+ The resume prompt argument is ignored when `--resume` is provided — the original prompt and plan are loaded from the checkpoint.
908
+
909
+ #### Example output
910
+
911
+ ```
912
+ ────────────────────────────────────────────────────────
913
+ snow factory · anthropic
914
+ Source: dev https://dev12345.service-now.com
915
+ Pipeline: dev → test → prod
916
+ ────────────────────────────────────────────────────────
917
+
918
+ [1/5] Planning
919
+ ────────────────────────────────────────────────────────
920
+ Employee Onboarding App
921
+ Automates new-hire onboarding with task assignment, document tracking, and notifications
922
+ scope: x_myco_onboard v1.0.0
923
+
924
+ Components (3) — ~14 artifacts
925
+ 1. Custom Tables (no deps)
926
+ Employee and HR document tracking tables
927
+ 2. Script Includes ← depends on: tables
928
+ OnboardingUtils class for task generation and notifications
929
+ 3. Business Rules ← depends on: tables, scripts
930
+ Auto-assign tasks on employee insert; notify on completion
931
+
932
+ ⚠ Risks:
933
+ • SMTP server must be configured for email notifications
934
+ • MID Server required for Active Directory sync
935
+
936
+ ? Execute factory pipeline? (3 components → dev → test → prod) Yes
937
+
938
+ [2/5] Building components
939
+ ────────────────────────────────────────────────────────
940
+ ✓ Custom Tables 2 artifacts
941
+ + table x_myco_onboard_employee
942
+ + table x_myco_onboard_doc
943
+ ✓ Script Includes 1 artifact
944
+ + script_include x_myco_onboard.OnboardingUtils
945
+ ✓ Business Rules 3 artifacts
946
+ + business_rule Auto-Assign Tasks on Insert
947
+ + business_rule Notify Manager on Completion
948
+ + scheduled_job Weekly Onboarding Report
949
+
950
+ ✔ 6 total artifacts combined
951
+
952
+ [3/5] Pushing to dev
953
+ ────────────────────────────────────────────────────────
954
+ created Table x_myco_onboard_employee
955
+ created Table x_myco_onboard_doc
956
+ created Script Include x_myco_onboard.OnboardingUtils
957
+ created Business Rule Auto-Assign Tasks on Insert
958
+ ...
959
+ 6 pushed, 0 failed
960
+
961
+ [4/5] Generating ATF tests
962
+ ────────────────────────────────────────────────────────
963
+ Employee Onboarding App — ATF Suite
964
+ 4 tests generated
965
+ • Test employee record creation and field defaults (3 steps)
966
+ • Test OnboardingUtils task generation (2 steps)
967
+ • Test business rule fires on insert (3 steps)
968
+ • Test manager notification trigger (2 steps)
969
+ ✓ Test suite created
970
+ https://dev12345.service-now.com/nav_to.do?uri=sys_atf_test_suite.do?sys_id=...
971
+ ```
972
+
973
+ #### Permission-denied errors
974
+
975
+ Some artifact types require elevated roles to push via the Table API:
976
+
977
+ | Artifact | Required role |
978
+ |---|---|
979
+ | `table` (`sys_db_object`) | `admin` or `delegated_developer` |
980
+ | `decision_table` (`sys_decision`) | `admin` or `developer` |
981
+ | `flow_action` (`sys_hub_action_type_definition`) | `flow_designer` + `IntegrationHub` |
982
+
983
+ When a 403 is encountered the artifact is **skipped** (shown in yellow) rather than failing the whole run. The generated update set XML is always written to disk regardless — use it to import via the UI when Table API access is restricted:
984
+
985
+ ```
986
+ System Update Sets → Retrieved Update Sets → Import XML → Load → Preview → Commit
987
+ ```
988
+
989
+ ---
990
+
991
+ ### `snow catalog`
992
+
993
+ Browse and search the ServiceNow Service Catalog.
994
+
995
+ ```bash
996
+ # List catalog items
997
+ snow catalog list
998
+ snow catalog list --category "Hardware"
999
+ snow catalog list --catalog "Employee Center" -l 50
1000
+
1001
+ # Search by name or description
1002
+ snow catalog search "VPN"
1003
+ snow catalog search "laptop" --limit 10
1004
+
1005
+ # Get details for a specific item (by name or sys_id)
1006
+ snow catalog get "Request VPN Access"
1007
+ snow catalog get abc1234...
1008
+
1009
+ # List catalog categories
1010
+ snow catalog categories
1011
+ snow catalog categories --catalog "IT Catalog"
1012
+ ```
1013
+
1014
+ **`snow catalog list` options:**
1015
+
1016
+ | Flag | Description |
1017
+ |---|---|
1018
+ | `-q, --query <encoded>` | Encoded query filter |
1019
+ | `--category <name>` | Filter by category name |
1020
+ | `--catalog <name>` | Filter by catalog title |
1021
+ | `-l, --limit <n>` | Max records (default: `25`) |
1022
+ | `--json` | Output as JSON |
1023
+
1024
+ **`snow catalog search` options:**
1025
+
1026
+ | Flag | Description |
1027
+ |---|---|
1028
+ | `-l, --limit <n>` | Max records (default: `20`) |
1029
+ | `--json` | Output as JSON |
1030
+
1031
+ **`snow catalog categories` options:**
1032
+
1033
+ | Flag | Description |
1034
+ |---|---|
1035
+ | `--catalog <name>` | Filter by catalog title |
1036
+ | `-l, --limit <n>` | Max records (default: `100`) |
1037
+ | `--json` | Output as JSON |
1038
+
1039
+ Sub-categories are indented based on their depth in the `full_name` hierarchy.
1040
+
1041
+ ---
1042
+
1043
+ ### `snow flow`
1044
+
1045
+ List and inspect Flow Designer flows, subflows, and custom actions.
1046
+
1047
+ ```bash
1048
+ # List flows
1049
+ snow flow list
1050
+ snow flow list --scope x_myco_myapp
1051
+ snow flow list -l 50
1052
+
1053
+ # List subflows instead
1054
+ snow flow list --subflows
1055
+ snow flow list --subflows --scope x_myco_myapp
1056
+
1057
+ # Get details and inputs for a specific flow (by name or sys_id)
1058
+ snow flow get "My Approval Flow"
1059
+ snow flow get abc1234...
1060
+
1061
+ # List custom Flow Designer actions
1062
+ snow flow actions
1063
+ snow flow actions --scope x_myco_myapp
1064
+ ```
1065
+
1066
+ **`snow flow list` options:**
1067
+
1068
+ | Flag | Description |
1069
+ |---|---|
1070
+ | `--subflows` | Show subflows instead of flows |
1071
+ | `--scope <prefix>` | Filter by application scope prefix |
1072
+ | `-q, --query <encoded>` | Additional encoded query filter |
1073
+ | `-l, --limit <n>` | Max records (default: `25`) |
1074
+ | `--json` | Output as JSON |
1075
+
1076
+ **`snow flow actions` options:**
1077
+
1078
+ | Flag | Description |
1079
+ |---|---|
1080
+ | `--scope <prefix>` | Filter by application scope prefix |
1081
+ | `-q, --query <encoded>` | Additional encoded query filter |
1082
+ | `-l, --limit <n>` | Max records (default: `25`) |
1083
+ | `--json` | Output as JSON |
1084
+
1085
+ `snow flow get` shows flow metadata, trigger type, run-as setting, and the list of typed input variables. It also prints the direct Flow Designer URL for the record.
1086
+
1087
+ Active flows are shown with a green `●`; inactive with a red `○`.
1088
+
1089
+ ---
1090
+
1091
+ ### `snow app`
1092
+
1093
+ List and inspect scoped applications on the active instance.
1094
+
1095
+ ```bash
1096
+ # List custom scoped applications (sys_app)
1097
+ snow app list
1098
+
1099
+ # Include all system scopes (sys_scope)
1100
+ snow app list --all
1101
+
1102
+ # Filter with an encoded query
1103
+ snow app list -q "vendor=Acme Corp"
1104
+
1105
+ # Get details for a specific app by scope prefix or name
1106
+ snow app get x_myco_myapp
1107
+ snow app get "My Custom App"
1108
+ snow app get abc1234... # sys_id also accepted
1109
+ ```
1110
+
1111
+ **`snow app list` options:**
1112
+
1113
+ | Flag | Description |
1114
+ |---|---|
1115
+ | `--all` | Include all system scopes, not just custom applications |
1116
+ | `-q, --query <encoded>` | Encoded query filter |
1117
+ | `-l, --limit <n>` | Max records (default: `50`) |
1118
+ | `--json` | Output as JSON |
1119
+
1120
+ `snow app get` shows scope prefix, sys_id, version, vendor, created/updated dates, and whether the scope has update set entries. It also prints helpful next-step commands for `snow factory` and `snow diff`.
1121
+
1122
+ ---
1123
+
1124
+ ### `snow log`
1125
+
1126
+ View system and application logs from the active instance.
1127
+
1128
+ ```bash
1129
+ # System log (default subcommand)
1130
+ snow log
1131
+ snow log system
1132
+ snow log --level err
1133
+ snow log --source Evaluator --limit 100
1134
+
1135
+ # Filter by scope
1136
+ snow log --scope x_myco_myapp
1137
+
1138
+ # Follow mode — polls for new entries every 5 seconds
1139
+ snow log --follow
1140
+ snow log --follow --interval 10000
1141
+
1142
+ # Application log (requires admin role)
1143
+ snow log app
1144
+ snow log app --scope x_myco_myapp
1145
+
1146
+ # Transaction log
1147
+ snow log tx
1148
+ snow log tx --slow 2000 # only show responses > 2000ms
1149
+ ```
1150
+
1151
+ #### `snow log system` (default)
1152
+
1153
+ Queries the `syslog` table. Output columns: timestamp, level, source, message.
1154
+
1155
+ | Flag | Description |
1156
+ |---|---|
1157
+ | `--level <level>` | Filter by level: `err`, `warn`, `info`, `debug` |
1158
+ | `--source <source>` | Filter by log source (e.g. `Evaluator`, `Script`) |
1159
+ | `--scope <prefix>` | Filter by application scope prefix |
1160
+ | `-q, --query <encoded>` | Additional encoded query filter |
1161
+ | `-l, --limit <n>` | Max records (default: `50`) |
1162
+ | `--follow` | Poll for new entries (Ctrl+C to stop) |
1163
+ | `--interval <ms>` | Polling interval in ms when using `--follow` (default: `5000`) |
1164
+ | `--json` | Output as JSON |
1165
+
1166
+ #### `snow log app`
1167
+
1168
+ Queries the `syslog_app_scope` table, which contains application-level log entries written by `gs.log()`, `gs.warn()`, etc. **Requires the `admin` role** — a clear error is shown if access is denied.
1169
+
1170
+ | Flag | Description |
1171
+ |---|---|
1172
+ | `--scope <prefix>` | Filter by application scope prefix |
1173
+ | `--source <source>` | Filter by log source |
1174
+ | `-l, --limit <n>` | Max records (default: `50`) |
1175
+ | `--follow` | Poll for new entries |
1176
+ | `--interval <ms>` | Polling interval in ms (default: `5000`) |
1177
+ | `--json` | Output as JSON |
1178
+
1179
+ #### `snow log tx`
1180
+
1181
+ Queries the `syslog_transaction` table. Output columns: timestamp, HTTP status, response time (highlighted red if > 2s), username, URL.
1182
+
1183
+ | Flag | Description |
1184
+ |---|---|
1185
+ | `-l, --limit <n>` | Max records (default: `25`) |
1186
+ | `--slow <ms>` | Only show transactions slower than this many milliseconds |
1187
+ | `--json` | Output as JSON |
1188
+
1189
+ ---
1190
+
1191
+ #### `snow ai test <path>`
1192
+
1193
+ Generate ATF tests for any previously generated build and push them to the active instance. Usable independently of `snow factory`.
1194
+
1195
+ ```bash
1196
+ # Generate and push tests for a build
1197
+ snow ai test ./my-build/
1198
+
1199
+ # Generate, push, and immediately run
1200
+ snow ai test ./my-build/ --run
1201
+
1202
+ # Custom suite name
1203
+ snow ai test ./my-build/my-build.manifest.json --suite-name "Sprint 42 — Onboarding Tests"
1204
+ ```
1205
+
1206
+ **Options:**
1207
+
1208
+ | Flag | Description |
1209
+ |---|---|
1210
+ | `--run` | Execute the test suite immediately after pushing via the ATF API |
1211
+ | `--suite-name <name>` | Override the generated suite name |
1212
+
1213
+ Requires access to `sys_atf_step_config`, `sys_atf_test`, `sys_atf_test_suite`, and `sys_atf_step` tables. ATF must be enabled on the instance.
1214
+
334
1215
  ---
335
1216
 
336
1217
  ### `snow provider`
@@ -677,7 +1558,18 @@ src/
677
1558
  instance.ts snow instance
678
1559
  table.ts snow table
679
1560
  schema.ts snow schema
680
- script.ts snow script
1561
+ script.ts snow script (pull/push/list/search/replace)
1562
+ bulk.ts snow bulk (update)
1563
+ user.ts snow user (add-to-group/remove-from-group/assign-role/remove-role)
1564
+ attachment.ts snow attachment (list/pull/push)
1565
+ updateset.ts snow updateset (list/current/set/show/capture/export/apply/diff)
1566
+ status.ts snow status
1567
+ diff.ts snow diff (cross-instance schema/script comparison)
1568
+ factory.ts snow factory (AI-orchestrated multi-env app pipeline)
1569
+ catalog.ts snow catalog (Service Catalog browse/search)
1570
+ flow.ts snow flow (Flow Designer flows, subflows, actions)
1571
+ app.ts snow app (scoped application metadata)
1572
+ log.ts snow log (system, app, and transaction logs)
681
1573
  provider.ts snow provider
682
1574
  ai.ts snow ai (build, chat, review, push)
683
1575
  lib/
@@ -686,6 +1578,7 @@ src/
686
1578
  llm.ts LLM provider abstraction (OpenAI, Anthropic, xAI, Ollama)
687
1579
  sn-context.ts ServiceNow system prompt and artifact type definitions
688
1580
  update-set.ts XML update set generation and Table API push
1581
+ atf.ts ATF test generation and execution utilities
689
1582
  types/
690
1583
  index.ts Shared TypeScript interfaces
691
1584
  ```