{"id":13496261,"url":"https://github.com/mxcl/swift-sh","last_synced_at":"2025-05-14T16:13:38.370Z","repository":{"id":45448083,"uuid":"165341891","full_name":"mxcl/swift-sh","owner":"mxcl","description":"Easily script with third-party Swift dependencies.","archived":false,"fork":false,"pushed_at":"2024-09-17T20:15:28.000Z","size":371,"stargazers_count":1819,"open_issues_count":21,"forks_count":60,"subscribers_count":23,"default_branch":"master","last_synced_at":"2025-04-11T06:16:22.310Z","etag":null,"topics":["scripting","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mxcl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","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},"funding":{"github":"mxcl","patreon":"mxcl"}},"created_at":"2019-01-12T03:30:36.000Z","updated_at":"2025-04-01T08:20:51.000Z","dependencies_parsed_at":"2024-10-30T13:02:05.352Z","dependency_job_id":"f15b44c4-53ab-4c47-8e4b-58ba75de42cc","html_url":"https://github.com/mxcl/swift-sh","commit_stats":{"total_commits":197,"total_committers":21,"mean_commits":9.380952380952381,"dds":0.2842639593908629,"last_synced_commit":"132622b333a490b89467bacfa53d943aac140a6d"},"previous_names":[],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mxcl%2Fswift-sh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mxcl%2Fswift-sh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mxcl%2Fswift-sh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mxcl%2Fswift-sh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mxcl","download_url":"https://codeload.github.com/mxcl/swift-sh/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248351394,"owners_count":21089272,"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","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":["scripting","swift"],"created_at":"2024-07-31T19:01:44.707Z","updated_at":"2025-04-11T06:16:48.147Z","avatar_url":"https://github.com/mxcl.png","language":"Swift","readme":"# `swift sh` ![badge-platforms] ![badge-languages] [![Build Status](https://travis-ci.com/mxcl/swift-sh.svg)](https://travis-ci.com/mxcl/swift-sh)\n\nWriting Swift scripts is *easy*:\n\n```sh\n$ cat \u003c\u003cEOF \u003e script\n#!/usr/bin/swift\nprint(\"Hi!\")\nEOF\n$ chmod u+x script\n$ ./script\nHi!\n```\n\nSadly, to use third-party dependencies we have to migrate our script to a swift\npackage and use `swift build`, a relatively heavy solution when all we wanted\nwas to whip up a quick script. `swift-sh` gives us the best of both worlds:\n\n```sh\n$ cat \u003c\u003cEOF \u003e script\n#!/usr/bin/swift sh\nimport PromiseKit  // @mxcl ~\u003e 6.5\nprint(Promise.value(\"Hi!\"))\nEOF\n$ chmod u+x script\n$ ./script\nPromise(\"Hi!\")\n```\n\nIn case it’s not clear, `swift-sh` reads the comment after the `import` and\nuses this information to fetch your dependencies.\n\n---\n\nLet’s work through an example: if you had a *single file* called `foo.swift`\nand you wanted to import [mxcl/PromiseKit](https://github.com/mxcl/PromiseKit):\n\n```swift\n#!/usr/bin/swift sh\n\nimport Foundation\nimport PromiseKit  // @mxcl ~\u003e 6.5\n\nfirstly {\n    after(.seconds(2))\n}.then {\n    after(.milliseconds(500))\n}.done {\n    print(\"notice: two and a half seconds elapsed\")\n    exit(0)\n}\n\nRunLoop.main.run()\n```\n\nYou could run it with:\n\n```\n$ swift sh foo.swift\n```\n\nOr to make it more “scripty”, first make it executable:\n\n```\n$ chmod u+x foo.swift\n$ mv foo.swift foo    # optional step!\n```\n\nAnd then run it directly:\n\n```\n$ ./foo\n```\n\n# Sponsorship\n\nIf your company depends on `swift-sh` please consider sponsoring the project.\nOtherwise it is hard for me to justify maintaining it.\n\n# Installation\n\n```\nbrew install swift-sh\n```\n\nOr you can build manually using `swift build`.\n\nInstallation results in a single executable called `swift-sh`, the `swift`\nexecutable will call this (provided it is in your `PATH`) when you type:\n`swift sh`.\n\nWe actively support both Linux and Mac and will support Windows as soon as it is\npossible to do so.\n\n# Usage\n\nAdd the *shebang* as the first line in your script: `#!/usr/bin/swift sh`.\n\nYour dependencies are determined via your `import` lines:\n\n```swift\n#!/usr/bin/swift sh\nimport AppUpdater    // @mxcl\n// ^^ https://github.com/mxcl/AppUpdater, latest version\n\nimport PromiseKit    // @mxcl ~\u003e 6.5\n// ^^ mxcl/PromiseKit, version 6.5.0 or higher up to but not including 7.0.0 or higher\n\nimport Chalk         // @mxcl == 0.3.1\n// ^^ mxcl/Chalk, only version 0.3.1\n\nimport LegibleError  // @mxcl == b4de8c12\n// ^^ mxcl/LegibleError, the precise commit `b4de8c12`\n\nimport Path          // mxcl/Path.swift ~\u003e 0.16\n// ^^ for when the module-name and repo-name are not identical\n\nimport BumbleButt    // https://example.com/bb.git ~\u003e 9\n// ^^ non-GitHub URLs are fine\n\nimport CommonTaDa    // git@github.com:mxcl/tada.git ~\u003e 1\n// ^^ ssh URLs are fine\n\nimport TaDa          // ssh://git@github.com:mxcl/tada.git ~\u003e 1\n// ^^ this style of ssh URL is also fine\n\nimport Foo  // ./my/project\nimport Bar  // ../my/other/project\nimport Baz  // ~/my/other/other/project\nimport Fuz  // /I/have/many/projects\n// ^^ local dependencies must expose library products in their `Package.swift`\n// careful: `foo/bar` will be treated as a GitHub dependency; prefix with `./`\n// local dependencies do *not* need to be versioned\n\n\nimport Floibles  // @mxcl ~\u003e 1.0.0-alpha.1\nimport Bloibles  // @mxcl == 1.0.0-alpha.1\n// ^^ alphas/betas will only be fetched if you specify them explicitly like so\n// this is per Semantic Versioning guidelines\n```\n\n`swift-sh` reads the comments after your imports and fetches the requested\nSwiftPM dependencies.\n\nIt is not necessary to add a comment specification for transitive dependencies.\n\n# Editing in Xcode\n\nThe following will generate an Xcode project (not in the working directory, we\nkeep it out the way in our cache directory) and open it, edits are saved to your\nscript file.\n\n```\n$ swift sh edit ./myScript\n```\n\n# Examples\n\n* [Tweet deleter](https://gist.github.com/mxcl/002c3514d50b73287c89268c45662394)\n* [PostgreSQL Check](https://gist.github.com/joscdk/c4b89add26509c6dfabf84974e62543d)\n\n# Converting your script to a package\n\nSimple scripts can quickly become bigger projects that would benefit from being\npackages that you build with SwiftPM. To help you migrate your project we\nprovide `swift sh eject`, for example:\n\n    $ swift sh eject foo.swift\n\ncreates a Swift package in `./Foo`, from now on use `swift build` in the\n`Foo` directory. Your script is now `./Foo/Sources/main.swift`.\n\n# Use in CI\n\nIf you want to make scripts available to people using CI; use `stdin`:\n\n    brew install mxcl/made/swift-sh\n    swift sh \u003c(curl http://example.com/yourscript) arg1 arg2\n\n# Internal Details\n\n`swift sh` creates a Swift `Package.swift` package manager project with\ndependencies in a directory below the swift-sh cache directory †,\nbuilds the executable, and then executes it via `swift run`.\nThe script is (only) rebuilt when the script file is newer than the executable.\n\n† Specify the cache parent directory using the (FreeDesktop) environment\nvariable XDG_CACHE_HOME.  If unspecified, on macOS `swif-sh` uses\n`$HOME/Library/Developer/swift-sh.cache`, and otherwise it uses\n`$HOME/.cache/swift-sh`.\n\n# Swift Versions\n\n`swfit-sh` v2 requires Swift 5.1. We had to drop support for Swift v4.2\nbecause maintenance was just too tricky.\n\n`swift-sh` uses the active tools version, (ie: `xcode-select`) or whichever\nSwift is first in the `PATH` on Linux. It writes a manifest for the package\nit will `swift build` with that tools-version. Thus Xcode 11.0 builds with Swift 5.1.\nDependencies build with the Swift versions they declare support for, provided\nthe active toolchain can do that (eg. Xcode 11.0 supports Swift 4.2 and above)\n\nTo declare a support for specific Swift versions in your script itself, use\n`#if swift` or `#if compiler` directives.\n\n# Alternatives\n\n* [Beak](https://github.com/yonaskolb/Beak)\n* [Marathon](https://github.com/JohnSundell/Marathon)\n\n---\n\n# Troubleshooting\n\n### `error: unable to invoke subcommand: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-sh`\n\nIf you got here via Google, you have a script that uses this tool, if you now\ninstall `swift-sh`, you will be able to run your script:\n\n    brew install mxcl/made/swift-sh\n\nOr see the [above installation instructions](#Installation).\n\n[badge-platforms]: https://img.shields.io/badge/platforms-macOS%20%7C%20Linux-lightgrey.svg\n[badge-languages]: https://img.shields.io/badge/swift-5.1%20%7C%205.2%20%7C%205.3%20%7C%205.4%20%7C%205.5%20%7C%205.6%20%7C%205.7%20%7C%205.8%20%7C%205.9%20%7C%206.0-orange.svg\n","funding_links":["https://github.com/sponsors/mxcl","https://patreon.com/mxcl"],"categories":["Swift","HarmonyOS","Automation DSLs and tools"],"sub_categories":["Windows Manager","macOS Environments"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmxcl%2Fswift-sh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmxcl%2Fswift-sh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmxcl%2Fswift-sh/lists"}