go-shellwords
A Go library that splits shell-style command-line strings into argument slices, honoring POSIX quoting, escaping, and substitution rules.
Repository Health
Technical Analysis
go-shellwords gives Go programs a small, dependency-free way to take a raw command-line string — the kind a user might type into a shell, or that arrives from a config file, SSH session, or subprocess wrapper — and split it into the argument slice a shell would produce. It implements POSIX-style word splitting: single and double quotes, backslash escaping, environment variable expansion ($FOO and ${FOO}), and optional backtick or $() command substitution, each of which can be toggled independently on the Parser struct.
The library exposes both a package-level Parse/ParseWithEnvs convenience API and a stateful Parser type for callers who need custom separators, a working directory for command substitution, or a custom Getenv function instead of os.Getenv. Recent versions add hardening against a class of security issues around unmatched parentheses in command substitution, addressed with explicit error returns rather than silently executing partial input.
What You Get
- Parse(line string) - a package-level function that tokenizes a command line into
[]stringusing default parser settings. - Parser struct - a stateful parser exposing
ParseEnv,ParseBacktick,ParseComment, a customGetenv, and aDirfor command substitution. - ParseWithEnvs - splits leading
KEY=VALUEenvironment assignments from the actual command arguments, mirroring how a shell treatsFOO=bar cmd args. - SetExcludeSeparators - lets callers mark specific characters (e.g.
;,\t) as non-separators for line-oriented parsing use cases. - Position tracking - after a
Parsecall,Parser.Positionreports where an unconsumed separator (like;or&&) was found, so callers can resume parsing the remainder of a multi-command line.
Common Use Cases
- Building a REPL or shell-like CLI - tokenizing typed-in commands the same way a real shell would before dispatching to
exec.Command. - Parsing user-supplied command templates - splitting a stored string like
ffmpeg -i "input file.mp4" -y out.mp4from a config or database field into a safe argv slice. - Re-implementing shell semantics in Go tools - task runners and automation tools that accept a single “command” string field and need to split it correctly, quotes and all.
- Environment-aware command construction - expanding
$VAR/${VAR}references inside a stored command string before executing it, without invoking a real shell.
Under The Hood
Architecture
The library is a flat, single-package implementation with no internal layering: shellwords.go holds the whole tokenizer as one large character-by-character state machine (Parser.Parse), tracking quote state (single/double), backtick/$() command-substitution state, escape state, and comment state via a handful of booleans, with platform-specific command execution split into util_posix.go and util_windows.go behind a shellRun function selected by build tags. There is no dependency injection or plugin surface; the only extension points are the public fields on Parser (ParseEnv, ParseBacktick, ParseComment, Getenv, Dir, excluded separators). Because the whole state machine lives in one function, changing tokenization behavior (e.g. adding a new quote style) means editing the central Parse loop directly rather than composing new behavior externally.
Tech Stack
The module (github.com/mattn/go-shellwords, Go 1.13) has zero third-party dependencies — it uses only the Go standard library (bytes, errors, os, os/exec, strings, unicode). Command substitution (backtick/$()) shells out via os/exec.Command, invoking $SHELL (or /bin/sh as a fallback) on POSIX and an equivalent path on Windows. There is no build system beyond go build/go test; CI is driven by a Travis config and a go.test.sh coverage script, with codecov integration referenced in the README badges.
Code Quality
Testing is thorough for a library this size: shellwords_test.go covers dozens of table-driven cases for quoting, escaping, environment expansion, comments, backtick/$() substitution, and error paths, and shellwords_security_test.go adds targeted regression tests for a fixed vulnerability class around unmatched closing parentheses in command substitution (previously a code-execution-adjacent risk when ParseBacktick was enabled on untrusted input). Error handling is explicit — the parser returns a plain errInvalidCmdLine sentinel error rather than panicking on malformed quoting or substitution syntax. Naming is idiomatic Go; there are no generic type parameters or heavy abstractions to assess for type safety. No linter or formatter config (e.g. .golangci.yml) is present in the repo, and CI is limited to Travis rather than GitHub Actions.
API Design
What distinguishes go-shellwords from a naive whitespace split is that it implements a meaningful subset of actual POSIX shell tokenization semantics — nested quoting, backslash escapes inside and outside quotes, environment variable expansion with ${VAR} brace syntax, and optional shell-out command substitution — while remaining a small, auditable, dependency-free codebase. The project’s own security test suite (added specifically to reject unmatched ) characters rather than executing arbitrary shell fragments) shows a deliberate hardening pass around the most dangerous feature (ParseBacktick/command substitution), which is opt-in rather than the default — a meaningful safety design choice for a library commonly used to parse externally-supplied strings.
Used by 4 apps in this directory
1Panel
Devops · Hosting Control Panel · Monitoring
The only open-source VPS control panel with native AI agent runtime — deploy websites, Docker stacks, and local LLMs from one web interface.
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.
Teleport
Security · Authentication
Zero-trust infrastructure access platform that replaces credentials and VPNs with short-lived certificates, SSO, and identity-aware proxies for SSH, Kubernetes, databases, RDP, and AI agents.
Uncloud
Devops
Deploy and scale containerised apps across any servers without Kubernetes or Swarm overhead