ServiceNow Flows
as Code

Read, create, validate, and export ServiceNow flows from the command line or REST API. Define flows in YAML. Deploy to any instance. Single binary, zero dependencies.

Terminal
$ letitflow-sn --instance https://myco.service-now.com \
    --sys-id a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4 \
    --format tree

Flow: Incident Assignment (flow, published)
Steps: 4 top-level, Inputs: 0, Outputs: 0, Variables: 1

FLOW  Incident Assignment
  1. 🔍 Look Up Record — Find Support Group
  2.   [If] Priority is Critical
       2.1   Send Email — Urgent P1 Email
       [Else]
       2.2   Log — Default handler
  3.   Update Record — Assign Incident

Features

Everything you need to manage ServiceNow flows programmatically.

🔍

Read Any Flow

Parse any flow by sys_id into human-readable text, tree diagrams, or structured YAML.

Create from YAML

Define flows in simple YAML. Create them in ServiceNow with triggers, steps, and values.

Export YAML

Export existing flows to YAML for version control, review, or migration between instances.

13 Trigger Types

Record, Scheduled, Service Catalog, Inbound Email, Knowledge Management, and more.

Complex Logic

If/Else, ForEach, DoUntil, Parallel, Try/Catch, Decision Tables — all supported.

Data Pills

Full pill reference resolution. Wire trigger outputs, step outputs, and variables across steps.

Offline Validation

Validate YAML flows without a ServiceNow connection. Catch errors before deployment.

REST API

Full HTTP API for CI/CD integration. Validate, create, read, and export flows programmatically.

🔒

OAuth2 + Basic

Client Credentials Grant or Basic Auth. Token caching with automatic refresh.

Parallel Fetch

5-phase parallel API calls with goroutines. Deduplication by UI ID. Fast even for large flows.

Single Binary

One Go binary with embedded web UI. No runtime dependencies. Deploy anywhere.

🌳

Flow Diagrams

ASCII tree output with box-drawing characters, step icons, and indented nesting.

Sample Flows

Define complex flows in readable YAML. Here are a few examples.

Simple Lookup & Update

Trigger on incident, find a group, assign it.

name: Simple Incident Assignment
trigger:
  type: record_created
  table: incident
steps:
  - action: lookup_record
    id: find_group
    inputs:
      table: sys_user_group
      conditions: "name=Service Desk"
  - action: update_record
    inputs:
      record: $trigger.current
      values:
        assignment_group: $find_group.record

Conditional Email

Branch on priority, send targeted emails.

name: Priority-Based Notification
trigger:
  type: record_created
  table: incident
  conditions: "priority<=2"
steps:
  - if: "Priority is Critical"
    inputs:
      lhs: $trigger.current.priority
      operator: "="
      rhs: "1"
    then:
      - action: send_email
        inputs:
          to: "oncall@example.com"
          subject: "CRITICAL: ..."
    else:
      - action: log
        inputs:
          message: "Low priority"

Loops & Parallel

ForEach loops inside parallel branches.

name: Change Notification and Tasks
trigger:
  type: record_created
  table: change_request
steps:
  - action: lookup_record
    id: find_cis
    inputs:
      table: cmdb_rel_ci
  - parallel: "Notify and create"
    branches:
      - - for_each: "Each CI"
          do:
            - action: send_email
      - - for_each: "Each CI"
          do:
            - action: create_record

Quick Start

Three steps to get started.

01 — Install
# Download the binary
$ curl -L -o letitflow-sn \
    github.com/.../releases
$ chmod +x letitflow-sn
02 — Read a Flow
$ letitflow-sn \
    --instance https://myco.sn.com \
    --sys-id abc123...def456 \
    --user admin --pass secret
03 — Start the API
$ letitflow-sn --serve :8080

# Landing page → /
# YAML Editor  → /editor
# REST API     → /api/v1/
# Swagger UI   → /api/docs