{"id":13564216,"url":"https://github.com/progrium/pluginhook","last_synced_at":"2025-04-11T16:03:56.702Z","repository":{"id":8973350,"uuid":"10716615","full_name":"progrium/pluginhook","owner":"progrium","description":"Simple dispatcher and protocol for shell-based plugins, an improvement to hook scripts","archived":false,"fork":false,"pushed_at":"2015-07-01T15:13:43.000Z","size":222,"stargazers_count":181,"open_issues_count":4,"forks_count":23,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-03-25T12:06:40.516Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"ruanyf/es6tutorial","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/progrium.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-06-16T06:26:21.000Z","updated_at":"2025-03-22T20:22:52.000Z","dependencies_parsed_at":"2022-09-10T01:51:33.870Z","dependency_job_id":null,"html_url":"https://github.com/progrium/pluginhook","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/progrium%2Fpluginhook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/progrium%2Fpluginhook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/progrium%2Fpluginhook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/progrium%2Fpluginhook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/progrium","download_url":"https://codeload.github.com/progrium/pluginhook/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248438493,"owners_count":21103409,"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":[],"created_at":"2024-08-01T13:01:28.143Z","updated_at":"2025-04-11T16:03:56.657Z","avatar_url":"https://github.com/progrium.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# pluginhook\n\nA simple plugin system for Bash programs that's better than just hook scripts.\n\n## Plugins as a better way\n\nLet's take the core benefits of hook scripts and re-structure it slightly:\n\n 1. Instead of focusing on hook scripts, we focus on plugins -- a directory of hook scripts\n 1. Like hook scripts, plugins are active by being in a certain place. But they can be named anything\n 1. Multiple plugins can handle a hook. Either for fanout event triggering, or for pipeline filtering\n\nSo what is a plugin? A directory full of hook scripts. When a hook is triggered, all arguments provided\nin the trigger are given to each hook script. They also receive STDIN in a pipelined fashion.\n\n## Triggering plugin hooks\n\nYou use the `pluginhook` command to trigger hooks as if you might call a traditional hook script directly.\nWhere before you might have triggered by calling something like:\n\n    hooks/post-commit $REV $USER\n\nYou'd instead trigger like this:\n\n    pluginhook post-commit $REV $USER\n\nThe `pluginhook` command simply loops through all plugin directories found in the path defined by the environment variable `PLUGIN_PATH` and passes the same arguments to any hook scripts by that name. This means installing a plugin is as simple as putting it in your `PLUGIN_PATH`. Then any plugin that has the `post-commit` hook script will be run.\n\n## Pipeline filtering with plugins\n\nYou don't just get a \"broadcast\" mechanism for arguments. You also get stream pipelining. If you pipe a stream\ninto pluginhook, it will be passed *through* each plugin hook, letting each plugin act as a filtering process. By clearly\ndefining how a hook should be used and how it can play well with others, this becomes very powerful infrastructure.\n\nHere is a plugin we'll call `upper` implementing a `text` hook (which would be in `$PLUGIN_PATH/upper/text`):\n\n    #!/usr/bin/env python\n    import sys\n    sys.stdout.write(sys.stdin.read().upper())\n  \nHere is a plugin we'll call `reverse` that also implements a `text` hook (`$PLUGIN_PATH/reverse/text`):\n\n    #!/usr/bin/env ruby\n    puts STDIN.read.strip.reverse\n    \nOne plugin uses Python to implement the hook, the other uses Ruby. But it doesn't matter, they work together when you trigger the hook:\n\n    $ echo \"hello world\" | pluginhook text\n    DLROW OLLEH\n\nOnly plugins that implement a hook are used as filters for that hook, so there's no need to implement pass-through hooks if a\nplugin doesn't care about a hook.\n\nIf ordering is important, you can always rename your plugin directory to start with a number, which will define an order of\nexecution. A plugin author might care about when it is run, but it's up to the user to take their advice or decide\nto run it in a different position in the order, by simply renaming the plugin script.\n\n## What's wrong with just hook scripts?\n\nLots of shell-based systems use hook scripts as a means to allow users to extend or customize behavior. Popular examples\nare [Git](https://www.kernel.org/pub/software/scm/git/docs/githooks.html) and [SVN](http://svnbook.red-bean.com/nightly/en/svn.ref.reposhooks.html), but many systems from [libvirt](http://www.libvirt.org/hooks.html) to [NPM](https://npmjs.org/doc/scripts.html) to [OS X](http://superuser.com/questions/295924/how-to-run-a-script-at-login-logout-in-os-x) use this pattern. Shell scripts make \nfor a great way to expose hooks because the shell environment is ubiquitous and lets you easily call into\nscripts or programs written in your language of choice.\n\nThe standard implementation of hook scripts is to have a shell script with an execute bit in a particular location\nthat's named after the hook. The most famous example is the \"post-commit\" hook of SVN, which if `hooks/post-commit`\nexists in your repository directory with an execute bit, it will trigger this script after each commit. Some systems\nlet you register hooks by providing a location instead of using convention. \n\nHowever, in either case, each hook points to **one** script. The only way for a third-party piece of software to \n\"hook in\" is to install itself as the one hook script, or have you manually install it by calling it from your \nexisting hook script. What's more, if a third-party piece of software wants to use multiple hooks, you have to\ndeal with this several times over. Not only is this a hassle, but leads to complex and non-obvious configurations.\n\n## Author\n\nJeff Lindsay \u003cprogrium@gmail.com\u003e\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogrium%2Fpluginhook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprogrium%2Fpluginhook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogrium%2Fpluginhook/lists"}