Introduction
snow-cli is a cross-platform command-line interface for working with ServiceNow instances.
It is designed for:
- developers who need quick access to ServiceNow APIs,
- automation scripts and CI jobs,
- coding agents and LLM workflows,
- teams that prefer machine-readable JSON, JSON Lines, TOON, or CSV output.
The binary is written in Rust and is intended to ship as a single executable with no runtime dependencies.
What you can do
With snow-cli, you can:
- manage connection profiles,
- log in using supported authentication methods,
- query, create, update, and delete Table API records,
- inspect table schemas,
- call raw REST API endpoints,
- run background scripts,
- search ServiceNow code,
- move data through export/import and seed workflows,
- generate shell completions.
Command style
Commands use a noun-verb structure:
snow-cli <noun> <verb> [options]
Examples:
snow-cli profile add dev --instance https://example.service-now.com --auth-method basic --username admin
snow-cli auth login
snow-cli table list incident --query 'active=true' --limit 20
Installation
Quick install
macOS and Linux
Copy the command below into your terminal. The script shows exactly what it will do before downloading anything:
curl -fsSL https://raw.githubusercontent.com/ewatch/snow-cli/main/scripts/install.sh | bash
You will see a plan like this and be asked to confirm:
Plan:
Download: https://github.com/ewatch/snow-cli/releases/download/v0.4.0/snow-cli-aarch64-apple-darwin.tar.gz
Release: v0.4.0
Install to: /Users/you/.local/bin
Binaries: snow-cli, snow-cli-ro
Proceed? [Y/n]
Skip the confirmation
If you are running this in CI or prefer no prompts:
FORCE=1 curl -fsSL https://raw.githubusercontent.com/ewatch/snow-cli/main/scripts/install.sh | bash
Use a different directory
INSTALL_DIR=/usr/local/bin curl -fsSL https://raw.githubusercontent.com/ewatch/snow-cli/main/scripts/install.sh | bash
Windows
Open PowerShell and run:
irm https://raw.githubusercontent.com/ewatch/snow-cli/main/scripts/install.ps1 | iex
The script shows the same plan-and-confirm flow. To skip the prompt in automation:
$env:FORCE = "1"; irm https://raw.githubusercontent.com/ewatch/snow-cli/main/scripts/install.ps1 | iex
What the script does (in plain English)
- Detects your operating system and CPU architecture.
- Finds the latest release on GitHub.
- Downloads the matching archive (
tar.gzfor macOS/Linux,zipfor Windows). - Extracts it to a temporary folder.
- Copies
snow-cliandsnow-cli-rointo the install directory. - Tells you if the directory is missing from your
PATHand how to add it.
No registry changes, no admin rights required by default, and the archive is deleted automatically.
Manual install (pre-built binaries)
If you prefer to install by hand, download the archive for your platform from the GitHub releases page.
| Platform | Archive |
|---|---|
| macOS Intel | snow-cli-x86_64-apple-darwin.tar.gz |
| macOS Apple Silicon | snow-cli-aarch64-apple-darwin.tar.gz |
| Linux x64 | snow-cli-x86_64-unknown-linux-gnu.tar.gz |
| Windows x64 | snow-cli-x86_64-pc-windows-msvc.zip |
The "unknown" in the Linux filename is not a placeholder — it is the standard Rust target triple vendor field (x86_64-unknown-linux-gnu), which is how the release archives are named.
Extract the archive and place snow-cli (and optionally snow-cli-ro) in a directory on your PATH.
Build from source
Clone the repository and build the release binary:
git clone https://github.com/ewatch/snow-cli.git
cd snow-cli
cargo build --release
The binaries are created at:
target/release/snow-cli
target/release/snow-cli-ro
Run:
./target/release/snow-cli --help
Development build
For local development, run through Cargo:
cargo run -- --help
cargo run -- table list --help
Verify the project
Before contributing changes, run:
cargo fmt -- --check
cargo test
cargo clippy -- -D warnings
Configuration file
snow-cli stores profile configuration in:
~/.servicenow/config.toml
Secrets are stored in the operating system keychain where possible, not in plaintext config files.
Quick start
This page shows a minimal first-time workflow.
1. Create a profile
snow-cli profile add dev \
--instance https://your-instance.service-now.com \
--auth-method basic \
--username your-user
You can also use the legacy alias:
snow-cli config add dev --instance https://your-instance.service-now.com --auth-method basic --username your-user
2. Store credentials
snow-cli auth login
For non-interactive use, pass a secret explicitly or through your automation environment:
snow-cli auth login --password '<password>'
3. Check authentication
snow-cli auth status
4. List records
snow-cli table list incident --query 'active=true' --limit 20
5. Get one record
snow-cli table get incident <sys_id>
6. Create a record
snow-cli table create incident --data '{"short_description":"Created from snow-cli"}'
You can also pipe JSON through stdin:
echo '{"short_description":"Created from stdin"}' | snow-cli table create incident
7. Choose output format
JSON is the default:
snow-cli table list incident --limit 5
Other supported formats include CSV, JSON Lines, TOON, and text where applicable:
snow-cli --output csv table list incident --fields number,short_description --limit 5
snow-cli --output jsonl table list incident --limit 5
snow-cli --output toon table list incident --limit 5
Testing with a Personal Developer Instance (PDI)
A ServiceNow Personal Developer Instance (PDI) is a free, full-featured instance you can use to test snow-cli safely without affecting production data.
Request a PDI
- Go to https://developer.servicenow.com/dev.do and sign in.
- Click Request Instance and choose a release family.
- Wait for the instance to be provisioned. You will receive:
- Instance URL, e.g.
https://dev123456.service-now.com - Username, usually
admin - Password (displayed once; save it securely)
- Instance URL, e.g.
Quick test with basic auth
The fastest way to verify snow-cli against your PDI is basic authentication.
1. Create a profile
snow-cli profile add pdi \
--instance https://dev123456.service-now.com \
--auth-method basic \
--username admin
Replace https://dev123456.service-now.com with your actual instance URL.
2. Log in
snow-cli auth login --profile pdi
When prompted, enter the admin password from your PDI request.
3. Verify
snow-cli auth status --profile pdi
snow-cli --profile pdi table list incident --limit 5
Testing read-only mode
snow-cli-ro is a read-only variant of the CLI. It is useful when you want to guarantee that no mutations happen on your PDI.
snow-cli-ro --profile pdi table list incident --limit 5
snow-cli-ro behaves exactly like snow-cli --read-only. Any command that would write, update, or delete data is blocked before it reaches the network.
Setting up OAuth on a PDI
If you want to test OAuth2 flows, you can create an OAuth application inside your PDI.
1. Create an OAuth application
- In your PDI, navigate to System OAuth > Application Registry.
- Click New and choose Create an OAuth API endpoint for external clients.
- Fill in:
- Name:
snow-cli - Redirect URL:
http://127.0.0.1:8080/oauth/callback - Active: checked
- Name:
- Click Submit.
- Open the newly created record and note:
- Client ID
- Client Secret (click the lock icon to reveal it)
2. Create an authorization-code profile
snow-cli profile add pdi-oauth \
--instance https://dev123456.service-now.com \
--auth-method oauth2 \
--client-id YOUR_CLIENT_ID \
--oauth-grant-type authorization-code
3. Log in
snow-cli auth login --profile pdi-oauth
The CLI opens a browser window. Sign in to your PDI and approve the OAuth request.
4. Verify
snow-cli --profile pdi-oauth table list incident --limit 5
PDI-specific tips
- Wakeup: PDIs hibernate after a period of inactivity. The first request after wakeup may take 30–60 seconds. Increase the timeout if needed:
snow-cli --profile pdi --timeout-secs 120 table list incident --limit 5 - Instance release: PDIs are recreated on major release upgrades. Save your profile config and re-create the profile on a new instance if needed.
- Data safety: PDIs are meant for experimentation. Feel free to create, update, and delete records. If something breaks, request a new instance.
Related pages
Configuration and authentication
snow-cli keeps connection metadata in a config file and stores secrets in the operating system keychain where possible.
Where configuration lives
By default, profiles are stored in:
~/.servicenow/config.toml
The config file contains non-secret settings such as:
- instance URL,
- authentication method,
- username,
- OAuth client ID and grant settings,
- mTLS certificate paths (not yet implemented),
- default profile name.
Secrets such as passwords, API tokens, OAuth client secrets, and stored OAuth tokens are kept outside the TOML file.
Profiles
Profiles describe how snow-cli connects to a ServiceNow instance.
Create a basic-auth profile:
snow-cli profile add dev \
--instance https://dev.service-now.com \
--auth-method basic \
--username admin
List configured profiles:
snow-cli profile list
Set the default profile:
snow-cli profile default dev
Show which profile is active:
snow-cli profile current
snow-cli profile show
Use a specific profile for one command:
snow-cli --profile dev table list incident --limit 10
For detailed profile management, see profile.
Authentication commands
Once a profile exists, store or refresh credentials with:
snow-cli auth login
snow-cli auth status
snow-cli auth token
snow-cli auth logout
For detailed auth behavior and secret input options, see auth.
Supported authentication methods
The CLI supports these --auth-method values:
basicoauth2api-keybrowser-session
In config.toml, the API key method is serialized as api_key.
Basic authentication
Store username in the profile and the password with auth login:
snow-cli profile add dev \
--instance https://dev.service-now.com \
--auth-method basic \
--username admin
snow-cli auth login --profile dev
OAuth 2.0
snow-cli supports three OAuth2 grant types:
client-credentialspasswordauthorization-code
Use authorization-code when you need the CLI to act in user scope. That flow uses a browser login, a localhost callback, and PKCE.
See the dedicated guide:
API key
Create a profile and store the token:
snow-cli profile add integration \
--instance https://dev.service-now.com \
--auth-method api-key
printf '%s' "$SNOW_API_TOKEN" | snow-cli auth login --profile integration --token-stdin
Browser session
browser-session profiles accept an already-authenticated Cookie header value from your browser. This is useful for instances that require SSO or SAML, where you can copy the cookie from an authenticated browser session.
Example profile:
snow-cli profile add sso-dev \
--instance https://dev.service-now.com \
--auth-method browser-session
Then provide the cookie at runtime via the SNOW_SESSION_COOKIE environment variable or the --session-cookie flag:
export SNOW_SESSION_COOKIE='JSESSIONID=...; glide_user_route=...'
snow-cli table list incident --limit 10 --profile sso-dev
The session cookie is never stored in the config file or keychain.
Global options
Common top-level flags:
snow-cli --profile dev <command>
snow-cli --instance https://override.service-now.com <command>
snow-cli --output json|csv|jsonl|toon|text <command>
snow-cli --timeout-secs 30 <command>
snow-cli -v <command>
snow-cli -vv <command>
Discover more
profilecommand referenceauthcommand referenceOAuth authorization code with PKCECommand reference
OAuth authorization code with PKCE
Use OAuth 2.0 authorization-code login when snow-cli must act in user scope instead of as a service account. This is the right setup when you want the CLI to operate as the signed-in human user and obtain a user-bound access token.
snow-cli implements this flow with:
- the ServiceNow authorization endpoint,
- a temporary localhost redirect listener,
- PKCE (
code_challenge_method=S256), - secure token storage in the OS keychain,
- automatic token refresh when a refresh token is available.
What you need from ServiceNow
Before configuring the CLI, create an OAuth application in ServiceNow that supports the authorization-code flow.
Create the OAuth application in ServiceNow
- Navigate to System OAuth > Application Registry.
- Click New and choose Create an OAuth API endpoint for external clients.
- Fill in:
- Name:
snow-cli(or any descriptive name) - Redirect URL:
http://127.0.0.1:8080/oauth/callback - Active: checked
- Name:
- Click Submit.
- Open the newly created record and note:
- Client ID
- Client Secret (click the lock icon to reveal it)
PDI tip: If you are using a Personal Developer Instance, the steps are the same. See Testing with a PDI for a full walkthrough.
You will need:
- the instance URL, for example
https://dev123456.service-now.com - the OAuth
client_id - an allowed redirect URI that matches the CLI profile
- the scopes you want to request
- optionally, a
client_secretif you are using a confidential client
Default redirect URI
If you do not override the redirect settings, snow-cli uses:
http://127.0.0.1:8080/oauth/callback
That means the redirect URI configured in ServiceNow should usually be:
http://127.0.0.1:8080/oauth/callback
Allowed redirect hosts
For safety, the CLI only allows loopback redirect hosts. Use one of:
127.0.0.1localhost::1
Non-loopback hosts such as 0.0.0.0, LAN IPs, or public hostnames are rejected.
Step 1: create a profile
Create an OAuth2 profile that uses the authorization-code grant:
snow-cli profile add user-scope \
--instance https://dev123456.service-now.com \
--auth-method oauth2 \
--client-id YOUR_CLIENT_ID \
--oauth-grant-type authorization-code \
--oauth-scope useraccount
Important profile options
--client-id: required for all OAuth2 flows--oauth-grant-type authorization-code: enables browser login with PKCE--oauth-scope: optional; defaults touseraccount--oauth-redirect-host: optional; defaults to127.0.0.1--oauth-redirect-port: optional; defaults to8080--oauth-redirect-path: optional; defaults to/oauth/callback
If you need a different redirect URI, change the profile and update the same value in ServiceNow:
snow-cli profile edit user-scope \
--oauth-redirect-host localhost \
--oauth-redirect-port 8484 \
--oauth-redirect-path /callback
That profile would require this redirect URI in ServiceNow:
http://localhost:8484/callback
Step 2: log in
Start the browser-based login:
snow-cli auth login --profile user-scope
What happens next:
snow-clistarts a temporary local HTTP listener on the configured loopback redirect URI.- It generates a PKCE
code_verifierandcode_challenge. - It prints the authorization URL and tries to open it in your browser.
- You sign in to ServiceNow and approve the OAuth request.
- ServiceNow redirects back to the local callback URL.
snow-cliexchanges the authorization code for tokens and stores them securely.
On success, the CLI prints a JSON summary including the redirect URI, requested scope, and whether a refresh token was returned.
Public PKCE client vs confidential client
Public PKCE client
If your ServiceNow OAuth client is configured as a public PKCE client, you can omit the client secret entirely:
snow-cli auth login --profile user-scope
This is the preferred setup for local user login flows.
Confidential client
If your ServiceNow OAuth client requires a secret, provide it during login:
printf '%s' "$SNOW_CLIENT_SECRET" | \
snow-cli auth login --profile user-scope --client-secret-stdin
The secret is optional for authorization-code profiles, but if you provide it, snow-cli will also use it for token refresh requests.
Step 3: verify the session
Check auth status:
snow-cli auth status --profile user-scope
Print the current access token:
snow-cli auth token --profile user-scope
Use the profile in normal commands:
snow-cli --profile user-scope table list incident --limit 10
Headless or remote-browser workflows
If you do not want the CLI to open the browser automatically, use --no-browser:
snow-cli auth login --profile user-scope --no-browser
The CLI prints the authorization URL so you can copy it into a browser manually.
Example config.toml entry
After creating the profile, the config file contains non-secret metadata similar to:
default_profile = "user-scope"
[profiles.user-scope]
instance = "https://dev123456.service-now.com"
auth_method = "oauth2"
client_id = "YOUR_CLIENT_ID"
oauth_grant_type = "authorization_code"
oauth_scope = "useraccount"
Redirect settings appear only when you override the defaults.
Troubleshooting
Redirect URI mismatch
If ServiceNow says the redirect URI is invalid, make sure these values match exactly:
- the redirect URI configured in ServiceNow
- the
snow-cliprofile redirect host, port, and path - the actual URI printed by
snow-cli auth login
Port already in use
If the CLI cannot bind the redirect listener, choose a different port:
snow-cli profile edit user-scope --oauth-redirect-port 8484
Then update the ServiceNow OAuth client redirect URI to the same port.
Login timed out
The CLI waits up to five minutes for the OAuth redirect. Re-run snow-cli auth login if the browser flow was interrupted.
Scope issues
If the token does not have the permissions you expect, review the requested OAuth scopes. useraccount is the default scope used by snow-cli when you do not specify --oauth-scope.
Accidentally reusing a confidential-client secret
For authorization-code profiles, if you omit --client-secret on a later login, snow-cli clears any previously stored secret for that profile. This helps public PKCE clients avoid sending a stale secret by accident.
Related pages
Command reference
snow-cli uses a noun-verb command style:
snow-cli <noun> <verb> [options]
Examples:
snow-cli profile add dev --instance https://dev.service-now.com --auth-method basic --username admin
snow-cli auth login
snow-cli table list incident --query 'active=true' --limit 20
Use the pages in this section for command-specific guidance. The built-in help remains the authoritative source for exact usage:
snow-cli --help
snow-cli <noun> --help
snow-cli <noun> <verb> --help
Global flags
Every command supports these top-level flags:
--profile <name>: use a specific saved profile--instance <url>: temporarily override the instance URL from the active profile--output <json|csv|jsonl|toon|text>: choose the stdout format--timeout-secs <seconds>: override the HTTP timeout for the current command-v,-vv,-vvv: increase log verbosity on stderr
Command pages
| Command | What it is for |
|---|---|
profile | Create, edit, inspect, and switch connection profiles |
auth | Log in, log out, inspect auth status, and print tokens |
table | CRUD operations and schema inspection for ServiceNow tables |
data | Export, validate, and import data artifacts |
seed | Planned test-data workflows |
scope | Inspect scopes, export inventory, and move files between scopes |
attachment | List, download, and upload attachments |
import-set | Load records into staging tables |
api | Send raw REST requests to arbitrary endpoints |
script | Run background scripts |
codesearch | Search code and metadata on an instance |
completions | Generate shell completion scripts |
Common patterns
Use a saved profile
snow-cli --profile prod table list incident --limit 10
Pipe JSON into commands that accept stdin
echo '{"short_description":"Created from stdin"}' | snow-cli table create incident
echo '{"user_name":"import-user"}' | snow-cli import-set load imp_user
Ask the CLI for help at the exact level you need
snow-cli auth --help
snow-cli auth login --help
snow-cli scope move-file --help
profile
Use profile to manage saved ServiceNow connection profiles.
snow-cli profile <verb> [options]
config remains available as a legacy alias for profile.
All profile subcommands also accept the global flags described in the command overview, although most profile-management tasks mainly use the command-specific flags below.
What a profile stores
A profile can contain:
- the instance URL,
- the auth method,
- the username for basic auth or OAuth password grant,
- OAuth client settings,
- mTLS certificate paths,
- SAML/SSO login URL.
Secrets are stored separately in the OS keychain.
profile add <name>
Create a new named profile.
snow-cli profile add <name> [options]
Important options:
--instance <url>: instance URL such ashttps://dev.service-now.com--auth-method <basic|oauth2|api-key|mtls|saml>--username <user>: used for basic auth or OAuth password grant--client-id <id>: required for OAuth2 profiles--oauth-grant-type <client-credentials|password|authorization-code>--oauth-scope <scope>: optional for authorization-code profiles, defaultuseraccount--oauth-redirect-host <host>--oauth-redirect-port <port>--oauth-redirect-path <path>--cert-path <path>and--key-path <path>: for mTLS profiles--sso-login-url <url>: for SAML/SSO profiles
Examples:
snow-cli profile add dev \
--instance https://dev.service-now.com \
--auth-method basic \
--username admin
snow-cli profile add user-scope \
--instance https://dev.service-now.com \
--auth-method oauth2 \
--client-id abc123 \
--oauth-grant-type authorization-code \
--oauth-scope useraccount
snow-cli profile add mtls-dev \
--instance https://dev.service-now.com \
--auth-method mtls \
--cert-path ./client.crt \
--key-path ./client.key
Notes:
- When you create the first profile,
snow-climakes it the default automatically. - If the profile already exists, use
profile editinstead. - For authorization-code OAuth2, see the dedicated PKCE guide.
profile edit <name>
Update an existing profile.
snow-cli profile edit <name> [options]
You can change only the fields you want. Omitted fields keep their existing values.
Examples:
snow-cli profile edit dev --username new-admin
snow-cli profile edit user-scope --oauth-scope "useraccount email"
snow-cli profile edit saml-dev --sso-login-url https://dev.service-now.com/login_with_sso.do
profile list
List all configured profiles.
snow-cli profile list
This is useful for checking:
- profile names,
- instance URLs,
- auth methods,
- which profile is the default.
Example:
snow-cli --output csv profile list
profile find --instance <value>
Find profiles by instance name, host, or full URL.
snow-cli profile find --instance dev123456
snow-cli profile find --instance dev123456.service-now.com
snow-cli profile find --instance https://dev123456.service-now.com
Use this when you know the instance but not the saved profile name.
profile sdk
Interoperate with ServiceNow now-sdk aliases.
snow-cli profile sdk <verb> [options]
Subcommands:
profile sdk list: list savednow-sdkaliasesprofile sdk import: copy one or morenow-sdkaliases intosnow-cliprofile sdk export: export asnow-cliprofile into thenow-sdkalias store
Examples:
snow-cli profile sdk list
snow-cli profile sdk import --alias dev
snow-cli profile sdk import --all
snow-cli profile sdk export prod --alias prod-sdk
Important options:
profile sdk import --alias <name>: import one aliasprofile sdk import --all: import every aliasprofile sdk import --set-default: set the imported profile as thesnow-clidefault when importing a single aliasprofile sdk export <profile> --alias <name>: change the destination alias nameprofile sdk export <profile> --set-default: make the exported alias thenow-sdkdefault
Note: current interoperability is aimed at basic-auth profiles.
profile default <name>
Set the profile used when --profile is not provided.
snow-cli profile default dev
This updates the default_profile entry in the config file.
profile current
Show a small summary of the active profile.
snow-cli profile current
This is the quickest way to confirm which profile the CLI will use right now.
profile show
Show the active profile configuration in more detail.
snow-cli profile show
Compared with profile current, this also includes the config path and profile details.
profile remove <name>
Delete a saved profile.
snow-cli profile remove <name>
Important options:
--yes: required when deleting the current default profile--new-default <name>: required replacement default when deleting the current default profile
Example:
snow-cli profile remove old-dev
snow-cli profile remove dev --yes --new-default prod
When a profile is removed, snow-cli also deletes stored credentials for that profile on a best-effort basis.
Related pages
auth
Use auth to store, inspect, and clear credentials for the active profile.
snow-cli auth <verb> [options]
All auth subcommands also accept the global flags from the command overview.
auth login
Authenticate and store credentials in the OS keychain.
snow-cli auth login [options]
auth login behaves differently depending on the profile's auth_method.
Which credentials are needed?
| Profile auth method | What must already be in the profile | What auth login needs |
|---|---|---|
basic | username | password |
oauth2 + client-credentials | client_id | client secret |
oauth2 + password | client_id, username | client secret and password |
oauth2 + authorization-code | client_id, optional redirect/scope settings | browser login, optional client secret |
api-key | no extra profile secret fields | API token |
browser-session | no extra profile fields | session cookie via env var or flag; auth login is not used |
Secret input options
Prefer interactive prompts or --*-stdin flags over putting secrets directly on the command line.
Important options:
--password/--password-stdin: basic auth password or OAuth password-grant password--token/--token-stdin: API token for API-key profiles--client-secret/--client-secret-stdin: OAuth client secret--session-cookie/--session-cookie-stdin: full authenticatedCookieheader value for SAML profiles--no-browser: print the OAuth authorization URL instead of trying to open it automatically--also-now-sdk: for basic auth, also write the successful login intonow-sdk--now-sdk-alias <name>: destination alias name when using--also-now-sdk--set-now-sdk-default: mark thatnow-sdkalias as default
Examples:
snow-cli auth login
printf '%s' "$SNOW_PASSWORD" | snow-cli auth login --password-stdin
printf '%s' "$SNOW_API_TOKEN" | snow-cli auth login --token-stdin
printf '%s' "$SNOW_CLIENT_SECRET" | snow-cli auth login --client-secret-stdin
printf '%s' "$SNOW_SESSION_COOKIE" | snow-cli auth login --session-cookie-stdin
OAuth authorization-code login
For authorization-code profiles, snow-cli:
- starts a temporary localhost callback listener,
- generates PKCE values,
- opens the authorization URL or prints it when
--no-browseris used, - waits for the redirect,
- exchanges the code for tokens,
- stores the resulting OAuth token set securely.
Public PKCE clients can omit the client secret. Confidential clients can provide one.
See OAuth authorization code with PKCE.
Browser session
For browser-session profiles, provide the full authenticated Cookie header value via the SNOW_SESSION_COOKIE environment variable or the --session-cookie / --session-cookie-stdin flags. This auth method does not use auth login.
auth status
Show the current authentication state for the active profile.
snow-cli auth status
Use it to confirm whether the required credentials are available.
auth token
Print the current access token to stdout.
snow-cli auth token
This is useful for piping into other tools. For OAuth2 profiles, the command prints an actual short-lived access token rather than a stored client secret.
Example:
snow-cli auth token | pbcopy
auth logout
Remove stored credentials for the active profile.
snow-cli auth logout
This clears the credential entries used by the current auth method.
Common workflows
Basic auth
snow-cli profile add dev \
--instance https://dev.service-now.com \
--auth-method basic \
--username admin
snow-cli auth login --profile dev
OAuth2 client credentials
snow-cli profile add integration \
--instance https://dev.service-now.com \
--auth-method oauth2 \
--client-id abc123 \
--oauth-grant-type client-credentials
printf '%s' "$SNOW_CLIENT_SECRET" | \
snow-cli auth login --profile integration --client-secret-stdin
OAuth2 authorization code with PKCE
snow-cli profile add user-scope \
--instance https://dev.service-now.com \
--auth-method oauth2 \
--client-id abc123 \
--oauth-grant-type authorization-code
snow-cli auth login --profile user-scope
Related pages
table
Use table for generic CRUD operations against ServiceNow tables.
snow-cli table <verb> [options]
All table subcommands also accept the global flags from the command overview.
table list <table>
List records from a table.
snow-cli table list <table> [options]
Important options:
--query <encoded-query>: ServiceNow encoded query string--fields <a,b,c>: comma-separated field list--limit <n>: maximum number of records to return--order-by <field>: sort by a field
Examples:
snow-cli table list incident --query 'active=true' --limit 20
snow-cli table list sys_user --fields sys_id,user_name,email --order-by user_name
Notes:
table listauto-paginates until it reaches the requested limit or exhausts the result set.- Use
--output csvwhen you want tabular export.
table get <table> <sys_id>
Fetch a single record.
snow-cli table get <table> <sys_id> [options]
Important options:
--fields <a,b,c>: restrict the returned fields
Example:
snow-cli table get incident 46d44a4b2f13000044e0bfc8fb99b6fd --fields number,short_description,state
table create <table>
Create a new record.
snow-cli table create <table> --data '{"field":"value"}'
Important options:
--data <json>: JSON object to send to the Table API
If --data is omitted and stdin is piped in, the command reads JSON from stdin.
Examples:
snow-cli table create incident --data '{"short_description":"VPN down"}'
echo '{"short_description":"Created from stdin"}' | snow-cli table create incident
table update <table> <sys_id>
Patch an existing record.
snow-cli table update <table> <sys_id> --data '{"field":"value"}'
Important options:
--data <json>: JSON object with fields to change
If --data is omitted and stdin is piped in, the command reads JSON from stdin.
Example:
snow-cli table update incident 46d44a4b2f13000044e0bfc8fb99b6fd --data '{"state":"2"}'
table delete <table> <sys_id>
Delete a record.
snow-cli table delete <table> <sys_id> [--yes]
Important options:
--yes: skip the confirmation prompt
Notes:
- In an interactive shell, the command asks for confirmation unless
--yesis used. - In non-interactive environments, use
--yesexplicitly.
Example:
snow-cli table delete incident 46d44a4b2f13000044e0bfc8fb99b6fd --yes
table schema <table>
Inspect table columns using sys_dictionary.
snow-cli table schema <table> [options]
Important options:
--extended: include metadata such as required, read-only, max length, default, and reference table--include-inherited: include fields inherited from parent tables
Examples:
snow-cli table schema incident
snow-cli table schema incident --extended
snow-cli table schema incident --extended --include-inherited
This is especially useful before building imports, exports, or scripted automation.
Common examples
snow-cli table list incident --query 'priority=1^active=true'
snow-cli table get sys_user <sys_id>
snow-cli table create cmdb_ci --data '{"name":"router-01"}'
snow-cli table update incident <sys_id> --data '{"assigned_to":"6816f79cc0a8016401c5a33be04be441"}'
snow-cli table delete incident <sys_id> --yes
Related pages
data
Use data for portable export, validation, and import workflows that sit above the raw Table API.
snow-cli data <verb> [options]
All data subcommands also accept the global flags from the command overview.
data export <table>
Export records from a single table into a portable artifact.
snow-cli data export <table> [options]
Important options:
--query <encoded-query>: restrict exported rows--fields <a,b,c>: only export selected fields--limit <n>: maximum records to export--order-by <field>: sort the export-o, --out <path>: write to a file instead of stdout
Examples:
snow-cli data export incident --query 'active=true'
snow-cli data export incident --fields sys_id,number,short_description --limit 50
snow-cli --output csv data export sys_user --fields sys_id,user_name,email --out users.csv
Use this command when you want a flat, single-table artifact that can later be validated or re-imported.
data export-package --file <spec> --out-dir <dir>
Export a multi-table dataset package from a manifest spec.
snow-cli data export-package --file dataset-spec.json --out-dir exported-dataset
Important options:
-f, --file <path>: dataset export spec file--out-dir <dir>: destination directory for the manifest and exported table files
Examples:
snow-cli data export-package --file dataset-spec.json --out-dir exported-dataset
snow-cli data validate --file exported-dataset/manifest.json
snow-cli data import --file exported-dataset/manifest.json
Note: data export-package does not support --output csv.
data validate --file <file>
Validate an export artifact or dataset package against the target instance.
snow-cli data validate --file export.json
Important options:
-f, --file <path>: file to validate
The validation report checks schema compatibility and reports errors and warnings before you try an import.
Note: data validate does not support --output csv.
data import --file <file>
Import a flat export artifact or dataset package.
snow-cli data import --file export.json [options]
Important options:
-f, --file <path>: file to import--dry-run: preview the import plan without creating records--import-set-table <table>: use the Import Set API for a flat table-export artifact--fail-on-error: exit non-zero when Import Set responses contain row-level errors
Examples:
snow-cli data import --file users.json
snow-cli data import --file users.json --dry-run
snow-cli data import --file users.json --import-set-table imp_user
snow-cli data import --file users.json --import-set-table imp_user --fail-on-error
Notes:
--import-set-tablecurrently works only for flat table-export artifacts, not multi-table package imports.- When
--import-set-tableis not used, the CLI falls back to direct create-only Table API writes. --fail-on-erroris mainly useful together with--import-set-table.data importdoes not support--output csv.
When to use data instead of table
Use data when you want:
- a portable export artifact,
- schema validation before import,
- a repeatable dataset package,
- a dry-run preview of an import,
- an Import Set-backed import path.
Use table for direct record-by-record CRUD operations.
Related pages
seed
seed is reserved for declarative test-data workflows.
snow-cli seed <verb> [options]
All seed subcommands also accept the global flags from the command overview.
Current status
The command surface exists, but the implementation is not finished yet. At the moment, these commands return a "planned but not implemented yet" error.
seed plan --file <file>
Intended purpose: validate a seed spec and show the execution plan.
snow-cli seed plan --file qa-fixture.json
Important options:
-f, --file <path>: seed specification file
seed apply --file <file>
Intended purpose: create test data from a seed spec.
snow-cli seed apply --file qa-fixture.json
Important options:
-f, --file <path>: seed specification file
seed cleanup <run_id>
Intended purpose: remove data created by a prior seed run.
snow-cli seed cleanup <run_id> [options]
Important options:
--dry-run: preview what would be deleted--yes: skip confirmation when deletion becomes available
Example:
snow-cli seed cleanup run-123 --dry-run
What to use today
Until seed is implemented, use:
datafor export and import workflowstablefor direct create/update/delete operationsimport-setfor staging-table loads
scope
Use scope to inspect ServiceNow application scope metadata and work with scope-related artifacts.
snow-cli scope <verb> [options]
All scope subcommands also accept the global flags from the command overview.
scope list [search]
List scopes and classify them by origin.
snow-cli scope list
snow-cli scope list incident
Important options:
[search]: optional search term for partial matches or exact scope names--kind <kind>: filter by one or more kinds--show-source-table: include the source table column in text output--show-sys-id: include the sys_id column in text output
Supported --kind values:
store-appplugincustom-appplatformplatform-app
Examples:
snow-cli scope list
snow-cli scope list sn_ot_incident_mgmt
snow-cli scope list incident --kind plugin --kind store-app
scope inspect <scope>
Inspect a scope and summarize its metadata.
snow-cli scope inspect <scope> [options]
<scope> can be either:
- a scope name such as
x_my_app, or - a scope
sys_id.
Important options:
--details <basic|full>: choose whether to include the full artifact list
Examples:
snow-cli scope inspect x_my_app
snow-cli scope inspect 4f7f9bfe1b2a9010d9f2ed7c2e4bcb12 --details full
Use basic when you only need counts and summary data. Use full when you want normalized artifact rows in the response.
scope inventory <scope>
Export normalized artifact rows for a scope.
snow-cli scope inventory <scope>
This is useful for:
- machine-readable analysis,
- CSV export,
- comparing application contents,
- downstream scripting.
Example:
snow-cli --output csv scope inventory x_my_app
scope move-file <table> <sys_id> --target-scope <scope>
Move one application file into another custom scope without changing its sys_id.
snow-cli scope move-file <table> <sys_id> --target-scope <scope> [options]
Important options:
--target-scope <scope>: required target scope name or scopesys_id--dry-run: validate and preview the move without persisting it--yes: confirm execution when warnings are reported
Examples:
snow-cli scope move-file sys_script_include 4f7f9bfe1b2a9010d9f2ed7c2e4bcb12 \
--target-scope x_target_app --dry-run
snow-cli scope move-file sys_script_include 4f7f9bfe1b2a9010d9f2ed7c2e4bcb12 \
--target-scope x_target_app --yes
Notes:
scope move-fileruns a background script behind the scenes.--dry-runis the safest way to see warnings and proposed field changes before you commit the move.
Related pages
attachment
Use attachment to work with files attached to ServiceNow records.
snow-cli attachment <verb> [options]
All attachment subcommands also accept the global flags from the command overview.
attachment list <table> <sys_id>
List attachments for a record.
snow-cli attachment list <table> <sys_id>
Arguments:
<table>: table name, for exampleincident<sys_id>: recordsys_id
Example:
snow-cli attachment list incident 46d44a4b2f13000044e0bfc8fb99b6fd
The result includes fields such as file name, content type, size, and download link.
attachment download <sys_id>
Download one attachment.
snow-cli attachment download <attachment_sys_id> [options]
Important options:
-o, --out <path>: write to a specific file path
Examples:
snow-cli attachment download 2d8b4c33db121010f4d224b5ca96198d
snow-cli attachment download 2d8b4c33db121010f4d224b5ca96198d --out incident-log.txt
If --out is omitted, the CLI tries to use the original attachment filename. If that is not safe or available, it falls back to <sys_id>.bin.
attachment upload <table> <sys_id> --file <path>
Upload a local file as an attachment.
snow-cli attachment upload <table> <sys_id> --file ./report.txt
Important options:
-f, --file <path>: local file to upload
Example:
snow-cli attachment upload incident 46d44a4b2f13000044e0bfc8fb99b6fd --file ./report.txt
Notes:
- The CLI reads the file locally and uploads it with the attachment API.
- Attachments larger than 100 MiB are rejected by the CLI before upload.
Related pages
import-set
Use import-set to load records into staging tables through the Import Set API.
snow-cli import-set <verb> [options]
All import-set subcommands also accept the global flags from the command overview.
import-set load <table>
Post one JSON object into a staging table.
snow-cli import-set load <table> [options]
Important options:
--data <json>: JSON object to load--fail-on-error: exit non-zero when the response contains row-level errors
Examples:
snow-cli import-set load imp_user --data '{"user_name":"snow-cli-user","email":"snow-cli-user@example.com"}'
echo '{"user_name":"stdin-user","email":"stdin-user@example.com"}' | snow-cli import-set load imp_user
snow-cli import-set load imp_user --fail-on-error --data '{"user_name":"ci-user","email":"ci-user@example.com"}'
Notes:
- If
--datais omitted and stdin is piped in, the command reads JSON from stdin. - The request is sent to
/api/now/import/{table}. - The command prints a structured summary with counts for inserted, updated, ignored, error, and other result rows.
--fail-on-erroris useful for CI or agent workflows where row-level failures must fail the command.
import-set transform <sys_id>
Reserved for separate transform execution.
snow-cli import-set transform <sys_id>
Current status:
- the command surface exists,
- the implementation is still a placeholder,
- some instances already run the transform automatically during
import-set load.
In other words, import-set load is the working path today.
Related pages
api
Use api when you want to call a ServiceNow endpoint directly instead of using a higher-level command.
snow-cli api <verb> [options]
All api subcommands also accept the global flags from the command overview.
Supported verbs
api get <path>api post <path>api put <path>api delete <path>
<path> should be a ServiceNow-relative path such as:
/api/now/table/incident?sysparm_limit=1
/api/x_myapp/status
Common options
-H, --header 'Key: Value': add a custom header; repeat the flag to send multiple headers--data <body>: request body forpostandput
Examples:
snow-cli api get /api/now/table/incident?sysparm_limit=1
snow-cli api post /api/x_myapp/action --data '{"dry_run":true}'
snow-cli api put /api/x_myapp/config --data '{"enabled":true}'
snow-cli api delete /api/x_myapp/config/abc123
snow-cli api get /api/x_myapp/status -H 'X-Trace-Id: abc123'
api get <path>
Send a GET request.
snow-cli api get <path> [-H 'Key: Value']
Use this for read-only endpoints.
api post <path>
Send a POST request.
snow-cli api post <path> [--data '{"key":"value"}']
If --data is omitted and stdin is piped in, the CLI reads the request body from stdin.
Example:
echo '{"dry_run":true}' | snow-cli api post /api/x_myapp/action
api put <path>
Send a PUT request.
snow-cli api put <path> [--data '{"key":"value"}']
Like post, this can also read the body from stdin.
api delete <path>
Send a DELETE request.
snow-cli api delete <path>
Use -H if the endpoint needs additional headers.
Response handling
snow-cli prints the raw response body to stdout.
- If the response is valid JSON and you use JSON-like output, the CLI pretty-prints it.
- If the response is not valid JSON, the body is printed as-is.
--output csvprints the raw body unchanged.
This makes api the most flexible command when you need an endpoint that does not yet have a dedicated command.
Related pages
script
Use script to execute a ServiceNow background script.
snow-cli script run [options]
All script subcommands also accept the global flags from the command overview.
script run
Execute a background script on the target instance.
snow-cli script run [options]
How to provide the script
You can provide script content in three ways:
--code <script>: inline code--file <path>: read from a local file- stdin: pipe the script into the command
Precedence is:
--code--file- stdin
Examples:
snow-cli script run --code 'gs.info("hello from snow-cli")'
snow-cli script run --file ./cleanup.js
printf '%s' 'gs.info("from stdin")' | snow-cli script run
Important options
-c, --code <script>: inline script text-f, --file <path>: local script file--scope <scope>: scope to run in, defaultglobal--endpoint <path>: execution endpoint, default/sys.scripts.do--rollback: record rollback context for database changes--sandbox: prevent database writes--scriptlet: run as a scriptlet with access to global server-side objects--quota-managed-transaction: use managed transaction limits for long-running scripts
Examples:
snow-cli script run --code 'gs.info("hello")' --scope x_my_app
snow-cli script run --file ./job.js --sandbox
snow-cli script run --code 'gs.sleep(1000); gs.info("done")' --quota-managed-transaction
Hints from live E2E testing
- For safe live verification on a real instance, start with
--sandboxso you can confirm auth, form bootstrap, and script execution without writing records. - All three input modes were validated end to end:
--code,--file, and stdin. - Multiline scripts also worked from both
--fileand stdin. - Some ServiceNow instances use older background script JavaScript parsing. If the instance reports an older script engine level (for example
Script ES Level: 0), wrapper syntax such as IIFEs may fail with errors likeInvalid function definitioneven though simpler multiline scripts work. - If you hit parser compatibility issues, prefer plain top-level statements over wrapper patterns.
Example multiline stdin run:
cat <<'EOF' | snow-cli script run --sandbox
var user = gs.getUserName();
gs.print('start');
gs.print('user=' + user);
gs.print('end');
EOF
When to use script
Use this command when you need to:
- run a quick background script,
- inspect data from server-side APIs,
- perform one-off maintenance,
- prototype logic before turning it into an app artifact.
For raw REST endpoints instead of background scripts, use api.
Related pages
codesearch
Use codesearch to search code and related metadata on a ServiceNow instance.
snow-cli codesearch search <query> [options]
All codesearch subcommands also accept the global flags from the command overview.
codesearch search <query>
Search instance code for a text query.
snow-cli codesearch search <query> [options]
Important options:
--source-table <table>: limit results to a specific source table such assys_script_includeorsys_script--limit <n>: maximum number of results, default100--current-scope: search only in the current scope--search-group <name>: advanced search-group override
Examples:
snow-cli codesearch search GlideRecord
snow-cli codesearch search GlideRecord --source-table sys_script_include
snow-cli codesearch search gs.info --current-scope
snow-cli codesearch search BusinessRule --limit 250
Notes:
- The default search group is
sn_devstudio.Studio Search Group. - Depending on the instance response shape, the CLI may print normalized records or pretty-printed JSON.
Related pages
completions
Use completions to generate shell completion scripts.
snow-cli completions <shell>
Supported shells:
bashzshfishpowershellelvish
Examples
Print a completion script to stdout:
snow-cli completions zsh
Save it to a file:
snow-cli completions bash > snow-cli.bash
snow-cli completions zsh > _snow-cli
snow-cli completions fish > snow-cli.fish
Typical installation patterns:
# bash
snow-cli completions bash > ~/.local/share/bash-completion/completions/snow-cli
# zsh
snow-cli completions zsh > ~/.zfunc/_snow-cli
# fish
snow-cli completions fish > ~/.config/fish/completions/snow-cli.fish
Notes
- The command writes the generated completion script to stdout.
- Unlike most commands, the useful output here is the shell script itself, not structured JSON.
- Re-run the command after upgrading the CLI if the command surface changed.
Deploying this book to GitHub Pages
This repository includes an mdBook setup for publishing the documentation as a static GitHub Pages site.
Local preview
Install mdBook:
cargo install mdbook --locked
Serve the book locally:
mdbook serve
Open the local URL printed by mdBook, usually:
http://localhost:3000
Build the static site:
mdbook build
The generated HTML is written to:
book/
The book/ directory is generated output and should not be committed.
GitHub Pages setup
The workflow in .github/workflows/pages.yml builds and deploys the book with GitHub Actions.
In GitHub, configure Pages like this:
Repository → Settings → Pages → Build and deployment → Source → GitHub Actions
Then push changes to main, or run the workflow manually from the Actions tab.
Taking the page down
To unpublish the site quickly:
- Go to
Repository → Settings → Pages. - Disable Pages or change the source away from the Pages workflow.
- Optionally disable or delete
.github/workflows/pages.yml.
Making the repository private usually removes public access shortly after GitHub updates Pages visibility, but disabling Pages is the most explicit option.
Project pages URL
For a repository named snow-cli, GitHub Pages typically publishes to:
https://<owner>.github.io/snow-cli/
If the repository name changes, update site-url in book.toml.
Further reading
The repository contains additional Markdown documentation for contributors and maintainers.
Project plan
Architecture decisions
docs/adr/README.mddocs/adr/0001-use-rust.mddocs/adr/0002-noun-verb-commands.mddocs/adr/0003-os-keychain-credentials.mddocs/adr/0004-toml-config-format.mddocs/adr/0005-json-error-output.mddocs/adr/0006-profile-resolution-and-command-ux.md
Design notes
Contributor guides
Backlog
Task tracking is managed with bd / beads. The historical phase backlog remains in: