{"id":30607074,"url":"https://github.com/boggydigital/clo","last_synced_at":"2025-08-30T03:26:38.906Z","repository":{"id":55044693,"uuid":"324663202","full_name":"boggydigital/clo","owner":"boggydigital","description":"🦒 Command-line objectives","archived":false,"fork":false,"pushed_at":"2025-08-29T20:03:39.000Z","size":401,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-29T22:36:24.930Z","etag":null,"topics":["cli","command-line","go","golang","objectives"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/boggydigital.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,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-12-27T01:08:13.000Z","updated_at":"2025-08-29T20:02:37.000Z","dependencies_parsed_at":"2023-11-11T04:23:53.064Z","dependency_job_id":"fc3016a5-07d4-4f97-8a4f-9e612599faf0","html_url":"https://github.com/boggydigital/clo","commit_stats":null,"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/boggydigital/clo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boggydigital%2Fclo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boggydigital%2Fclo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boggydigital%2Fclo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boggydigital%2Fclo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/boggydigital","download_url":"https://codeload.github.com/boggydigital/clo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boggydigital%2Fclo/sbom","scorecard":{"id":246918,"data":{"date":"2025-08-11","repo":{"name":"github.com/boggydigital/clo","commit":"b2f59e698f62328cf346dbddd69222c89e268957"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.6,"checks":[{"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":"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":"Maintained","score":0,"reason":"1 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":"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":"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/test.yml: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":"Pinned-Dependencies","score":3,"reason":"dependency not pinned by hash detected -- score normalized to 3","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/boggydigital/clo/test.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/boggydigital/clo/test.yml/main?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   1 out of   1 goCommand 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":"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: GNU Affero General Public License v3.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":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"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":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"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-17T07:46:22.723Z","repository_id":55044693,"created_at":"2025-08-17T07:46:22.723Z","updated_at":"2025-08-17T07:46:22.723Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272778191,"owners_count":24991500,"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","status":"online","status_checked_at":"2025-08-29T02:00:10.610Z","response_time":87,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["cli","command-line","go","golang","objectives"],"created_at":"2025-08-30T03:26:25.629Z","updated_at":"2025-08-30T03:26:38.868Z","avatar_url":"https://github.com/boggydigital.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Clo logo](clogo.png)\n\n# Clo (Command line objectives)\n\nClo is a Golang module to build declarations of a command-line app objectives - commands and\narguments with values. Clo processes user provided command-line app input string (args) and returns\na structured `Request` object. Clo takes care of a `help` command (perhaps more in the future).\n\n## Using clo in your app\n\nWhile clo has been designed with Go 1.16 embedding in mind, we'll provide directions on how to use\nit today and will update once 1.16 is released.\n\n### Using clo module\n\n- Run `go get github.com/boggydigital/clo`\n- Import `github.com/boggydgital/clo`\n- Create declarations in `clo.json`\n- Load definitions using `defs, _ := clo.LoadDefinitions(\"clo.json\")`\n- Call `clo.Parse(os.Args[1:], defs)` to get a `Request` struct\n- Route to app code using `Request.Command` and pass `Request.Arguments`\n\nHere is an example of a `main.go` that implements this approach (NOTE: error handling is omitted for\nbrevity)\n\n```go\npackage main\n\nimport (\n\t\"github.com/boggydigital/clo\"\n\t\"{your-app-module}/cmd\"\n\t\"os\"\n)\n\nfunc main() {\n\tdefs, _ := clo.LoadDefinitions(\"clo.json\")\n\n\t// Parse `os.Args` using definitions to get `Request` data\n\treq, _ := clo.Parse(os.Args[1:], defs)\n\n\t// Route request to app command handlers\n\tcmd.Route(req, defs)\n}\n```\n\n### Routing command requests and handling built-in commands\n\nTo route command-line objectives to app handlers you might add a `cmd/route.go` with a\nsingle `Route` func that routes arguments data to command handlers.\n\nNOTE: In order to allow clo to handle built-in commands, in your `Route` handler you need to\nsend `nil` and unknown commands to `clo.Route`.\n\nExample:\n\n```go\npackage cmd\n\nimport (\n\t\"github.com/boggydigital/clo\"\n)\n\nfunc Route(req *clo.Request, defs *clo.Definitions) error {\n\n\t// allow clo to handle nil requests (this will show help by default)\n\tif req == nil {\n\t\treturn clo.Route(nil, defs)\n\t}\n\n\tswitch req.Command {\n\tcase \"yourCommand\":\n\t\t// route yourCommand here\n\t\t// ...\n\tdefault:\n\t\t// allow clo to handle unknown commands\n\t\treturn clo.Route(req, defs)\n\t}\n\n\treturn nil\n}\n```\n\n### Getting values from a Request\n\n`Request` provides few shortcuts to get values:\n\n- `ArgVal(arg string)` - gets a single (first) value for an argument\n- `ArgValues(arg string)` - gets all argument values specified in a `Request`\n- `Flag(arg string)` - returns true is argument has been provided (with or without values)\n\nExample:\n\n```go\npackage cmd\n\nimport (\n\t\"github.com/boggydigital/clo\"\n)\n\nfunc Route(req *clo.Request, defs *clo.Definitions) error {\n\tif req == nil {\n\t\treturn clo.Route(nil, defs)\n\t}\n\tswitch req.Command {\n\tcase \"validate\":\n\t\treturn Validate(req.ArgVal(\"path\"), req.Flag(\"verbose\"))\n\tdefault:\n\t\treturn clo.Route(req, defs)\n\t}\n}\n```\n\nwhere `Validate` is defined as:\n\n```go\npackage cmd\n\nfunc Validate(path string, verbose bool) error { \n\t\n\t// validate a file and display each test results if verbose was requested\n\t// ...\n\t\n\treturn nil\n}\n```\n\n## Command-line objectives calling convention\n\nApp that uses clo would support the following calling convention:\n\n`app command [arguments [values]]`\n\n- Commands don't have any prefix. Commands can be specified by a prefix - the first command to match\n  provided prefix would be used.\n- Arguments are specified with `-` or `--` prefixes. `--debug` is the same as `-debug` and, assuming\n  there are no other arguments that start with `d`, it'll be the same as `--d` and `-d`\n- Values are specified without any prefix.\n\n## Creating clo.json definitions\n\nClo.json has the following top-level properties:\n\n- `version` - version of the definitions file, currently the only supported version is `1`\n- `cmd` - commands, arguments specified as a map:\n\n```json\n{\n  \"cmd\": {\n    \"validate\": [\n      \"path\",\n      \"verbose\"\n    ]\n  }\n}\n```\n\n- `help` - help messages specified for topics (topic is a `:` delimited list of `command:argument`):\n\n```json\n{\n  \"help\": {\n    \"clo\": \"command-line objectives\",\n    \"validate\": \"validates that provided file doesn't have errors\",\n    \"validate:path\": \"path to the file that should be validated\",\n    \"validate:verbose\": \"print result of every validation test\"\n  }\n}\n```\n\n### Specifying argument values\n\nCommand arguments can also specify values supported by that argument. If values are specified for an\nargument, only those values would be considered valid and processing user input would stop when a\ndifferent value is specified. Values are specified following a `=` sign:\n\n```json\n{\n  \"cmd\": {\n    \"command1\": [\n      \"argument1=value1,value2\",\n      \"argument2\"\n    ]\n  }\n}\n```\n\nIn that declaration `argument1` can only be specified with either `value1` or `value2`,\nwhile `argument2` can be specified with any arbitrary value.\n\n### Objectives attributes\n\nTo provide more control to authors clo supports several inline attributes that can be used to define\nconstraints or set defaults:\n\n- `_` - **default**. Applies to command, attributes, values:\n    - When specified on a command, this command will be used if no other command has been a match.\n      Example: `clo clo.json` is the same as `clo validate clo.json` if `validate_` command was\n      specified as default.\n    - When specified on an argument, this argument will be used if no other argument has been a\n      match. Example: `clo validate clo.json` is the same as `clo validate --path clo.json`\n      if `path_` was specified as default.\n    - When specified on a value, this argument value pair will be added to `Request` if the user\n      didn't provide another value for that pair.\n\n- `!` - **required**. Applies to arguments. If set - argument value must be provided (can be in a form of\n  default value). Example:\n\n```json\n{\n  \"cmd\": {\n    \"validate_\": [\n      \"path_!\"\n    ]\n  }\n}\n```\n\n- `...` - **multiple**. Applies to arguments. If set - argument can take more than one value. If not set - parsing multiple values for such argument would result in error.\n\n- `$` - **env. variable**. Applies to arguments. If set - argument value can be read from env. variable, unless specified by the user.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboggydigital%2Fclo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboggydigital%2Fclo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboggydigital%2Fclo/lists"}