{"id":43132522,"url":"https://github.com/brianm/kongcue","last_synced_at":"2026-01-31T21:48:39.869Z","repository":{"id":327834242,"uuid":"1110976629","full_name":"brianm/kongcue","owner":"brianm","description":"Kong + Cue","archived":false,"fork":false,"pushed_at":"2025-12-08T02:16:14.000Z","size":74,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-09T19:33:23.291Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/brianm.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":"2025-12-06T03:03:11.000Z","updated_at":"2025-12-08T02:16:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/brianm/kongcue","commit_stats":null,"previous_names":["brianm/kongcue"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/brianm/kongcue","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brianm%2Fkongcue","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brianm%2Fkongcue/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brianm%2Fkongcue/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brianm%2Fkongcue/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brianm","download_url":"https://codeload.github.com/brianm/kongcue/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brianm%2Fkongcue/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28956868,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-31T18:30:42.805Z","status":"ssl_error","status_checked_at":"2026-01-31T18:30:19.593Z","response_time":128,"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":[],"created_at":"2026-01-31T21:48:39.815Z","updated_at":"2026-01-31T21:48:39.861Z","avatar_url":"https://github.com/brianm.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# kongcue\n\nA Go library that bridges [Kong](https://github.com/alecthomas/kong) CLI parsing with [CUE](https://cuelang.org/)-based configuration files.\n\n## Installation\n\n```bash\ngo get github.com/brianm/kongcue\n```\n\n## Quick Start\n\nEmbed `kongcue.Config` in your CLI struct to automatically load config files and resolve flag values:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/brianm/kongcue\"\n)\n\ntype cli struct {\n\tName   string         `default:\"world\"`\n\tConfig kongcue.Config `default:\"./config.{yml,yaml,cue,json}\" sep:\";\"`\n}\n\nfunc (c *cli) Run() error {\n\tfmt.Printf(\"Hello, %s\\n\", c.Name)\n\treturn nil\n}\n\nfunc main() {\n\tvar c cli\n\tktx := kong.Parse(\u0026c, kongcue.Options())\n\terr := ktx.Run()\n\tktx.FatalIfErrorf(err)\n}\n```\n\nWith `config.yml`:\n```yaml\nname: \"Brian\"\n```\n\n```bash\n./myapp              # Hello, Brian (from config)\n./myapp --name Alice # Hello, Alice (CLI overrides config)\n```\n\n**Note**: `kongcue.Options()` is required when using `kongcue.Config` or `kongcue.ConfigDoc`. If you use `kongcue.AllowUnknownFields()`, it includes `Options()` automatically.\n\n## Features\n\n- **Multiple file formats**: YAML, JSON, and CUE files\n- **Glob patterns**: Load configs with patterns like `~/.myapp/*.{yaml,yml}`\n- **Config unification**: Multiple config files are merged; conflicts produce errors\n- **Automatic name mapping**: CLI flags (`--ca-url`) map to config keys (`ca_url`)\n- **Command hierarchy**: Flags resolve based on subcommand context\n- **Schema validation**: Config keys are validated against CLI flags\n\n## Glob Patterns\n\nYou can use bash style glob patterns (provided by [doublestar](https://github.com/bmatcuk/doublestar?tab=readme-ov-file#patterns)).\n\nNote that if you use `{yml,yaml,cue,json}` style brace expansion and a default value, you will need to tell kong to use a seperator other than `,` or it will split inside the braces, so use something like:\n\n```go\nConfig kongcue.Config `default:\"./config.{yml,yaml,cue,json}\" sep:\";\"`\n````\n\nThis tells kong to use a `;` as the seperator between values, so you could do:\n\n```go\nConfig kongcue.Config `default:\"/etc/foo.cue;~/.config/foo/config.{yaml,cue,json}\" sep:\";\"`\n````\n\nTo tell it to look in `/etc/foo.cue` and `~/.config/foo/config.{yaml,cue,json}`.\n\n## Schema Validation\n\nBy default, config files are validated against your CLI struct. Unknown keys that don't correspond to any CLI flag will cause an error:\n\n```\nerror: unknown configuration key: typo_field: field not allowed\n       Hint: Check that all config keys correspond to valid CLI flags\n```\n\nThis catches typos and stale config keys early.\n\nTo allow extra fields in config files (useful if configs are shared with other tools), use `AllowUnknownFields()`:\n\n```go\nctx := kong.Parse(\u0026cli, kongcue.AllowUnknownFields())\n```\n\n## Schema Documentation Command\n\nAdd a command that prints the CUE schema for your CLI's configuration:\n\n```go\ntype cli struct {\n\tName      string            `help:\"Name to greet\"`\n\tServer    serverCmd         `cmd:\"\" help:\"Run the server\"`\n\tConfigDoc kongcue.ConfigDoc `cmd:\"config-doc\" help:\"Print config schema\"`\n\tConfig    kongcue.Config    `default:\"./config.yaml\"`\n}\n```\n\nRunning `./myapp config-doc` outputs a CUE schema:\n\n```cue\n// Configuration schema for validating config files.\n//\n// This schema is written in CUE, a configuration language that\n// validates and defines data. Learn more at https://cuelang.org\n//\n// To validate your config file against this schema:\n//   1. Save this schema to a file (e.g., schema.cue)\n//   2. Run: cue vet -d '#Root' schema.cue your-config.yaml\n//\n// Fields marked with ? are optional. Fields without ? are required.\n#Root: close({\n\t// Name to greet\n\tname?: string\n\t// Run the server\n\tserver?: #Server\n})\n#Server: close({\n\t// Server port\n\tport?: int\n})\n```\n\nThe schema includes:\n- **Help text as comments**: Kong `help:\"...\"` tags become CUE documentation\n- **Required field markers**: Fields with `required:\"\"` don't have `?` and must be present\n- **Nested definitions**: Each subcommand gets its own `#Definition`\n\nUsers can validate their config files using the [CUE CLI](https://cuelang.org/docs/introduction/installation/):\n\n```bash\n./myapp config-doc \u003e schema.cue\ncue vet -d '#Root' schema.cue config.yaml\n```\n\n## Configuration Formats\n\nAll formats are parsed using CUE, which means you get CUE's type checking and unification:\n\n**YAML** (`config.yaml`):\n```yaml\nverbose: 2\nagent:\n  ca_url: \"https://ca.example.com\"\n```\n\n**JSON** (`config.json`):\n```json\n{\n  \"verbose\": 2,\n  \"agent\": {\n    \"ca_url\": \"https://ca.example.com\"\n  }\n}\n```\n\n**CUE** (`config.cue`):\n```cue\nverbose: 2\nagent: {\n  ca_url: \"https://ca.example.com\"\n}\n```\n\n## Naming Convention\n\nCLI flags use kebab-case, config files use snake_case:\n\n| CLI Flag | Config Key |\n|----------|------------|\n| `--ca-url` | `ca_url` |\n| `--log-file` | `log_file` |\n\nThis avoids quoted field names in CUE (where `-` is the subtraction operator).\n\n## Command Path Resolution\n\nFlags are resolved using the command hierarchy. For a CLI like:\n\n```go\ntype cli struct {\n    Verbose int `name:\"verbose\"`\n    Agent struct {\n        CaURL string `name:\"ca-url\"`\n    } `cmd:\"\"`\n}\n```\n\n- `--verbose` resolves to `verbose` in config\n- `agent --ca-url` resolves to `agent.ca_url` in config\n\n## Multiple Config Files\n\nSpecify multiple config files with repeated flags:\n\n```bash\n./myapp --config base.yaml --config overrides.yaml\n```\n\nFiles are unified in order. Conflicting values (same key, different values) produce an error.\n\n## Low-Level API\n\nFor more control, use the loader and resolver directly:\n\n```go\nconfig, err := kongcue.LoadAndUnifyPaths([]string{\n    \"~/.myapp/config.yaml\",\n    \"./local.yaml\",\n})\nif err != nil {\n    log.Fatal(err)\n}\n\nctx := kong.Parse(\u0026cli, kong.Resolvers(kongcue.NewResolver(config)))\n```\n\n## License\n\nApache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrianm%2Fkongcue","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrianm%2Fkongcue","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrianm%2Fkongcue/lists"}