@jacebenson/jsn 4.3.8-dev.60 → 4.3.9-dev.61

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 (2) hide show
  1. package/README.md +11 -539
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,567 +1,39 @@
1
- # JSN — ServiceNow CLI
1
+ # JSN: ServiceNow CLI
2
2
 
3
- A command-line interface for ServiceNow. Type `jsn` and start working — no web UI needed.
4
-
5
- Works standalone or with AI agents (Claude Code, OpenCode, Hermes, Cursor, Copilot).
3
+ A command-line interface for ServiceNow. Read and update records, manage flows, inspect platform data, and automate routine work from your terminal or AI agent.
6
4
 
7
5
  ## Install
8
6
 
9
- ```bash
10
- npm install -g @jacebenson/jsn
11
- ```
12
-
13
- Node.js 22.5.0 or newer. macOS, Linux, Windows.
14
-
15
- The install also copies an AI agent skill file to `~/.agents/skills/servicenow/SKILL.md`.
16
-
17
- ### Install from GitHub (test unreleased builds)
18
-
19
- To test a branch or the freshly merged `main` before it's published to npm:
20
-
21
- ```bash
22
- npm install -g github:jacebenson/jsn#main # merged but not yet tagged
23
- npm install -g github:jacebenson/jsn#<branch> # any PR/feature branch
24
- ```
25
-
26
- Go back to the released version with:
7
+ Requires Node.js 22.5.0 or newer. Supports macOS, Linux, and Windows.
27
8
 
28
9
  ```bash
29
10
  npm install -g @jacebenson/jsn
11
+ jsn setup
30
12
  ```
31
13
 
32
- **Note:** git installs build `better-sqlite3` (docs search) from source, so the machine needs build tools (Python, make, a C++ compiler).
33
-
34
- ## Direct MID installation
35
-
36
- ```sh
37
- jsn midservers add --install-method direct --name worker1
38
- ```
39
-
40
- Official x86-64 ZIPs for Linux and Windows, selected from the instance's
41
- `mid.version`. Credentials are prompted and validated before installation.
42
- Linux supports a user-owned background runtime. Windows currently prepares
43
- private files and offers a foreground console, not native service registration.
44
- See [direct MID installation](docs/mid-direct-install.md) for security boundaries,
45
- lifecycle commands and the untested Windows host phases. Docker remains available.
46
-
47
- ## Customization reports
48
-
49
- ```sh
50
- jsn customizations capture --label before-upgrade --customer-scope x_acme_app
51
- jsn customizations list
52
- jsn customizations show <run_id>
53
- jsn customizations html <run_id> # writes customizations-<run_id>.html
54
- jsn customizations html <run_id> --out review.html
55
- jsn customizations compare <baseline_id> <new_id> --json
56
- jsn customizations show <run_id> --get data.coverage
57
- jsn customizations show <run_id> --get data.triage
58
- ```
59
-
60
- Capture data access uses Table API GET requests only. Captures never run
61
- background scripts or create, update or delete instance records. Standard
62
- authentication still applies, including OAuth refresh, local refreshed-credential
63
- storage and session/GCK bootstrap, which can make authentication POST requests.
64
- Expired credentials without a usable refresh token require login. Reports are private local JSON files in
65
- `$JSN_DATA_HOME/customizations`, defaulting to `~/.jsn/customizations`. List,
66
- show and compare work offline. Interactive terminals offer local report pickers;
67
- pass explicit IDs with JSON, pipes or `--get`.
68
-
69
- The bounded inventory joins visible `sys_metadata`, `sys_scope` and
70
- `sys_upgrade_history_log` records. `ootb_modifications` contains artifacts
71
- with historical skipped-upgrade evidence, not a verified current OOTB diff.
72
- Because the broad `sys_metadata` read is an arbitrary `sys_id`-ordered slice
73
- (994 of 621972 rows on a large instance), it is reported as a **bounded sample,
74
- not an inventory**: it only ever describes the rows the page budget reached.
75
- The skipped-upgrade artifacts are inventoried separately and completely for the
76
- observed history: after the filtered upgrade-history read, every observed
77
- `sys_update_name` is resolved with chunked GET-only
78
- `sys_update_nameIN<chunk of names>` lookups on `sys_metadata`, so an artifact
79
- with skipped-upgrade evidence appears in `ootb_modifications` even when it falls
80
- far outside the sample. `coverage.upgrade_evidence` reports the skipped rows
81
- observed, the distinct update names, how many resolved by direct lookup, the
82
- unresolved name list and any failed lookup chunks.
83
- `customer_app_artifacts` contains only scopes explicitly declared with repeatable
84
- `--customer-scope` values or sys_ids. The instance verifies the scope identity,
85
- not its ownership. Installed/vendor scopes are never automatically called
86
- customer-built. Other visible artifacts remain `unclassified`, and both those
87
- categories cover only what the bounded sample read.
88
-
89
- Each item reports identity, scope, evidence, unknown risk with rationale and a
90
- review recommendation. Historical OOTB findings include the known skipped-upgrade
91
- impact and explicit unknown baseline, runtime impact and dependencies. No
92
- reversion is performed or recommended as safe without further investigation.
93
-
94
- `show` adds a computed `data.triage` view with evidence confidence, the reason for
95
- the classification and concrete review steps; it does not alter saved captures or
96
- pretend to score risk. `html` exports a self-contained offline report with search,
97
- classification filters, grouping, evidence, coverage and links back to records.
98
- The default output is `customizations-<run_id>.html`; existing files are never
99
- overwritten. The report does not change ServiceNow records.
100
-
101
- Defaults are 100 records per page and 10 pages per source. Adjust `--page-size`
102
- and `--max-pages` within the documented limits. Source coverage compares the rows
103
- fetched with the Stats API count for the same query and reports both. A page
104
- shorter than the requested size never implies exhaustion; `exhausted` is reported
105
- only when the fetched rows account for the available total, and an unavailable
106
- count is reported as unknown rather than implied completeness. Other statuses
107
- distinguish missing fields, unstable pagination and read failures. Both the count
108
- and the rows reflect visible ACL-filtered records, so hidden rows cannot be ruled
109
- out and reports remain `incomplete`. An empty category does not prove that no
110
- customizations exist. A 2xx table body without a `result` array is treated as an
111
- unavailable source, never as an empty table.
112
-
113
- Comparisons show newly observed, no-longer-observed and changed metadata/evidence.
114
- They ignore local capture IDs, labels, timestamps and enumeration order.
115
- They do not prove record creation/deletion or detect source-body changes without
116
- captured metadata changes. Changed entries render the concrete before/after field
117
- values, and additions/removals list the artifact's name, table, scope, category
118
- and evidence basis. When either report has an unavailable or empty source, the
119
- comparison status is `unreliable` and those differences are labelled as missing
120
- coverage instead of mass creation or deletion. Compare only reports from the same
121
- instance.
122
-
123
- Provider contract: [ServiceNow Customizations Unchanged](https://www.servicenow.com/docs/r/xanadu/platform-administration/customizations-unchanged-related-list.html)
124
- explains that the `Skipped` disposition preserves customizations. Other skip
125
- reasons are not treated as equivalent evidence. This command cannot establish a
126
- trusted baseline from that history alone.
127
-
128
- The verified provider join is `sys_upgrade_history_log.file_name` to
129
- `sys_metadata.sys_update_name`, not the log's nonexistent `name` field. Capture
130
- uses raw values from `sysparm_display_value=all`: disposition `4` or `104`
131
- means Skipped or Skipped (second pass). Resolution `reviewed_reverted` excludes
132
- that history row; a present empty resolution is distinct from a missing field.
133
- The upgrade-history read is filtered server-side to those dispositions so a
134
- bounded capture spends its pages on preserved-customization evidence instead of
135
- arbitrary history rows, and `unmatched_upgrade_records` counts only that filtered
136
- population, not all upgrade history. The filtered history is the unit of the
137
- inventory claim: every observed `file_name` is then resolved against visible
138
- `sys_metadata` with chunked GET-only `sys_update_nameIN<chunk>` lookups, so
139
- skipped artifacts are inventoried from the history instead of from the arbitrary
140
- `sys_id`-ordered metadata sample. `unmatched_upgrade_records` and
141
- `coverage.upgrade_evidence.unresolved_update_names` describe only names no
142
- visible metadata row matched; a failed lookup chunk is reported rather than
143
- treated as an absent artifact.
144
- These values were checked against the PDI dictionary, choices and actual joined
145
- rows. Display labels are not used for classification.
146
-
147
- ## Quick Start
148
-
149
- ```bash
150
- jsn setup # Interactive: add, switch, remove, modify instances
151
- jsn incidents list --query "priority=1" # Critical incidents
152
- ```
153
-
154
- ## What It Does
14
+ See the [setup guide](docs/docs-setup.md) to connect an instance safely.
155
15
 
156
- jsn talks to the ServiceNow REST API. Read, create, update, delete — tickets, users, groups, records on any table. Inspect flows and business rules. Export update sets. Run background scripts.
157
-
158
- Everything outputs JSON when piped, styled tables in a terminal.
16
+ ## Try it
159
17
 
160
18
  ```bash
161
- # Core ticket work
162
19
  jsn incidents list --query "active=true^priority=1"
163
- jsn incidents INC0010001
164
- jsn incidents create --description "Server down" --priority 1
165
-
166
- # Admin tasks
167
- jsn flows list # Interactive picker with pagination
168
- jsn flows show "Assign Task" # Full flow detail
169
- jsn flows executions # All states, newest first
170
- jsn flows executions --active # Only waiting/running/queued
171
- jsn flows executions --since "2026-08-25 00:00:00" --until "2026-08-26 00:00:00"
172
- jsn flows executions --summary # Server totals + sampled duration metrics by flow
173
- jsn flows executions --limit 100 # Inspect more rows from the matching population
174
- jsn flows executions --record <sys_id> # Executions for one source record
175
- jsn flows create --data-file flow.manifest.json # Create a draft record-triggered flow
176
- jsn rules list --query "collection=incident"
177
- jsn updatesets set "My Feature"
178
-
179
- # Generic table access
180
- jsn records list --table incident --limit 50 --json | jq '.data.records[].number'
181
- jsn records create --table incident --data '{"short_description":"test"}'
182
- jsn records list --table incident --limit 50 --get "data.records.0.number" # no jq needed
183
- jsn records list --table incident --query "active=true" # totals included by default
184
- jsn records list --table incident --limit 10 --no-count # opt out of the total query
185
- jsn records bulk --table incident --query "priority=1" --set '{"state":"3"}' # dry-run by default
186
- jsn records get --table incident --sys-id 8a1234abcd5678 --attachments # record + its files
187
- jsn records list --table incident --limit 10 --csv # output CSV
188
-
189
- # Read-only cross-profile record diff
190
- jsn diff record --table incident --sys-id <sys_id> --profile-a dev --profile-b prod
191
- jsn diff record --table incident --sys-id <sys_id> --profile-a dev --profile-b prod --ignore state
192
- jsn diff record --table incident --sys-id <sys_id> --profile-a dev --profile-b prod --no-ignore
193
-
194
- # Script execution
195
- jsn eval "gs.info('Hello World')"
196
- cat script.js | jsn eval --stdin # pipe a script in (no shell escaping)
197
-
198
- # Now GraphQL (documents may contain mutations; read-only profiles are blocked)
199
- jsn graphql --query '{ GlideRecord_Query { incident(pagination: {limit: 2}) { _results { number { value } } } } }'
200
- cat incident.graphql | jsn graphql --stdin --variables '{"limit":2}'
201
-
202
- # Saved query snippets (stored locally, run against the active profile)
203
- jsn snippets save open-inc --table incident --query "active=true"
204
- jsn snippets run open-inc
205
-
206
- # Live log tailing (Ctrl+C to stop)
207
- jsn logs follow --level error --tail 10
208
- ```
209
-
210
- ### Update set completion
211
-
212
- ```bash
213
- jsn updatesets complete # Current set, opens a notes editor in a human terminal
214
- jsn updatesets complete "My Feature" --notes "Fixed validation" --force --json
215
- ```
216
-
217
- `complete [name]` saves concise bullet-list notes in the selected set's Description
218
- and marks it complete. Omit the name to use the current set. Explicit names
219
- must be unique; for duplicate names, select the intended set with `updatesets set`
220
- and complete it without a name. ServiceNow's normal batch completion rules still
221
- apply: completing a parent can complete its children. Notes are not copied to children.
222
-
223
- Existing Description text is preserved exactly. The command shows it and asks
224
- before appending notes, unless `--force` or the profile's `skip_confirmations`
225
- policy explicitly allows the append. Scripts and JSON output must supply
226
- nonempty `--notes`; they never open prompts. Separate multiple notes with real
227
- newlines. Success requires readback of both Description and state. If verification
228
- fails, inspect the set before retrying because the write may have partially succeeded.
229
-
230
- ### Flow Designer actions
231
-
232
- `actions` and `action` are the same command. `list`, `show`, and explicit
233
- `delete` remain available. In a human terminal, omit the target to open a
234
- searchable picker. Create and edit guide you through provider schemas and save
235
- full Process Flow definitions, not ordinary table-field updates.
236
-
237
- ```bash
238
- jsn actions create # Guided scope, name, schemas, inputs and script
239
- jsn actions edit # Pick an action, edit its saved definition
240
- jsn actions definition # Pick and inspect a complete definition
241
- jsn actions test --wait # Pick an action, supply saved-schema inputs, confirm
242
- jsn actions step-types # Pick the exact transaction scope
243
- ```
244
-
245
- Script inputs offer a file path or your `$VISUAL`/`$EDITOR`. New script steps can
246
- declare outputs and map them to action outputs. Variable declarations reuse
247
- provider schema templates and receive fresh UI identities. Unknown nested
248
- schema fields are retained. Unsupported input types stop with instructions to
249
- use `--data-file`; JSN does not silently omit them or invent schema defaults.
250
- Creation waits for an explicit final confirmation before allocating a parent.
251
- It saves a draft only and never publishes or runs it automatically.
252
-
253
- For automation, keep using explicit identifiers and full JSON:
254
-
255
- ```bash
256
- jsn actions step-types --scope <scope_sys_id> --get data > step-types.json
257
- jsn actions create --scope <scope_sys_id> --data-file new-action.json --json
258
- jsn actions definition <action_sys_id> --get data > action.json
259
- # Edit action.json, retaining its ID, scope, lifecycle fields and all arrays.
260
- jsn actions update <action_sys_id> --data-file action.json --json
261
- jsn action edit <action_sys_id> --data-file action.json --json # same operation
262
- jsn actions test <action_sys_id> --force --output-map '{"response":"hello"}' --wait --timeout 60 --json
263
- jsn actions test <action_sys_id> --force --data-file action.json --output-map '{"response":"hello"}' --wait --get data.outputs.response.value
264
- jsn actions delete <action_sys_id> --force # explicit cleanup, never automatic
20
+ jsn records list --table incident --limit 10 --json
21
+ jsn flows list
265
22
  ```
266
23
 
267
- Existing targets infer their exact transaction scope from the action record.
268
- An explicit `--scope` must match that record byte-for-byte and exist in
269
- `sys_scope`. For Global, use the literal sys_id `global`.
24
+ Run `jsn --help` for the command list. See the [CLI guide](docs/cli-guide.md) for authentication, output formats, development, and examples. The [docs site](https://jacebenson.github.io/jsn/) has feature guides.
270
25
 
271
- This **illustrative create document** shows an input/script/output mapping.
272
- Replace `<SCRIPT_STEP_TYPE_SYS_ID>` with the target's `step-types` result.
273
- Start from that step type's full input/output schemas, preserving runtime
274
- settings, status outputs and any other required fields. The shortened example
275
- is not a captured or instance-verified template. New steps/variables need their
276
- own identifiers; do not clone another action's record IDs. Leave new steps'
277
- `step_id` and `action` blank or omitted. Create binds their `action` to the newly
278
- allocated parent; persisted step IDs or parent bindings are rejected before creation.
26
+ ## AI agents
279
27
 
280
- ```json
281
- {
282
- "name": "Echo response",
283
- "description": "Return the supplied response",
284
- "internal_name": "echo_response",
285
- "inputs": [{"name": "response", "label": "Response", "type": "string", "mandatory": true}],
286
- "outputs": [{"name": "response", "label": "Response", "type": "string", "value": "{{step[11111111-2222-4333-8444-555555555555].response}}"}],
287
- "steps": [{
288
- "cid": "11111111-2222-4333-8444-555555555555",
289
- "step_type": "SCRIPT",
290
- "step_type_id": "<SCRIPT_STEP_TYPE_SYS_ID>",
291
- "label": "Echo script",
292
- "order": 1,
293
- "inputs": [
294
- {"name": "required_run_time", "type": "choice", "value": "instance"},
295
- {"name": "script", "type": "script", "value": "(function execute(inputs, outputs) { outputs.response = inputs.response; })(inputs, outputs);"}
296
- ],
297
- "outputs": [],
298
- "extended_inputs": [{"name": "response", "type": "string", "value": "{{inputs.response}}", "extended": true}],
299
- "extended_outputs": [{"name": "response", "type": "string", "extended": true}]
300
- }]
301
- }
302
- ```
303
-
304
- Create first inserts the parent in `sys_hub_action_type_definition`, reads that
305
- parent's own Process Flow defaults, then saves the inputs, outputs and nonempty
306
- steps with the internal `/api/now/processflow/action/action_types/{id}` PUT.
307
- It retains fresh lifecycle/status metadata instead of copying source snapshot
308
- or status IDs. A subsequent definition GET plus `/step_instances` GET verifies
309
- scripts, mappings and schemas. Update requires a complete document from
310
- `definition`, including target-owned lifecycle fields. Omitted fields are
311
- rejected before mutation. A PUT timeout triggers readback, not another PUT;
312
- `persisted_after_timeout` means persistence was verified, not that HTTP success
313
- was received. Failed creation reports the parent ID and leaves cleanup to you.
314
-
315
- Test sends `action`, `outputMap`, `runOnThread` and `tracingEnabled` to `/test`.
316
- Despite its wire name, `--output-map` supplies **action inputs**. Without
317
- `--wait`, success means dispatch only, with `status: dispatched` and no outputs.
318
- With `--wait`, JSN requires a `COMPLETE` context, blank `error_message`, and each
319
- declared user output's actual value from `sys_flow_runtime_value`. Output entries
320
- have `value`, `displayValue` and `hasValue`; false, zero and empty strings count.
321
- Failures, denied/missing outputs and timeouts exit nonzero. The wait budget
322
- starts after dispatch, defaults to 60 seconds, and is capped at 3600 seconds.
323
- Timeout does not cancel the server execution. Draft actions can be tested without
324
- publication. Testing runs their scripts and can have side effects. It requires
325
- interactive confirmation or `--force`, unless the profile explicitly skips
326
- confirmations. Read-only profiles block create/update/delete/test. No publish
327
- or snapshot command is added.
328
- These internal endpoints and runtime-table permissions can vary by instance.
329
-
330
- ### Flow execution fields
331
-
332
- ### Flow Designer terminal workflows
333
-
334
- ```bash
335
- jsn flows create # Guided record trigger and published action inputs
336
- jsn flows edit # Pick an inactive Draft, edit condition or existing inputs
337
- jsn flows show # Pick a flow to inspect
338
- jsn flows status # Pick a flow to diagnose
339
- jsn flows test # Pick flow and a record from its actual trigger table, confirm
340
- jsn flows publish # Pick a flow, explicitly confirm activation
341
- # Automation must explicitly confirm publication too:
342
- jsn flows publish <flow_sys_id> --force --json
343
- ```
344
-
345
- Wizards and omitted-target pickers require both a prompt-capable terminal and
346
- `auto` output. `--json`, explicit formats, `--get`, `--data`, `--data-file`,
347
- `--output-map`, pipes, `CI`, `NONINTERACTIVE` and `JSN_NO_PROMPTS=1` never open a
348
- wizard. In those modes provide identifiers and required scope/record/data
349
- explicitly. Tests, publish and deletion require `--force` or the profile's
350
- existing explicit skip-confirmations setting when prompting is unavailable.
351
- Read-only profiles still block mutations before authentication or prompting.
352
- Press Escape in record pickers or Ctrl+C in any wizard to cancel. Refusing a
353
- final confirmation leaves the instance untouched.
354
-
355
- Existing action/flow scopes come from saved raw identifiers. New scopes offer
356
- the active application preference if available, then a searchable scope picker.
357
- No scope name is guessed. Input pills are passed through unchanged.
358
-
359
- Flow edits are limited to the existing manifest contract. They do not rename
360
- flows, add/remove steps, implement Flow Logic, subflows, variables or error
361
- handling. Flow deletion remains unsupported. Action deletion retains its
362
- existing explicit parent-record cleanup and absence readback, not a new native
363
- builder deletion lifecycle. See [command coverage and local proof](docs/flow-designer-interactive.md).
364
-
365
- ### Flow creation manifest
366
-
367
- `jsn flows create` accepts `--data-file` or inline `--data`, or guides human
368
- terminal users without those options. The supported slice
369
- supports one `record_create_or_update` trigger and published Action types whose
370
- input schemas are available from the instance. JSN resolves action metadata,
371
- defaults, and typed inputs from ServiceNow; callers do not provide GraphQL or
372
- editor-generated identifiers.
373
-
374
- ```json
375
- {
376
- "name": "JSN-STUDY-ticket-log",
377
- "description": "Log JSN study tickets",
378
- "scope": "<SCOPE_SYS_ID>",
379
- "trigger": {
380
- "type": "record_create_or_update",
381
- "table": "ticket",
382
- "condition": "short_descriptionSTARTSWITHJSN-STUDY-"
383
- },
384
- "actions": [
385
- { "type": "Log", "inputs": { "log_level": "info", "log_message": "Ticket received" } }
386
- ]
387
- }
388
- ```
389
-
390
- `scope` is required; JSN never defaults it to a tenant-specific or captured
391
- scope. The record-trigger condition currently accepts one simple encoded-query
392
- predicate (`fieldSTARTSWITHvalue`, `field=value`, `fieldLIKEvalue`, and the
393
- equivalent single-predicate operators). Compound `^`/`^OR` expressions are
394
- rejected until their predicate AST mapping is proven against the instance.
395
-
396
- Creation leaves the flow in Draft and inactive, then creates and reads back an
397
- Autosave version. `flows publish` remains a separate lifecycle operation: it
398
- reads the saved ProcessFlow definition, POSTs `/snapshot`, creates an
399
- `Activate/Publish` version, reads version history, and verifies `active=true`.
400
- Do not use it in a dry-run: publishing activates the flow.
401
-
402
- `jsn flows test <identifier> --record <sys_id>` is also a mutating operation.
403
- It requires confirmation (or `--force`), reads the saved definition, verifies
404
- that the supplied record exists in the record-trigger table, and POSTs the full
405
- definition to the ProcessFlow test endpoint. A response with only a context ID
406
- is reported as accepted, not completed. Test runs execute actions and can have
407
- side effects; this slice does not execute test flows during development.
408
-
409
- Flow Logic, subflows, flow-variable lifecycle, and error handling are deferred
410
- and rejected by this slice rather than silently ignored.
411
-
412
- `jsn flows update <identifier> --data-file update.json` updates supported fields
413
- of existing inactive Draft flows. The manifest may contain only `trigger` (with
414
- `table` and/or `condition`) and `actions`. Each action selects one saved instance
415
- by its one-based `order` and reusable action `type` (name or sys_id). Its `inputs`
416
- object may change only inputs already present in that saved Action. The CLI reads
417
- the saved component identities itself; manifests never carry UI UUIDs. Omitted
418
- trigger fields, Action inputs, metadata, and other flow components are preserved.
419
- Names must resolve to exactly one flow, and the protected `jace-test-flow` is
420
- rejected. Update sends the captured GraphQL `triggerInstances.update` and/or
421
- `actions.update` shapes, reads the full ProcessFlow definition back, creates an
422
- Autosave version, and reports update-set captures. It never publishes or
423
- activates the flow. Unsupported Flow Logic, subflows, variables, error handling,
424
- new Action inputs, ambiguous selectors, active flows, and non-Draft flows are
425
- rejected before mutation.
426
-
427
- `jsn flows executions` reads `sys_flow_context` and returns both the raw row and a normalized `execution` object. JSN discovers the runtime columns from `sys_dictionary` first, then uses these mappings:
428
-
429
- - `started`: `started`, `start_time`, `started_at`, then `sys_created_on`
430
- - `ended`: `ended`, `end_time`, `ended_at`, then `completed_on`
431
- - `duration_seconds`: stored `duration`, `run_time`, or `execution_duration`, otherwise `ended - started`
432
- - `waiting_age_seconds`: current time minus `started` while the status is waiting, queued, paused, or pending
433
- - `execution_age_seconds`: current time minus `started` while the status is running, executing, or processing
434
- - `status`: `state`, then `status`, then `execution_state`
435
- - `error`: `error`, `error_message`, `exception`, then `message`
436
-
437
- The timestamp fields are instance-dependent. `sys_created_on` is a fallback for when the context row was created, not a claim that it is the true runtime start time.
438
-
439
- ## Commands
440
-
441
- Run `jsn` for the full grouped list. Commands are organized by ServiceNow domain:
442
-
443
- **Core** — `incidents`, `changes`, `requests`, `tasks`, `tickets`
444
-
445
- **Automation** — `flows`, `actions`, `rules`, `scrapi`, `updatesets`, `eval`, `rest`
446
-
447
- **Upgrade review** — [`skipped-updates`](docs/skipped-updates.md) discovers existing unresolved skips, reviews current/base field changes and known dependencies, and processes only explicitly selected actions after an exact batch preview and one confirmation.
448
-
449
- **Access** — `acls`, `roles`, `scopes`, `properties`, `privileges`
450
-
451
- **User Experience** — `forms`, `lists`, `clientscripts`, `uipolicies`, `uiactions`
452
-
453
- **Data** — `records` (list/get/create/update/delete/count/bulk/attachments), `diff record` (cross-profile read-only comparison), `tables`, `columns`, `includes`, `import`, `logs` (list/show/follow), `snippets` (save/run), `users`, `groups`
454
-
455
- **Platform** — `platform health` (cluster records) and `platform stats` (bounded, read-only `/xmlstats.do` summary; allowlisted metrics only)
456
-
457
- Every command supports `--json`, `--query`, and `--help`.
458
-
459
- For multiline script fields, `--data-file` parses the file as UTF-8 JSON and
460
- passes the resulting values through unchanged. On Windows PowerShell, generate
461
- the payload as JSON text and inspect it before invoking JSN, for example:
462
-
463
- ```powershell
464
- $script = [string](Get-Content -Path .\Example.script.js -Raw)
465
- $payload = @{ script = $script; description = 'Example' } |
466
- ConvertTo-Json -Depth 5 -Compress
467
- Set-Content -Path .\Example.update.json -Value $payload -Encoding UTF8
468
- Get-Content .\Example.update.json -Raw | ConvertFrom-Json | Select-Object -ExpandProperty script
469
- jsn includes update Example --data-file .\Example.update.json --json
470
- ```
471
-
472
- `JSON.parse` preserves a JSON string as a JavaScript string, and the SDK
473
- serializes update payloads with `JSON.stringify`. If the file already contains
474
- a `{value=...}` or FileSystem-provider representation, that text is external
475
- to JSN and must be corrected before the update. Use a read-back command or
476
- `records update --strict` where applicable to verify persisted fields.
477
-
478
- ## Instances
479
-
480
- Switch between instances without re-authenticating.
481
-
482
- ```bash
483
- jsn setup # Interactive: add, switch, remove, or modify instances
484
- jsn auth status # Dashboard — auth state, read-only 🔒, skip-confirmations ⚡
485
- ```
486
-
487
- `jsn setup` is the human front door — one command, interactive menu. For scripts and CI, use the atomic commands:
488
-
489
- ```bash
490
- jsn auth login https://dev12345.service-now.com # Add + authenticate (scripted)
491
- jsn auth refresh # Manually refresh the OAuth token
492
- jsn auth switch dev12345 # Flip the active profile (scripted)
493
- jsn auth modify dev12345 # Toggle read-only / skip confirmations
494
- ```
495
-
496
- ## Output Formats
497
-
498
- | Flag | When to use |
499
- |------|-------------|
500
- | (default) | Terminal — styled tables |
501
- | `--json` | Pipelines, scripts |
502
- | `--markdown` | Documentation |
503
- | `--quiet` / `-q` | Data only, no envelope |
504
- | `--csv` | Spreadsheets (opens straight into Excel) |
505
- | `--get <path>` | Pull one value out of the JSON envelope — no jq (e.g. `--get "data.records.0.number"`) |
506
-
507
- ## Authentication
508
-
509
- JSN supports OAuth 2.0 with PKCE, Basic Auth, and browser-session auth. Credentials are stored in the operating system's credential store, with a file fallback under `~/.config/servicenow/credentials/` when the keyring is unavailable.
510
-
511
- ```bash
512
- jsn auth login https://dev12345.service-now.com
513
- ```
514
-
515
- For Basic Auth, set `SN_USERNAME` and `SN_PASSWORD`, then run `jsn auth login --basic <instance>`.
516
- For browser-session auth, run `jsn auth login --gck <instance>` and paste the request headers when prompted.
517
-
518
- For CI/CD, set environment variables:
519
-
520
- ```bash
521
- export SERVICENOW_INSTANCE_URL="https://dev12345.service-now.com"
522
- export SERVICENOW_OAUTH_TOKEN="***"
523
- jsn incidents list
524
- ```
525
-
526
- For the credential identity, auth-method, diagnostics, migration, and concurrency contract, see [`docs/AUTH_LIFECYCLE.md`](docs/AUTH_LIFECYCLE.md).
527
-
528
- GraphQL uses ServiceNow's `/api/now/graphql` endpoint and sends `{query, variables}` through the authenticated SDK transport. The command preserves GraphQL `data` and `errors`; introspection and available namespaces depend on the target instance.
529
-
530
- `jsn platform stats` uses a fixed `GET /xmlstats.do` request. It never accepts a processor path, query parameters, or request body, and it does not emit raw XML, cookies, credentials, or full node identifiers. Oversized, HTML/login, permission, unsupported, timeout, and malformed responses are reported with bounded collector statuses; missing metrics remain unavailable rather than being reported as zero.
531
-
532
- ## Local data
533
-
534
- JSN stores durable local data under `~/.jsn/`. Documentation lives in
535
- `~/.jsn/docs/`, including `docs.db`, the ServiceNowDocs source checkout, and
536
- community markdown. Configuration stays under `~/.config/servicenow/` and
537
- credentials use the operating system's credential store, with a file fallback under `~/.config/servicenow/credentials/`.
538
-
539
- Existing installations migrate documentation from
540
- `~/.cache/servicenow-cli/docs/` automatically the first time the docs data is
541
- accessed. The old directory is removed only after the destination is verified.
542
-
543
-
544
- ## AI Agents
545
-
546
- jsn ships with a skill file that tells AI agents how to use it. Installed automatically to `~/.agents/skills/servicenow/SKILL.md`.
547
-
548
- ```bash
549
- jsn skill show # View the skill
550
- jsn skill install # Install to Hermes
551
- jsn skill install --target all # All supported agents
552
- ```
28
+ JSN includes a skill for Claude Code, OpenCode, Hermes, Cursor, Copilot, and other agents. Use `jsn skill install --target all` to install it or `jsn skill show` to inspect it.
553
29
 
554
30
  ## Development
555
31
 
556
32
  ```bash
557
- git clone https://github.com/jacebenson/jsn.git
558
- cd jsn
559
33
  npm install
560
34
  npm test
561
35
  ```
562
36
 
563
- Releases run from the GitHub Actions workflow. Dispatch `Release production` with `patch`, `minor`, or `major`. The workflow tests and lints the repo, bumps the version, pushes the commit and tag, dispatches the npm publish workflow, and creates the GitHub release.
564
-
565
37
  ## License
566
38
 
567
39
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jacebenson/jsn",
3
- "version": "4.3.8-dev.60",
3
+ "version": "4.3.9-dev.61",
4
4
  "description": "A command-line interface for ServiceNow that follows the Unix philosophy: simple, composable, and scriptable.",
5
5
  "type": "module",
6
6
  "bin": {