Skip to content

cybersorcerer/go-zcli

Repository files navigation

zcli - Command Line Interface to z/OS

zcli is a command line interface (CLI) to IBM z/OS REST services, allowing you to interact with z/OS from your local machine. It communicates with z/OSMF (z/OS Management Facility) REST APIs to manage jobs, datasets, files, filesystems, software instances, and more.

Features

  • Jobs - List, submit, cancel, hold, release, change class; browse spool files in a TUI
  • Datasets - List, read, create, delete; list members; utilities (copy, rename, hrecall, hmigrate, hdelete, AMS)
  • Files - List, retrieve, write, create, delete z/OS UNIX files; chmod, chown, chtag, extattr
  • Filesystems - Create, delete, mount, unmount, list z/OS UNIX filesystems (zFS)
  • MFS - List mounted filesystems with optional TUI browser
  • Software - Query SMP/E CSI, list software instances, check critical/software/fixcat updates, export, dataset listing
  • Console - Issue z/OS console commands with full support for solicited/unsolicited message detection, async mode, custom console names, and console attributes (auth, routcode, mscope, storage, auto); retrieve delayed responses, detection results, and hardcopy logs
  • Parmlib - Validate syntax of z/OS parmlib members (all 38 supported types); supports active member validation, specific member, deep LOADxx traversal, and stdin input
  • TSO - Issue TSO/E commands
  • Topology - List groups, sysplexes, systems; validate system/plex connectivity
  • Notifications - List and send z/OSMF notifications
  • Subsystems - List MVS subsystems with optional TUI
  • Sysvar - Get, create, delete, import, and export z/OSMF system variables with optional TUI (including inline create and delete actions)
  • RTD - Retrieve runtime diagnostic data
  • Info - Retrieve z/OSMF server information
  • Profile - Display zcli connection profiles

Requirements

  • Go 1.22 or later (for building from source)
  • Access to a z/OSMF instance on z/OS 2.4 or later

Installation

From source

git clone <repository-url>
cd zcli
make build-local
make install

This builds the binary for your platform and installs it to $HOME/bin.

Cross-platform build

make build

Produces binaries in bin/ for:

  • macOS (amd64, arm64)
  • Linux (amd64, s390x)
  • Windows (amd64)

Build on z/OS

Cross-compilation for z/OS is not supported. Build natively on z/OS using the Open Enterprise SDK for Go.

This project uses the following extended modules that require special handling on z/OS: golang.org/x/sys, golang.org/x/sync, golang.org/x/text

Before building, update the extended modules to their latest z/OS-compatible versions:

go get golang.org/x/sys@latest
go get golang.org/x/sync@latest
go get golang.org/x/text@latest
go mod tidy

Then build:

go build -ldflags '-X main.version=v0.5.1 -X main.commit=$(git rev-parse --short HEAD)' -o zcli .

GitHub Releases

When a version tag (e.g. v0.5.1) is pushed, GitHub Actions automatically builds all platform binaries and creates a release with the artifacts attached.

git tag v0.5.1
git push origin v0.5.1

Configuration

zcli reads its configuration from ~/.config/zcli/zcli.json. The configuration file contains z/OSMF connection profiles and default settings.

Example configuration

{
  "profiles": {
    "my_zosmf": {
      "type": "zosmf",
      "properties": {
        "host": "zosmf.example.com",
        "port": "443",
        "protocol": "https",
        "user": "MYUSER",
        "password": "mypassword",
        "encoding": "IBM-1047",
        "rejectUnauthorized": false
      }
    }
  },
  "defaults": [
    {
      "profiles": [
        { "zosmf": "my_zosmf" }
      ]
    }
  ]
}

Usage

zcli [command] [subcommand] [flags]

Global flags

Flag Short Description
--profile-name z/OSMF profile to use (default: from config)
--verify TLS certificate verification (default: false)
--debug -d Enable debug logging
--format Output format: json or text (default: json)

Examples

# Get z/OSMF server information
zcli info

# List jobs with TUI
zcli jobs ls --tui --prefix 'TEST*' --status active

# List jobs as JSON
zcli jobs ls --owner MYUSER --prefix 'BATCH*'

# Submit a job from local file
zcli jobs submit --file-name /path/to/job.jcl

# Submit a job from host dataset or UNIX file
zcli jobs submit --remote-file 'MYUSER.JCL(TESTJOB)'
zcli jobs submit --remote-file '/u/myuser/myjob.jcl'

# Submit with internal reader options
zcli jobs submit --file-name /path/to/job.jcl --intrdr-class A --intrdr-recfm F --intrdr-lrecl 80

# Submit with JCL symbols
zcli jobs submit --file-name /path/to/job.jcl --jcl-symbol DSN=MYUSER.DATA --jcl-symbol VOL=MYVOL

# Submit with notification
zcli jobs submit --file-name /path/to/job.jcl --notification-url https://my.server/notify --notification-options 0,1,2

# List datasets
zcli datasets list --dsn-level 'MYUSER.**'

# List datasets with volume filter
zcli datasets list --dsn-level 'SYS1.**' --volser SYSRES

# List datasets with custom attributes and max items
zcli datasets list --dsn-level 'MYUSER.**' --attributes base --max-items 50

# List members of a PDS
zcli datasets members --ds-name 'SYS1.PROCLIB'

# List members with base attributes
zcli datasets members --ds-name 'SYS1.PROCLIB' --attributes base,total

# List members with pattern filter
zcli datasets members --ds-name 'SYS1.PROCLIB' --pattern 'IEF*' --max-items 20

# Read a dataset member
zcli datasets read --ds-name 'MYUSER.JCL' --member-name TESTJOB

# Read as binary
zcli datasets read --ds-name 'MYUSER.LOAD' --member-name MYPROG --data-type binary

# Read with record range (first 10 records)
zcli datasets read --ds-name 'MYUSER.DATA' --record-range '0-9'

# Search for a string in a dataset
zcli datasets read --ds-name 'MYUSER.JCL' --member-name TESTJOB --search 'EXEC PGM'

# Search with regex
zcli datasets read --ds-name 'MYUSER.JCL' --member-name TESTJOB --research 'EXEC +PGM' --insensitive false

# Read an uncataloged dataset
zcli datasets read --ds-name 'OLD.DATA' --volser VOL001

# Read with ENQ lock for editing
zcli datasets read --ds-name 'MYUSER.DATA' --obtain-enq SHRW

# Write a local file to a sequential dataset
zcli datasets write --ds-name 'MYUSER.DATA' --local-file data.txt

# Write a local file to a PDS member (creates member if it does not exist)
zcli datasets write --ds-name 'MYUSER.JCL' --member-name TESTJOB --local-file testjob.jcl

# Write from stdin
cat modified.txt | zcli datasets write --ds-name 'MYUSER.JCL' --member-name TESTJOB --stdin

# Write binary data
zcli datasets write --ds-name 'MYUSER.LOAD' --member-name MYPROG --data-type binary --local-file myprog.obj

# Write to uncataloged dataset
zcli datasets write --ds-name 'OLD.DATA' --volser VOL001 --local-file data.txt

# Atomic exclusive lock/write/unlock (ENQ auto-released after write)
zcli datasets write --ds-name 'SYS1.PARMLIB' --member-name SMFPRM00 --obtain-enq EXCLU --local-file smfprm00.txt

# Read-modify-write pipeline with ENQ held across steps
REF=$(zcli datasets read --ds-name 'SYS1.PARMLIB' --member-name SMFPRM00 --obtain-enq EXCLU | grep 'X-IBM-Session-Ref' | awk '{print $2}')
# ... modify data locally ...
zcli datasets write --ds-name 'SYS1.PARMLIB' --member-name SMFPRM00 --session-ref "$REF" --release-enq --local-file smfprm00.txt

# Optimistic locking via ETag (rejected with HTTP 412 if modified since read)
ETAG=$(zcli datasets read --ds-name 'SYS1.PARMLIB' --member-name SMFPRM00 --return-etag | grep 'Etag' | awk '{print $2}')
zcli datasets write --ds-name 'SYS1.PARMLIB' --member-name SMFPRM00 --if-match "$ETAG" --local-file smfprm00.txt

# Create a PDS
zcli datasets create --ds-name 'MYUSER.NEW.PDS' --dsorg PO --recfm FB --lrecl 80

# Create a sequential dataset
zcli datasets create --ds-name 'MYUSER.NEW.SEQ' --dsorg PS --primary 20 --secondary 10

# Delete a dataset
zcli datasets delete --ds-name 'MYUSER.OLD.DATA'

# Delete a PDS member
zcli datasets delete --ds-name 'MYUSER.JCL' --member-name OLDJOB

# Rename a dataset
zcli datasets utilities rename --ds-name 'MYUSER.NEW.NAME' --from-ds-name 'MYUSER.OLD.NAME'

# Rename a PDS member
zcli datasets utilities rename --ds-name 'MYUSER.JCL' --member-name NEWMEM --from-ds-name 'MYUSER.JCL' --from-member OLDMEM

# Copy a dataset
zcli datasets utilities copy --ds-name 'MYUSER.TARGET' --from-ds-name 'MYUSER.SOURCE' --replace

# Copy all members
zcli datasets utilities copy --ds-name 'MYUSER.TARGET.PDS' --from-ds-name 'MYUSER.SOURCE.PDS' --from-member '*' --replace

# Copy a single member to a new name
zcli datasets utilities copy --ds-name 'MYUSER.PDS' --member-name NEWMEM --from-ds-name 'MYUSER.PDS' --from-member OLDMEM

# Copy from a z/OS UNIX file to a dataset
zcli datasets utilities copy --ds-name 'MYUSER.DATA' --from-file '/u/myuser/input.txt'

# Recall a migrated dataset
zcli datasets utilities hrecall --ds-name 'MYUSER.ARCHIVED' --wait

# Migrate a dataset
zcli datasets utilities hmigrate --ds-name 'MYUSER.OLDDATA'

# Delete a migrated dataset backup
zcli datasets utilities hdelete --ds-name 'MYUSER.OLDBACKUP' --purge

# Invoke IDCAMS Access Method Services
zcli datasets utilities ams \
  --input "DEFINE CLUSTER(NAME (MYUSER.KSDS) VOLUMES(VSER05)) -" \
  --input "DATA  (KILOBYTES (50 5))"

# Delete a VSAM cluster via AMS
zcli datasets utilities ams --input "DELETE MYUSER.KSDS CLUSTER"

# AMS on a remote system
zcli datasets utilities ams --input "LISTCAT ALL" --target-system SYSB

# List z/OS UNIX files
zcli files list --path-name /u/myuser

# Retrieve a z/OS UNIX file
zcli files retrieve --zunix-file-name /u/myuser/hello.c

# Hold a job (sync by default, use --async for v1.0 async processing)
zcli jobs hold --jobname TESTJOB --jobid JOB01234
zcli jobs hold --jobname TESTJOB --jobid JOB01234 --async

# Hold/release/cancel on a remote system
zcli jobs hold --jobname TESTJOB --jobid JOB01234 --target-system SYSB --target-user USER1 --target-password secret

# Change job class (sync by default)
zcli jobs change-class --jobname TESTJOB --jobid JOB01234 --class B
zcli jobs change-class --jobname TESTJOB --jobid JOB01234 --class B --async

# List z/OS UNIX filesystems (TUI)
zcli filesystems list --tui

# Create a zFS filesystem
zcli filesystems create --fs-name MYUSER.GO.ZFS --cyls-pri 100 --cyls-sec 20 --owner MYUSER --perms 755

# List mounted filesystems (TUI)
zcli mfs --tui

# Issue a console command
zcli console command -c 'd a,l' --text

# Issue a console command with keyword detection
zcli console command -c 'd a,PEGASUS' --sol-key PEGASUS --text

# Issue a console command asynchronously
zcli console command -c 's PEGASUS' --async --unsol-key PEGASUS

# Issue a console command with custom console and auth
zcli console command -c 'd a,l' -n MYCONSOL --auth MASTER --routcode ALL

# Retrieve a delayed console response
zcli console get-response -k C6557643 --text

# Retrieve unsolicited keyword detection result
zcli console get-detection -k dec6800

# Retrieve hardcopy log entries (relative time)
zcli console log --ago 1h --text
zcli console log --ago 30m --hardcopy OPERLOG --text

# Retrieve hardcopy log entries (absolute time, various formats)
zcli console log --time "2026-03-28 10:00" --direction forward --text
zcli console log --time 08:30 --time-range 30m --text
zcli console log --time 2026-03-28T10:00:00Z --hardcopy SYSLOG --sys-name MAIN

# Validate parmlib syntax (all active members of a type)
zcli parmlib validate BPXPRM --text

# Validate a specific parmlib member
zcli parmlib validate BPXPRM --member BPXPRM00 --dataset SYS1.PARMLIB --text

# Validate all members of a type via specific LOADxx
zcli parmlib validate CONSOL --load-member LOADAC --load-dataset SYS1.PARMLIB --text

# Validate all parmlib types deeply
zcli parmlib validate LOAD --deep --text

# Validate parmlib content from stdin
cat /tmp/BPXPRM00 | zcli parmlib validate BPXPRM --text

# Issue a TSO command
zcli tso command --command 'LISTCAT'

# List MVS subsystems
zcli subsystems list

# List MVS subsystems with TUI
zcli subsystems list --tui

# Filter subsystems by ID
zcli subsystems list --ssid 'JES*'

# Get system variables
zcli sysvar get -x MAISEC -y MAIN

# Get system variables with TUI (supports create and delete)
zcli sysvar get -x MAISEC -y MAIN --tui

# Create/update system variables
zcli sysvar create -x MAISEC -y MAIN --var MYVAR=value1 --desc "My variable"

# Delete system variables
zcli sysvar delete -x MAISEC -y MAIN --var MYVAR

# Export system variables to z/OS file
zcli sysvar export -x MAISEC -y MAIN --file /u/myuser/vars.csv -w

# Export and download locally
zcli sysvar export -x MAISEC -y MAIN --file /u/myuser/vars.csv -w --local ./vars.csv

# Import system variables from z/OS file
zcli sysvar import -x MAISEC -y MAIN --file /u/myuser/vars.csv

# Upload local file and import
zcli sysvar import -x MAISEC -y MAIN --file /u/myuser/vars.csv --local ./vars.csv

# Query SMP/E CSI
zcli software query csids \
  --global-csi MY.GLOBAL.CSI \
  --entry SYSMOD \
  --subentries APPLY,ERROR \
  --filter "ename='HBB77E0'"

# List software instances
zcli software instances list

# List datasets of a software instance
zcli software instances silistds --uuid <uuid>

# List topology groups
zcli topology groups

# Validate system connectivity
zcli topology validate system --name MYSYS

# Use a specific profile
zcli --profile-name my_other_zosmf info

TUI keyboard shortcuts

The interactive TUI (Terminal User Interface) is available for jobs ls, mfs, filesystems list, subsystems list, and sysvar get (use --tui flag).

Jobs TUI:

Key Action
Ctrl+S / Enter Select job files / spool content
F3 Go back to previous view
Ctrl+R Refresh job list
Ctrl+L Cancel selected job
Ctrl+H Hold selected job
Ctrl+E Release selected job
Ctrl+C Quit
F7 / F8 Page up / down
G / g Jump to bottom / top

Filesystems TUI:

Key Action
Enter View filesystem details
F3 Go back to list
Ctrl+N Create new zFS filesystem (11-field form)
Ctrl+U Unmount selected filesystem (with confirmation)
Ctrl+X Delete selected filesystem (with confirmation)
Ctrl+R Refresh
Ctrl+C Quit
F7 / F8 Page up / down

MFS TUI:

Key Action
Ctrl+S / Enter View filesystem details
F3 Go back to list
Ctrl+R Refresh
Ctrl+C Quit

Subsystems TUI:

Key Action
Ctrl+R Refresh
Ctrl+C Quit
F7 / F8 Page up / down

Sysvar TUI:

Key Action
Ctrl+N Create / update a variable
Ctrl+X Delete selected variable (with confirmation)
Ctrl+R Refresh
Ctrl+C Quit
Tab Navigate form fields
F3 Cancel form / go back
F7 / F8 Page up / down

Console command flags

The console command subcommand supports the full z/OSMF REST Console API:

Flag Description
--command/-c z/OS command to issue (required)
--console-name/-n EMCS console name, 2-8 chars (default: defcn)
--async/-a Issue command asynchronously
--system/-s Target system in the sysplex
--sol-key Keyword to detect in command response
--sol-key-regex Treat sol-key as a regular expression
--unsol-key Keyword to detect in unsolicited messages
--unsol-key-regex Treat unsol-key as a regular expression
--detect-time Seconds to detect unsol-key (server default: 30)
--unsol-detect-sync Detect unsol-key synchronously
--unsol-detect-timeout Timeout for synchronous detection (server default: 20)
--auth Console authority: MASTER, ALL, INFO, CONS, IO, SYS
--routcode Routing codes: ALL, NONE, or list
--mscope Message scope: ALL, LOCAL, or system names
--storage Storage in KB for message queuing (1-2000)
--auto Automation: YES or NO
--text Format response as readable text

Console log flags

Flag Description
--ago Start time relative to now: 30s, 10m, 2h, 1h30m (overrides --time)
--time Start time: 2006-01-02, 2006-01-02 15:04, 15:04, 15:04:05, or ISO 8601
--timestamp Start time as UNIX timestamp in milliseconds (overrides --time and --ago)
--time-range Time range: nnnu where u is s/m/h (e.g. 10m, 1h, 30s); default 10m
--direction Direction from start time: forward or backward (default: backward)
--hardcopy Log source: operlog or syslog (default: operlog, fallback syslog)
--sys-name System name for SYSLOG (only valid with --hardcopy syslog)
--text Display messages as formatted text

Parmlib validate flags

Flag Short Description
--member -m Specific member name to validate (e.g. BPXPRM01)
--dataset Dataset containing the member (e.g. SYS1.PARMLIB)
--volser Volser for dataset if not cataloged
--load-member LOADxx member name for type resolution (e.g. LOADAC)
--load-dataset Dataset containing the LOADxx member
--load-volser Volser for load-dataset if not cataloged
--deep Validate all types deeply — only valid with LOAD
--system Remote system name in the sysplex
--text Display the response as formatted text

Build

make build-local    # Build for current platform
make build          # Cross-platform build
make build-zos      # Show z/OS native build instructions
make install        # Install to $HOME/bin
make clean          # Remove build artifacts
make dep            # Download and tidy dependencies
make vet            # Run go vet
make lint           # Run golangci-lint
make test           # Run tests

License

Copyright (c) 2025, 2026 Sir Tobi aka Cybersorcerer

See LICENSE for details.

About

CLI for z/OS z/OSMF REST API

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors