glippy

module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 27, 2026 License: 0BSD

README

Glippy

Glippy is a Go-native formatter, linter, and safe fixer built as one cohesive developer tool. Its formatter expands compressed but valid Go and makes deterministic width-aware layout decisions. Its linter keeps correctness-focused defaults, pays only for the analysis tiers enabled rules require, and routes all source changes through an explicit conflict-safe transaction.

Glippy v1 is the first stable Glippy release line. The catalog contains 129 rules, including 20 rules with safe, suggestion, or unsafe fixes. Official artifacts support macOS and Linux on amd64 and arm64; Windows is unsupported. The existing v0.1.0 release remains Gox under github.com/faustbrian/gox; its module tags, binary, archives, and attestations are immutable historical identities. The maintainer accepted the documented Glippy ecosystem-collision risk for the initial Glippy development line; that product decision is not legal clearance. Untagged commits and locally built binaries remain unsupported development artifacts.

Why Glippy

Gofmt intentionally leaves many layout choices alone. Glippy gives hostile valid source one canonical readable form. For example:

if _,err:=client.Discover(nil);!errors.Is(err,ErrContextRequired){t.Fatal(err)}

becomes:

if _, err := client.Discover(nil); !errors.Is(err, ErrContextRequired) {
	t.Fatal(err)
}

Long expressions and lists use grammar-aware broken forms. Operators remain where Go semicolon insertion is safe, and multiline lists receive required trailing commas. Comments, directives, literal spelling, explicit source structure, and build intent remain part of the validation contract rather than being reconstructed from go/ast alone.

The formatter owns whitespace and canonical layout. Lint rules own behavioral diagnostics and named source transformations. Semantic refactors do not hide inside formatting, and layout policy is not duplicated as lint noise.

Product Direction

  • Go-native frontend: Glippy builds on the standard parser, AST, token, type checker, package loader, CFG, SSA, and go/analysis ecosystem.
  • Deterministic layout: a document IR selects one flat or canonical broken form with bounded fit work.
  • High-signal linting: correctness is the default preset group; suspicious, performance, complexity, style, pedantic, and nursery groups are composable opt-ins. Nursery rules are validation candidates excluded from curated profiles; v1 freezes their shipped IDs and reporting contracts while restriction rules remain individually selected.
  • Demand-driven analysis: syntax-only work does not construct types, CFG, or SSA; deeper representations are shared within one package run. CFG and SSA consumers share demand-driven no-return and nil/error return summaries, while lifecycle rules consume versioned parameter and receiver effects for root modules plus reachable workspace and local replacement modules, without retaining dependency syntax as lint targets. Lock rules share one bounded fixed-point state transition over each function CFG, distinguish read and write modes, and consume configured blocking-call contracts without repeating propagation per rule. Closed-resource analysis uses the same bounded worklist contract and consumes proven close effects without treating ownership borrowing as proof of unchanged resource state. Exact project contracts can also require individual call results to be used; ignored contracted results report without duplicating the broader discarded-error diagnostic. Exact returned-alias contracts preserve outstanding lifecycle obligations when ownership returns to the same tracked value.
  • Safe source changes: fixes carry source identity and safety class; conflicts, stale ranges, and failed validation cannot silently write source. Accepted fixes may declare exact required imports, while the coordinator owns collision checks, fix-caused cleanup, and deterministic add/remove provenance without becoming a general import organizer.
  • One product, separate engines: formatting, diagnostics, fix coordination, filesystem replacement, and reporting retain distinct owners.

Oxfmt and Oxlint are the product-experience references for a fast, focused, predictable formatter and linter. Oxc is the reference for shared compiler-style infrastructure. Go's specification and supported toolchains remain the syntax and semantic authority. Glippy does not copy ESLint's plugin architecture, configuration breadth, or default product model.

Commands

glippy fmt [paths...]
glippy fmt --write [paths...]
glippy fmt --check [paths...]
glippy fmt --diff [paths...]
glippy lint [paths...]
glippy lint --fix [paths...]
glippy lint --fix --diff [paths...]
glippy lint --fix-suggestions --diff [paths...]
glippy lint --fix-unsafe --diff [paths...]
glippy lint -Wperformance -Dwarnings [paths...]
glippy lint --only=<rules> [paths...]
glippy lint --except=<rules> [paths...]
glippy lint --new-from=<git-ref> [paths...]
glippy lint --generate-baseline=<path> [paths...]
glippy lint --reporter=github [paths...]
glippy lint --reporter=sarif [paths...]
glippy lint --reporter=short [paths...]
glippy lint --stats[=text|json] [paths...]
glippy check [paths...]
glippy check --new-from=<git-ref> [paths...]
glippy check --stats[=text|json] [paths...]
glippy lsp [--fix-suggestions] [--fix-unsafe]
glippy init [--profile=<profile>] [directory]
glippy config check [path]
glippy config show [path]
glippy rules [--preset=<preset>] [--fixable] [--tier=<tier>]
glippy explain <rule>
glippy explain <rule> --json
glippy version
glippy completion <bash|zsh|fish>
glippy help [command]

Running glippy, glippy --help, or glippy -h prints the top-level command summary. glippy help <command> and <command> --help or <command> -h print the exact usage accepted by that command.

glippy check ./... is the non-mutating combined CI entry point. Safe fixes are selected with lint --fix; suggestion and unsafe classes require their own explicit flags. Existing findings can be captured without weakening new-code policy through a deterministic lint baseline, or hidden without a baseline during incremental adoption with --new-from=origin/main. See the command reference for inputs, reporters, exit categories, and write behavior.

Lint and combined check support GitHub workflow annotations and SARIF 2.1.0 in addition to human text and Glippy's versioned JSON envelope. Formatter-only commands remain text|json because GitHub and SARIF report diagnostics rather than formatted source streams.

Default human diagnostics render bounded physical-source frames with precise primary underlines, related locations, notes, help, and fix safety. Use --reporter=short for the source-free path:line:column form in logs. Machine reporters remain source-free and never include replacement text.

lint and combined check also provide opt-in execution statistics through --stats or --stats=json. Diagnostics keep their selected standard-output format, while statistics use standard error so machine consumers can capture the two versioned documents independently. Statistics explain tier and dependency loading, per-rule findings and cost, suppression and baseline counts, and persistent-cache outcomes. They are intentionally absent from ordinary runs.

glippy lsp provides full-buffer synchronization, live syntax or typed diagnostics, document formatting, version-bound individual fixes, and a whole-document "fix all safe" action over standard input/output. It analyzes the editor's exact buffer through package overlays, never writes source, and uses the same configuration, cache, suppression, baseline, formatter, and fix validation contracts as the command-line paths. Suggestion and unsafe actions remain hidden unless their corresponding LSP flags are supplied.

Document analysis runs outside the protocol loop. Rapid replacements coalesce behind a short bounded debounce, cancel an active older snapshot, and publish only results whose complete document versions are still current. Code actions wait for the matching analysis; a later edit rejects the queued request as content-modified instead of applying stale state.

Typed workspace analysis retains at most eight validated package results per session within a deterministic 128 MiB accounted-memory budget. Format-capable source is charged at sixteen times its exact bytes and compact dependency source at twice its bytes; this is a stable eviction weight, not an operating-system RSS measurement. An edit reloads its package and open reverse dependants while unaffected packages reuse their exact prior result against the current complete overlay. Captured disk sources, Go-file directory membership, module/workspace control files, baselines, configuration identity, and document digests all invalidate reuse. A separate eight-entry, 128 MiB typed graph session retains compact dependency types without dependency syntax or type-value maps. For a clean package or coherent base, internal-test, and external-test package family whose imports, source membership, build selection, and project controls remain compatible, Glippy reparses and re-typechecks every retained variant without invoking the primary package loader, then rebuilds required CFG and SSA state. External tests bind to the freshly checked internal variant rather than stale retained types. This applies to nested packages as well as a package at the project root. Changed active source in the main module, an active workspace module, or a local filesystem replacement reparses and re-typechecks its retained reverse dependency closure and rebuilds selected-module effect facts before root diagnostics. Exact overlays may replace already selected local dependency source. Newly direct root imports already present in the retained graph are admitted without a full load. Imports added by a changed local dependency reuse the retained package identity when available or use the same bounded exact types loader. Newly loaded mutable local layers are rechecked against compatible retained transitive types before reverse dependency and effect reconstruction. Uncertain or malformed test package families, unresolved dependency imports, cgo-generated sources, changed source or build selection, module or workspace control changes, parse or type errors, immutable dependency edits, and external file notifications fall back to a complete load. The ordinary aggregate retained weight is therefore 256 MiB; it remains a deterministic eviction model rather than an RSS promise.

glippy init creates a starter .glippy.toml without overwriting an existing path. The default, recommended, strict, and pedantic profiles provide increasing curated policy without requiring projects to assemble groups and exact rules manually; glippy init --profile=strict selects one explicitly. glippy config check validates discovered or explicit policy, while glippy config show explains the resolved profile, presets, rule severities and reasons, analysis tier, file policies, baseline, suppressions, cache settings, and configured project semantic contracts. Static versioned contract files can declare exact project or dependency function effects such as no-return, required results, ownership transfer, conditional nilness, blocking, and returned aliases without loading executable plugins. Ordered [[lint.overrides]] entries can adjust exact rule severities for project-relative glob paths such as tests, fixtures, generated adapters, or migration trees without introducing nested configuration files.

Use glippy rules to discover the compiled catalog by preset, fix availability, or exact analysis tier. lint --only and lint --except apply exact comma-separated rule IDs after project policy, with exclusions winning over inclusions. Both lint and check accept ordered Clippy-style -A/--allow, -W/--warn, -D/--deny, and -F/--forbid directives targeting exact rule IDs, selectable groups, or the currently enabled warnings set. Later directives override earlier ones, except that a forbidden rule cannot be lowered. explain --json exposes the same canonical metadata through a schema-versioned machine contract.

The nursery group is never included by default, recommended, strict, or pedantic. It contains opt-in rules still undergoing broad corpus validation. Beginning with v1, its shipped IDs, membership, severities, reporting boundaries, and fixes follow the compatibility policy. Select it explicitly with lint.presets = ["nursery"], -Wnursery, or glippy rules --preset=nursery.

[[lint.overrides]]
paths = ["**/*_test.go", "testdata/**"]

[lint.overrides.rules]
discarded-error = "off"
blank-error-discard = "warn"

The pedantic catalog includes bounded Go-native simplifications for blank identifiers, direct closures, nil-and-length checks, time helpers, buffer conversions, constant formatting, and case-normalized comparisons. Five narrow transformations plus the constant-format operand replacement are available only through lint --fix-suggestions and still pass conflict, formatting, parse, typed-validation, and atomic-write gates. It also reports undocumented empty conditional branches, direct integer min/max update patterns, and redundant explicit variable types. Only the redundant-type rule offers a safe fix, and it refuses edits that would remove a comment.

The opt-in complexity catalog measures structural nesting, logical function lines, parameter count, and result count with bounded per-rule thresholds. Test files are excluded by default, and these advisory API or decomposition findings never enter the correctness preset or offer automatic fixes.

The suspicious catalog also checks stream iteration through the shared control-flow tier. unchecked-rows-error and unchecked-scanner-error require every normally returning path after a direct database/sql.Rows.Next or bufio.Scanner.Scan loop to observe the matching terminal error. Discarded results and checks against a reassigned iterator do not satisfy the contract.

The opt-in error-flow catalog includes overwritten-error, typed-nil-error-return, shadowed-error, and nil-error-wrap. The shadow rule deliberately does not warn about ordinary nested if err := ... handling: it reports only stale outer errors carried out of loops and deferred assignments that update a shadowing error instead of the named result. nil-error-wrap reports %w operands proven nil directly or through an exact selected-module sibling result relationship whose dominated state makes a non-nil error impossible.

The default output-integrity catalog distinguishes three writer failures: discarded Flush or Close errors, CSV flushing without observing Writer.Error, and successful tar, gzip, multipart, ascii85, base32, or base64 output paths that use a directly acquired writer without finalizing or transferring it.

The default correctness catalog checks direct database/sql transaction lifecycles. After a conventional successful DB.Begin, DB.BeginTx, or Conn.BeginTx guard, sql-transaction-not-completed requires every normally returning path to commit, roll back, or transfer ownership of the transaction. Conditional cleanup and reassignment cannot silently discharge another open path.

The opt-in resource-not-closed rule applies the same bounded obligation model to local values with Close() error. Cleanup or ownership transfer must cover every normally returning path, so a close on only one branch and reassignment before cleanup both report. Exact receiver summaries also recognize direct terminal methods such as a locally proven Shutdown that closes the same receiver; dynamic, conditional, and promoted receiver behavior remains conservative. The same receiver facts establish closed state for resource-used-after-close.

The opt-in http-response-body-not-closed rule covers the standard-library gap where *http.Response is not itself a closer. After a successful direct package or Client request guard, every normal return must close or transfer the body. Passing the body to a reader does not count as transfer, so early status and read-error returns before a later close still report.

The opt-in http-response-body-used-after-close rule follows the same direct request boundary and reports reads, selected io consumers, and repeated closes reached only after every path has closed the body. Conditional closure, aliases, transfer, asynchronous or deferred execution, and unknown helpers remain conservative. The rule is suspicious rather than correctness because a custom RoundTripper can supply an io.ReadCloser with implementation-specific post-close behavior.

The restriction catalog includes blank-error-discard, direct-panic, process-exit, context-background, context-todo, and exported-api-documentation. Projects can enable these policies only by exact rule ID to require explicit error handling, keep process termination at an owned boundary, audit root and placeholder contexts, or enforce documented exported contracts. Each rule excludes test files unless its typed include-tests option is enabled, and the restriction group cannot be enabled wholesale.

Installation

Install the stable CLI from source with Go 1.27:

go install github.com/faustbrian/glippy/cmd/glippy@v1.0.0
glippy version

Prebuilt macOS and Linux archives, manifests, and checksums are published on the v1.0.0 GitHub Release. Verify a downloaded file's GitHub provenance with:

gh attestation verify <downloaded-artifact> --repo faustbrian/glippy

Gox v0.1.0 remains an immutable historical release under its original module, binary, configuration, and artifact identities. It is superseded by Glippy v1.

Pin the same stable version for every developer and CI job. Do not run another formatter after Glippy: documented width, import-order, literal, parentheses, alignment, and empty-statement choices are not universally gofmt fixed points. Use the migration guide before changing a repository's formatter authority.

Current Target Boundary

  • Source language: Go 1.25 through Go 1.27.
  • Runtime targets: macOS and Linux on amd64 and arm64.
  • Unsupported runtime targets: Windows and all other operating systems.
  • Write and fix claims: recorded local-filesystem combinations only; network, distributed, and userspace filesystems and forced-power-loss durability are outside the guarantee.
  • Ordinary operation: no telemetry or source transmission; formatting and syntax rules do not invoke the Go command, while typed analysis uses the documented go/packages boundary with network access disabled by default.

The support policy, supported Go versions, and CLI filesystem contract define the precise scope.

Documentation

Security reports follow SECURITY.md. Glippy is licensed under the BSD Zero Clause License, and release archives reproduce that license and all applicable third-party notices. Ordinary development pushes cannot create a tag or release.

Directories

Path Synopsis
benchmarks
cmd
glippy command
internal
analysis
Package analysis schedules native rules over shared run-owned representations.
Package analysis schedules native rules over shared run-owned representations.
baseline
Package baseline owns deterministic, source-bound lint adoption waivers.
Package baseline owns deterministic, source-bound lint adoption waivers.
cache
Package cache owns deterministic persistent-cache identity and storage.
Package cache owns deterministic persistent-cache identity and storage.
changed
Package changed resolves source lines owned by a Git change relative to a deterministic merge base.
Package changed resolves source lines owned by a Git change relative to a deterministic merge base.
cli
Package cli owns Glippy command dispatch and process-facing I/O contracts.
Package cli owns Glippy command dispatch and process-facing I/O contracts.
completion
Package completion renders deterministic shell completion scripts.
Package completion renders deterministic shell completion scripts.
config
Package config owns typed Glippy configuration defaults and decoding.
Package config owns typed Glippy configuration defaults and decoding.
contracts
Package contracts owns strict, versioned project semantic contracts.
Package contracts owns strict, versioned project semantic contracts.
corpus
Package corpus owns the pinned external-repository validation contract.
Package corpus owns the pinned external-repository validation contract.
diff
Package diff renders deterministic, bounded unified source differences.
Package diff renders deterministic, bounded unified source differences.
discovery
Package discovery owns deterministic filesystem input selection.
Package discovery owns deterministic filesystem input selection.
filesystem
Package filesystem owns validated source snapshots and atomic replacement.
Package filesystem owns validated source snapshots and atomic replacement.
fix
Package fix coordinates selected lint fixes over one immutable source file.
Package fix coordinates selected lint fixes over one immutable source file.
format
Package format lowers Go syntax into the Glippy document model.
Package format lowers Go syntax into the Glippy document model.
format/doc
Package doc provides the language-neutral document model used by the Glippy formatter.
Package doc provides the language-neutral document model used by the Glippy formatter.
goversion
Package goversion resolves and validates the Go source language version for one project path without invoking the Go command.
Package goversion resolves and validates the Go source language version for one project path without invoking the Go command.
lsp
Package lsp owns Glippy's bounded JSON-RPC editor protocol surface.
Package lsp owns Glippy's bounded JSON-RPC editor protocol surface.
release
Package release builds deterministic prototype release artifacts.
Package release builds deterministic prototype release artifacts.
releasecmd command
Command releasecmd builds deterministic maintainer-only release artifacts.
Command releasecmd builds deterministic maintainer-only release artifacts.
report
Package report owns stable machine-readable command result envelopes.
Package report owns stable machine-readable command result envelopes.
rulecatalog
Package rulecatalog composes native Glippy rules with admitted analyzers.
Package rulecatalog composes native Glippy rules with admitted analyzers.
ruledoc command
Command ruledoc renders the built-in lint catalog from canonical metadata.
Command ruledoc renders the built-in lint catalog from canonical metadata.
rules
Package rules defines native lint-rule contracts and canonical metadata.
Package rules defines native lint-rule contracts and canonical metadata.
source
Package source owns immutable physical Go source units and their lexical reconstruction data.
Package source owns immutable physical Go source units and their lexical reconstruction data.
suppressions
Package suppressions parses and owns physical lint-suppression ranges.
Package suppressions parses and owns physical lint-suppression ranges.
version
Package version resolves deterministic binary version metadata.
Package version resolves deterministic binary version metadata.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL