Agile local development CLI and VS Code integration for the ServiceNow platform. Synchronize widgets, scripts, and other records across multiple projects (clients/instances) securely and organized.
- Multi-Project: Manage multiple clients in the
projects/folder. - Secure Authentication:
- OAuth 2.0 (Browser Login) - No passwords in text files!
- Basic Auth support (
.envuser/password) if needed. - Local Encryption: OAuth Tokens are saved encrypted (
AES-256) using a Zsh secret key (Memory-only).
- VS Code Tasks: Ready-to-use buttons for
Pull,Push,Watch, andCreate Project. - Collision Protection: Checks if the file was modified on the server before uploading.
- Context Aware: Each record gets its own folder with separate scripts (
server.js,client.js,template.html). - ๐ค AI-Ready: Generates
_ai_context.mdwith tags and_record.jsonwith metadata to help AI agents understand your ServiceNow instance. - Creation & Bulk Push: Create new records by just making a folder and pushing it.
- ๐ค AI Documentation: Includes detailed instructions for AI agents (
.github/copilot-instructions.md,AI_GUIDE.md).
Ensure Node.js (v18+) is installed.
cd _tool
npm installTo secure the token cache (.token_cache.json), define a master password in your system environment variables (not in the project).
Add to your ~/.zshrc (or ~/.bashrc):
# Password to encrypt ServiceNow Sync tokens locally
export SN_ENC_SECRET="a-very-secure-secret-phrase-only-you-know"Then reload: source ~/.zshrc.
To run snsync from anywhere, add to your ~/.zshrc:
alias snsync='node /Users/palomo/workspace/sn/_tool/sn-sync.js'Then reload: source ~/.zshrc. Adjust the path if your repo lives elsewhere.
- Full Project: Downloads all tables defined in
sn-config.json. - Custom Query: Search for specific records interactively.
- Tip: Enable "AI Context" when asked to tag records with keywords (e.g.,
Finance,Auth).
- Tip: Enable "AI Context" when asked to tag records with keywords (e.g.,
- Edit & Sync: Just save the file (
.js,.html) and run the "Push" task (or use Watch mode). - Create New Record:
- Create a folder inside the table folder (e.g.,
src/sys_script_include/MyNewScript). - Add your
script.js. - Run
snsync --push projects/myproject/src/sys_script_include/MyNewScript. - The script creates the record, gets the
sys_id, and saves it locally.
- Create a folder inside the table folder (e.g.,
- Bulk Create: Run push on the Table folder to create all new subfolders at once.
- Context Tags: Every record can have
_ai_context.md. Search for "Context: MyTag" to find all related files. - Metadata:
_record.jsoncontains the full record payload (display values, types) for the AI to analyze.
Use the --catalog-item flag to pull everything related to a single catalog item: settings, form variables, and client scripts. Files are automatically organized in one folder instead of scattered across multiple table folders.
1. Pull a complete catalog item:
node snsync --pull --catalog-item <catalog_item_sys_id> --project projects/your-projectExample:
node snsync --pull --catalog-item a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 --project projects/myprojectWhat gets pulled:
- โ Catalog item (settings, description, execution plan)
- โ All form variables (questions with editable parameters)
- โ All client scripts (onChange, onSubmit validation)
- โ Flow Designer flow (workflow actions - if assigned to catalog item)
2. The organized structure:
src/
โโโ Your_Catalog_Item_Name/
โโโ catalog_item/
โ โโโ _record.json โ Edit: title, price, roles, workflow, visibility
โ โโโ description.html โ Edit: catalog description
โ โโโ script.js โ Edit: execution plan (if any)
โโโ variables/
โ โโโ role/
โ โ โโโ _record.json โ Edit: label, mandatory, order, tooltip, help_text
โ โโโ team_name/
โ โ โโโ _record.json โ Edit variable parameters
โ โโโ ...
โโโ client_scripts/
โ โโโ On_Change_of_role/
โ โ โโโ script.js โ Edit: validation logic
โ โโโ popup_on_submit/
โ โ โโโ script.js โ Edit: submission behavior
โ โโโ ...
โโโ flow/
โโโ flow.json โ Edit: workflow approval rules (DECODED!)
3. Edit files locally:
// Example: catalog_item/_record.json
{
"short_description": { "value": "Request Software License" },
"price": { "value": "0" },
"active": { "value": "true" },
"roles": { "value": "itil,admin", "display_value": "ITIL, Admin" },
"no_cart": { "value": "true" }
}4. Push changes back:
node snsync --push --project projects/your-project --update-set "My Update Set"๐ก Leave
--update-setout to use the instance's current active Update Set, or setupdateSetSysIdpermanently insn-config.json.
5. Validate UI-to-script mapping after catalog changes:
node snsync --validate-catalog-mapping --project projects/your-projectOptional flags:
--catalog Access_request_to_GitHub(validate one catalog folder)--catalog-path src(custom catalog base path)--strict(fail if expected catalog folder is missing)
If your catalog item has a flow assigned, it's automatically pulled as flow/flow.json with all actions decoded and ready to edit!
Example flow.json structure:
{
"_meta": {
"sys_id": "66abc0dd87f932105668c88d0ebb359f",
"flow_id": "88a75b531b8952107fca32231b4bcb09",
"name": "Access request to GitHub",
"last_updated": "2025-12-12 14:54:46"
},
"actions": {
"b397fbe08785f210f7a2a60d3fbb359a": {
"order": 8,
"ui_id": "25fd2f8f-12ba-4c14-9ecd-39bf5e20312a",
"config": {
"approval_conditions": "ApprovesRejectsAnyG[{{static.d3a933afc383ee1048abf00c0501311b}}]",
"additional_approvers": "",
"reminder_frequency": 0,
"reminder_threshold": 0
}
}
}
}Common flow edits:
- Skip an approval (auto-approve):
"approval_conditions": "" // Empty = auto-skip- Change approval to a different group:
"approval_conditions": "ApprovesRejectsAnyG[{{static.YOUR_GROUP_SYS_ID}}]"- Change approval to a specific user:
"approval_conditions": "ApprovesRejectsAnyU[{{static.USER_SYS_ID}}]"- Require manager approval:
"approval_conditions": "ApprovesRejectsAnyU[{{triggerref.request_for.manager}}]"After editing, just push:
node snsync --push projects/your-project/src/Your_Catalog_Item/flow/flow.json --project projects/your-project --update-set "My Update Set"โจ The tool automatically re-encodes, validates, and pushes the flow into your Update Set!
- Finding the sys_id: Open the catalog item in ServiceNow โ Right-click header โ Copy sys_id
- Bulk editing: Use find/replace across all
_record.jsonfiles to update multiple parameters at once - No prompts: Unlike custom queries, catalog item pulls run without interruptions (no AI context prompts)
workspace/sn/
โโโ _tool/ # The brain of operations
โ โโโ sn-sync.js # Main script
โ โโโ create-project.js # Scaffolding script
โ โโโ sn-config-template.json
โโโ projects/ # Your Clients/Instances
โ โโโ client_A/
โ โ โโโ .env # Instance Configs (Ignored in Git)
โ โ โโโ sn-config.json # Table mappings for this project
โ โ โโโ src/ # Downloaded Source Code
โ โโโ client_B/
Use the VS Code Task to create everything automatically:
- Open Command Palette (
Cmd+Shift+P). - Type "Run Task" -> "SN: Create New Project ๐".
- Fill in the data:
- Name:
client_x(folder name). - URL:
https://dev12345.service-now.com - Client ID/Secret: If using OAuth (Recommended).
- User/Pass: Leave blank if using OAuth.
- Name:
This will create projects/client_x with .env and sn-config.json ready.
We recommend using the tasks configured in .vscode/tasks.json instead of manual terminal.
- SN: Pull (Download) Project: Downloads EVERYTHING defined in
sn-config.json. - SN: Pull Custom (Query): Downloads only a specific table/query (e.g.,
incidentwithactive=true). Note: Ensure custom tables/fields are mapped insn-config.json. - SN: Pull Current Record Only: If a file is open, updates only that specific record (surgical).
- SN: Push Current File: Sends the file currently open in the editor. Prompts for an Update Set name (leave blank to use the instance default).
- SN: Watch (Monitor): Runs in background sending any saved file automatically.
- SN: Open Record in Browser: Opens the current file's record directly in the browser.
Each project has its sn-config.json defining what to sync.
Update Set (optional):
{
"updateSetSysId": "My Update Set Name",
"mapping": { ... }
}Set this once to avoid being prompted on every push. Accepts a name (resolved automatically) or a 32-char sys_id. Leave empty to use the instance's current active Update Set.
Table mapping example:
"sp_widget": {
"filter": "sys_updated_onONToday@javascript:gs.beginningOfToday()@javascript:gs.endOfToday()",
"fields": ["template", "script", "client_script", "css"],
"ext": {
"template": "html",
"script": "server.js",
"client_script": "client.js"
},
"saveContext": true
}- filter: ServiceNow Encoded Query.
- fields: Table fields to download.
- ext: File extension for each field.
- saveContext: Saves a schema JSON to help AI/Copilot understand user configs.
The tool supports synchronization for the following ServiceNow tables:
Core Scripts:
sys_script_include- Server-side Script Includessys_script_client- Client Scriptssys_script- Business Rulessys_ui_script- UI Scriptssys_ui_action- UI Actionssysauto_script- Scheduled Jobssysevent_script_action- Event Script Actions
Service Catalog:
sc_cat_item- Catalog Itemssc_cat_item_producer- Record Producerscatalog_script_client- Catalog Client Scriptsitem_option_new- Catalog Variables
Workflows:
wf_workflow- Workflow Definitionswf_activity- Workflow Activitiessys_hub_flow- Flow Designer Flowssys_hub_action_type_definition- Flow Designer Actions
Service Portal:
sp_widget- Service Portal Widgetssp_angular_provider- Angular Providerssp_page- Service Portal Pagessp_css- Portal CSS
UI Components:
sys_ui_macro- UI Macrossys_ui_page- UI Pagessys_ui_policy- UI Policies
Integration:
sys_ws_operation- Web Service Operationssys_rest_message_fn- REST Message Functions
- In ServiceNow, create an OAuth API Endpoint (Create Application Endpoint).
- Redirect URL:
http://localhost:3000/callback
- Redirect URL:
- Copy Client ID and Client Secret.
- In
.env, setSN_CLIENT_IDandSN_CLIENT_SECRET. LeaveSN_USERempty. - When running the tool, it will open the browser for you to log in.
- In
.env, fillSN_USERandSN_PASSWORD.
-
"Version Conflict" Error? Someone edited the file on the server after you downloaded it. Do a Pull and then apply your changes again.
-
Invalid/Expired Token? The tool will try to renew automatically. If it fails, it will reopen the browser for re-authentication.
-
Where are my files? Check if
sn-config.jsonhas the correct filter (e.g.,sys_updated_onONTodayonly downloads things from today).