Developing ServiceNow Apps with the Now SDK
Guide for ServiceNow app development using the Now SDK: project setup, fluent authoring, build/deploy workflow, and CLI reference. Start here when working on a new ServiceNow application or with the Now SDK before consulting artifact-specific guides.
When to Use
- Setting up a new ServiceNow application project from scratch
- Working with the ServiceNow SDK (
@servicenow/sdk) CLI commands - Scaffolding project structure, modules, or fluent definitions
- Building, deploying, or iterating on a ServiceNow app locally
- Authenticating the SDK against a ServiceNow instance
- Answering questions about SDK capabilities, fluent language, or project configuration
Prerequisites
- Node.js 20 or later (LTS recommended)
- npm (bundled with Node.js)
- Access to a ServiceNow instance (PDI or enterprise) with admin or developer credentials
Installation
Non-Interactive Scaffolding (Recommended for Agents)
Create a new application:
npx @servicenow/sdk init \
--appName "My App" \
--packageName "my-app" \
--scopeName "x_my_app" \
--template "base"
Important: The scope name must be formatted as
x_<company_code>_<app_name>(if you do not have maint access). Choose one of these options:
- Provide the company code found under the sys_property
glide.appcreator.company.code.- Use the generated name at your own risk.
Convert an existing application from an instance:
npx @servicenow/sdk init \
--from <sys_id_of_sys_app_record>
initcreates files in the current working directory. It does not create a subdirectory.
After scaffolding:
npm install
Interactive Scaffolding
npx @servicenow/sdk init
Prompts for app scope, name, and target instance. Run npm install after completion.
CLI Commands Reference
| Command | Purpose |
|---|---|
init | Scaffold a new project. Flags: --appName, --packageName, --scopeName, --template. |
auth | Authenticate. --add <url> --type basic|oauth to add, --list to check, --use <alias> to set default. |
build | Compile fluent source files. Validates syntax and reports errors. |
install | Push built artifacts to the instance. Requires prior auth. |
transform | Convert existing instance artifacts into fluent source files. |
download | Download specific records or update sets from an instance. |
query | Query instance data via Table API. Use -o json for structured output. See query-guide.md. |
dependencies | Fetch TypeScript type definitions for platform APIs. |
clean | Remove build output and cached artifacts. |
pack | Package the app into a ZIP with update set XML and package_inventory.csv (SHA-256 manifest). |
Project Structure
src/
fluent/
index.now.ts # Main fluent entry point
example.now.ts # Example fluent definition
tsconfig.json # Fluent TypeScript config
server/
script.ts # Example server-side script
tsconfig.json # Server TypeScript config
now.config.json # App metadata: scope, scopeId, name
package.json
Organize artifacts by type using kebab-case naming:
src/fluent/
business-rules/
my-rule.now.ts
client-scripts/
my-script.now.ts
now.config.json
{
"scope": "x_my_app",
"scopeId": "26571502d0a642339adf60a7edf6fab9",
"name": "My App",
"tsconfigPath": "./src/server/tsconfig.json"
}
Does not contain instance connection info -- that is managed via auth.
Development Workflow
init-- Scaffold the project (one-time).npm install-- Install SDK and dependencies (one-time).auth-- Authenticate against your instance (or verify existing auth with--list).- Write fluent -- Create
.now.tsfiles undersrc/fluent/. Write server scripts insrc/server/. build-- Compile and validate fluent definitions.install-- Install compiled artifacts on the instance.- Iterate -- Repeat steps 4-6.
For brownfield projects, use transform to pull instance artifacts into fluent source first (see below).
Build & Install Cycle
After writing or editing fluent definitions, run the build then the deploy command. This is the core inner-loop you repeat on every change.
Prefer the package.json npm scripts over the underlying now-sdk build / now-sdk install commands — a complete application may have additional build steps wired into those scripts.
# 1. Compile and validate fluent source into deployable artifacts
npm run build
# 2. Push the built artifacts to the authenticated instance
npm run deploy
npm run build(runsnow-sdk build) transpiles the SDK project and writes the output artifacts. Build errors (invalid references, type mismatches, malformed definitions) are reported here -- fix them before deploying.npm run deploy(runsnow-sdk install) deploys the most recent build output to the instance selected viaauth. It requires a prior successfulbuildand valid credentials to be configured already.- MUST: Ensure build has passed before deploying! A failed build leaves the previous artifacts in place, so deploying without rebuilding pushes stale output.
Converting Existing Applications
From an Instance
Convert a scoped application already installed on an instance:
npx @servicenow/sdk init --from <sys_id_of_application>
Use --auth <alias> to specify which instance credentials to use. Without it, the default alias is used. Run npm install after.
From an Existing Repository
If the app already has a git repo with XML metadata:
npx @servicenow/sdk init --from <path_to_repo>
Existing metadata XML and supporting files are placed inside the metadata folder, and fluent configuration files are added alongside them.
Converting XML to Fluent DSL
After initializing from an instance or repo, application metadata will be in the metadata folder in its original XML form. Use transform to convert XML files into Fluent code:
# Transform a single file
npx @servicenow/sdk transform --from metadata/update/sys_script_<sys_id>.xml
# Transform the whole app at once
npx @servicenow/sdk transform --from .
# Transform a specific directory
npx @servicenow/sdk transform --from metadata/update
Transformed files are scaffolded into the generated directory (configurable in now.config.json) and removed from metadata upon successful conversion.
Note: Records that exist as both a fluent entity (
.now.tsfile) and an XML file inmetadatawill use the XML version onbuild. Remove converted XML files to avoid conflicts.
Run npx @servicenow/sdk transform --help for the full list of options.
Authentication
Checking Existing Credentials
npx now-sdk auth --list
Adding Credentials (Interactive)
npx now-sdk auth --add <instance-url> --type <basic|oauth>
basic: Username and password. Suitable for local development and PDIs.oauth: OAuth-based. Suitable for enterprise instances.
Prompts for alias, username, and password. Credentials stored in .now-sdk/ (gitignored).
Setting a Default
npx now-sdk auth --use <alias>
Adding Credentials (Non-Interactive)
Pass --username to skip the username prompt and --password-stdin to pipe the password through stdin instead of being prompted. Useful for agent-driven setup (Claude Code, scripts) where typing into the prompt isn't possible. Same pattern as docker login --password-stdin:
echo "$SN_PASSWORD" | npx now-sdk auth --add <instance-url> \
--type basic --alias <alias> --username <user> --password-stdin
Credentials are stored exactly the same way as the interactive flow — subsequent now-sdk deploy --auth <alias> calls work as expected. The password never appears in ps, shell history, or log files.
--password-stdin only applies to basic auth; with --type oauth it is ignored (OAuth uses a browser-based code grant). Empty stdin or running with --password-stdin outside a pipe produces a clear error rather than hanging.
Non-Interactive (CI/CD)
See CI Integration 'ci-integration' topic for more information
Key Concepts
Fluent Language (SDK 4.x Object-Based API)
TypeScript-based DSL for defining ServiceNow artifacts:
import { BusinessRule } from '@servicenow/sdk/core'
import { myScriptFunction } from '../server/script'
BusinessRule({
$id: Now.ID['my-rule'],
name: 'Uppercase Short Description',
table: 'incident',
when: 'after',
action: ['insert', 'update'],
order: 100,
script: myScriptFunction,
})
- The
Nowglobal (e.g.Now.ID[...]) is available with no import — the SDK registers it automatically during build and through the language server. - Import artifact types from
@servicenow/sdk/core. - Server-side logic is written as functions in
src/server/and passed via thescriptproperty. Seemoduletopic for more information
TypeScript Types
Run npx now-sdk dependencies to fetch type definitions for platform APIs and tables on the connected ServiceNow instance, enabling IDE autocompletion.