{"id":24302790,"url":"https://github.com/taigrr/piper","last_synced_at":"2026-03-06T20:31:57.516Z","repository":{"id":102067046,"uuid":"389019425","full_name":"taigrr/piper","owner":"taigrr","description":"Patchbay style distributed pipe using NATS.io","archived":false,"fork":false,"pushed_at":"2026-02-23T16:34:49.000Z","size":68,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-02-24T00:27:28.951Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/taigrr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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}},"created_at":"2021-07-24T06:22:20.000Z","updated_at":"2026-02-23T16:34:53.000Z","dependencies_parsed_at":"2023-04-15T13:47:53.405Z","dependency_job_id":null,"html_url":"https://github.com/taigrr/piper","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/taigrr/piper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taigrr%2Fpiper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taigrr%2Fpiper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taigrr%2Fpiper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taigrr%2Fpiper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/taigrr","download_url":"https://codeload.github.com/taigrr/piper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taigrr%2Fpiper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30196173,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T19:07:06.838Z","status":"ssl_error","status_checked_at":"2026-03-06T18:57:34.882Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2025-01-17T00:19:23.617Z","updated_at":"2026-03-06T20:31:57.492Z","avatar_url":"https://github.com/taigrr.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## What?\n\nPiper is a [https://patchbay.pub/](https://patchbay.pub/) inspired shell tool that lets you connect separate shells together over a NATS based middleware.\n\nYou can use it to build things like network aware clipboards, notifications from servers to your desktop, ad hoc assembled work queues for doing shell based work on many cores and more.\n\n * It has two basic modes of operation: multi consumer and multi producer or a work queue style multi producer to a load shared group of consumers\n * By default the publisher will block until there are consumers, by default it will give up after 1 hour, you can adjust this using `--timeout 5m` or by setting `PIPER_TIMEOUT=5m` for example\n * An asynchronous mode, that avoid above blocking, is support if you have NATS JetStream\n * In synchronous mode no data is stored, it's all ephemeral and the data is private to either your own NATS servers or your account on Synadia NGS (NATS as a Service). This means we won't be doing anything like serving web pages but with the shell utility scope I quite like it\n * It's secure your data can not be accessed by anyone else\n * Your data is compressed, NATS isn't great for large payloads but this will help a bit\n\n## Multi Producer to Multi Consumer\n\nThe n:n mode means any one can send a notify and any listeners on the given channel will all get the message, here are a few use cases.\n\n### Network aware speech synth\n\nOn your desktop(s) listen to messages, here using the OS X CLI tool `say` that reads out whatever it receives over your speakers:\n\n```\nwhile true\ndo\n  piper listen say | xargs say\nend\n```\n\nOn any other machine:\n\n```\n$ ./longjob.sh ; piper say \"long job completed\"\n```\n\nOnce `longjob.sh` completes your speakers will say it's done.\n\nYou can also `brew install terminal-notifier` and use that to get nice popups on your desktop with configurable titles, sound etc, for example instead of `xargs say` you'd use `terminal-notifier -title Piper -sound default`\n\n## Network aware clipboard\n\nOn your desktop(s) run this:\n\n```\nwhile true\ndo\n  piper listen clipboard | pbcopy\nend\n```\n\nNow on any other machine you can send data to your clipboard quite easily:\n\n```\n$ ls | piper clipboard\n```\n\n## Multi Producer to Load shared grouped Consumers\n\nTo demonstrate the load shared group we can resize a set of png images across 2 shells, more useful utilities would be to fetch images from a s3 bucket and put smaller ones back, the requests would just be the file names or urls, but lets keep it simple:\n\nOn one shell run this:\n\n```\n#!/bin/bash\n\nfor filename in *.png\ndo\n    echo $filename | piper notify resize\ndone\n```\n\nOn 2 other shells run this:\n\n```\n#!/bin/bash\n\nwhile true\ndo\n  filename=$(piper listen resize --group)\n  base=$(basename \"${filename}\" .png)\n  echo $filename\n  convert -size 50%x50% \"${filename}\" \"${base}-small.jpg\"\ndone\n```\n\nYour images will now be resized using max 2 cores.\n\n## Asynchronous Mode\n\nThe examples above shows a blocking - synchronous - operation. While no persistence is needed it does mean your notifier is coupled to your listener and if either dies so does all progress.\n\nPiper supports NATS JetStream (currently in preview) for persistence, in this case the notifier will publish data into JetStream and the listener will read from JetStream like a work queue.\n\nIf your NATS network has JetStream you can do `piper setup` to configure the required settings in JetStream and pass `-a` or set `PIPER_ASYNC=1` in your environment.  Once this is done Piper will be asynchronous.\n\n## Setup\n\nTo use it you need a [NATS](https://nats.io) server, or you can sign up for a free [NGS](https://synadia.com/ngs) account.\n\nTo use your own NATS server set `PIPER_SERVER=your.nats.server:4222`.\n\nIf you need a NATS credential, such as with NGS or your own account enabled NATS, set `PIPER_CREDENTIAL=/path/to/your.creds` or place the same file in `~/.piper.creds`.\n\nWhen in persistent mode data is kept for up to 24 hours or until any listener consumed it whichever comes first.\n\n### Synadia NGS\n\n[NGS](https://synadia.com/ngs) is a managed NATS network, it's global deployed in many regions and delivered as a utility, there is a generous free tier thats a really good fit for this tool.  Data is private within an account so other users would not be able to see your piper data, though if you wished you could arrange sharing between accounts.\n\nOnce you've signed up for an account you can create your own piper user limited to what piper needs like this:\n\n```\n$ nsc add user -a YOUR_ACCOUNT \\\n     --allow-pub \"piper.\u003e,_INBOX.\u003e\" \\\n     --allow-sub \"piper.\u003e,_INBOX.\u003e\" \\\n     --name piper\n```\n\nJust change `YOUR_ACCOUNT` to your own account name, then:\n\nThis will create `~/.nkeys/creds/synadia/YOUR_ACCOUNT/piper.creds ~/.piper.creds`, you'd copy this one file to any node that wants to use piper and NGS.\n\n```\n$ cp ~/.nkeys/creds/synadia/YOUR_ACCOUNT/piper.creds ~/.piper.creds\n$ export PIPER_NGS=1\n```\n\nAnd you're good to go, you'll now connect to your nearest NGS server and the traffic will securely travel within your own account with no others being able to see it.\n\nThe subject names that piper makes are basically `piper.\u003cname\u003e`, so using the standard facilities in NGS `nsc` utility you could share piper data between different accounts securely.\n\n## TODO?\n\n * Encryption of the data\n * Once there is a data store as a service on NGS I'd like to add features that can persist data into that\n\n## Status?\n\nBasic features work as I want them to work and I really like it\n\n## Contact?\n\nR.I.Pienaar | rip@devco.net | [@ripienaar](https://twitter.com/ripienaar)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaigrr%2Fpiper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftaigrr%2Fpiper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaigrr%2Fpiper/lists"}