{"id":13548672,"url":"https://github.com/shoobyban/sshman","last_synced_at":"2026-03-09T23:45:49.564Z","repository":{"id":57625593,"uuid":"400511554","full_name":"shoobyban/sshman","owner":"shoobyban","description":"SSH Manager - manage users through authorized_keys files","archived":false,"fork":false,"pushed_at":"2025-10-29T08:24:34.000Z","size":6322,"stargazers_count":51,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-29T09:22:32.040Z","etag":null,"topics":["ssh","ssh-key","user-management","utility"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"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/shoobyban.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":"2021-08-27T13:04:47.000Z","updated_at":"2025-10-29T07:43:27.000Z","dependencies_parsed_at":"2022-08-27T09:51:52.395Z","dependency_job_id":null,"html_url":"https://github.com/shoobyban/sshman","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/shoobyban/sshman","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shoobyban%2Fsshman","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shoobyban%2Fsshman/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shoobyban%2Fsshman/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shoobyban%2Fsshman/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shoobyban","download_url":"https://codeload.github.com/shoobyban/sshman/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shoobyban%2Fsshman/sbom","scorecard":{"id":820582,"data":{"date":"2025-08-11","repo":{"name":"github.com/shoobyban/sshman","commit":"f47d7cd6a407d266a241f4a0519ebeb2680ddd9b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/push.yaml:1","Warn: no topLevel permission defined: .github/workflows/release.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/push.yaml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/shoobyban/sshman/push.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/push.yaml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/shoobyban/sshman/push.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/push.yaml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/shoobyban/sshman/push.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/push.yaml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/shoobyban/sshman/push.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yaml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/shoobyban/sshman/release.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yaml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/shoobyban/sshman/release.yaml/main?enable=pin","Warn: containerImage not pinned by hash: tests/docker/Dockerfile:1: pin your Docker image by updating alpine to alpine@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1","Info:   0 out of   5 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact 1.2.0 not signed: https://api.github.com/repos/shoobyban/sshman/releases/49388555","Warn: release artifact v1.1.0 not signed: https://api.github.com/repos/shoobyban/sshman/releases/49017999","Warn: release artifact v1.0.2 not signed: https://api.github.com/repos/shoobyban/sshman/releases/48582355","Warn: release artifact v1.0.1 not signed: https://api.github.com/repos/shoobyban/sshman/releases/48582036","Warn: release artifact v1.0.0 not signed: https://api.github.com/repos/shoobyban/sshman/releases/48576676","Warn: release artifact 1.2.0 does not have provenance: https://api.github.com/repos/shoobyban/sshman/releases/49388555","Warn: release artifact v1.1.0 does not have provenance: https://api.github.com/repos/shoobyban/sshman/releases/49017999","Warn: release artifact v1.0.2 does not have provenance: https://api.github.com/repos/shoobyban/sshman/releases/48582355","Warn: release artifact v1.0.1 does not have provenance: https://api.github.com/repos/shoobyban/sshman/releases/48582036","Warn: release artifact v1.0.0 does not have provenance: https://api.github.com/repos/shoobyban/sshman/releases/48576676"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":0,"reason":"35 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-wf5p-g6vw-rhxx","Warn: Project is vulnerable to: GHSA-jr5f-v2jv-69x6","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-67mh-4wv8-2f99","Warn: Project is vulnerable to: GHSA-jchw-25xp-jwwc","Warn: Project is vulnerable to: GHSA-cxjh-pqwp-8mfp","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-mwcw-c2x4-8c55","Warn: Project is vulnerable to: GHSA-7fh5-64p2-3v2j","Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-mv48-hcvh-8jj8","Warn: Project is vulnerable to: GHSA-353f-5xf4-qw67","Warn: Project is vulnerable to: GHSA-c24v-8rfc-w8vw","Warn: Project is vulnerable to: GHSA-8jhw-289h-jh2g","Warn: Project is vulnerable to: GHSA-64vr-g452-qvp3","Warn: Project is vulnerable to: GHSA-9cwx-2883-4wfx","Warn: Project is vulnerable to: GHSA-vg6x-rcgg-rjx6","Warn: Project is vulnerable to: GHSA-x574-m823-4x7w","Warn: Project is vulnerable to: GHSA-4r4m-qw57-chr8","Warn: Project is vulnerable to: GHSA-xcj6-pq6g-qj4x","Warn: Project is vulnerable to: GHSA-356w-63v5-8wf4","Warn: Project is vulnerable to: GHSA-859w-5945-r5v3","Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7","Warn: Project is vulnerable to: GO-2025-3770","Warn: Project is vulnerable to: GO-2022-0968 / GHSA-gwc9-m7rh-j2ww","Warn: Project is vulnerable to: GO-2021-0356 / GHSA-8c26-wmh5-6g9v","Warn: Project is vulnerable to: GO-2024-2961","Warn: Project is vulnerable to: GO-2023-2402 / GHSA-45x7-px36-x8w8","Warn: Project is vulnerable to: GO-2024-3321 / GHSA-v778-237x-gjrc","Warn: Project is vulnerable to: GO-2025-3487 / GHSA-hcg3-q754-cr77"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-23T15:25:07.252Z","repository_id":57625593,"created_at":"2025-08-23T15:25:07.252Z","updated_at":"2025-08-23T15:25:07.252Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30316812,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T20:05:46.299Z","status":"ssl_error","status_checked_at":"2026-03-09T19:57:04.425Z","response_time":61,"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":["ssh","ssh-key","user-management","utility"],"created_at":"2024-08-01T12:01:13.096Z","updated_at":"2026-03-09T23:45:44.553Z","avatar_url":"https://github.com/shoobyban.png","language":"Go","readme":"# SSH Manager - manage access through authorized_key files on remote hosts\n\n[![Build Status](https://github.com/shoobyban/sshman/actions/workflows/push.yaml/badge.svg?branch=main)](https://github.com/shoobyban/sshman/actions/workflows/push.yaml)\n[![Awesome GO](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/avelino/awesome-go)\n[![Go Report Card](https://goreportcard.com/badge/github.com/shoobyban/sshman)](https://goreportcard.com/report/github.com/shoobyban/sshman)\n\nThis is a simple tool that I came up after having to on-boarding and off-boarding developers on a wide of environments from AWS to 3rd party hosting providers.\n\nAs every one of my creations this tool is solving _my_ problems. It does not warranty your problem will be solved, but in that highly unlikely event please let me know, fixes and pull requests, issues are all very welcome without again the promise that I'll do anything, I'm normally really busy, apologies.\n\n**Caution**: Plan your group memberships carefully, keep your management key out of any groups so you don't accidentally remove management key from any host, locking yourself out.\n\n## Installation\n\n```sh\n$ go get github.com/shoobyban/sshman\n```\n\n## How does it work?\n\nThis tool needs to be run from a host that will be able to access all hosts with a working ssh key, one you don't share with anybody else. Configuration is saved into `~/.ssh/.ssmman`, if you need to move tool to any other host, copy this and the binary and you are set up. Configuration will not have any sensitive information.\n\nThere are two main resource entities in sshman: users and hosts. Users are identified by the public ssh key and labeled by their email address for simplicity, although email address is not used as an email so can be anything like sam-key-1 sam-key-2, useful when a user has multiple keys for different purposes (this is absolutely not necessary in most cases, but sshman supports it).\n\n![Users CRUD](docs/screenshot1.png)\n\nThe main concept of sshman is group, organising users onto \"group of hosts\" or hosts by \"group of users\", like `live-hosts`, `staging-hosts`, `production`, or `{client1}`, `{client2}`, but you can also create \"groups\" for every email address or every host. Groups are like tagging, by tagging a user and a host with the same group name the user will be able to access the host.\n\nTo add a host into the sshman configuration, provide an alias, an ssh `.pub` keys and groups that the host belongs to if already defined. Adding the host will initiate an auto-discovery functionality that will download all ssh keys from the host as newly defined users and create pseudo groups for recognised users that have access to that host.\n\n![Adding u user](docs/screenshot2.png)\n\n### Configuration file\n\nConfiguration is saved into `~/.ssh/.ssmman`, it is a JSON file with all hosts, users and groups. Probably configuration is not the right word for this.\n\n## Usage\n\n### Adding Hosts\n\nFirst, you need hosts, that you can already access, with `~/.ssh/authorized_keys` files on the host. Password auth doesn't work yet, there are plans to support initial configuration through user+password.\n\nTo add a host, the syntax is\n\n`sshman add host {alias} {host_address:port} {user} {~/.ssh/working_keyfile.pub} [group1 group2 ...]`\n\nWhere groups are optional, can be provided later.\n\nAdding a host for example:\n\n```sh\n$ sshman add host google my.google.com:22 myuser ~/.ssh/google deploy hosting google\n```\n\nIn this example `google` will be my alias, sshman will access `my.google.com` on port 22, with `myuser` user using `~/.ssh/google` private ssh key from the current user's folder, the host will belong to three groups: `deploy`, `hosting` and `google`. Sshman will save the given values into its configuration, access the host with the provided credentials, check for `~/.ssh/authorized_keys` file, download the users, cross-referencing them with the current user list, adding a new group when necessary.\n\n### Adding Users\n\nThis is optional if you already have all the users on the hosts and you just want to be able to move them around, auto discovery will auto-add the users for you, but defining new users will require this step.\n\nSyntax is\n\n`sshman add user {email} {sshkey.pub} [group1 group2 ...]`\n\nWhere groups are optional, can be provided later.\n\nFor example:\n\n```sh\n$ sshman add user email@test.com ~/.ssh/user1.pub production-team staging-hosts\n```\n\n`email@test.com` will be the label, it doesn't have to be an email address, but easier to identify and have secondary administrative value. `~/.ssh/user1.pub` will be read into the configuration and can be discarded right after this step if not used anywhere else. The user in this example will belong to the groups `production-team` and `staging-hosts`, if there are hosts in these groups the user's public ssh key information will be added to the `~/.ssh/authorized_keys` files for all hosts where the user's key was still not on.\n\n### Auto Discovery users on added hosts\n\nTo run auto discovery users on added hosts, or to refresh the configuration if any 3rd party has changed `~/.ssh/authorized_keys` files, run:\n\n```sh\n$ sshman update\n```\n\n### Listing who's on what host\n\n```sh\n$ sshman list auth\n```\n\nThis will display host alias -\u003e email list mapping, easy to grep or add to reports.\n\n### Listing what user and host is in what group\n\nEasier to explain this with an example scenario:\n\n```sh\n$ sshman list groups\nproduction-team hosts: [client1.live live2 host3 client1.uat]\nproduction-team users: [email1@test.com email2@company.com]\ndev-team hosts: [staging.test.com client1.staging]\ndev-team users: [junior1@test.com email1@test.com email2@company.com]\n```\n\nNotice that group alias is in every line with \"hosts\" and \"users\" for using `grep` on the list.\n\n### Listing added hosts\n\nLists host aliases, what host/port, host is in what groups.\n\n```sh\n$ sshman list hosts\nclient1.staging        \tstaging.client1.com:22              [production-team dev-team]\nclient1.uat        \t    uat.client1.com:22               \t[production-team dev-team]\nclient1.live        \twww.client1.com:22               \t[production-team]\n```\n\n### Listing added users with groups\n\n```sh\n$ sshman list users\n```\n\nWill return a mapping of email to groups.\n\n### Renaming users and hosts\n\nRename a user (modify email) or host (modify alias).\n\n```sh\n$ ./sshman rename user oldemail@host.com newemail@host.com\n\n$ ./sshman rename host oldalias newalias\n```\n\n### Modifying user and host groupping\n\nModify user's groups, or remove groups from user to allow global access:\n\n```sh\n$ ./sshman groups user email@host.com group1 group2\n```\n\nModify host groups or remove from all groups:\n\n```sh\n$ ./sshman groups host hostalias group1 group2\n```\n\nNote: Removing host from a group will remove all users that are on the host only because of that group. If the host is in another group, the users that are in both groups will not be removed.\n\n### Things To Fix Before Release\n\n- [x] Fix adding users\n- [x] Bug: Adding host on frontend does not add keyfile entry into storage, edit afterwards does\n- [x] Bug: Renaming host (alias) created a new entry, did not delete old\n- [x] Group editing\n  - [x] Add group should add users and groups\n  - [x] Update group should remove / add resources\n  - [x] Delete group should remove resources\n- [x] Test all CRUD (users, hosts, groups) together\n- [x] Re-read config with file watcher in web mode\n- [x] Screenshot with test data (not with sensitive data)\n- [x] Reuse stored ssh key for modifying user\n- [x] Adding host to download information without the need of running update\n- [x] Complete CRUD for missing use cases\n- [x] Web interface\n- [ ] Testing document for full coverage\n- [ ] Configuration into interface so testing can be done without isTest() style checks\n- [ ] All user functions should have unit tests\n- [ ] All host functions should have unit tests\n- [ ] All group functions should have unit tests\n- [ ] All config functions should have unit tests\n- [ ] All core functionality should have unit tests\n- [ ] Edge case: deleting user should delete the user from all hosts (unless canceled from changeset)\n- [ ] Misfeature: Changing keyfile on host does not upload new key with old and delete old\n- [ ] Misfeature: Adding host does not check if host config is working\n- [ ] Misfeature: Adding host with groups does not upload initial users from group\n- [ ] Misfeature: Modifying user groups does not upload / delete hosts\n\n### TODO For Next Release\n\n- [ ] Web authentication\n- [ ] Delete host with editing ssh keys\n- [ ] Auto-group host specific users (when user is on several hosts, create a group for them, auto-merge groups when possible)\n- [ ] CLI to use API (not sure)\n- [ ] Web Interface Authentication (where to store creds?)\n- [ ] Updated At timestamps\n- [ ] Audit log\n  - [ ] audit log logging all changes from changeset (sync op) on apply\n- [ ] Implement user \"role\" group of groups for RBAC level of abstraction (developers role = uat-servers+staging-servers group)\n- [ ] Testing connection after creating authorized_keys entry\n\n### (Possible) Future Plans\n\n- [ ] Changeset based operation (see [Future plans details](docs/Plans.md))\n- [ ] Web Aria tags (at least tagging buttons better and connecting labels)\n- [ ] More backend (currently `.ssh/.sshman` JSON configuration file)\n- [ ] Adding host key to server using password auth\n- [ ] Text UI based on Web frontend\n- [ ] State handling (see [Future plans details](docs/Plans.md))\n- [ ] Edit multiple items (see [Future plans details](docs/Plans.md))\n\n## Credits\n\nMost of the credits go to the pain of being a CTO for 16+ years in small and mid-sized companies, where SSH key management is not solved.\n\nThe project would have been much harder without the works of [Steve Francia](https://github.com/spf13) and all the cobra and viper contributors, the web UI relies on [Chi](https://github.com/go-chi/chi) and [Vue](https://github.com/vuejs/).\n\nWeb UI embedding wouldn't be working without [Gregor Best](https://github.com/farhaven), nerd-sniped him into helping me with a tricky bug on Gophers Slack.\n\nI love the Go community.\n","funding_links":[],"categories":["Go","Utilities","公用事业公司","Utility"],"sub_categories":["Utility/Miscellaneous","实用程序/Miscellaneous","HTTP Clients","Fail injection"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshoobyban%2Fsshman","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshoobyban%2Fsshman","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshoobyban%2Fsshman/lists"}