@jacebenson/jsn 4.3.9 → 4.3.10-dev.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -539
- package/package.json +1 -1
- package/src/auth.js +81 -38
- package/src/browser-auth.js +162 -0
- package/src/browser-launch.js +148 -0
- package/src/capabilities.js +10 -0
- package/src/cli.js +2 -2
- package/src/commands/auth.js +763 -650
- package/src/commands/flows.js +17 -7
- package/src/commands/midservers.js +1 -1
- package/src/commands/setup.js +25 -20
- package/src/commands/skill.js +1 -1
- package/src/commands/skipped-updates.js +1 -1
- package/src/commands/updatesets.js +14 -2
- package/src/errors.js +8 -0
- package/src/flow-create.js +329 -74
- package/src/flow-designer-interactive.js +11 -6
- package/src/flow-safe-edit.js +48 -0
- package/src/paginated-search.js +2 -2
- package/src/prompts.js +43 -0
package/README.md
CHANGED
|
@@ -1,567 +1,39 @@
|
|
|
1
|
-
# JSN
|
|
1
|
+
# JSN: ServiceNow CLI
|
|
2
2
|
|
|
3
|
-
A command-line interface for ServiceNow.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
164
|
-
jsn
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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