{"id":30824194,"url":"https://github.com/tbidne/shrun","last_synced_at":"2025-09-06T11:52:40.560Z","repository":{"id":37724768,"uuid":"367789488","full_name":"tbidne/shrun","owner":"tbidne","description":"A utility program for running shell commands concurrently.","archived":false,"fork":false,"pushed_at":"2025-08-18T00:08:03.000Z","size":6928,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-18T01:04:49.723Z","etag":null,"topics":["command-line","concurrency","shell-scripting","utils"],"latest_commit_sha":null,"homepage":"https://tbidne.github.io/shrun","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tbidne.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-05-16T05:06:15.000Z","updated_at":"2025-08-18T00:08:07.000Z","dependencies_parsed_at":"2023-12-08T03:26:58.342Z","dependency_job_id":"776829b2-1149-4844-9692-a1636c0b3516","html_url":"https://github.com/tbidne/shrun","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/tbidne/shrun","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbidne%2Fshrun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbidne%2Fshrun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbidne%2Fshrun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbidne%2Fshrun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tbidne","download_url":"https://codeload.github.com/tbidne/shrun/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbidne%2Fshrun/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273899915,"owners_count":25187737,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-06T02:00:13.247Z","response_time":2576,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["command-line","concurrency","shell-scripting","utils"],"created_at":"2025-09-06T11:52:35.346Z","updated_at":"2025-09-06T11:52:40.537Z","avatar_url":"https://github.com/tbidne.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# Shrun\n\n## Run Shell Commands Concurrently\n\n[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/tbidne/shrun?include_prereleases\u0026sort=semver\u0026labelColor=2f353e)](https://github.com/tbidne/shrun/releases/)\n[![ci](http://img.shields.io/github/actions/workflow/status/tbidne/shrun/ci.yaml?branch=main)](https://github.com/tbidne/shrun/actions/workflows/ci.yaml)\n[![MIT](https://img.shields.io/github/license/tbidne/shrun?color=blue\u0026labelColor=2f353e)](https://opensource.org/licenses/MIT)\n\n![linux](https://img.shields.io/static/v1?label=\u0026message=linux\u0026logo=linux\u0026logoColor=white\u0026labelColor=2f353e\u0026color=blue)\n![apple](https://img.shields.io/static/v1?label=\u0026message=osx\u0026logo=apple\u0026labelColor=2f353e\u0026color=blue)\n\n![demo](./examples/demo.gif)\n\n\u003c/div\u003e\n\n---\n\n### Table of Contents\n- [Motivation](#motivation)\n- [Introduction](#introduction)\n- [Installation](#installation)\n- [Building](#building)\n  - [Cabal](#cabal)\n  - [Stack](#stack)\n  - [Nix](#nix)\n- [Configuration](#configuration)\n- [FAQ](#faq)\n\n# Motivation\n\n`shrun` was borne of frustration. Suppose we need to run several shell commands on a regular basis e.g. updates after pulling the latest code. These can be run manually in separate terminals:\n\n```sh\ncmd1\ncmd2\ncmd3\n...\n```\n\nBut this can be a lot of repetitive typing, especially when the commands are longer. Thus an alias is born:\n\n```sh\nalias run_commands=\"cmd1 \u0026\u0026 cmd2 \u0026\u0026 cmd3 ...\"\n```\n\nAll well and good, but this approach has several deficiencies:\n\n1. There is no information about how long the commands have been running. If any of the commands are long-lived, how would we know when it has been \"too long\" and the commands should be cancelled? We could use a wall clock or a stopwatch, but that is imprecise and requires remembering every time the commands are run, which is certainly unsatisfying.\n\n1. These commands are all run synchronously even though there may be no relation between them. For example, three commands that each take 5 minutes will combine to take 15 minutes. This is usually unnecessary.\n\n1. Related to above, if any command fails then subsequent ones will not be run. This can be frustrating, especially when a quicker command in the beginning prevents a longer one at the end from even starting.\n\n1. If the alias is tweaked to run all regardless (`cmd1; cmd2; cmd3 ...`), then it can be difficult to determine which, if any, failed. Additionally, understanding logs is much harder.\n\n1. It does not scale. Imagine we have variations of `cmd3` we want to run under different circumstances. We could create multiple aliases:\n\n\n        alias run_commands_cmd3a=\"cmd1 \u0026\u0026 cmd2 \u0026\u0026 cmd3a\"\n        alias run_commands_cmd3b=\"cmd1 \u0026\u0026 cmd2 \u0026\u0026 cmd3b\"\n\n    But this is messy and grows exponentially in the number of aliases for each variation.\n\n`shrun` purports to overcome these limitations.\n\n# Introduction\n\nIn a nut-shell (😉), `shrun` is a wrapper around running shell commands. For instance:\n\n```sh\nshrun \"some long command\" \"another command\"\n```\n\nWill run `some long command` and `another command` concurrently.\n\nA running timer is provided, and stdout will be updated when a command finishes or crashes.\n\n# Installation\n\nThe [releases](https://github.com/tbidne/shrun/releases) page has binaries built for several platforms. If there are no binaries for your platform, it is possible to [build shrun](#building) yourself.\n\n# Building\n\nIf you have never built a haskell program before, [Cabal](#cabal) is probably the best choice.\n\n## Cabal\n\n### Prerequisites\n\n* [`cabal 3.8+`](https://www.haskell.org/cabal/download.html)\n* [`ghc 9.6 - 9.12`](https://gitlab.haskell.org/ghc/ghc/-/wikis/GHC%20Status)\n\nThe easiest way to install these is generally [`ghcup`](https://www.haskell.org/ghcup/).\n\nThe current \"blessed\" version is `ghc-9.10.1`.\n\n### Build Shrun\n\nOnce you have `cabal` and `ghc`, `shrun` can be built locally with `cabal build` or installed globally (e.g. `~/.local/bin/shrun`) with `cabal install`.\n\nFor further reproducibility, an optional freeze files can be used for the \"blessed\" compiler.\n\n```sh\ncabal build --project-file cabal.ghc\u003cXYZ\u003e.project\n```\n\n## Stack\n\n### Prerequisites\n\n* [`stack`](https://docs.haskellstack.org/en/stable/)\n\nLike `cabal` and `ghc`, `stack` can be installed with [`ghcup`](https://www.haskell.org/ghcup/).\n\n### Build Shrun\n\nOnce you have `stack`, `shrun` can be built with `stack build` or installed globally (i.e. `~/.local/bin/shrun`) with `stack install`.\n\n## Nix\n\n### Prerequisites\n\n* [nix](https://nixos.org/download.html)\n\n### Manually\n\nBuilding with `nix` uses [flakes](https://nixos.wiki/wiki/Flakes). `shrun` can be built with `nix build`, which will compile and run the tests.\n\n### Nix expression\n\nBecause `shrun` is a flake, it can be built as part of a nix expression. For instance, if you want to add `shrun` to `NixOS`, your `flake.nix` should have:\n\n```nix\n# flake.nix\n{\n  inputs.shrun.url = \"github:tbidne/shrun/main\";\n}\n```\n\nThen include this in the `systemPackages`:\n\n```nix\n# wherever your global packages are defined\n{\n  environment.systemPackages = [\n    shrun.packages.\"${system}\".default\n  ];\n}\n```\n\n# Configuration\n\nSee [configuration.md](documentation/configuration.md) for the available options.\n\n# FAQ\n\nSee [faq.md](documentation/faq.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftbidne%2Fshrun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftbidne%2Fshrun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftbidne%2Fshrun/lists"}