pflag
A drop-in replacement for Go's flag package that adds POSIX/GNU-style double-dash flags and shorthand letters.
Repository Health
Technical Analysis
pflag is a drop-in replacement for Go’s standard library flag package, implementing POSIX/GNU-style command-line flag parsing. Where the standard flag package only understands single-dash flags, pflag adds double-dash long flags (--verbose), single-letter shorthand flags (-v), combinable boolean shorthands (-abc), and the -- argument terminator, matching the conventions Unix users expect from any serious CLI tool.
Because it mirrors the standard flag package’s API almost exactly, most codebases can switch by changing a single import alias (import flag "github.com/spf13/pflag"). It adds typed accessors (GetInt, GetString, etc.), flag deprecation and hiding, custom name-normalization functions, and structured error types with Unwrap support for use with Go’s errors.Is/errors.As. It has zero external dependencies and is the flag-parsing engine underneath Cobra, Kubernetes’ kubectl, Docker, Helm, and a large share of the Go CLI ecosystem.
What You Get
- Long (
--flag) and shorthand (-f) flag definitions via*Pvariants of every standard constructor (IntP,BoolVarP,VarP, etc.) - Combinable boolean shorthand flags on the command line (
-abcinstead of-a -b -c) - Typed value getters on a
FlagSet(GetInt,GetString,GetDuration, …) so callers don’t need to track pointers - Structured, typed errors (
NotExistError,ValueRequiredError,InvalidValueError,InvalidSyntaxError) that implementUnwrapfor use witherrors.Is/errors.As - Flag deprecation and hiding (
MarkDeprecated,MarkHidden,MarkShorthandDeprecated) for maintaining CLI backward compatibility - Custom flag-name normalization (
SetNormalizeFunc) for treating-,_, and.as equivalent, or aliasing renamed flags - Interop with Go’s native
flagpackage viaAddGoFlagSet, so third-party libraries that still register standard flags keep working
Common Use Cases
- Building a CLI tool with GNU-style flags - a Go program wants
--verbose/-vstyle flags instead offlagpackage’s single-dash-only syntax - Implementing subcommands - each subcommand gets its own independent
pflag.FlagSet, the same pattern Cobra builds subcommand parsing on top of - Migrating from Go’s flag package with minimal changes - swap the import alias to
flag "github.com/spf13/pflag"and existingflag.String()/flag.Parse()call sites keep compiling - Supporting deprecated or renamed flags without breaking scripts -
MarkDeprecatedandSetNormalizeFunclet a CLI evolve its flag names while still accepting the old ones - Bridging third-party flag registrations -
AddGoFlagSetpulls in flags declared with the standard library’sflagpackage (e.g. fromglog) into the samepflag.FlagSet
Under The Hood
Architecture
pflag centers on the FlagSet type (flag.go), which owns two maps keyed by flag name and shorthand plus an ordered slice for stable iteration, and every constructor (String, Int, BoolVarP, …) is a thin wrapper that allocates a typed Value implementation and registers it via FlagSet.VarP. Each primitive type (string, int, bool, duration, IP, slices of each, …) lives in its own file (string.go, int_slice.go, duration.go, ipnet.go, etc.) implementing the small Value interface (String(), Set(string) error, Type() string), so adding a new flag type is additive and doesn’t touch the parser core. Parsing itself walks os.Args-style slices token by token in parseArgs, dispatching to parseLongArg or parseShortArg depending on the leading dashes, and a package-level CommandLine FlagSet plus top-level functions (pflag.String(), pflag.Parse()) exist purely as convenience wrappers over an application-created FlagSet, matching the standard library’s ergonomics. This is a flat, single-responsibility layout: parsing, storage, and value types are cleanly separated, and nothing in the core loop depends on any one flag type.
Tech Stack
pflag is pure Go with zero runtime dependencies (go.mod declares only module github.com/spf13/pflag and go 1.12, no require block), which is deliberate for a library this deep in the Go CLI ecosystem’s dependency graph. It targets the standard library exclusively (fmt, strconv, errors, os, net, time) and its own golangflag.go shim provides one-way interop with the standard flag package rather than depending on it as a library. CI (.github/workflows/ci.yaml) runs the test suite against a matrix from Go 1.12 through current stable plus “oldstable”, reflecting a deliberate promise of long backward compatibility for a foundational dependency.
Code Quality
The repository carries roughly one test file per feature file (32 _test.go files against a similar count of implementation files), covering both individual value types (bool_test.go, ip_test.go, duration_slice_test.go) and end-to-end flag-parsing behavior (flag_test.go, printusage_test.go). CI runs tests with -race, and errors are represented as concrete exported types (NotExistError, ValueRequiredError, InvalidValueError, InvalidSyntaxError in errors.go) that implement the error interface and, where they wrap an underlying cause, Unwrap() error — enabling callers to use errors.As instead of string-matching error messages. Naming is consistent with the standard library’s flag package throughout (XxxVarP for pointer-binding shorthand variants, GetXxx for typed lookups), which lowers the cost of reading the source for anyone already familiar with flag.
What Makes It Unique
pflag’s specific niche is being the POSIX/GNU-flag layer that a large share of the Go CLI ecosystem (Cobra, and transitively kubectl, Helm, Docker CLI, and many others) is built on, while staying a near drop-in replacement for the standard library rather than a from-scratch flag-parsing API. Its typed-error refactor (NotExistError/ValueRequiredError/etc. with Unwrap support) is a comparatively recent addition that lets consuming tools programmatically distinguish failure modes instead of parsing human-readable strings, without changing the error text those tools already print to users.
Used by 33 apps in this directory
listmonk
Blogging · Marketing
High-performance, self-hosted newsletter and mailing list manager packaged as a single binary with built-in analytics, transactional messaging, and multi-channel delivery.
Multica
AI Assistants · AI Development
Turn coding agents into real teammates — assign issues, track progress, and compound reusable skills across a vendor-neutral, self-hosted platform.
NetBird
Security
Replace your VPN with a zero-trust WireGuard overlay network that auto-connects devices, enforces SSO and posture checks, and deploys in under 5 minutes.
Okteto
Developer Tools · Devops
Develop applications directly inside your Kubernetes cluster with real-time file sync and instant hot-reload — no more docker build/redeploy cycles.
Onyx
AI Agents · AI Assistants · Knowledge Management
Self-hostable AI platform with agentic RAG, 50+ connectors, deep research, code execution, and support for every major LLM provider.
opencloud
File Storage
Open source file management and collaboration platform that keeps your data under your control, no database required.
OpenMeter
Developer Tools · Invoicing Finance
Open-source metering and billing engine for AI, agentic, and DevTool monetization — ingest usage events in real time and turn them into accurate invoices automatically.
Ory Kratos
Authentication
API-first identity and user management that handles login, registration, MFA, and recovery so your application never has to.
Rill
Analytics · Data Engineering
The fastest BI tool for humans and agents — define metrics, models, and dashboards as code and query them instantly on ClickHouse or DuckDB.