{"id":13564970,"url":"https://github.com/vladimirvivien/gosh","last_synced_at":"2025-04-05T13:07:37.836Z","repository":{"id":144201298,"uuid":"85513452","full_name":"vladimirvivien/gosh","owner":"vladimirvivien","description":"Gosh -  a pluggable framework for building command shell programs","archived":false,"fork":false,"pushed_at":"2020-01-14T22:54:55.000Z","size":23,"stargazers_count":533,"open_issues_count":3,"forks_count":53,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-03-29T12:07:45.399Z","etag":null,"topics":["cli","command-line","go","go-buildmode","golang","plugin","shared-library","shell"],"latest_commit_sha":null,"homepage":"","language":"Go","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/vladimirvivien.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,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-03-19T22:26:51.000Z","updated_at":"2025-03-28T03:16:56.000Z","dependencies_parsed_at":"2023-06-18T14:54:00.054Z","dependency_job_id":null,"html_url":"https://github.com/vladimirvivien/gosh","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/vladimirvivien%2Fgosh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vladimirvivien%2Fgosh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vladimirvivien%2Fgosh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vladimirvivien%2Fgosh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vladimirvivien","download_url":"https://codeload.github.com/vladimirvivien/gosh/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247339158,"owners_count":20923014,"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":["cli","command-line","go","go-buildmode","golang","plugin","shared-library","shell"],"created_at":"2024-08-01T13:01:38.688Z","updated_at":"2025-04-05T13:07:37.815Z","avatar_url":"https://github.com/vladimirvivien.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Gosh - A pluggable interactive shell written Go\n\n`Gosh` (or Go shell) is a framework that uses Go's plugin system to create\nfor building interactive console-based shell programs.  A gosh shell is\ncomprised of a collection of Go plugins which implement one or more commands.\nWhen `gosh` starts, it searches directory `./plugins` for available shared object\nfiles that implement command plugins.\n\n## Getting started\n\n#### Pre-requisites\n\n* Go 1.8 or above\n* Linux\n* Mac OSX\n\nGosh makes it easy to create shell programs.  First, download or clone this \nrepository.  For a quick start, run the following:\n\n```bash\ngo run shell/gosh.go\n```\nThis will produce the following output:\n```bash\n\n                        888\n                        888\n                        888\n .d88b.  .d88b. .d8888b 88888b.\nd88P\"88bd88\"\"88b88K     888 \"88b\n888  888888  888\"Y8888b.888  888\nY88b 888Y88..88P     X88888  888\n \"Y88888 \"Y88P\"  88888P'888  888\n     888\nY8b d88P\n \"Y88P\"\n\nNo commands found\n```\nAfter the splashscreen is displayed, `gosh` informs you that `no commands found`, as expected.  Next,\nexit the `gosh` shell (`Ctrl-C`) and let us compile the example plugins that comes with the source code.\n\n```bash\ngo build -buildmode=plugin  -o plugins/sys_command.so plugins/syscmd.go\n```\nThe previous command will compile `plugins/syscmd.go` and outputs shared object\n`plugins/sys_command.so`, as a Go plugin file.  Verify the shared object file was created:\n\n```\n\u003e ls -lh plugins/\ntotal 3.2M\n-rw-rw-r-- 1  4.5K Mar 19 18:23 syscmd.go\n-rw-rw-r-- 1  3.2M Mar 19 19:14 sys_command.so\n-rw-rw-r-- 1  1.4K Mar 19 18:23 testcmd.go\n```\nNow, when gosh is restarted, it will dynamically load the commands implemented in the shared object file:\n\n```bash\n\u003e go run shell/gosh.go\n...\n\nLoaded 4 command(s)...\nType help for available commands\n\ngosh\u003e\n```\n\nAs indicated, typing `help` lists all available commands in the shell:\n\n```bash\ngosh\u003e help\n\nhelp: prints help information for other commands.\n\nAvailable commands\n------------------\n      prompt:\tsets a new shell prompt\n         sys:\tsets a new shell prompt\n        help:\tprints help information for other commands.\n        exit:\texits the interactive shell immediately\n\nUse \"help \u003ccommand-name\u003e\" for detail about the specified command\n```\n## A command\nA Gosh `Command` is represented by type `api/Command`:\n```go\ntype Command interface {\n\tName() string\n\tUsage() string\n\tShortDesc() string\n\tLongDesc() string\n\tExec(context.Context, []string) (context.Context, error)\n}\n```\n\nThe Gosh framework searches for Go plugin files in the `./plugins` directory.  Each package plugin must \nexport a variable named `Commands` which is of type  :\n```go\ntype Commands interface {\n  ...\n\tRegistry() map[string]Command\n}\n```\nType `Commands` type returns a list of `Command` via the `Registry()`.  \n\nThe following shows example command file [plugins/testcmd.go](./plugins/testcmd.go). It implements\ntwo commands via types `helloCmd` and `goodbyeCmd`. The commands are exported via type `testCmds` using\nmethod `Registry()`:\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/vladimirvivien/gosh/api\"\n)\n\ntype helloCmd string\n\nfunc (t helloCmd) Name() string      { return string(t) }\nfunc (t helloCmd) Usage() string     { return `hello` }\nfunc (t helloCmd) ShortDesc() string { return `prints greeting \"hello there\"` }\nfunc (t helloCmd) LongDesc() string  { return t.ShortDesc() }\nfunc (t helloCmd) Exec(ctx context.Context, args []string) (context.Context, error) {\n\tout := ctx.Value(\"gosh.stdout\").(io.Writer)\n\tfmt.Fprintln(out, \"hello there\")\n\treturn ctx, nil\n}\n\ntype goodbyeCmd string\n\nfunc (t goodbyeCmd) Name() string      { return string(t) }\nfunc (t goodbyeCmd) Usage() string     { return t.Name() }\nfunc (t goodbyeCmd) ShortDesc() string { return `prints message \"bye bye\"` }\nfunc (t goodbyeCmd) LongDesc() string  { return t.ShortDesc() }\nfunc (t goodbyeCmd) Exec(ctx context.Context, args []string) (context.Context, error) {\n\tout := ctx.Value(\"gosh.stdout\").(io.Writer)\n\tfmt.Fprintln(out, \"bye bye\")\n\treturn ctx, nil\n}\n\n// command module\ntype testCmds struct{}\n\nfunc (t *testCmds) Init(ctx context.Context) error {\n\tout := ctx.Value(\"gosh.stdout\").(io.Writer)\n\tfmt.Fprintln(out, \"test module loaded OK\")\n\treturn nil\n}\n\nfunc (t *testCmds) Registry() map[string]api.Command {\n\treturn map[string]api.Command{\n\t\t\"hello\":   helloCmd(\"hello\"),\n\t\t\"goodbye\": goodbyeCmd(\"goodbye\"),\n\t}\n}\n\nvar Commands testCmds\n```\n\n## License\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvladimirvivien%2Fgosh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvladimirvivien%2Fgosh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvladimirvivien%2Fgosh/lists"}