🏰 Kivia
Self-documenting Name Analyser for Go
Name things so your code explains itself.
Kivia is a fast, local-only analyser that flags abbreviated or compressed identifiers in Go code. It is built for teams that want explicit, readable naming conventions without external AI calls.
Philosophy
Identifier names should be fully self-documenting.
Kivia enforces a strict readability standard:
- Prefer full words to shorthand
- Avoid ambiguous abbreviations
- Keep the naming intent obvious from the identifier itself
Examples:
userNum → invalid (num is an abbreviation)
ctx → invalid (ctx is an abbreviation)
userCount → valid
requestContext → valid
Rules
- Abbreviations are violations: Tokens such as
ctx, expr, and num are flagged.
- Compressed tokens are violations: Non-word compressed forms are flagged.
- Strictness is configurable:
- Default: pragmatic strict (allows common technical tokens)
--strict: absolute strict (flags everything, including common technical tokens)
- Minimum length is explicit:
--min-eval-length controls whether short identifiers are evaluated.
How It Works
Kivia parses Go source using the standard library's AST, extracts identifiers, tokenises names (camel/snake/kebab), and evaluates each token against a local NLP dictionary pipeline.
- No network requests
- No LLM/API dependency
- Deterministic local analysis
Installation
go install github.com/Fuwn/kivia@latest
Or build locally:
go build -o ./bin/kivia ./cmd/kivia
Usage
# Analyse a package tree
kivia --path ./...
# Enforce absolute strict mode
kivia --path ./... --strict
# Ignore single-letter names during evaluation
kivia --path ./... --min-eval-length 2
# Ignore specific violations
kivia --path ./... --ignore name=ctx --ignore file=testdata
# JSON output without context payload
kivia --path ./... --format json --omit-context
Flags
| Flag |
Description |
--path |
Path to analyse (directory, file, or ./...). |
--strict |
Enforce absolute strict mode. The default mode is pragmatic and strict. |
--omit-context |
Hide usage context in output. |
--min-eval-length |
Minimum identifier length in runes to evaluate (must be >= 1). |
--format |
Output format: text or json. |
--fail-on-violation |
Exit with code 1 when violations are found. |
--ignore |
Ignore violations by matcher. Repeatable. Prefixes: name=, kind=, file=, reason=, func=. |
Ignore Matchers
--ignore supports targeted filtering:
name=<substring>
kind=<substring>
file=<substring>
reason=<substring>
func=<substring>
Without a prefix, the matcher is applied as a substring across all violation fields.
Example:
kivia --path ./... \
--ignore name=ctx \
--ignore reason=abbreviation \
--ignore file=_test.go
Output
Text (default)
internal/example/sample.go:12:9 parameter "ctx": Contains abbreviation: ctx.
context: type=context.Context, function=Handle
JSON
{
"violations": [
{
"identifier": {
"name": "ctx",
"kind": "parameter",
"file": "internal/example/sample.go",
"line": 12,
"column": 9,
"context": {
"enclosingFunction": "Handle",
"type": "context.Context"
}
},
"reason": "Contains abbreviation: ctx."
}
]
}
Identifier Scope (Go)
Kivia currently extracts and evaluates:
- Types
- Functions and methods
- Receivers
- Parameters
- Named results
- Variables (
var/const and :=)
- Range keys and values
- Struct fields
- Interface methods
Dictionary and NLP Source
Kivia loads its dictionary in this order:
KIVIA_DICTIONARY_PATH (if set)
- System dictionary (
/usr/share/dict/words, /usr/dict/words)
- Embedded fallback dictionary
A local fuzzy model cache is stored in the user cache directory to speed up repeat runs.
License
Licensed under either of Apache License, Version 2.0 or
MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.