shops is a simple command-line tool written in Go that helps you simplify the way you manage configuration across a set of machines by using regular POSIX shell.
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Go to file
James Mills 87b8207b1a
Fix error logging
2 years ago
.chglog Fix import paths 2 years ago
examples Validate actions really fixed failing checks (#14) 2 years ago
testdata Validate actions really fixed failing checks (#14) 2 years ago
tools Add Makefile and release tools 2 years ago
.gitignore Add /dist to .gitignore 2 years ago
.goreleaser.yml Fix versioning of binaries in releases 2 years ago Fix import paths 2 years ago
LICENSE Updated docs, added LICENSE 2 years ago
Makefile Fix versioning the binaries 2 years ago Fix import paths 2 years ago
_config.yml Set theme jekyll-theme-architect 2 years ago
config.go Validate actions really fixed failing checks (#14) 2 years ago
error.go Fix bug with exitStatus.Error() and improve error hanadling when actions fail 2 years ago
go.mod Fix exit error/status handling 2 years ago
go.sum Fix exit error/status handling 2 years ago
local.go Fix exit error/status handling 2 years ago
main.go Validate actions really fixed failing checks (#14) 2 years ago
options.go Fix -c/--continue-on-error (#11) 2 years ago
result.go Validate actions really fixed failing checks (#14) 2 years ago
runner.go Validate actions really fixed failing checks (#14) 2 years ago
ssh.go Fix error logging 2 years ago
target.go Validate actions really fixed failing checks (#14) 2 years ago
template.go Fix bug rendering single-line funcs 2 years ago
utils.go Fix default user ot be current user from environment 2 years ago
utils_test.go Add another test case for ssh://host:port 2 years ago
version.go Initial Commit 2 years ago

shops - Shell Operations

GitHub All Releases Go Report Card codebeat badge GoDoc

shops is a simple command-line tool written in Go that runs a sequence of items (shell snippets) as "checks" and based on exit status of those checks runs "actions" to correct fails items.

shops also lets you copy files and directories to target(s) and define shell functions for improved readability and reuse of common logic all in regular shell.

shops is your configuration management tool of choice when Chef, Puppet, Ansible are all too complicated and all you really want to do is run a bunch of regular shell against a set of hosts.

Table of Contents

Created by gh-md-toc

Getting Started

Install from Releases

You can install shops by simply downloading the latest version from the Release page for your platform and placing the binary in your $PATH.

For convenience you can run one of the following shell pipelines which will download and install the latest release binary into /usr/local/bin (modify to suit):

For Linux x86_64:

curl -s | grep browser_download_url | grep Linux_x86_64 | cut -d '"' -f 4 | wget -q -O - -i - | tar -xv shops && mv shops /usr/local/bin/shops

For macOS x86_64:

curl -s | grep browser_download_url | grep Darwin_x86_64 | cut -d '"' -f 4 | wget -q -O - -i - | tar -xv shops && mv shops /usr/local/bin/shops

Install from Homebrew

On macOS you can install shops using Homebrew:

brew tap prologic/shops
brew install shops

Install from Source

To install shops from source you can run go get directly if you have a Go environment setup:

go get

NOTE: Be sure to have $GOBIN (if not empty) or your $GOPATH/bin in your $PATH. See Compile and install packages and dependencies

Or grab the source code and build:

git clone
cd shops
make build

And optionally run make install to place the binary shops in your $GOBIN or $GOPATH/bin (again see note above).


Using shops is quite simple. The basic usage is as follows:

shops -f /path/to/spec.yml <target1> <target2> <targetN>

Where target is either local:// to run the spec against localhost or hostname or hostname:port. See the format for targets above.

For example running the included sample.yml specification file which can be found in the ./testdata directory in the source tree as well as other examples:

shops -f ./testdata/sample.yml

Will perform the following:

  • Copy to /root/ on the server
  • Ensure /tmp/foo exists
  • Check the uptime of the server and display it.


shops -f ./testdata/sample.yml -> /root/ ✅
  Ensure /root/foo exists ✅ -> /root/foo
  Ensure sshbox is running ✅ ->
  Check Uptime ✅ -> 13:58:27 up 3 days,  1:38,  0 users,  load average: 0.00, 0.00, 0.00


Targets are specified in the form:


For local targets, only the type is required, e.g: local://.

For remote targets, the user and port are optional and if not specified in the target they default to the -u/--user (default: root) and -p/--port (default: 22) flags respectively.


Please peruse the Examples where I (and hopefully others) will place real-life examples of various types of tasks over time. Mostly these are biased towards my home infrastructure (a little server room with a 22RU rack cabinet and server gear). If you end up using shops in your infrastructure, even if it's just a Raspberry Pi, feel free to submit PR(s) to add useful examples and use-cases here too! 🙇


Remote targets are operated on via the SSH protocol using the ssh:// type which is implied by default or if the target looks like it might be a hostname or host:port pair.

Right now the only supported authentication methods are:

  • SSH Agent

This means you must have a locally running ssh-agent and it must have the identities you intend to use to operate on.

You can list these with ssh-add -l. If you do not have any listed this is likely the most common cause of "authentication failure" errors.

There is an issue (#9) in the backlog to address adding support for other authentication mechanisms such as:

  • Password based authentication with secure prompts
  • Key based authentication by providing an identity file and securely prompting for passphrase if applicable.

Specification File Format

The specification file format is a simple YAML file with the following structure:

veresion: 1

  FOO: bar
  BAR: ${FOO}

  - source: foo
    target: /tmp/foo

  foo: |
    echo "I am a function!"

  - name: Check #1
    check: true
    actino: foo
  - name: Checek #2
    check: false
    action: echo ${BAR}

A valid spec consists of a number of top-level keys:

  • version -- Which for the moment is ignored, but might be used to version the specification file for future enhancements in a backwards compatible way.
  • env -- Environment variables defined as a map of keys and values (order is preserved) and shell interpolation is supported. Shell interpolation occurs on the target(s), not locally. Variables can be overridden with the -e/--env flag with the form KEY[=<value>]. If value is omitted the value is taken from the local environment where shops is run.
  • files -- Declares one or more files or directories to be copied to each target. Directories are copied recursively. Currently no checks are performed, but this is planned (#4).
  • funcs -- A mapping of function name to the function's body. There is no need to write the function name with foo() { ... } as the shops runner(s) will do this automatically when injecting functions into the session(s) (in fact doing so in an error).
  • items -- One or more items of configuration to be applied to each target. Each item declares a "check" and "action". Checks and actions are written in regular shell. If a check fails, the action is run to correct the failed state. If all checks pass, no actions are run. If an action fails the target is considered failed unless -c/--continue-on-error flag is passed to shops.


shops by default-runs the "check" of each item to validate the "action".

If an action is intended to be run regardless of the state of the check, then the skip_validation key can be set to true to skip validation.


version: 1

  - name: Skip validation
    check: false
    action: echo "Hello World"

This behavior ensures that not only are failed checks fixed by appropriate actions, but that those actions are validated to be correct against the check asserting the state in the first place.


shops is licensed under the terms of the MIT License