cheat sheet

Zowe CLI

Open-source command-line bridge into z/OS — manage datasets, jobs, USS files, consoles, TSO, and Db2 from Mac/Linux/Windows over z/OSMF or RSE-API.

Zowe CLI — Modern z/OS DevOps from your laptop

What it is

Zowe CLI is the open-source command-line tool that lets you drive z/OS from a Mac, Linux, or Windows workstation as if it were any modern cloud platform. It is the flagship component of the Zowe project (hosted by the Linux Foundation's Open Mainframe Project) and talks to the mainframe over z/OSMF REST APIs by default, or RSE-API if your shop has it deployed. Reach for Zowe whenever you want to script mainframe work into CI/CD — submit a JCL, wait for it, download SYSOUT, list a PDS, ping a Db2 subsystem — without firing up a 3270 emulator or relying on FTP. The legacy alternative is FTP or bpxbatch over SSH; Zowe is strictly better for automation because it returns structured JSON, plugs into npm/Node tooling, and authenticates with team config profiles checked into the repo.

Install

Zowe CLI is distributed as an npm package and requires Node.js 18 LTS or newer. Most teams install per-project (committed alongside package.json); a global install is fine for personal laptops.

bash
# Per-project (preferred for CI/CD repos)
npm install -D @zowe/cli@latest

# Global
npm install -g @zowe/cli

# Add a useful extender — RSE API connection type
npm install -g @zowe/rse-api-for-zowe-cli

# Mainframe-shop alternative: from an offline npm bundle
npm install -g ./zowe-cli-3.x.x.tgz

Output: (none — exits 0 on success)

Verify the install:

bash
zowe --version
zowe plugins list

Output:

text
3.2.1
─────────────────────────────────────────────────
Installed plugins:

 -- pluginName: @zowe/cics-for-zowe-cli
 -- package: @zowe/cics-for-zowe-cli
 -- version: 5.1.0

 -- pluginName: @zowe/db2-for-zowe-cli
 -- package: @zowe/db2-for-zowe-cli
 -- version: 6.3.0

Syntax

Every Zowe command follows zowe <group> <action> <object> [args]. --help works at every level; the abbreviation engine accepts any unique prefix (so zowe fl ls ds 'ALICE.*' is the same as zowe files list data-set 'ALICE.*').

bash
zowe <group> <action> <object> [positional] [--flag value] \
     [--zosmf-profile <name>] [--response-format-json]

Output: (none — exits 0 on success)

Essential global options

OptionMeaning
--zosmf-profile <name>Pick a non-default profile from your zowe.config.json.
--rfj / --response-format-jsonEmit a single JSON envelope — script-friendly.
--show-inputs-onlyPrint the resolved parameters and exit without calling z/OSMF.
`--log-level <DEBUGINFO
--no-promptFail rather than prompt for missing values (CI safety).
--reject-unauthorized falseAccept self-signed certs (dev only — never production).
--ru falseShort form of --reject-unauthorized false.
--user <id> / --password <pw>Override credentials from the profile.
--token-type <kind> / --token-value <jwt>Use a Single Sign-On token.
--cert-file <pem> / --cert-key-file <pem>Mutual TLS authentication.

Initial setup — zowe config init

zowe config init creates a team-config file (zowe.config.json + optional zowe.schema.json) that captures every connection profile a project needs in one committable artifact. Run it once per repo; commit the JSON and let teammates fill in their own credentials in a sibling zowe.config.user.json (gitignored).

bash
# Project-local config (recommended for CI/CD repos)
zowe config init

# User-level (~/.zowe/) — for ad-hoc laptop work
zowe config init --global-config

# Non-interactive with defaults
zowe config init --default --prompt false

Output (interactive):

text
✔ Please enter the host name of your z/OSMF server: zosmf.example.com
✔ Please enter the port number of your z/OSMF server: 10443
✔ Please enter your z/OSMF username: ALICE
✔ Please enter your z/OSMF password: ********
✔ Should we reject self-signed certificates? No
✔ Should we store credentials securely (OS keyring)? Yes

Saved config to /Users/alice/code/alice-zos/zowe.config.json

The generated zowe.config.json looks like this:

jsonc
{
  "$schema": "./zowe.schema.json",
  "profiles": {
    "alicezosmf": {
      "type": "zosmf",
      "properties": {
        "host": "zosmf.example.com",
        "port": 10443,
        "rejectUnauthorized": false
      },
      "secure": ["user", "password"]
    },
    "alicebase": {
      "type": "base",
      "properties": { "host": "zosmf.example.com", "rejectUnauthorized": false },
      "secure": ["user", "password"]
    }
  },
  "defaults": { "zosmf": "alicezosmf", "base": "alicebase" }
}

Output: (none — exits 0 on success)

The secure array tells Zowe to keep those fields out of the JSON and in the OS keyring (Keychain on macOS, DPAPI on Windows, libsecret on Linux).

Profile management

A profile binds a profile type (zosmf, rse, tso, db2, cics, ssh, endevor, …) to a host + credentials. The default profile of each type is used unless --<type>-profile <name> overrides it.

bash
# List every profile and its defaults
zowe config list

# Show one profile (secrets redacted)
zowe config list profiles.alicezosmf

# Add a second z/OSMF profile in-place
zowe config set profiles.aliceprodzosmf.type zosmf
zowe config set profiles.aliceprodzosmf.properties.host prodzosmf.example.com
zowe config set profiles.aliceprodzosmf.properties.port 10443

# Switch the default for the type
zowe config set defaults.zosmf aliceprodzosmf

# Remove a profile
zowe config set profiles.alicezosmf null

# Update only the secure (keyring) values
zowe config secure

Output (zowe config list):

text
defaults:
  zosmf: alicezosmf
  base:  alicebase
  tso:   alicetso
  ssh:   aliceuss
profiles:
  alicezosmf:    { type: zosmf,   host: zosmf.example.com,  port: 10443 }
  aliceprodzosmf:{ type: zosmf,   host: prodzosmf.example.com, port: 10443 }
  alicetso:      { type: tso,     account: ACCT,            characterSet: 697 }
  aliceuss:      { type: ssh,     host: zos.example.com,    port: 22 }

Connection profile types

TypeReaches viaUsed by
zosmfz/OSMF REST APIfiles, jobs, console, tso (default backend)
rseRSE API serverSame commands when shop runs RSE-API
tsoz/OSMFTSO address-space defaults (account, region, proc)
sshOpenSSH on USSzowe uss issue ssh for shell commands
db2Db2 Connectzowe db2 (Db2 plug-in)
cicsCMCIzowe cics (CICS plug-in)
baseShared credentials inherited by all profiles
apimlAPI Mediation LayerMulti-gateway token auth (Zowe v3+)

Zowe v3 LTS — what changed from v2

Zowe v3 went GA in October 2024 and is the current Active LTS release; Zowe v3 LTS runs until Q1 2027, at which point v3 becomes maintenance and v4 takes over as Active LTS. The current shipping release at the time of writing is v3.2.x. If you are still on v2 (or older), three breaking changes will hit you on upgrade.

ChangeImpact
Legacy .profile files no longer supportedPre-v2 profile files are auto-converted on first v3 run, but only zowe.config.json team config is honoured going forward.
apiml profile type replaces single-base APIML tokenMultiple API ML gateways can each hold their own token simultaneously.
IMS API, deprecated Jobs/Data Set APIs, APIML metrics service removed from coreWorkflows that called these endpoints directly must move to the supported equivalents or an extender plug-in.

apiml profile type — multi-gateway token auth

In v2 the team config could reference a single API Mediation Layer endpoint through the base profile; one apimlAuthenticationToken lived in the keyring. v3 introduces apiml as a first-class profile type — define one per gateway, and each carries its own token in flight. This is the right shape for shops with multiple LPARs or a production / DR pair where one Zowe session needs to talk to both.

jsonc
{
  "profiles": {
    "alicestgapiml": {
      "type": "apiml",
      "properties": {
        "host": "stg-apiml.example.com",
        "port": 7554,
        "basePath": "/api/v1",
        "rejectUnauthorized": true
      },
      "secure": ["tokenValue"]
    },
    "aliceprodapiml": {
      "type": "apiml",
      "properties": {
        "host": "prod-apiml.example.com",
        "port": 7554,
        "basePath": "/api/v1"
      },
      "secure": ["tokenValue"]
    }
  },
  "defaults": { "apiml": "alicestgapiml" }
}

Acquire and store the per-gateway token:

bash
zowe auth login apiml --apiml-profile alicestgapiml
zowe auth login apiml --apiml-profile aliceprodapiml

# Use a specific gateway for a command
zowe files list data-set 'ALICE.*' --apiml-profile aliceprodapiml

# Confirm both tokens are live
zowe config list defaults
zowe auth list --rfj | jq '.data'

Output:

text
Logged in to authentication service alicestgapiml.
Logged in to authentication service aliceprodapiml.
[
  { "profile": "alicestgapiml",  "tokenType": "apimlAuthenticationToken" },
  { "profile": "aliceprodapiml", "tokenType": "apimlAuthenticationToken" }
]

The Zowe Explorer for VS Code (v3.x) honours the same apiml profile type and presents a profile switcher in its tree view.

Migrating from v2 .profile files

If your repo still has v1/v2 .profile directories (~/.zowe/profiles/), the first time you run any v3 command Zowe creates an equivalent zowe.config.json in the user-config directory and prints a one-line conversion summary. The original .profile files are left in place but unused.

bash
# Verify the conversion happened
ls ~/.zowe/
cat ~/.zowe/zowe.config.json | jq '.profiles | keys'

Output:

text
profiles/  zowe.config.json   ...
[
  "alicezosmf",
  "alicebase",
  "alicetso"
]

APIs removed from v3 core

Three sets of endpoints that lived in v2 core are gone from v3 core (still available through plug-ins where applicable):

  • IMS API — moved to @zowe/ims-for-zowe-cli plug-in.
  • Deprecated Jobs / Data Set API endpoints — the v1-era REST paths are archived; current commands now call the modern z/OSMF endpoints. If you wrote bespoke clients against the old paths, retest against z/OSMF directly.
  • APIML metrics service — removed entirely; if you scraped its /metrics endpoint, switch to z/OSMF's own SMF + Prometheus exporters or to a sysview-style tool.

SDK regression notes worth checking: Zowe SDKs were updated to 8.28.0 to fix a bug where copying a PDS member across LPARs failed with a 403. If you pin Node SDK versions in CI, bump past 8.28.

Datasets — zowe files

zowe files covers every common dataset operation: list, view, allocate, copy, upload, download, delete. The verb-noun structure mirrors the operations you do in ISPF.

List datasets and members

bash
# Datasets matching a pattern
zowe files list data-set 'ALICE.*'

# Long form with attributes
zowe files list data-set 'ALICE.*' --attributes

# Members of a PDS
zowe files list all-members 'ALICE.JCL.LIB'

# Filter members by pattern
zowe files list all-members 'ALICE.JCL.LIB' --pattern 'ALICE*'

# USS files in a directory
zowe files list uss-files /u/alice

Output (list data-set --attributes):

text
ALICE.JCL.LIB     PO-E   FB    80    27920  3390
ALICE.SOURCE      PO-E   FB    80    27920  3390
ALICE.NEW.DATA    PS     FB    80    27920  3390
ALICE.REPORT.GDG  GDG-B  -     -     -      -

Download and upload

bash
# Single sequential dataset to a local file
zowe files download data-set 'ALICE.NEW.DATA' \
    --file ./local/alice-new-data.txt

# A PDS — each member becomes one file under a directory
zowe files download all-members 'ALICE.JCL.LIB' \
    --directory ./jcl --extension .jcl

# A USS file
zowe files download uss-file /u/alice/.profile --file ./profile.txt

# A USS directory recursively
zowe files download uss-dir /u/alice/scripts --directory ./scripts

# Upload one file as a new dataset
zowe files upload file-to-data-set ./local/job.jcl 'ALICE.JCL.LIB(NEWJOB)'

# Upload an entire directory to a PDS (filenames become member names)
zowe files upload dir-to-pds ./jcl 'ALICE.JCL.LIB'

# Upload a local file to USS
zowe files upload file-to-uss ./script.sh /u/alice/script.sh \
    --binary false

Output (download all-members):

text
Member(s) downloaded successfully: 38
Files: ./jcl/ALICEJ01.jcl, ./jcl/ALICEJ02.jcl, ...

Allocate and delete

bash
# Allocate a new PS sequential dataset (FB80, 5 cyl primary)
zowe files create data-set-sequential 'ALICE.NEW.PS' \
    --record-format FB --record-length 80 --block-size 27920 \
    --primary-space 5 --secondary-space 2 --alcunit CYL

# Allocate a new PDS-E (library)
zowe files create data-set-partitioned 'ALICE.NEW.LIB' \
    --record-format FB --record-length 80 \
    --primary-space 5 --secondary-space 2 --alcunit CYL \
    --data-set-type LIBRARY

# Allocate a VSAM KSDS
zowe files create data-set-vsam 'ALICE.NEW.KSDS' \
    --data-set-organization INDEXED --record-size 80 --key-length 10

# Allocate "like" an existing dataset
zowe files create data-set-like 'ALICE.NEW.COPY' --like 'ALICE.SOURCE'

# Delete a dataset (without prompting)
zowe files delete data-set 'ALICE.OLD.DATA' --for-sure

# Delete a single PDS member
zowe files delete data-set 'ALICE.JCL.LIB(OLDMEM)' --for-sure

Output (create data-set-sequential):

text
Data set created successfully.

Copy and rename

bash
# Copy a PDS member
zowe files copy data-set 'ALICE.JCL.LIB(SRC)' 'ALICE.JCL.LIB(DST)'

# Copy a sequential dataset
zowe files copy data-set 'ALICE.OLD.PS' 'ALICE.NEW.PS'

# Cross-system copy via z/OSMF (same z/OSMF cluster)
zowe files copy data-set 'A.B.C' 'D.E.F' --replace

# Rename
zowe files rename data-set 'ALICE.TEMP' 'ALICE.KEEPER'
zowe files rename data-set-member 'ALICE.JCL.LIB' OLDMEM NEWMEM

Output:

text
Data set copied successfully.

Jobs — zowe jobs

zowe jobs is the SDSF you can script: submit JCL, query status by jobid, fetch spool, cancel, purge. Every command takes --rfj for JSON output.

Submit a job

bash
# Submit a member from a PDS, do not wait
zowe jobs submit data-set 'ALICE.JCL.LIB(ALICEJ01)'

# Submit a local file
zowe jobs submit local-file ./alicej01.jcl

# Submit inline JCL from stdin
cat ./alicej01.jcl | zowe jobs submit stdin

# Submit and wait until the job finishes
zowe jobs submit data-set 'ALICE.JCL.LIB(ALICEJ01)' \
    --wait-for-output --rfj

# Submit and download all spool files when it finishes
zowe jobs submit data-set 'ALICE.JCL.LIB(ALICEJ01)' \
    --view-all-spool-content

# Submit with a job-name override (substituted at submit time)
zowe jobs submit data-set 'ALICE.JCL.LIB(ALICEJ01)' \
    --job-name ALICEAD1

Output (submit data-set with --wait-for-output):

text
jobid:    JOB04219
jobname:  ALICEJ01
status:   OUTPUT
retcode:  CC 0000

Inspect, cancel, purge

bash
# Status by jobid
zowe jobs view job-status-by-jobid JOB04219

# Full structured response
zowe jobs view job-status-by-jobid JOB04219 --rfj

# All jobs for a prefix and owner
zowe jobs list jobs --prefix 'ALICEJ*' --owner ALICE

# List the spool files of one job
zowe jobs list spool-files-by-jobid JOB04219

# Fetch one spool file
zowe jobs view spool-file-by-id JOB04219 102

# Cancel a running job
zowe jobs cancel job JOB04219

# Purge an OUTPUT job and all its spool
zowe jobs delete job JOB04219

Output (list jobs):

text
jobid    jobname  owner  status  retcode
JOB04219 ALICEJ01 ALICE  OUTPUT  CC 0000
JOB04220 ALICEJ02 ALICE  ACTIVE  -
JOB04221 ALICEJ03 ALICE  INPUT   -

Download spool

bash
# Download every spool file of a job into a directory
zowe jobs download output JOB04219 --directory ./out/JOB04219

# Just JESMSGLG, JESJCL, JESYSMSG (skip program SYSOUT)
zowe jobs download output JOB04219 --directory ./out/JOB04219 \
    --omit-jobid-directory --extension .txt

# Inline view of a single spool DD
zowe jobs view spool-file-by-id JOB04219 4

Output:

text
Successfully downloaded 5 spool files to ./out/JOB04219

MVS console — zowe console

zowe console issues operator commands (the kind you would type on a system console or with /cmd in SDSF) and returns the responses. Backed by z/OSMF's Console service.

bash
# Issue a single MVS command
zowe console issue command 'D A,L'

# JES2 slash-command (must be quoted; the leading $ is part of the command)
zowe console issue command '$DJ ALL,Q=A'

# Issue and stream the response (long-running ops like D IPLINFO)
zowe console issue command 'D IPLINFO' --rfj

# Use a named console other than the default
zowe console issue command 'D OMVS' --console-name CON1

Output (D A,L):

text
RESPONSE-1:  CNZ4106I 12.34.56 DISPLAY ACTIVITY 999
RESPONSE-2:    JOBS     M/S    TS USERS    SYSAS    INITS   ACTIVE/MAX VTAM
RESPONSE-3:    00007    00037  00012       00037    00010    00012/00250
RESPONSE-4:  ALICEJ01  ALICE    OWT
RESPONSE-5:  ALICEJ02  ALICE    OWT

TSO — zowe tso

zowe tso opens a TSO address space, runs commands or REXX, and returns output. Use it whenever you need TSO-only commands like LISTCAT, LISTDS, or to invoke a CLIST/EXEC.

bash
# One-shot TSO command (auto-create/close address space)
zowe tso issue command 'STATUS'

# Run a REXX EXEC by full member name (no allocation needed)
zowe tso issue command "EX 'ALICE.EXEC(MYREXX)' 'ARG1'"

# Long-lived address space — start, run multiple, then stop
zowe tso start address-space
# returns: servletKey ALICE-12345-xxxxxx
zowe tso send address-space ALICE-12345-xxxxxx --data 'STATUS'
zowe tso send address-space ALICE-12345-xxxxxx --data 'TIME'
zowe tso stop address-space ALICE-12345-xxxxxx

# Interactive ping-pong (REPL-style)
zowe tso ping address-space ALICE-12345-xxxxxx

Output (issue command 'STATUS'):

text
ALICEJ01  JOB04219  OUTPUT
ALICEJ02  JOB04220  ACTIVE

USS — zowe uss and zowe files USS verbs

zowe uss issue ssh shells out via SSH (requires the ssh profile, not z/OSMF). For file work USS is reachable through both zowe files uss-* verbs (z/OSMF) and direct SSH.

bash
# Run a shell command via SSH
zowe uss issue ssh 'uname -a; df -k /tmp'

# Run a long-form script via SSH
zowe uss issue ssh "cd /u/alice && ./build.sh"

# Create a USS file via z/OSMF
zowe files create uss-file /u/alice/notes.txt --mode 644

# Create a USS directory
zowe files create uss-directory /u/alice/runs --mode 755

# Tagged file: upload as text in IBM-1047
zowe files upload file-to-uss ./run.sh /u/alice/run.sh \
    --binary false --encoding IBM-1047

# Compare local content with USS file
zowe files compare uss-files /u/alice/run.sh ./run.sh

Output (uss issue ssh 'uname -a'):

text
OS/390 SYSPLEX1 24.00 03 8561

Plug-ins

Zowe CLI is extensible — plug-ins add new groups (cics, db2, endevor, ftp, mq, imperative). They are npm packages too, installed via zowe plugins install.

bash
# List installed plug-ins
zowe plugins list

# Install from npm
zowe plugins install @zowe/cics-for-zowe-cli@latest
zowe plugins install @zowe/db2-for-zowe-cli@latest

# Install from a local tarball
zowe plugins install ./zowe-endevor-cli-7.0.0.tgz

# Update everything
zowe plugins update

# Uninstall
zowe plugins uninstall @zowe/db2-for-zowe-cli

# Validate (re-run install hooks if a profile-schema changed)
zowe plugins validate

Output (plugins install):

text
Installed plugin name = '@zowe/cics-for-zowe-cli'
Successfully installed

CI/CD usage

Zowe shines when wired into pipelines — secrets supplied as env vars, commands invoked from scripts, JSON parsed by the next step. The two patterns below are battle-tested.

Headless authentication

In CI, never run zowe config init interactively. Supply credentials as env vars; Zowe reads ZOWE_OPT_USER, ZOWE_OPT_PASSWORD, etc. automatically.

bash
export ZOWE_OPT_USER="$MAINFRAME_USER"
export ZOWE_OPT_PASSWORD="$MAINFRAME_PASSWORD"
export ZOWE_OPT_HOST="$ZOSMF_HOST"
export ZOWE_OPT_PORT="$ZOSMF_PORT"
export ZOWE_OPT_REJECT_UNAUTHORIZED=true

zowe zosmf check status --rfj | jq '.data.zosmfFullVersion'

Output:

text
"31.0.0"

Per-environment profile selection

Commit a zowe.config.json with multiple profile blocks; use --zosmf-profile to pick at runtime.

bash
# Run against staging
zowe jobs submit data-set 'ALICE.JCL.LIB(NIGHTLY)' \
    --zosmf-profile alicestgzosmf --wait-for-output --rfj

# Run against production
zowe jobs submit data-set 'ALICE.JCL.LIB(NIGHTLY)' \
    --zosmf-profile aliceprodzosmf --wait-for-output --rfj

Output: (none — exits 0 on success)

JSON output and scripting

--rfj (response-format-json) wraps every command in {"success", "exit_code", "message", "stdout", "stderr", "data"}. Pipe to jq to extract just what you need.

bash
zowe files list data-set 'ALICE.*' --rfj | jq -r '.data[] | .dsname'
zowe jobs view job-status-by-jobid JOB04219 --rfj | jq -r '.data.retcode'
zowe jobs list jobs --prefix 'ALICEJ*' --owner ALICE --rfj \
    | jq -r '.data[] | select(.status=="OUTPUT") | .jobid'

Output:

text
ALICE.JCL.LIB
ALICE.NEW.DATA
ALICE.SOURCE

Common pitfalls

  1. Storing the password in zowe.config.json instead of the keyring — accidental commit leaks it. Always keep the credential field in the secure array so it lands in the OS keyring.
  2. --reject-unauthorized false in production — silently accepts MITM certs. Use only for first-time POCs; install your shop's CA in the OS trust store and remove the flag.
  3. Submitting JCL without --wait-for-output — the command exits before the job finishes, so a failing return code is invisible to the pipeline. Add --wait-for-output --rfj and inspect .data.retcode.
  4. Mixing global and project configs — both load and the project wins, but the merge can be surprising. zowe config report shows the effective merged view.
  5. EBCDIC-vs-ASCII surprises on USS upload--binary true skips translation; --binary false translates using the file's tagged encoding. Tag the destination first (chtag -tc IBM-1047 file).
  6. z/OSMF auto-purge of OUTPUT jobs — long-running CI that fetches spool may race the purge interval. Fetch the spool before exit, do not assume it stays around.
  7. Issuing console commands without RBA authorization — z/OSMF Console service requires CONSOLE class RACF profile MVS.MCSOPER.<conid>. The error is IEE712I, not a Zowe message.
  8. Plug-in version drift across teammates — pin plug-ins in package.json if you go per-project. zowe plugins list --verbose reports active versions.
  9. zowe tso issue command for long-running output — output cuts at the TSO message limit. Use a started address space and send/receive in chunks, or write to a dataset and download.
  10. Forgetting --encoding IBM-1047 when uploading source — z/OSMF defaults to the system codepage which may not be 1047. Always set encoding explicitly for source members.

Real-world recipes

Submit, wait, download — the canonical CI loop

The whole reason people install Zowe: submit a JCL from a build pipeline, wait for it, download SYSOUT, fail the pipeline on a non-zero return code.

bash
#!/usr/bin/env bash
set -euo pipefail

JOB="$(zowe jobs submit data-set 'ALICE.JCL.LIB(NIGHTLY)' \
       --wait-for-output --rfj)"

JOBID="$(jq -r '.data.jobid'  <<< "$JOB")"
RC="$(jq    -r '.data.retcode' <<< "$JOB")"

zowe jobs download output "$JOBID" --directory "./out/$JOBID"

echo "$JOBID finished with $RC"
[[ "$RC" == "CC 0000" ]] || exit 1

Output:

text
JOB04219 finished with CC 0000

Promote source PDS → USS git repo → back to PDS

Round-trip a PDS through git: download every member as a file, commit, edit, push, then upload the changed members back.

bash
# 1. Pull the PDS into ./src/
zowe files download all-members 'ALICE.SOURCE' --directory ./src \
    --extension .cbl --binary false --encoding IBM-1047

# 2. Commit & edit & test on your laptop
git add ./src && git commit -m "snapshot"
# ... edit files in your editor ...
git commit -am "fix: handle null in COMPUTE-TOTAL"

# 3. Push changed files back into the PDS
git diff --name-only HEAD~1 HEAD | while read -r f; do
    member="$(basename "$f" .cbl | tr '[:lower:]' '[:upper:]')"
    zowe files upload file-to-data-set "$f" "ALICE.SOURCE($member)" \
        --binary false --encoding IBM-1047
done

Output:

text
Member(s) downloaded successfully: 47
Data set member uploaded successfully: ALICE.SOURCE(BILLCALC)
Data set member uploaded successfully: ALICE.SOURCE(LEDGER01)

Find a job by its NOTIFY name, dump its first SYSOUT

After kicking off ALICEJ01 from ISPF you want the latest sysout on your laptop without opening SDSF.

bash
JOBID="$(zowe jobs list jobs --prefix ALICEJ01 --owner ALICE --rfj \
         | jq -r '.data | sort_by(.jobid) | last | .jobid')"

zowe jobs view spool-file-by-id "$JOBID" 4

Output:

text
1                                                                          IEF142I ALICEJ01 STEP01 - STEP WAS EXECUTED - COND CODE 0000
                                                                          IGD104I  ALICE.NEW.DATA RETAINED

Bulk-allocate a tree of test datasets

Allocate 20 sequential datasets from a Bash loop — a task that would otherwise require 20 ISPF panel screens or a JCL with 20 IEFBR14 steps.

bash
for i in $(seq -w 1 20); do
    zowe files create data-set-sequential "ALICE.TEST.DAT${i}" \
        --record-format FB --record-length 80 --block-size 27920 \
        --primary-space 1 --alcunit CYL
done

Output:

text
Data set created successfully.
Data set created successfully.
...

One-line MVS health check from a shell

A sanity sweep before kicking off a batch overnight: confirm z/OSMF, JES2, and the target Db2 subsystem are alive.

bash
zowe zosmf check status --rfj | jq -r '.data.zosmfFullVersion'
zowe console issue command '$DI'  --rfj | jq -r '.data.commandResponse' | tail -2
zowe console issue command '-DIS GROUP'  --console-name SDSN

Output:

text
31.0.0
$HASP890 INIT(1) ACTIVE
$HASP890 INIT(2) ACTIVE
DSN9022I -DSN1 DISPLAY GROUP REPORT FOLLOWS

Schedule a Zowe job from GitHub Actions

The full pipeline pattern — checkout the repo, install Zowe, decrypt secrets, submit JCL, fail on non-zero RC.

yaml
name: Nightly mainframe build
on:
  schedule: [{ cron: "0 2 * * *" }]
  workflow_dispatch:

jobs:
  run-nightly:
    runs-on: ubuntu-latest
    env:
      ZOWE_OPT_USER:     ${{ secrets.MAINFRAME_USER }}
      ZOWE_OPT_PASSWORD: ${{ secrets.MAINFRAME_PASSWORD }}
      ZOWE_OPT_HOST:     ${{ secrets.ZOSMF_HOST }}
      ZOWE_OPT_PORT:     "10443"
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - run: npm install -g @zowe/cli@latest
      - name: Submit nightly
        run: |
          OUT="$(zowe jobs submit data-set 'ALICE.JCL.LIB(NIGHTLY)' \
                 --wait-for-output --rfj)"
          echo "$OUT" | jq .
          RC="$(echo "$OUT" | jq -r '.data.retcode')"
          [[ "$RC" == "CC 0000" ]] || exit 1
      - if: failure()
        run: zowe jobs download output "$(echo "$OUT" | jq -r '.data.jobid')" \
             --directory ./nightly-out
      - uses: actions/upload-artifact@v4
        with:
          name: nightly-spool
          path: ./nightly-out

Output: (none — exits 0 on success)

Bridge to USS, run a shell script, ship the artifact back

A common DevOps pattern — code lives on USS, a Bash build runs there, and the resulting tar lands on your laptop.

bash
zowe uss issue ssh "cd /u/alice/build && ./build.sh > build.log 2>&1"
zowe files download uss-file /u/alice/build/build.log --file ./build.log
zowe files download uss-file /u/alice/build/dist.tar  --file ./dist.tar --binary

Output:

text
USS file downloaded successfully to ./build.log
USS file downloaded successfully to ./dist.tar

Inspect VSAM cluster from the CLI

zowe files list cannot read VSAM directly, but Zowe can submit a one-shot IDCAMS LISTCAT job and download its sysout.

bash
cat > /tmp/idcams.jcl <<'JCL'
//ALICEAD1 JOB (ACCT),'ALICE DEV',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//STEP1    EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
  LISTCAT ENTRIES('ALICE.VSAM.KSDS') ALL
/*
JCL

zowe jobs submit local-file /tmp/idcams.jcl --wait-for-output \
    --view-all-spool-content > /tmp/listcat.out
grep -E '(CLUSTER|HI-USED|HI-ALLOC|FREESPACE)' /tmp/listcat.out

Output:

text
CLUSTER ------ ALICE.VSAM.KSDS
       HI-USED-RBA------------4096
       HI-ALLOC-RBA----------40960
       FREESPACE-%CI--------------10
       FREESPACE-%CA--------------20

Compare a local file to a PDS member without checkout

Quick diff between your laptop's working copy and what is currently in the PDS — useful before an upload.

bash
zowe files compare data-set 'ALICE.JCL.LIB(NIGHTLY)' \
    --file ./nightly.jcl

Output:

text
< Line 23: NOTIFY=&SYSUID,REGION=4M
> Line 23: NOTIFY=&SYSUID,REGION=0M

Sources