Use the OINK CLI
oink is an optional Go CLI for Hugo sites. The local 0.1.0-dev candidate
focuses on diagnosis, real output checks, initialization, builds, theme
upgrades, and guarded maintenance plans. Hugo remains the renderer. Sites
continue to work with ordinary Hugo.
This guide describes the reduced command surface on 2026-10-04. The CLI has no established public release or distribution. Earlier R1–R8 acceptance belongs to its historical source and binaries. The CLI contract defines current behavior. Studio, general editing, context, snippets, editor setup, and CI generation are retired.
The current cached-module move integration failed once and passed a targeted rerun; the intermittent failure remains open. For the recorded scope, see the verification limits.
Build and install locally
From an available oink-cli source checkout, use Go 1.26 or newer and Make:
The export affects this shell only. The CLI does not install system tools or
change a shell profile. make install PREFIX=/your/prefix chooses another
prefix; BINDIR=/your/bin selects the exact directory. A source build needs
the dependencies in go.sum; make deps explicitly prepares them when network
access is available. The build and install targets then use the local
toolchain without downloading dependencies or another Go compiler.
The dated runtime acceptance record exercised its identified historical candidate on macOS arm64, native Linux arm64 and Linux amd64 emulated through QEMU TCG, with Go 1.27.1, Hugo Extended 0.166.0 and the public OINK v1.1.0 module. The Hugo version gate accepts Extended 0.160.1 or newer; this is not a claim that every accepted version has been tested. The embedded Starter documents Hugo Extended 0.165.0 or newer and requires Go 1.27. Those Linux tests ran as nonroot users on ext4 with provisioned offline dependencies; required filesystem/signal and selected actual-Hugo cases execute. Optional tools absent from a guest stay explicit skips; they have separate host protocol evidence. Two fresh builds reproduced all five archives, and the three declared runtime archives were extracted and executed outside a checkout without Node. Darwin amd64 is an experimental archive and remains unverified after actual Bad CPU type; cross-compilation does not prove runtime support. Windows is outside the declared scope. These results remain bound to the recorded source and archives; they do not qualify the later reduced CLI or a newly built executable automatically.
make release VERSION=0.1.0-dev DIST=dist prepares four binary archives, a
source archive, and SHA256SUMS in a new or empty directory. It does not
publish them. See the archive acceptance and reproduction steps
for the exercised platform and reproducibility limits.
Create a site from the fixed Starter
Prepare the public theme once if it is not already cached. This explicit provisioning command may use the network:
init accepts a new directory or an existing empty directory. Its parent must
exist. It refuses existing files, including dotfiles, and refuses a symbolic
link as the target. It validates a temporary candidate before creating any
target file and detects target changes during that operation.
Choose --profile project (the default), docs, blog, or book. project
keeps the complete previous Starter projection. The other choices retain their
archived content section and adapt the existing localized site title, home
cards/actions and navigation to that section. Selected content and shared
assets/examples/workflows/license retain their archived bytes; generated
configuration and homepage YAML are the only serialized profile projections.
The archived workflow examples remain unchanged and are not the checksum-bound
CI plans from ci init.
Language choices remain en (default), en,zh, and all (English, Chinese and
French), independently of the selected profile. Every composition uses the
same MIT-licensed Starter commit
137843b25bacd76ddd1f7ce71330bf2e3155b954 embedded in the executable, pins OINK
v1.1.0 with recorded Go checksums and disables enableGitInfo before the first
Git commit. No runtime template fetch, Git initialization or commit occurs.
Unknown profiles fail before writing; unavailable or failed required Hugo
validation leaves the new/empty target unchanged.
Edit the title and baseURL in my-docs/hugo.yaml, then edit the home data and
sample content using the Starter tutorial. After
creating Git history yourself, you can enable enableGitInfo if wanted.
Ordinary Hugo can build the generated site without the CLI:
This uses the GOMODCACHE exported above and provisioned dependencies. All
12 profile/language combinations passed ordinary warning-strict Hugo at both
root and /manual/ URLs (24 builds). Rendered local references were checked,
and complete source bytes/modes/file inventories compared equal before/after.
Public init/check tests separately cover all four profiles in English and
bilingual configurations, default-project byte/mode parity and failure paths.
Create ordinary content
Start from the initialized bilingual site above. Preview a new bundle and its Chinese draft, inspect the diff and candidate result, then apply the saved plan:
--language defaults to the effective default language; --kind defaults to
page and also accepts docs, blog, or book. The site-relative bundle path
must map unambiguously through actual content mounts and their language-site
matrix. Language directories retain distinct physical indexes; shared filenames
use the actual language relationships. Existing bundles or
same-page sibling files are preserved. The primary file is an ordinary page;
selected translation files are drafts with the supplied title as placeholder.
They remain unreviewed until explicit human review. Each proposed file must
be recognized as one actual site-owned Hugo page with actual rendered outputs;
link-only/no-output, ignored or build-never new files cannot pass merely because
existing content builds cleanly.
Saving a plan does not write those site files. Apply rechecks the bound fresh
directory and source state and preserves later editor attachments on failure.
Configure editor hints and snippets with the ordinary site editor. The CLI no longer generates these settings.
Inspect pages and committed impact
Use an actual page ID, Hugo Path, permalink or captured source path. The language:path ID removes multilingual selector ambiguity:
Choose IDs from the actual captured page facts; these example pages must exist
in your site. inspect exposes observed references, actual outputs, translation
peers and physical bundle inputs. impact renders the selected committed Git
tree and the current site, including old deleted identities and unchanged
inbound pages. Changed global configuration/templates/data and uncertain
ownership expand scope. An observed alias output with unproven page ownership
also causes full scope, without guessing an owner from front matter.
check --since currently runs the full current check. Read
data.check_scope: full separately from causal data.impact.full_scope.
Completed inspect/impact queries return 0 while quality findings remain
in data.current_check; full checking retains policy findings 1. Missing
or unrenderable history is required incomplete 2: known current facts remain
visible, while old identities and changes stay unknown. Current external
local dependencies are never borrowed as historical bytes. A committed
site-owned theme is supported; symlink/submodule and required unsupported or
incomplete history states are explicit limits.
Preview and apply a content move
Use clean physical site-relative file/bundle paths and save the new plan
outside the selected site. The preview shows original checks, a provisional
route probe, final validation, translation/attachment mappings, byte/full-mode
diffs, actual old/new routes, alias advice and manual references. A provisional
probe may report stale-link findings 1; only the final candidate can validate
the plan. Raw HTML, shortcode output, transformed or ambiguous destinations
are not rewritten. Repeated ordinary Markdown destinations can also stay
manual when exact source/output occurrence ownership is unproven, including
aggregate/print output. Their final broken targets return 1 and no plan is
saved. Review manual source locations and actual output pointers in your editor,
then create a fresh preview. A moved attachment needs a proven new published
URL, not merely a new physical path. Paired equal-byte processed image outputs
can be proven while absolute original-resource URLs remain manual; those
unproven URLs are not constructed automatically.
Aliases are advice for review, not automatically serialized front matter.
Explicit saved apply captures and regenerates the actual proof before selected
writes. Complete source hashes/modes/inventory, external inputs and fresh
target directories remain guarded. Existing targets, later source/attachment/
configuration edits or mode changes return 2 without overwriting them.
The move preserves original modes and binary bytes, unrelated files and the
Git index; it does not commit. The resulting ordinary Hugo inputs remain
buildable with Hugo independently of the CLI. Inspect the named recovery
directory if an apply reports a failure during writes.
Diagnose and validate an existing site
Run these commands from any directory and select exactly one site:
doctor reports the real Hugo executable and version, required tools, the
declared theme pin, effective Hugo configuration, module graph and mounts,
workspaces, replacements, vendor presence, languages, and enabled outputs.
It does not build the site. Keep the raw subprocess evidence alongside the
structured findings when investigating a Hugo error.
check copies the inputs into a disposable directory, isolates build outputs
and caches, invokes Hugo with --panicOnWarning, and checks supported local
links, anchors, resources, and machine-output references against the rendered
files. Hugo itself enumerates each page’s enabled output formats and URLs for
each language, including front matter overrides and statically authored pages
excluded from ordinary page lists. A temporary verification output is added
only in the disposable copy and removed before artifact checks. The CLI does
not infer routes from Markdown filenames. Disabled machine outputs are not
errors. Coverage entries identify checks that were
completed, omitted, unsupported, or incomplete. Browser interactions,
accessibility, external URL availability, server redirects, and deployment are
outside this static check.
JSON data.pages supplies Hugo’s page identities, actual routes, aliases,
languages, translations, publication settings, known source provenance and
outputs. data.references supplies observed rendered references and checked
anchor state. Generated pages with no proven file retain an explicit unknown
source. These are production-view facts; their presence does not certify
undeclared translation coverage or invent a Markdown source line.
Human output summarizes page/reference counts; use JSON for the full arrays.
Both commands preserve source files. --keep-work retains the disposable
directory and reports its path for inspection; otherwise it is removed. Use
--config FILE, --environment NAME, and --hugo PATH when the site needs a
specific configuration, environment, or Hugo executable. Configuration files
must be inside the selected site. For inspection, --environment takes
precedence over HUGO_ENVIRONMENT; otherwise the environment is production.
If Hugo adds or changes go.mod or go.sum in the temporary copy, the CLI
reports that required dependency preparation remains unreviewed; it does not
apply those changes to the source or silently call the original inputs ready.
--release disables both Go and Hugo workspaces and disables environment and
Hugo-configuration replacements in the disposable copy. It preserves go.mod
replacements. A local
OINK replacement must be reviewed explicitly before claiming a public-pin
check; the CLI does not silently delete it. Vendor evidence is also separate:
a public requirement in go.mod does not establish which bytes are in
_vendor.
The initial isolated-check scope has these limits:
| Input shape | Current behavior |
|---|---|
Normal checkout with its own .git directory, or materialized files without Git |
Supported within the other documented boundaries |
Linked Git worktree with a .git file |
Rejected; use a separate materialized copy with its own Git metadata if Git history is needed |
| Mounted symlinks or mounts still pointing outside the isolated snapshot | Rejected; materialize those inputs inside the selected site or supported local dependency |
| Unmounted auxiliary symlinks | Omitted from the snapshot; this does not validate their contents |
Mounts using excluded public, resources, node_modules, or tmp trees |
Rejected when they are required source inputs; keep authored/generated source in a dedicated source directory |
Custom HUGO_CONFIGDIR outside the supported config location |
Rejected; use the site’s config tree or an explicit in-site --config file |
Hugo content adapters (_content.gotmpl) |
Complete enabled-output enumeration is unsupported; check and candidate validation return incomplete work |
| Multihost language configuration | Unsupported for full output validation; returns incomplete work rather than treating each host as one output tree |
Likewise, disabling page rendering or selecting render segments that omit an
enabled language’s verification output cannot produce a successful full
check. These are coverage limits, not instructions to delete a worktree,
replacement, symlink, or authored content. doctor can still inspect supported
configuration without claiming a completed output build.
Select checks and record project policy
Create a regular oink.yaml at the site’s root when the project needs explicit
checking policy. It uses schema_version: oink.policy/v1 in one YAML document.
Keep languages, menus, URLs and theme versions in existing Hugo/module inputs.
Unknown policy keys/groups, invalid reviews and required disabled groups
return 2.
This example retains required links and demonstrates a reviewed finding and a separately deployed URL scope. Replace illustrative paths and review metadata with actual project decisions:
Rules use exact diagnostic IDs and error, warning or info. Exclusion
globs use clean relative paths; recursive ** and escape paths are unsupported.
Excluded findings stay visible with disposition: "excluded" and review
metadata. Checks never create review records as a side effect. Required
build/input/tool failures and unsupported coverage remain 2 despite policy.
For a site at https://example.org/manual/, same-origin HTML /status/
references normally fail as outside the published base path. The reviewed
scope declares that separate application; availability remains untested.
Complete path-segment matching excludes /status-other/. A scope cannot hide
missing targets inside /manual/ or required local machine-output references.
Without a policy, check enables required links, translations and style.
check links, check translations and check style each select one required
engine; unselected groups report optional not_checked. Explicit policy groups
can disable optional checks. Every check retains its strict Hugo prerequisites.
Declare translation coverage
Start with Hugo’s actual page identities in check --json (data.pages), then
declare the source Page.Path scope and required enabled languages. Paths are
Hugo source identities, independent of slug, URL, aliases or language prefixes.
Extend the same single oink.yaml object; this complete example also declares
protected prose and the baseline path:
Use real page paths, filenames, IDs and protected literals from your project.
mode defaults to localized, drafts to include. Strict mode with
explicit_ids: true requires complete recognized explicit-ID correspondence;
localized mode protects the selected ids. Placeholder counts, named fenced
code, required dotted fields and equal dotted values are separate opt-in
constraints. Other prose, heading counts and code may differ.
drafts: ignore skips draft sources and treats draft targets as unavailable;
require-published requires the source and required targets in the production
view. Hugo-disabled known languages are optional not_applicable; unknown
languages fail policy loading. Without scopes, existing default-language pairs
and duplicate relationships are inspected, but universal localization is not
required. JSON data.translations distinguishes missing, draft and hash-review
states. An explicit nonpublishable analysis includes draft/future/expired pages
without replacing production output or publishing them.
Inspect source rules and provenance
Generic rules inspect recognized explicit IDs and declared protected prose.
The parser follows effective Hugo markup.goldmark.parser.attribute.title
and .block, plus markup.goldmark.extensions.passthrough.enable and its
configured .delimiters. These settings remain in Hugo configuration.
It keeps original UTF-8/CRLF/BOM offsets and accepts
unknown valid YAML/TOML/JSON front matter. Code, shortcode bodies, raw HTML and
math contents are excluded from prose evidence; an attribute after a fence is
not treated as a supported code attribute. Unsupported required source syntax
or absent declared protected inputs returns 2.
The small native OINK v1.1.0 catalog reports advisory code/table conflicts,
deprecated attribution fields and attributes the published theme drops.
data.native_rule_provenance records immutable source/license hashes. The
catalog runs only for a SHA-verified actual public module-cache mount. Other
versions, replacements, vendor copies and unknown identities report optional
native-theme-rules: not_checked; generic rules still run. Review this coverage
before treating the check as complete for a particular component.
Review translations and apply metadata plans
Use the exact Hugo IDs or unambiguous captured source filenames from the report:
Review previews .oink/translations.json (oink.translations/v1) after candidate
validation. It never writes the site during preview. The record binds full
source/translation byte SHA-256 values and explicit reviewer/reason/time.
--reviewed-at RFC3339 is optional and defaults to current UTC. No record means
unknown; current, source_changed, translation_changed and both_changed
describe hashes since review, without judging translation accuracy. Modification
time is not review evidence. diff shows captured source text for comparison.
To acknowledge completed, reviewed existing findings while keeping them visible:
The default baseline is .oink/baseline.json (oink.baseline/v1); baseline in
policy can select another clean relative file. Acknowledged exact rule,
normalized location/pointer and condition remain visible with
disposition: "baseline" and review metadata. Severity changes do not invalidate
that fingerprint; new conditions still block. Required incomplete work cannot
be captured or hidden by a baseline.
Both preview commands require reviewer and reason. --plan FILE creates a new
oink.plan/v1 file without overwriting; omitting it prints the validated plan
only. Review the readable diff, site, file list and base byte/mode guards before
plans apply. That command validates a fresh isolated candidate and refuses
stale guards, escapes, .git, symlinks and nonregular files. It writes only
the plan’s selected files; these commands do not use --write. Failed partial
writes restore owned unchanged files and preserve later editor bytes, modes or
deletions. The reported recovery directory retains original/concurrent evidence.
Preview and apply one theme upgrade
Choose an explicit release tag. The following command validates a candidate and prints the proposed module-file changes without applying them:
The normal human output shows a unified module diff, mode changes and bounded
route/alias/capability changes. In JSON, review data.plan_id, data.changes,
data.comparison, baseline/candidate check summaries and raw evidence. A
missing old URL/output blocks the update unless an observed redirect at its
old output file proves preservation; unknown custom alias identity stays
incomplete. This is not universal theme or browser compatibility. To apply
the freshly revalidated reviewed plan, use its recorded ID:
The CLI changes only the selected go.mod and go.sum bytes after candidate
validation. It preserves unrelated requirements, replacement directives,
comments, and unrelated uncommitted work. --write refuses uncommitted changes
to either selected file, and detects changes after planning. Recovery evidence
identifies backups and any rollback that could not safely restore a
concurrently changed file.
The ID binds current copied source bytes/modes/inventory and actual comparison, not just module-file text. A later source/workspace/dependency edit requires a new preview; only selected module files are applied. Unknown resolved pins or changed/unknown renderer/environment cannot pass. Comparison supports a single HTTP(S) base origin/path; multihost inputs stay incomplete. Emitted byte hashes also bind the ID, so nondeterministic templates can require a refreshed preview. No configuration migration is performed automatically; review unsupported changes manually.
An OINK go.mod replace is a blocking condition for this public-pin workflow.
A site containing _vendor is also refused: this release does not refresh
vendor content. Prepare a separate reviewed copy, update the intended pin and
run hugo mod vendor explicitly, then review and validate the entire vendor
change. A go.mod bump alone is never reported as a vendor upgrade.
Preview and build through Hugo
Arguments after -- go directly to Hugo. The CLI shows the effective command
and forwards process cancellation. dev runs hugo server; build selects
the production environment by default and adds --panicOnWarning. These are
direct Hugo operations by default and may create the site’s normal output and
cache files. They do not run the reference checks performed by oink check.
Check and export one build
Choose a real publication URL in OINK_PUBLIC_BASE_URL, prepare the site’s
exact dependencies, then use a fresh output directory and separate new manifest:
Add --network to this operation only if its dependencies or required remote
resources need downloading. An example/local publication address is a release
error; ordinary diagnosis reports a warning. --release also checks actual
public theme resolution independently of local Git history or declared pins.
Hugo renders one isolated production output. The CLI checks, seals and exports
that same tree without rebuilding or changing site sources. Required incomplete
coverage returns 2; blocking findings return 1. Neither result creates a verified
export. An explicit scoped translation policy needing publication-excluded Hugo
identities returns 2; run standalone check/translations for the full
nonpublishable maintenance view, or deliberately select a production policy.
The command does not infer identities from filenames.
The destination must be new or empty and its parent must exist. The manifest
must be a new file outside the public tree. Existing entries are preserved;
failed partial export remains explicitly unverified. Optional --marker adds
only the artifact identity at .well-known/oink-build.json; without the flag,
no marker is added. The local oink.artifact/v1 manifest records original
input identity, known Git state, effective settings/theme/tools, required
coverage, Hugo routes and exact file digests/modes. It excludes absolute local
paths and logs and is saved with mode 0600. Keep it outside the upload.
Managed builds allow only --minify, --gc, --ignoreCache and --noTimes
after --, with optional boolean =true/=false. The ordinary build example
above still accepts transparent Hugo arguments.
Verify artifacts and a deployed site
Immediately before uploading, check the exported directory offline:
This compares the exact files, bytes and full modes. Missing, additional or
modified files invalidate the previous identity. Upload this directory without
rebuilding; preserve its hidden .well-known marker when enabled.
After a separately authorized deployment, check its public URL explicitly:
Verification reads every declared file and distinct actual Hugo route, including
language/subpath URLs, and compares bounded decoded response digests plus recorded HTML
canonical/language identities and the enabled marker. HTTP cannot inspect local
file modes. Wrong content, a soft-404 or a different captured identity returns
1. Timeouts, authentication/rate-limit failures, server unavailability and a
missing required marker return 2; redirects outside the selected origin/path
are blocked. No credentials are discovered or sent. A build’s --network
permission does not authorize this later request or any upload.
Retired CI generation
ci init is removed. Keep CI configuration in the site or Starter.
Local CLI validation does not execute hosted CI or deploy a site. Previously
saved CI plans are rejected by plans apply.
Check explicitly registered sites
Workspace and adapter examples passed owning/runtime, actual protocol, four-consumer parity/preservation and canonical source/render gates. A07/A15 supported scope is accepted locally in the R6 record. They do not describe a published CLI release or a completed platform refresh.
Create a separate registry such as oink.workspace.yaml beside your selected
projects. Its only site fields are name and directory; keep Hugo settings
in each site and checking policy in that site’s oink.yaml.
| Command | Selection |
|---|---|
workspace list --workspace FILE |
List explicit entries without running Hugo |
workspace check [GROUP] --workspace FILE [--sites NAME,NAME] |
Check all or an exact subset, in registry order |
check ... --workspace FILE --site NAME |
Run the normal single-site check for one registered name |
plans apply FILE --workspace FILE --site NAME |
Revalidate and apply only a plan bound to that named canonical site |
Names are case sensitive ASCII identifiers matching
[A-Za-z][A-Za-z0-9_-]{0,63}. A regular nonsymlink registry has one strict YAML
document, 1–64 nonoverlapping sites and a 256 KiB limit. Directories are literal
relative paths from its actual parent, or absolute paths; no environment/glob
expansion or sibling discovery occurs. Canonical aliases identify the same site
and cannot register it twice. Missing directories remain listed; their check
returns 2, while the remaining explicit sites are still checked. The aggregate
returns 2 before 1 before 0, preserving full per-site findings and coverage.
Omitting --sites means all registered sites; an explicit list rejects blanks,
duplicates and unknown names and keeps registry order.
A direct command needs --site NAME; there is no default registry site. init,
artifacts and verify do not accept registry selection. Save a
reviewed plan outside its site, then explicitly apply it to the same name:
Use actual page identities returned by your site’s checks for the review
selectors. Selecting blog for a plan bound to docs returns 2 before a
source write. Preview, validation, freshness and byte/mode safeguards are the
same as direct single-site use; no other registered or neighboring site is
updated automatically.
Configure already provisioned optional tools
The CLI does not install markdownlint, Vale or lychee. After provisioning tools
separately, add explicit entries to the selected site’s oink.yaml. The current
protocols are markdownlint-cli 0.49.1, Vale 3.24.0 and lychee 0.24.2;
other reported versions remain unsupported until qualified.
enabled defaults to true, required to false, and command to the kind’s
name. You can select one provisioned executable by name or absolute path;
commands are not shell snippets. Configuration paths must be clean relative
paths inside the captured site. Process time defaults to 60 seconds, with
bounded nondefault values 1–300. Unavailable optional tools show omissions;
required unavailability or unsupported protocol returns 2. A problem baseline
or lower rule severity cannot turn required incompletion into success.
Markdownlint and Vale belong to style; lychee belongs to links. Select the
group whose tools you intend to run:
The second command explicitly permits actual external HTTP requests. Without
--network, lychee is not invoked: optional coverage is not_checked, required
coverage returns 2. A successful native local-links check does not attest
external availability. HTTP 401, 403, 408, 425, 429, 5xx, DNS/TLS
failures and timeouts are inconclusive, not definite broken links. Other failed
4xx responses are typed findings. External locations remain actual output
files and DOM pointers; the CLI does not guess their Markdown line.
For markdownlint, use declarative JSON, YAML or TOML, for example:
JS/JSONC configs, custom rules and extends are unsupported. The CLI stages
a private rule object behind an unpredictable JSON pointer so upstream rc data
does not change its effective rules. Vale requires an explicit INI and captured
styles. A supported minimal configuration is:
Provide declarative rule files under styles/Project/. Supported rule kinds are
existence, substitution, repetition, occurrence, consistency,
capitalization and sequence. Actions, scripts, packages, sync, conversion
assets and style pipelines require manual review and are not executed by this
adapter. Lychee accepts these bounded request settings:
Allowed ranges are 1–300 seconds, 0–3 retries and 1–32 concurrent requests.
The literal cache = false is also accepted; cache = true is refused. Cache
and preprocessors are disabled; arbitrary extra tool arguments are not
accepted. No adapter fixes or formats source files. Code prose is outside
source attribution; Markdown structure and fence/inline code boundaries remain
available to markdownlint, while Vale receives the prose-only mask. Private
masks preserve proven UTF-8/BOM/CRLF boundaries around front matter, shortcodes,
raw HTML, configured math and attributes; findings from excluded/synthetic text
remain omissions. Only already captured site-owned Markdown is read for prose
tools.
Inspect data.adapters, adapter.KIND coverage and raw evidence before
interpreting an exit. Each adapter retains version/executable/configuration
hashes and protocol provenance. Caller proxy URLs/credentials and Node preload
settings are not forwarded; literal NO_PROXY/no_proxy host-list data may be
retained for the qualified runtime. This does not disable every operating-system
proxy route or create a network sandbox. Network checks do not verify external
fragments, browser behavior or remote content identity.
Retired local Studio
studio is removed from the CLI. Use an ordinary editor and oink dev for
a site preview. Read maintenance facts through inspect and structured reports.
The dated R7 acceptance remains historical evidence for its identified inputs.
Retired Studio views
Read page and quality facts with inspect, check, and structured reports.
Retired browser targets
The CLI Studio browser test targets are removed with the implementation. Current CLI checks remain Go and actual Hugo tests.
Retired general editing
edit and Studio editing are removed. Edit source with an ordinary editor,
then run check. new, move, review records, and baseline plans retain
candidate validation and byte/mode guards. Previously saved editing plans
are rejected. The dated R8 record remains historical evidence.
Retired edit commands
The edit text|field|snippet|attachment command family is removed.
Run new --help or move --help for the retained bounded file workflows.
Retired Studio editing
The CLI does not serve an editor or accept browser Apply requests.
Retained plan review
Retained previews display the complete proposed diff. Save a new plan, then
explicitly run plans apply FILE --site DIR. Candidate validation, source and
external input guards, and concurrent-edit recovery remain required.
Network and offline operation
Network access is disabled by default; --offline makes that choice explicit.
Missing dependencies produce an incomplete result. The CLI does not install
Hugo, download a Go toolchain, change global configuration, or enable telemetry.
Allow the current operation to use the network only when intended:
--network and --offline cannot be combined. Diagnostic and validation
operations use disposable caches; a download there does not establish a
persistent cache for the next offline run. For repeatable offline work,
provision the exact module versions in a normal Go module cache and set
GOMODCACHE explicitly as shown above. Include all transitive dependencies
needed by your site. Isolated validation reuses provisioned module download
artifacts, not Hugo’s global remote-resource (GetRemote) cache. A prewarmed
remote-resource cache alone does not make this check work offline. Materialize
required remote content as local site resources, or explicitly use
--network for that build. Theme assets that already ship as local files do
not require such a download.
Text, JSON, YAML, and automation
| Option | Output |
|---|---|
| Default | Concise colored English text |
--json, -J |
One JSON oink.result/v1 object |
--yaml, -Y |
One YAML document with the same result fields and types |
--verbose, -v |
All findings, coverage details, and tool logs |
--no-color |
Plain English text |
Choose one structured format. Nonempty NO_COLOR or TERM=dumb also disables
text colors. Structured output adds no terminal colors. Tool logs go to
stderr. --format json|yaml and --non-interactive remain hidden compatibility
options. Every command is non-interactive.
Default text shows status, counts, up to eight active findings, and explicit coverage omissions. Detailed facts and reviewed findings remain available in structured results. Plan and upgrade previews retain their complete diffs. Cobra owns command dispatch and focused help. CLI messages use short, active English sentences inspired by ASD-STE100; this does not assert certification. User content and external tool evidence retain their original language.
| Exit code | Meaning |
|---|---|
0 |
Requested work completed without blocking findings |
1 |
Completed checks found a policy problem |
2 |
Required work could not complete, including tool, build, or I/O failure |
Always inspect coverage alongside the exit code. An exit code of zero from
doctor does not prove a build, and a successful static check does not prove
browser behavior or a public deployment. These commands do not commit, push,
publish a theme, or deploy a site.