{"id":13410380,"url":"https://github.com/hedzr/cmdr","last_synced_at":"2026-02-15T05:04:23.017Z","repository":{"id":53776338,"uuid":"186799383","full_name":"hedzr/cmdr","owner":"hedzr","description":"POSIX-compliant command-line UI (CLI) parser and Hierarchical-configuration operations","archived":false,"fork":false,"pushed_at":"2026-01-24T10:25:29.000Z","size":3386,"stargazers_count":142,"open_issues_count":0,"forks_count":10,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-01-24T21:16:01.606Z","etag":null,"topics":["argument-parser","argument-parsing","cli","cmdr","cmdr-addons","command-line","command-line-interface","command-line-parser","commandline","commandline-arguments","commandline-interface","commandlineparser","fossa-status","getopt","hierarchy-configurations","jaro-winkler-distance","posix","posix-compatible","posix-compliant","subcommand"],"latest_commit_sha":null,"homepage":"https://docs.hedzr.com/docs/cmdr.v2/","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/hedzr.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","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},"funding":{"custom":"https://paypal.me/hezr/3"}},"created_at":"2019-05-15T09:58:02.000Z","updated_at":"2026-01-24T10:25:28.000Z","dependencies_parsed_at":"2023-02-17T20:46:07.142Z","dependency_job_id":"a51985d2-8e87-4ed8-8f8f-301a39190eba","html_url":"https://github.com/hedzr/cmdr","commit_stats":{"total_commits":1600,"total_committers":3,"mean_commits":533.3333333333334,"dds":"0.0050000000000000044","last_synced_commit":"8f82f675873e15d8ac30932785681a75cb673b39"},"previous_names":[],"tags_count":229,"template":false,"template_full_name":null,"purl":"pkg:github/hedzr/cmdr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hedzr%2Fcmdr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hedzr%2Fcmdr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hedzr%2Fcmdr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hedzr%2Fcmdr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hedzr","download_url":"https://codeload.github.com/hedzr/cmdr/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hedzr%2Fcmdr/sbom","scorecard":{"id":459534,"data":{"date":"2025-08-11","repo":{"name":"github.com/hedzr/cmdr","commit":"a4c9f6d565befe88287042be51f41ea33e70e342"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.4,"checks":[{"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":"Maintained","score":10,"reason":"30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","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":"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":"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release-build.yml:10","Warn: no topLevel permission defined: .github/workflows/linter.yml:1","Warn: no topLevel permission defined: .github/workflows/nightly-build.yml:1","Warn: no topLevel permission defined: .github/workflows/release-build.yml:1","Warn: no topLevel permission defined: .github/workflows/test.yml:1"],"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":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/linter.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/hedzr/cmdr/linter.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/linter.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/hedzr/cmdr/linter.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nightly-build.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/hedzr/cmdr/nightly-build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nightly-build.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/hedzr/cmdr/nightly-build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-build.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/hedzr/cmdr/release-build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-build.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/hedzr/cmdr/release-build.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release-build.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/hedzr/cmdr/release-build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/hedzr/cmdr/test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/hedzr/cmdr/test.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:2","Warn: containerImage not pinned by hash: Dockerfile:49","Info:   0 out of   7 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned","Info:   0 out of   2 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":"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":"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":"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":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"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 v2.1.51 not signed: https://api.github.com/repos/hedzr/cmdr/releases/238814649","Warn: release artifact v2.1.50 not signed: https://api.github.com/repos/hedzr/cmdr/releases/237127087","Warn: release artifact v2.1.48 not signed: https://api.github.com/repos/hedzr/cmdr/releases/236742338","Warn: release artifact v2.1.47 not signed: https://api.github.com/repos/hedzr/cmdr/releases/235423417","Warn: release artifact v2.1.46 not signed: https://api.github.com/repos/hedzr/cmdr/releases/232704556","Warn: release artifact v2.1.51 does not have provenance: https://api.github.com/repos/hedzr/cmdr/releases/238814649","Warn: release artifact v2.1.50 does not have provenance: https://api.github.com/repos/hedzr/cmdr/releases/237127087","Warn: release artifact v2.1.48 does not have provenance: https://api.github.com/repos/hedzr/cmdr/releases/236742338","Warn: release artifact v2.1.47 does not have provenance: https://api.github.com/repos/hedzr/cmdr/releases/235423417","Warn: release artifact v2.1.46 does not have provenance: https://api.github.com/repos/hedzr/cmdr/releases/232704556"],"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":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-19T10:43:39.148Z","repository_id":53776338,"created_at":"2025-08-19T10:43:39.148Z","updated_at":"2025-08-19T10:43:39.148Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29469921,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-15T04:35:06.950Z","status":"ssl_error","status_checked_at":"2026-02-15T04:33:41.357Z","response_time":118,"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":["argument-parser","argument-parsing","cli","cmdr","cmdr-addons","command-line","command-line-interface","command-line-parser","commandline","commandline-arguments","commandline-interface","commandlineparser","fossa-status","getopt","hierarchy-configurations","jaro-winkler-distance","posix","posix-compatible","posix-compliant","subcommand"],"created_at":"2024-07-30T20:01:06.535Z","updated_at":"2026-02-15T05:04:23.010Z","avatar_url":"https://github.com/hedzr.png","language":"Go","readme":"# cmdr\n\n![Go](https://github.com/hedzr/cmdr/workflows/release-build/badge.svg)\n![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/hedzr/cmdr)\n[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/hedzr/cmdr.svg?label=release)](https://github.com/hedzr/cmdr/releases)\n[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/hedzr/cmdr) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fhedzr%2Fcmdr.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fhedzr%2Fcmdr?ref=badge_shield)\n[![go.dev](https://img.shields.io/badge/go.dev-reference-green)](https://pkg.go.dev/github.com/hedzr/cmdr/v2)\n[![Go Report Card](https://goreportcard.com/badge/github.com/hedzr/cmdr)](https://goreportcard.com/report/github.com/hedzr/cmdr/v2)\n[![codecov](https://codecov.io/gh/hedzr/cmdr/branch/master/graph/badge.svg)](https://codecov.io/gh/hedzr/cmdr/v2)\u003c!--\n[![Coverage Status](https://coveralls.io/repos/github/hedzr/cmdr/badge.svg?branch=master)](https://coveralls.io/github/hedzr/cmdr/v2?branch=master)--\u003e\n[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go#command-line)\n[![DocSite](https://img.shields.io/badge/Cmdr-Docs-blue)](https://docs.hedzr.com/docs/cmdr/v2/)\n\n`cmdr` is a POSIX-compliant, command-line argument parser library with Golang.\n\n`cmdr` integrates app-settings manager (`Store`) for developing CLI app rapidly.\n\n1. Our license moved to Apache 2.0 since v2.\n2. The minimal toolchain moved to go1.25+ since v2.1.68, or go1.24+ since v2.1.55.\n3. DocSite published at [docs.hedzr.com](https://docs.hedzr.com/docs/cmdr/v2/).\n4. Starting a new app with [cmdr-go-starter](https://github.com/hedzr/cmdr-go-starter) Template repo.\n5. [Coming soon] Starting your app with [cmdr-cli] commandline tool.\n\nThe stable API starts since v2.1 and v2.2.\n\n![cover](https://user-images.githubusercontent.com/12786150/72876202-f49ee500-3d30-11ea-9de0-434bf8decf90.gif)\u003c!-- built by https://ezgif.com/ --\u003e\n\n## Motivation\n\nThere are many dirty codes in the cmdr.v1 which cannot be refactored as well. It prompted we reimplment a new one as v2.\n\nThe passing winter, we did rewrite the cmdr.v2 to keep it clean and absorbed in parsing and dispatching.\nSome abilities were removed and relayouted to new modules.\nThat's why the `Option Store` has been split as a standalone module [hedzr/store](https://github.com/hedzr/store)[^1].\nA faster and colorful slog-like logger has been implemented freshly as [hedzr/logg](https://github.com/hedzr/logg)[^3].\n[hedzr/evendeep](https://github.com/hedzr/evendeep)[^2] provides a deep fully-functional object copy tool. It helps to deep copy some internal objects easily. It is also ready for you.\n[hedzr/is](https://github.com/hedzr/is)[^4] is an environment detecting framework with many out-of-the-box detectors, such as `is.InTesting` and `is.InDebugging`.\n\nAnyway, the whole supply chain painted:\n\n```mermaid\ngraph BT\n  hzis(hedzr/is)--\u003ehzlogg(hedzr/logg/slog)\n  hzis--\u003ehzdiff(hedzr/evendeep)\n  hzlogg--\u003ehzdiff\n  hzerrors(gopkg.in/hedzr/errors.v3)--\u003ehzdiff\n  hzerrors--\u003ehzstore(hedzr/store)\n  hzis--\u003ehzstore(hedzr/store)\n  hzlogg--\u003ehzstore(hedzr/store)\n  hzdiff--\u003ehzstore(hedzr/store)\n  hzlogg--\u003ecmdr(hedzr/cmdr/v2)\n  hzis--\u003ecmdr\n  hzlogg--\u003ecmdr\n  hzdiff--\u003ecmdr\n  hzstore--\u003ecmdr\n\n```\n\n\u003e 1. The .netCore version [Cmdr.Core](https://github.com/hedzr/Cmdr.Core) is available now.\n\u003e 2. A cxx version [`cmdr-cxx`](https://github.com/hedzr/cmdr-cxx) was released (Happy Spring Festival 2021).\n\u003e 3. The docsite has been released at \u003chttps://docs.hedzr.com/\u003e.\n\n## Features\n\nv2 is in earlier state but the baseline is stable:\n\n- Basic command-line arguments parser like POSIX getopt and go stdlib flag.\n  - Short flag, single character or a string here to support golang CLI style\n    - Compact flags if possible. Also the sticky value will be parsed. For example: `-c1b23zv` = `-c 1 -b 23 -z -v`\n    - Hit info: `-v -v -v` = `-v` (hitCount == 3, hitTitle == 'v')\n    - Optimized for slice: `-a 1,2,3 -a 4 -a 5,6` =\u003e []int{1,2,3,4,5,6}\n    - Value can be sticked or not. Valid forms: `-c1`, `-c 1`, `-c=1` and quoted: `-c\"1\"`, `-c'1'`, `-c=\"1\"`, `-c='1'`, etc.\n    - ...\n\n  - Long flags and aliases\n  - Eventual subcommands: an `OnAction` handler can be attached.\n  - Eventual subcommands and flags: PreActions, PostAction, OnMatching, OnMatched, ...,\n  - Auto bind to environment variables, For instance: command line `HELP=1 app` = `app --help`.\n  - Builtin commands and flags:\n    - `--help`, `-h`\n    - `--version`, `-V`\n    - `--verbose`. `-v`\n    - ...\n\n  - Help Screen: auto generate and print\n  - Smart suggestions when wrong cmd or flag parsed. Jaro-winkler distance is used.\n\n- Loosely parse subcmds and flags:\n  - Subcommands and flags can be input in any order\n  - Lookup a flag along with subcommands tree for resolving the duplicated flags\n\n- Can integrate with [hedzr/store](https://github.com/hedzr/store)[^1]\n  - High-performance in-memory KV store for hierarchical data.\n  - Extract data to user-spec type with auto-converting\n  - Loadable external sources: environ, config files, consul, etcd, etc..\n    - extensible codecs and providers for loading from data sources\n\n- Three kinds of config files are searched and loaded via `loaders.NewConfigFileLoader()`:\n  1. __Primary__: main config, shipped with installable package.\n  2. __Secondary__: 2ndry config. Wrapped by reseller(s).\n  3. __Alternative__: user's local config, writeable. The runtime changeset will be written back to this file while app stopping.\n\n- Variety of approaches for building command system with attached flags\n  1. traditional stream calls (`app.Cmd(\"verbose\", \"v\").Action(onVerbose)`)\n  2. concise modes by [`Create`](https://pkg.go.dev/github.com/hedzr/cmdr/v2#Create) and cmd/xxcmd.go\n  3. use [`Create.BuildFrom`](https://pkg.go.dev/github.com/hedzr/cmdr/v2#Create) to build cmdsys from a struct value via `[App.FromStruct]`, see example [#example_Create_buildFromStructValue](https://pkg.go.dev/github.com/hedzr/cmdr/v2/#example_Create_buildFromStructValue); or, attaching subcmds and flags to a subcmd by `app.Cmd().FromStruct(\u0026root{})` following any traditional calls.\n\n- Generating shell autocompletion scripts\n  - supported shells are: zsh, bash, fish, powershell, ...\n  - auto install the scripts for zsh shell.\n\n- Generating command manpages for software deployment time.\n\n- TODO\n  - ...\n\n[^1]: `hedzr/store` is a high-performance configure management library\n[^2]: `hedzr/evendeep` offers a customizable deepcopy tool to you. There are also deepequal, deepdiff tools in it.\n[^3]: `hedzr/logg` provides a slog like and colorful logging library\n[^4]: `hedzr/is` is a basic environ detectors library\n\nMore minor details need to be evaluated and reimplemented if it's still meaningful in v2.\n\n### News\n\nGetting started from [New](https://pkg.go.dev/github.com/hedzr/cmdr/v2#New) or [Create](https://pkg.go.dev/github.com/hedzr/cmdr/v2#Create) function, and see the quickstart docs at [Concise Version - hzDocs](https://docs.hedzr.com/en/docs/cmdr/v2/guide/g02-concise-version/) and [Step by step - hzDocs](https://docs.hedzr.com/en/docs/cmdr/v2/guide/steps/).\n\nSince v2.0.3, loaders had been splitted as a standalone repo so that we can keep cmdr v2 smaller and independer. See the relevant subproject [cmdr-loaders](https://github.com/hedzr/cmdr-loaders)[^5].\n\nSince v2.1.12, we did main alternative features like autocompletion generating, manpage reading and generating, and made quite a lot of fixes and improvments. Now the main APIs come to stable.\n\nSince v2.1.26, we added `App.FromStruct(structValue, opts...)` to build the command system from a struct-value, which deconstructs the given struct's definitions and constrcts the cmd-sys. And we also added `App.Cmd().FromStruct(\u0026root{})` to build for a subcmd in a later release. Now the parsed cmdline args will be written into your struct value. For more detail, see also [From struct-value and Tag - hzDocs](https://docs.hedzr.com/en/docs/cmdr/v2/guide/steps/g13-build-from-struct/)\n\nThe full-functional tests and examples are moved into [cmdr-tests](https://github.com/hedzr/cmdr-tests).\n\n[^5]: `hedzr/cmdr-loaders` provides an external config file loaders with GNU File Standard supports.\n\n## History\n\nv2.2 would be a stable version:\n\n- v2.2.0 PLANNED: the final stable version for v2.\n- v2.1.x: preview version for the new APIs.\n- Full list: [CHANGELOG](https://github.com/hedzr/cmdr/blob/master/CHANGELOG)\n\n## Guide\n\nPlease go to our docsite for these pages:\n\n- [Concise Version - hzDocs](https://docs.hedzr.com/en/docs/cmdr/v2/guide/g02-concise-version/)\n- [Step by step - hzDocs](https://docs.hedzr.com/en/docs/cmdr/v2/guide/steps/)\n- ...\n\nYou can build command system by kinds of forms:\n\n1. traditional stream calls style (`app.Cmd(\"verbose\", \"v\").Action(onVerbose)`)\n2. concise style by `[Create](https://pkg.go.dev/github.com/hedzr/cmdr/v2#Create)` and cmd/xxcmd.go\n3. passing config arg style by `[cmdr.NewAppWithConfig(config)]`\n4. struct tag style: using `[cmdr.Create().BuildFrom()](https://pkg.go.dev/github.com/hedzr/cmdr/v2#Creator.BuildFrom)` to build command system from a struct value, see example [#example_Create_buildFromStructValue](https://pkg.go.dev/github.com/hedzr/cmdr/v2#example-Create-BuildFromAStructValue); or, attaching subcmds and flags to a subcmd by `app.Cmd().FromStruct(\u0026root{})` following any traditional calls.\n\nGetting started from [New](https://pkg.go.dev/github.com/hedzr/cmdr/v2#New) or [Create](https://pkg.go.dev/github.com/hedzr/cmdr/v2#Create) function.\n\n### Traditional style\n\n```go\n\tapp.Cmd(\"soundex\", \"snd\", \"sndx\", \"sound\").\n\t\tDescription(\"soundex test\").\n\t\tGroup(\"Test\").\n\t\tTailPlaceHolders(\"[text1, text2, ...]\").\n\t\tOnAction(soundex).\n\t\tBuild()\n```\n\n### Concise version\n\nA typical cli-app can be (its concise version at [examples/tiny/concise/main.go](https://github.com/hedzr/cmdr/blob/master/examples/tiny/concise/main.go)):\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"io\"\n    \"os\"\n\n    \"github.com/hedzr/cmdr/v2\"\n    \"github.com/hedzr/cmdr/v2/cli\"\n    \"github.com/hedzr/cmdr/v2/examples/cmd\"\n    \"github.com/hedzr/cmdr/v2/examples/dyncmd\"\n\n    \"github.com/hedzr/is/dir\"\n    logz \"github.com/hedzr/logg/slog\"\n    \"gopkg.in/hedzr/errors.v3\"\n)\n\nconst (\n    appName = \"lite-app\"\n    desc    = `lite-app version of tiny app.`\n    version = cmdr.Version\n    author  = `The Example Authors`\n)\n\nfunc main() {\n    ctx, cancel := context.WithCancel(context.Background())\n    defer cancel()\n\n    app := cmdr.Create(appName, version, author, desc).\n        WithAdders(cmd.Commands...).\n        Build()\n\n    if err := app.Run(ctx); err != nil {\n        logz.ErrorContext(ctx, \"Application Error:\", \"err\", err) // stacktrace if in debug mode/build\n        os.Exit(app.SuggestRetCode())\n    } else if rc := app.SuggestRetCode(); rc != 0 {\n        os.Exit(rc)\n    }\n}\n\nvar Commands = []cli.CmdAdder{\n    jumpCmd{},\n    wrongCmd{},\n    invokeCmd{},\n    presetCmd{},\n}\n\ntype jumpCmd struct{}\n\nfunc (jumpCmd) Add(app cli.App) {\n    app.Cmd(\"jump\").\n        Description(\"jump command\").\n        Examples(`jump example`). // {{.AppName}}, {{.AppVersion}}, {{.DadCommands}}, {{.Commands}}, ...\n        Deprecated(`v1.1.0`).\n        Group(\"Test\").\n        // Group(cli.UnsortedGroup).\n        // Hidden(false).\n        OnEvaluateSubCommands(dyncmd.OnEvalJumpSubCommands).\n        OnEvaluateSubCommandsFromConfig().\n        // Both With(cb) and Build() to end a building sequence\n        With(func(b cli.CommandBuilder) {\n            b.Cmd(\"to\").\n                Description(\"to command\").\n                Examples(``).\n                Deprecated(`v0.1.1`).\n                OnAction(func(ctx context.Context, cmd cli.Cmd, args []string) (err error) {\n                    // cmd.Set() == cmdr.Set(), cmd.Store() == cmdr.Store()\n                    cmd.Set().Set(\"tiny3.working\", dir.GetCurrentDir())\n                    println()\n                    println(\"dir:\", cmd.Set().WithPrefix(\"tiny3\").MustString(\"working\"))\n\n                    cs := cmdr.Store().WithPrefix(\"jump.to\")\n                    if cs.MustBool(\"full\") {\n                        println()\n                        println(cmd.Set().Dump())\n                    }\n                    cs2 := cmd.Store()\n                    if cs2.MustBool(\"full\") != cs.MustBool(\"full\") {\n                        logz.Panic(\"a bug found\")\n                    }\n                    app.SetSuggestRetCode(1) // ret code must be in 0-255\n                    return                   // handling command action here\n                }).\n                With(func(b cli.CommandBuilder) {\n                    b.Flg(\"full\", \"f\").\n                        Default(false).\n                        Description(\"full command\").\n                        Build()\n                })\n        })\n}\n\ntype wrongCmd struct{}\n\nfunc (wrongCmd) Add(app cli.App) {\n    app.Cmd(\"wrong\").\n        Description(\"a wrong command to return error for testing\").\n        Group(\"Test\").\n        // cmdline `FORCE_RUN=1 go run ./tiny wrong -d 8s` to verify this command to see the returned application error.\n        OnAction(func(ctx context.Context, cmd cli.Cmd, args []string) (err error) {\n            dur := cmd.Store().MustDuration(\"duration\")\n            println(\"the duration is:\", dur.String())\n\n            ec := errors.New()\n            defer ec.Defer(\u0026err) // store the collected errors in native err and return it\n            ec.Attach(io.ErrClosedPipe, errors.New(\"something's wrong\"), os.ErrPermission)\n            // see the application error by running `go run ./tiny/tiny/main.go wrong`.\n            return\n        }).\n        Build()\n}\n\ntype invokeCmd struct{}\n\nfunc (invokeCmd) Add(app cli.App) {\n    app.Cmd(\"invoke\").Description(`test invoke feature`).\n        With(func(b cli.CommandBuilder) {\n            b.Cmd(\"shell\").Description(`invoke shell cmd`).InvokeShell(`ls -la`).UseShell(\"/bin/bash\").OnAction(nil).Build()\n            b.Cmd(\"proc\").Description(`invoke gui program`).InvokeProc(`say \"hello, world!\"`).OnAction(nil).Build()\n        })\n}\n\ntype presetCmd struct{}\n\nfunc (presetCmd) Add(app cli.App) {\n    app.Cmd(\"preset\", \"p\").\n        Description(\"preset command to inject into user input\").\n        With(func(b cli.CommandBuilder) {\n            b.Flg(\"preset\", \"p\").\n                Default(false).\n                Description(\"preset arg\").\n                Build()\n            b.Cmd(\"cmd\", \"c\").Description(\"inject `-pv` into user input cmdline\").\n                PresetCmdLines(`-pv`).\n                OnAction(func(ctx context.Context, cmd cli.Cmd, args []string) (err error) {\n                    _, err = app.DoBuiltinAction(ctx, cli.ActionDefault)\n                    return\n                }).Build()\n        })\n}\n```\n\n### From a struct value\n\nAdding subcmds and flags to an existed command `multiCmd` is dead simple, this way:\n\n```go\npackage cmd\n\nimport (\n\t\"context\"\n\t\"os\"\n\n\t\"github.com/hedzr/cmdr/v2/cli\"\n\t\"github.com/hedzr/is\"\n\tlogz \"github.com/hedzr/logg/slog\"\n)\n\ntype multiCmd struct{}\n\nfunc (multiCmd) Add(app cli.App) {\n\tif is.DebuggerAttached() {\n\t\tlogz.SetLevel(logz.TraceLevel)\n\t\tapp.WithOpts(cli.WithArgs(os.Args[0], \"~~tree\"))\n\t}\n\tapp.Cmd(\"multi\", \"m\", \"\").\n\t\tDescription(\"multi-level test and imported form struct\").\n\t\t// Group(\"Test\").\n\t\tTailPlaceHolders(\"[text1, text2, ...]\").\n\t\tOnAction(soundex).\n\t\tFromStruct(root{}).\n\t\tWith(func(b cli.CommandBuilder) {\n\t\t\t// b.FromStruct(\u0026root{})\n\t\t})\n}\n\ntype root struct {\n\tb   bool // unexported values ignored\n\tInt int  `cmdr:\"-\"` // ignored\n\tA   `title:\"a-cmd\" shorts:\"a,a1,a2\" alias:\"a1-cmd,a2-cmd\" desc:\"A command for demo\" required:\"true\"`\n\tB\n\tC\n\tF1 int\n\tF2 string\n}\n\ntype A struct {\n\tD\n\tF1 int\n\tF2 string\n}\ntype B struct {\n\tF2 int\n\tF3 string\n}\ntype C struct {\n\tF3 bool\n\tF4 string\n}\ntype D struct {\n\tE\n\tFromNowOn F\n\tF3        bool\n\tF4        string\n}\ntype E struct {\n\tF3 bool `title:\"f3\" shorts:\"ff\" alias:\"f3ff\" desc:\"A flag for demo\" required:\"true\"`\n\tF4 string\n}\ntype F struct {\n\tF5 uint\n\tF6 byte\n}\n\n// a --f1 1 --f2 str\n// --a.f1 1 --a.f2 str\n\nfunc (A) With(cb cli.CommandBuilder) {\n\t// customize for A command, for instance: fb.ExtraShorts(\"ff\")\n\tlogz.Info(\".   - A.With() invoked.\", \"cmdbuilder\", cb)\n}\nfunc (A) F1With(fb cli.FlagBuilder) {\n\t// customize for A.F1 flag, for instance: fb.ExtraShorts(\"ff\")\n\tlogz.Info(\".   - A.F1With() invoked.\", \"flgbuilder\", fb)\n}\n\n// Action method will be called if end-user type subcmd for it (like `app a d e --f3`).\nfunc (E) Action(ctx context.Context, cmd cli.Cmd, args []string) (err error) {\n\tlogz.Info(\".   - E.Action() invoked.\", \"cmd\", cmd, \"args\", args)\n\t_, err = cmd.App().DoBuiltinAction(ctx, cli.ActionDefault, stringArrayToAnyArray(args)...)\n\treturn\n}\n\n// Action method will be called if end-user type subcmd for it (like `app a d f --f5=7`).\nfunc (s F) Action(ctx context.Context, cmd cli.Cmd, args []string) (err error) {\n\t(\u0026s).Inc()\n\tlogz.Info(\".   - F.Action() invoked.\", \"cmd\", cmd, \"args\", args, \"F5\", s.F5)\n\t_, err = cmd.App().DoBuiltinAction(ctx, cli.ActionDefault, stringArrayToAnyArray(args)...)\n\treturn\n}\n\nfunc (s *F) Inc() {\n\ts.F5++\n}\n\nfunc stringArrayToAnyArray(args []string) (ret []any) {\n\tfor _, it := range args {\n\t\tret = append(ret, it)\n\t}\n\treturn\n}\n```\n\nFor the detail, or check out its bindable version, go to [From struct-value and Tag - hzDocs](https://docs.hedzr.com/en/docs/cmdr/v2/guide/steps/g13-build-from-struct/).\n\n### Next Step\n\nMore examples please go to [cmdr-tests/examples](https://github.com/hedzr/cmdr-tests/tree/master/examples).\n\n## License\n\nSince v2, our license moved to Apache 2.0.\n\n[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fhedzr%2Fcmdr.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fhedzr%2Fcmdr?ref=badge_large)\n","funding_links":["https://paypal.me/hezr/3"],"categories":["Command Line","命令行","cli","Go","Build Automation","命令行工具### 标准 CLI`用于创建一个标准命令行应用程序的库`","命令行工具"],"sub_categories":["Standard CLI","标准CLI","标准 CLI"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhedzr%2Fcmdr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhedzr%2Fcmdr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhedzr%2Fcmdr/lists"}