AI Agent Support
Use AI coding assistants like Cursor, GitHub Copilot, and Windsurf with sn-scriptsync for automated ServiceNow development.
Last updated: January 24, 2026
Version 4.0 of sn-scriptsync brings native AI coding assistant support. Changes made by AI tools are automatically detected and synced to your ServiceNow instance.
Supported AI Tools
sn-scriptsync works with any tool that modifies files on disk:
- Cursor (with Claude, GPT-4, etc.)
- GitHub Copilot
- Windsurf
- Cline / Claude Dev
- Aider
- Any other AI coding assistant or external editor
How It Works
- Automatic detection — File changes are detected via file system watcher
- Smart batching — Changes are intelligently grouped and deduplicated for efficiency
- Multi-field batching — Multiple field changes on the same record are combined into a single API call
- Configurable delay — The
syncDelaysetting controls sync frequency (default: 30 seconds, set to 0 to disable)
Manual saves (Ctrl+S / Cmd+S) always sync immediately, bypassing the queue.
Pending Saves Queue
A tree view panel shows files waiting to sync:
- Pause/Resume queue functionality
- Sync Now button for immediate sync
- Remove individual files from the queue
AI Agent Instructions
When you start sn-scriptsync, an agentinstructions.md file is written to your workspace root. It contains guidelines for AI agents to work effectively with sn-scriptsync — file-structure patterns, Agent API documentation, and ServiceNow best practices.
Recommended: import or reference it instead of renaming. Keeping agentinstructions.md as the single source of truth lets the extension keep it up to date automatically when you upgrade. Point your tool's own rules file at it:
- Cursor → in
.cursorrules(or a file under.cursor/rules/) add:Follow the rules in @agentinstructions.md - Claude → in
CLAUDE.mdadd:@agentinstructions.md - GitHub Copilot → copy into
.github/copilot-instructions.md(Copilot has no import; see auto-refresh below) - Windsurf → copy into
.windsurfrules(no import; see auto-refresh below)
Keeping the docs and skills up to date
agentinstructions.md and the on-demand skills under agentrules/skills/ are regenerated by the extension on every start and re-synced whenever their version is newer than the copy in your workspace. To pull the latest, update the sn-scriptsync extension and reload VS Code (or run ServiceNow ScriptSync: Enable). Renamed or removed skills are cleaned up automatically, and any file you authored yourself is never touched.
Prefer your own agent instructions?
If you maintain your own CLAUDE.md / AGENTS.md / .cursorrules and don't want the managed reference block added to them, set sn-scriptsync.agentInstructions.autoUpdate to false. The extension then stops injecting and refreshing that block inside your files — but still keeps agentinstructions.md and agentrules/skills/ current, so you can reference them on demand yourself (for example @agentinstructions.md, or point your agent at a specific agentrules/skills/<name>/SKILL.md).
Creating New Artifacts with AI
AI agents can create new ServiceNow artifacts by creating files in the correct folder structure:
{instance}/{scope}/{table}/{name}.{field}.{extension}
For example, to create a new Script Include:
myinstance/global/sys_script_include/MyNewUtils.script.js
The extension will automatically detect the new file, create the record in ServiceNow, and update _map.json with the new sys_id.
Agent API
For advanced integrations, sn-scriptsync exposes a programmatic Agent API so AI tools can drive ServiceNow directly. There are two transports for the same set of commands:
- HTTP API (recommended) — a local HTTP server, the preferred, event-driven transport.
- File-based API (legacy) — a folder queue of JSON files, kept for backward compatibility.
HTTP API (recommended)
When the extension starts it launches a local HTTP server bound to 127.0.0.1, preferring the fixed port 1977 (it falls back to a random free port only when 1977 is taken), secured with a per-session token. Send commands with a single POST /api call, passing the token in the X-Agent-Token header:
curl -s -X POST http://127.0.0.1:1977/api \
-H "X-Agent-Token: <token>" \
-H "Content-Type: application/json" \
-d '{ "id": "chk_1", "command": "check_connection", "instance": "dev12345" }'
Connect any agent in two lines (Pro)
Everything above — file-watcher sync, agentinstructions.md, and the Agent API via the workspace port file — works free: agents inside your editor (Cursor, Copilot, or a CLI agent started in the sync workspace) need no license. Pro adds connect-from-anywhere for external terminal agents (Claude Code, Codex): a well-known per-user port file plus a paste-anywhere instruction snippet, so agents find ScriptSync without knowing the workspace.
Run sn-scriptsync: Copy agent connect instructions from the VS Code command palette (or click Connect an agent in the SN Utils helper tab; the block also appears in the helper tab's sync log when ScriptSync connects) and paste the snippet into any AI agent's instructions — a global CLAUDE.md, AGENTS.md, a Devin playbook, any system prompt. Requires an active SN Utils Pro, Trial, or Enterprise license in the connected browser (the global port file is only written then). The agent then needs no workspace files at all:
GET http://127.0.0.1:1977/api/instructions— full usage docs, served by the running extension itself (no auth), so they always match the installed version.GET /api/skillsand/api/skills/<name>serve the on-demand skills the same way.- Token (and the actual port, if 1977 was taken):
~/.sn-scriptsync/agent-port.json.
Discovering the endpoint
The extension publishes the live endpoint to two places: ~/.sn-scriptsync/agent-port.json (well-known per-user location, readable from any directory, written with user-only permissions — Pro: only written while a Pro/Trial/Enterprise license is connected) and .vscode/sn-agent-port.json in your workspace (always written, free):
{
"port": 1977,
"token": "4f9a…hex…",
"pid": 68861,
"apiVersion": 7,
"startedAt": 1730000000000
}
Treat these files as a hint and validate before trusting them — a copy can be stale after a crash or (the workspace copy) a machine move or cloud-sync. Do this every session and never cache the port/token:
- Read
port,token, andpidfrom~/.sn-scriptsync/agent-port.json(fall back to.vscode/sn-agent-port.jsonon older versions). - Call
GET http://127.0.0.1:<port>/api/health(no auth required). - Trust the endpoint only if the request succeeds (HTTP 200),
health.pidmatches the file'spid, andhealth.apiVersionis one you support. - If any check fails (no file, connection refused, pid/version mismatch), fall back to the file-based API.
- Read the available commands from
health.commands[]rather than hard-coding them.
curl -s http://127.0.0.1:1977/api/health
# → { "status": "success", "apiVersion": 7, "commands": [ … ], "pid": 68861 }
Request and response shape
Every authenticated request is a POST /api with a JSON body containing a command, an optional id (auto-generated if omitted), an optional instance, and command-specific params:
{ "id": "upd_1", "command": "update_record", "instance": "dev12345",
"params": { "table": "sys_script_include", "sys_id": "…", "field": "script", "content": "gs.info('hi');" } }
Successful responses echo the id/command and carry a result:
{ "id": "upd_1", "command": "update_record", "status": "success",
"result": { "success": true, "table": "sys_script_include", "sys_id": "…", "field": "script" },
"timestamp": 1730000001235 }
Errors return status: "error" with a structured code:
{ "status": "error", "code": "E_BROWSER_DISCONNECTED", "error": "No browser helper tab is connected." }
| Code | HTTP | Meaning |
|---|---|---|
E_INVALID_PARAMS / E_INVALID_REQUEST | 400 | Malformed request or missing params |
E_UNAUTHORIZED | 401 | Missing/invalid X-Agent-Token |
E_UNKNOWN_COMMAND | 404 | No such command |
E_INSTANCE_REQUIRED / E_INSTANCE_NOT_FOUND | 422 | Instance not resolvable |
E_DISABLED | 423 | Feature disabled via settings |
E_PAUSED | 423 | Agent access is paused via the pause switch in the SN Utils helper tab — resume it there |
E_SERVER_NOT_RUNNING / E_BROWSER_DISCONNECTED | 503 | Can't reach ServiceNow |
E_TIMEOUT | 504 | Round-trip exceeded the deadline |
E_ACL / E_TOKEN_EXPIRED | 502 | ServiceNow rejected the request |
E_INTERNAL | 500 | Unexpected error |
Available Commands
The same commands work over both transports. The authoritative list for your installed version is always health.commands[].
Connection & sync
| Command | Description |
|---|---|
check_connection | Verify the server is running and a browser tab is connected; also reports which SN Utils build is on the other end (helper.debuggerAvailable, tier) |
get_capabilities | Preflight what the helper tab can do right now — license tier, whether the browser debugger (CDP) is usable (cdp.available), and which write/create/delete permission gates are enabled |
get_instance_info | Resolved instance name and connection flags |
get_sync_status | Inspect the pending-file sync queue |
sync_now | Flush all pending files to ServiceNow immediately |
get_last_error | Read the last remote sync error |
clear_last_error | Clear the recorded error |
Records
| Command | Description |
|---|---|
create_artifact | Create a record from a fields payload (executes immediately) |
pull_records | Pull records from ServiceNow and store code fields into canonical local files with _map.json tracking (alias: pull_artifacts) |
get_record | Fetch a single record by table and sys_id |
update_record | Update a single field on an existing record |
update_record_batch | Update multiple fields on one record in a single round-trip |
get_table_metadata | Fetch column metadata for a table (mandatory fields, types, references) |
check_name_exists_remote | Ask ServiceNow whether a record name already exists |
Query
| Command | Description |
|---|---|
query_records | Run an encoded query against any table |
get_parent_options | Fetch reference options (e.g. parent services for a REST endpoint) |
code_search | Run the SN Utils GraphQL field-index code search across script tables and return structured matches (Pro feature — needs an active SN Utils Pro/Trial/Enterprise license in the connected browser) |
Local files
| Command | Description |
|---|---|
list_tables | List table folders under the instance |
list_artifacts | List artifact files in a table folder |
check_name_exists | Look up a name in local _map.json files |
get_file_structure | Return the file-naming convention and code fields per table |
validate_path | Validate a proposed file path against the convention |
Browser
| Command | Description |
|---|---|
open_in_browser | Open a record/widget form in the connected browser |
activate_tab | Find a tab by URL pattern and activate (or open) it |
refresh_preview | Refresh widget/portal preview tabs |
take_screenshot | Capture a ServiceNow URL/tab to screenshots/. Picks the best available path: granted tab, else silently via the Chrome debugger (Debug edition + Pro + debugger setting; result says capturedVia: "debugger"), else asks for the one-time icon-click grant |
upload_attachment | Attach a file (disk path or base64) to a record |
run_slash_command | Execute an SN Utils slash command (e.g. /tn, /bg) |
switch_context | Switch update set, application scope, or domain |
Browser debugger (CDP) — needs the Debug edition build + a Pro subscription, off by default
These commands drive the connected ServiceNow tab through the Chrome DevTools Protocol (chrome.debugger) for things the normal content-script bridge can't do — network bodies, console errors, beyond-viewport screenshots, and captured dialog text. They are an escalation: reach for the g_form / REST commands first.
| Command | Description |
|---|---|
start_network_capture | Start recording network traffic (method/URL/headers and, by default, response bodies). Supports urlFilter, includeBodies, includeTypes, maxEntries, maxBodyBytes |
stop_network_capture | Stop the capture and return the recorded requests; detaches the debugger unless another capture/handler is still active |
start_console_capture | Start capturing console.* output, log entries, and uncaught exceptions |
stop_console_capture | Stop the capture and return the collected entries (kind: console / log / exception) |
capture_full_page | Full-page (entire scrollable page) or single-element (selector) screenshot saved under screenshots/. Needs no per-tab grant, unlike take_screenshot |
set_dialog_handler | Auto-answer and record native confirm() / alert() / prompt() / beforeunload dialogs (autoAccept, promptText). Persists across navigations |
clear_dialog_handler | Remove the dialog handler and return the dialogs intercepted while it was active |
debugger_detach | Force-detach the debugger and drop the banner — a safety net if a session was left open |
A typical "why did that request fail?" loop:
start_network_capture (urlFilter: "/api/now") start_console_capture → run_ui_action / click_element / navigate (reproduce the action) stop_network_capture (inspect status + response body) stop_console_capture (inspect client-side errors)
All browser-debugger commands share these error codes: E_PRO_REQUIRED, E_DISABLED, E_CDP_UNAVAILABLE, E_DEBUGGER_BUSY, E_NO_TAB, E_BROWSER_DISCONNECTED, E_TIMEOUT (plus E_NO_ELEMENT for capture_full_page with a selector).
File-based API (legacy)
Human Review Queue & Security Gates
Starting with ScriptSync 4.8.0 and SN Utils 10.1.7.5, high-risk agent operations and instance authorizations are governed interactively in the SN Utils ScriptSync Helper tab:
1. Two-Phase Human Review Queue
When an AI agent requests a high-impact operation (such as run_background_script or delete_record), the command is held in a Review Queue:
- An interactive review card appears in the helper tab with the code payload or delete target.
- A 5-minute expiry countdown timer starts, the page title alerts you, and the favicon flashes.
- You can inspect the operation, enter optional feedback, and click Approve once or Reject.
- If rejected or timed out, the agent receives an immediate, structured
E_USER_REJECTEDorE_REVIEW_EXPIREDresponse.
2. Per-Instance Security Permissions
In the helper tab's Instances & Permissions tab, you can toggle individual capabilities per instance:
- Scripts: Allow or disallow background script execution.
- Deletes: Allow or disallow deleting records via the API.
- Create: Allow creating new artifacts.
- REST Write: Allow direct REST record updates.
Toggles persist across sessions and synchronize live with connected agents and editor instances.
Standalone CLI & MCP Server (@snutils/snu)
AI agents outside VS Code (Claude Code, terminal agents, standalone scripts) can use the official @snutils/snu CLI and MCP server:
# Run standalone SN Utils agent commands npx -y @snutils/snu@latest context npx -y @snutils/snu@latest pull sys_script "nameSTARTSWITHincident" --limit 10 npx -y @snutils/snu@latest query incident "active=true" --limit 5 npx -y @snutils/snu@latest search "GlideRecord"
To use it as an MCP server in Claude Code, Cursor, Claude Desktop, or Windsurf, one command detects your installed AI tools and writes the configuration for you:
npx -y @snutils/snu@latest setup
Prefer to configure manually? snu setup --print shows the copy-paste blocks for every client, or add this entry yourself:
{
"mcpServers": {
"sn-utils": {
"command": "npx",
"args": ["--yes", "--prefer-online", "@snutils/snu@latest", "--mcp"]
}
}
}
The configuration is static and secret-free: the bridge port and auth token are discovered at call time from the local port file, so the same entry works for every user and machine, and a project-scoped config file is safe to commit and share with your team.
Security
Comprehensive security measures protect your workspace and ServiceNow instance:
- Interactive Human Review — High-impact actions require explicit developer approval in the browser helper tab before execution
- Per-Instance Access Control — Granular permission switches per connected ServiceNow instance
- Local-only HTTP server — bound to
127.0.0.1(never exposed on the network), preferring fixed port 1977 with an ephemeral fallback - Per-session token — every
POST /apirequest must carry theX-Agent-Token: <token>header; the token is regenerated each session - Pause switch — one click in the SN Utils helper tab blocks all incoming agent commands (
E_PAUSED) while manual editor saves keep working - Workspace boundary enforcement — All file operations are restricted to the local workspace with strict path containment checks