@jacebenson/jsn 3.1.0 → 3.1.1
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/package.json +3 -2
- package/skills/servicenow/SKILL.md +41 -123
- package/src/cli.js +247 -200
- package/src/commands/_ticket.js +14 -1
- package/src/commands/auth.js +10 -1
- package/src/commands/catalog.js +179 -292
- package/src/commands/dev/_generic.js +39 -51
- package/src/commands/dev/_simple.js +27 -0
- package/src/commands/dev/b4rules.js +5 -0
- package/src/commands/dev/forms.js +123 -255
- package/src/commands/dev/logs.js +42 -9
- package/src/commands/groupmembers.js +10 -1
- package/src/commands/grouproles.js +10 -1
- package/src/commands/groups.js +12 -1
- package/src/commands/records.js +13 -1
- package/src/commands/skill.js +11 -1
- package/src/commands/tickets.js +12 -1
- package/src/commands/users.js +12 -1
- package/src/help.js +125 -78
- package/src/helpers.js +33 -20
- package/src/paginated-search.js +187 -155
- package/src/sdk.js +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jacebenson/jsn",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.1",
|
|
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": {
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"node": ">=18.0.0"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@inquirer/core": "^10.1.0",
|
|
30
31
|
"@inquirer/prompts": "^7.5.1",
|
|
31
32
|
"chalk": "^5.4.1",
|
|
32
33
|
"cli-table3": "^0.6.5",
|
|
@@ -34,7 +35,7 @@
|
|
|
34
35
|
},
|
|
35
36
|
"devDependencies": {
|
|
36
37
|
"@eslint/js": "^10.0.1",
|
|
37
|
-
"@inquirer/search": "^4.2.
|
|
38
|
+
"@inquirer/search": "^4.2.1",
|
|
38
39
|
"globals": "^17.6.0"
|
|
39
40
|
},
|
|
40
41
|
"files": [
|
|
@@ -12,151 +12,76 @@ compatibility: |
|
|
|
12
12
|
Requires jsn CLI (github.com/jacebenson/jsn). Install via:
|
|
13
13
|
npm install -g @jacebenson/jsn
|
|
14
14
|
Works with Claude Code, OpenCode, Cursor, and agentskills-compatible tools.
|
|
15
|
-
|
|
16
|
-
Windows users: Install Node.js first, then the npm command above. If jsn is not
|
|
17
|
-
in your PATH, the setup command will automatically detect its location and show
|
|
18
|
-
the correct command path.
|
|
19
15
|
metadata:
|
|
20
16
|
author: jacebenson
|
|
21
|
-
version: "1.1
|
|
17
|
+
version: "3.1.1"
|
|
22
18
|
repository: https://github.com/jacebenson/jsn
|
|
23
19
|
---
|
|
24
20
|
|
|
25
|
-
# Jace's ServiceNow CLI
|
|
21
|
+
# Jace's ServiceNow CLI (jsn)
|
|
26
22
|
|
|
27
|
-
Explore and manage ServiceNow instances.
|
|
23
|
+
Explore and manage ServiceNow instances. Interactive paginated pickers with server-side search on all list commands.
|
|
28
24
|
|
|
29
25
|
## Discovery
|
|
30
26
|
|
|
31
|
-
Commands are self-documenting. Use these to learn what's available:
|
|
32
|
-
|
|
33
27
|
```bash
|
|
34
|
-
jsn --help #
|
|
35
|
-
jsn <command> --help
|
|
28
|
+
jsn --help # All commands grouped by domain
|
|
29
|
+
jsn <command> --help # Flags, subcommands, and examples
|
|
36
30
|
```
|
|
37
31
|
|
|
32
|
+
## Interactive Picker
|
|
33
|
+
|
|
34
|
+
All `list` subcommands use a paginated interactive picker in TTY mode:
|
|
35
|
+
- Arrow through items (10 per page)
|
|
36
|
+
- Type to search (server-side LIKE query)
|
|
37
|
+
- Scroll past last loaded item to load next page
|
|
38
|
+
- Enter to select, Esc to cancel
|
|
39
|
+
- Falls back to table output with `--json`
|
|
40
|
+
|
|
38
41
|
## Agent Rules
|
|
39
42
|
|
|
40
|
-
1. **Output modes** — `--json` when parsing data;
|
|
43
|
+
1. **Output modes** — `--json` when parsing data; text when presenting to humans
|
|
41
44
|
2. **Use sys_id for updates** — All update/delete operations require sys_id
|
|
42
45
|
3. **Check auth first** — Run `jsn auth status` before operations
|
|
43
46
|
4. **NEVER logout** — Only run `jsn auth logout` if the user explicitly asks
|
|
44
47
|
5. **Use `--profile <name>`** to target a specific instance, or `jsn profiles use <name>` to change default
|
|
45
|
-
6. **Before using `eval` or `rest`** — Ask
|
|
46
|
-
7. **CONFIRM before destructive operations** —
|
|
47
|
-
|
|
48
|
-
## ⚠️ Destructive Operations Require Confirmation
|
|
49
|
-
|
|
50
|
-
**jsn does not have a `--confirm` or `--dry-run` flag.** It assumes you mean what you type. This means **YOU** (the agent) are the safety layer.
|
|
51
|
-
|
|
52
|
-
**Before any write operation, you MUST:**
|
|
53
|
-
|
|
54
|
-
1. **Show the user what you found** — Run a `list` or `show` command first
|
|
55
|
-
2. **Present the exact command you plan to run** — Include the sys_id, table name, and data
|
|
56
|
-
3. **Wait for explicit approval** — "Proceed? [y/N]" or similar
|
|
57
|
-
|
|
58
|
-
**Examples of destructive commands that require confirmation:**
|
|
59
|
-
- `jsn records --table <name> create`
|
|
60
|
-
- `jsn records --table <name> update <sys_id>`
|
|
61
|
-
- `jsn records --table <name> delete <sys_id>`
|
|
62
|
-
- `jsn updatesets set <name>`
|
|
63
|
-
- `jsn profiles remove <name>`
|
|
64
|
-
- Any `delete`, `update`, `create`, `set`, or `remove` subcommand
|
|
65
|
-
|
|
66
|
-
**Good pattern:**
|
|
67
|
-
```
|
|
68
|
-
User: "Delete that incident"
|
|
69
|
-
Agent: "Found: INC0010001 'Server down' (sys_id: abc123...)
|
|
70
|
-
Command: jsn records --table incident delete abc123...
|
|
71
|
-
Proceed? [y/N]"
|
|
72
|
-
User: "y"
|
|
73
|
-
Agent: [runs command]
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
**Bad pattern:**
|
|
77
|
-
```
|
|
78
|
-
User: "Delete that incident"
|
|
79
|
-
Agent: [immediately runs jsn records --table incident delete ...]
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## ⚠️ AVOID `jsn eval` for Record Creation
|
|
83
|
-
|
|
84
|
-
**Why:** `jsn eval` runs server-side JavaScript in the global scope. It returns HTTP 200 even when:
|
|
85
|
-
- The insert fails due to ACL violations
|
|
86
|
-
- Mandatory fields are missing
|
|
87
|
-
- The record lands in the wrong scope
|
|
88
|
-
- Logic errors prevent the insert entirely
|
|
89
|
-
|
|
90
|
-
**The AI trap:** Agents see "success" and assume the record was created. It wasn't.
|
|
91
|
-
|
|
92
|
-
**Always use instead:** `jsn records --table <name> create` — it returns the created record with sys_id or an explicit validation error.
|
|
93
|
-
|
|
94
|
-
**Only use `eval` when:** No specific command exists, `records` lacks required fields, and `rest` doesn't work. This is rare.
|
|
48
|
+
6. **Before using `eval` or `rest`** — Ask: *"Is there a more specific jsn command?"* Prefer specific over generic over escape hatch over eval.
|
|
49
|
+
7. **CONFIRM before destructive operations** — Show what will be created/updated/deleted and ask for approval.
|
|
95
50
|
|
|
96
51
|
## Command Hierarchy
|
|
97
52
|
|
|
98
53
|
Pick the most specific tool for the job. **Never default to eval** — it's the last resort:
|
|
99
54
|
|
|
100
|
-
1. **Specific commands** — `jsn flows`, `jsn rules`, `jsn
|
|
101
|
-
2. **`jsn records --table <name>`** — generic CRUD on any table
|
|
102
|
-
3. **`jsn rest`** — raw Table API escape hatch
|
|
103
|
-
4. **`jsn eval`** — ⚠️ **LAST RESORT ONLY**
|
|
104
|
-
5. **Ask the human** — if none of the above work
|
|
105
|
-
|
|
106
|
-
##
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
Breadcrumbs suggest next commands — follow them for navigation.
|
|
55
|
+
1. **Specific commands** — `jsn flows`, `jsn rules`, `jsn catalogitems`, etc.
|
|
56
|
+
2. **`jsn records --table <name>`** — generic CRUD on any table
|
|
57
|
+
3. **`jsn rest`** — raw Table API escape hatch
|
|
58
|
+
4. **`jsn eval`** — ⚠️ **LAST RESORT ONLY**
|
|
59
|
+
5. **Ask the human** — if none of the above work
|
|
60
|
+
|
|
61
|
+
## Key Commands
|
|
62
|
+
|
|
63
|
+
| Domain | Commands |
|
|
64
|
+
|--------|---------|
|
|
65
|
+
| **Core** | `incidents`, `changes`, `requests`, `tasks` |
|
|
66
|
+
| **Catalog** | `catalogitems list/show/create` — items with variables and flow info |
|
|
67
|
+
| **Automation** | `flows`, `actions`, `rules`, `workflows`, `triggers`, `scheduledjobs` |
|
|
68
|
+
| **Access** | `acls`, `b4rules`, `roles`, `groups`, `users` |
|
|
69
|
+
| **UX** | `forms` (section/element layout), `lists`, `clientscripts`, `uipolicies` |
|
|
70
|
+
| **Data** | `tables`, `columns`, `includes`, `logs`, `properties`, `records` |
|
|
71
|
+
| **Config** | `setup`, `auth`, `profiles`, `updatesets`, `scopes` |
|
|
72
|
+
| **Developer** | `eval`, `rest`, `skill`, `version` |
|
|
122
73
|
|
|
123
74
|
## Troubleshooting Field Behavior
|
|
124
75
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
**Check order (priority):**
|
|
128
|
-
|
|
129
|
-
1. **Before-query business rules** — `sys_script` with `when=before`, `action=query`, matching `collection` (table)
|
|
130
|
-
```bash
|
|
131
|
-
jsn records list --table sys_script --query "collection=sys_user^when=before^action=query^active=true" --json
|
|
132
|
-
```
|
|
133
|
-
A common case: inactive user filters on `sys_user` are implemented as a before-query BR that adds `active=true` to the query condition.
|
|
134
|
-
|
|
135
|
-
2. **ACLs** — `sys_security_acl` — read/write/delete permissions on tables and fields
|
|
136
|
-
```bash
|
|
137
|
-
jsn acls list --query "name=incident" --json
|
|
138
|
-
```
|
|
76
|
+
Check order (priority):
|
|
139
77
|
|
|
140
|
-
|
|
78
|
+
1. **Before-query business rules** — `sys_script` with `when=before`, `action=query`
|
|
141
79
|
```bash
|
|
142
|
-
jsn
|
|
80
|
+
jsn b4rules list --query "collection=sys_user"
|
|
143
81
|
```
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
jsn records list --table sys_script_client --query "table=incident^active=true" --json
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
5. **UI policies** — `sys_ui_policy` — form-level field behavior (mandatory, read-only, visible)
|
|
151
|
-
```bash
|
|
152
|
-
jsn records list --table sys_ui_policy --query "table=incident^active=true" --json
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
**Example:** "Why can't I pick an inactive user on the incident form?"
|
|
156
|
-
- First guess: Dictionary reference qualifier on `caller_id`? → Check `sys_dictionary`
|
|
157
|
-
- Most likely: Before-query BR on `sys_user` that filters `active=true` → Check `sys_script` first
|
|
158
|
-
|
|
159
|
-
**Rule of thumb:** If a picker is silently filtering results (no error, just fewer options), it's a before-query BR. If it shows an error, it's an ACL or dictionary constraint.
|
|
82
|
+
2. **ACLs** — `jsn acls list --query "name=incident"`
|
|
83
|
+
3. **Dictionary overrides** — `jsn records list --table sys_dictionary --query "name=incident^element=caller_id"`
|
|
84
|
+
4. **Client scripts** / **UI policies** — form-level field behavior
|
|
160
85
|
|
|
161
86
|
## Configuration
|
|
162
87
|
|
|
@@ -164,11 +89,4 @@ When a user asks about field behavior (why a picker won't show inactive users, w
|
|
|
164
89
|
~/.config/servicenow/
|
|
165
90
|
├── config.json # Profiles and settings
|
|
166
91
|
└── credentials.json # Auth tokens (fallback)
|
|
167
|
-
|
|
168
|
-
.servicenow/ # Per-repo config (optional)
|
|
169
|
-
└── config.json # Project-specific settings
|
|
170
92
|
```
|
|
171
|
-
|
|
172
|
-
**Environment variables:**
|
|
173
|
-
- `SERVICENOW_TOKEN` — Override stored token
|
|
174
|
-
- `SERVICENOW_INSTANCE` — Override instance URL
|