How it works Professions For Engineers For Lawyers Quick start
hint/professions/for software engineers
@openhint/hintbook-software-engineer

Ship code that obeys the spec — not the vibe.

The software-engineer hintbook gives your .hint files a precise vocabulary for architecture, data models, behavior, and constraints. Compile it into a binding prompt and your agent implements exactly what you declared — in dependency order, with no stubs, no invented features.

src/compression/middleout.ts.hint Markdown
Middle-out compression core for Pied Piper. # entity CompressionResult {#result} ## field weissmanScore Decimal string, two places. Never float. # func compress {#compress} ## arg input The raw byte buffer. Must not be mutated. ## result A CompressionResult; throws on empty input. ## flow 1. Reject empty input with CompressionError. 2. Run the middle-out pass. 3. Compute the Weissman score. ## bad LossyFallback Never silently fall back to lossy. # rule Determinism Same input → byte-identical output.

Schema, not suggestion

An entity compiles to a binding data contract — no renamed fields, no changed types, nothing extra or missing.

Anti-patterns enforced

A bad block carries the strongest enforcement language in the book — real past failures the agent must never reintroduce.

Context inherits

A folder's _.hint wraps everything beneath it, so stack, build pipeline, and dependency policy are always in scope.

The vocabulary

Thirty-plus keywords across intent, data, behavior, UI & constraints.

Every keyword is a markdown heading that compiles into an explicit, named tag the agent is trained to obey. Reach for the most specific one — a field inside an entity beats a bullet list in prose.

Intent & scope
goalwhy · intent
Why the work exists and the outcome it must produce — the tie-breaker for everything the spec leaves unstated.
scopenongoal · outofscope
What is in scope and explicitly out — the agent builds everything in, nothing out, and reports rather than expanding.
doneacceptance · criteria
Observable conditions for "done" — proven with a test, a command, or an observation, never merely asserted.
Project context
appapplication
The domain, purpose, and overall structure — informs naming and architecture everywhere.
langlanguage
Language and runtime target. Only its syntax, APIs, and idioms are allowed.
depdeps · dependency
The approved dependency whitelist. Nothing outside it gets installed or imported without asking.
build
Build and test commands. Generated code must never break these pipelines.
module liblibrary
Existing modules and libraries to reuse — never reimplement what they already provide.
namespace
The package / module path all code in this scope is emitted under.
resresource read
Assets to honor and files to read first — match their conventions instead of guessing.
Data
entity
A data model with an exact schema — no renamed fields, changed types, extra or missing fields.
field
One named property: type, optionality, validation. Implemented exactly as declared.
table column row
Tabular structures, their columns, and exact rows: names, types, labels, constraints.
dataconst · value
A named constant or magic value — used exactly as given, referenced rather than duplicated.
Behavior
funcfunction
A binding function contract — arguments, return, errors, and logic flow are all mandatory.
arg resultreturn
Inputs and output: declared types and shapes, honored on every code path.
flow
A step-by-step sequence the implementation must follow without skipping validations.
action
A macro behavior invoked by name — its steps executed exactly whenever triggered.
error
Exact error types under exact conditions — never substituted, wrapped, or renamed; each backed by a regression test.
Constraints & tests
rule
Non-negotiable system-level mandates every function and data path must satisfy.
bad
Unconditional prohibitions — real past failures, never reintroduced even if examples suggest them.
good example
Required patterns and few-shot demonstrations to replicate exactly.
test
Scenarios that must all appear in the test output: edge cases, mock shapes, assertions.
User interface
ui form block image
UI surfaces, forms, reusable components, and images — only the declared elements, all of them.
Spec-internal
notesnote
Author-facing notes dropped from the compiled prompt — reminders and TODOs the agent never sees.
See it compile

One spec. A binding prompt. A reviewable report.

The same .hint file drives every mode. Watch the compression spec become a deterministic implementation prompt — then an audit report when run with --mode review.

src/compression/middleout.ts.hint
# func compress {#compress} Compresses a buffer middle-out. ## arg input The raw byte buffer. Must not be mutated. ## result A CompressionResult; throws CompressionError on empty input. ## flow 1. Reject empty input with CompressionError. 2. Run the middle-out pass. 3. Compute the Weissman score. ## bad LossyFallback Never silently fall back to lossy compression.
hint src/compression/middleout.tsimplement
<function_contract name="compress" id="compress"> Compresses a buffer middle-out. <argument name="input"> The raw byte buffer. Must not be mutated. </argument> <return> A CompressionResult; throws CompressionError on empty input. </return> <logic_flow> 1. Reject empty input with CompressionError. 2. Run the middle-out pass. 3. Compute the Weissman score. </logic_flow> <prohibited_anti_patterns name="LossyFallback"> Never silently fall back to lossy compression. </prohibited_anti_patterns> </function_contract>

$ hint --mode review src/compression/middleout.ts | claude -p

violationmiddleout.ts · L41–48 → bad LossyFallback

The catch block falls back to gzip() on a failed pass. The LossyFallback prohibition forbids any silent fallback. Minimal fix: re-throw CompressionError.

gapmiddleout.ts · return → result

Empty input returns an empty buffer instead of throwing. The result contract requires CompressionError on empty input — currently unhandled.

riskmiddleout.ts · L12 → arg input

input.sort() mutates the argument. The input arg states it must not be mutated. Operate on a copy.

Verdict: does not conform — 1 violation, 1 gap, 1 risk.

Three modes

Same spec. Different job.

compile · default

Implement

A senior engineer implementing the project from a binding specification.

Read it all, implement in dependency order, reuse declared modules, ship production quality — no placeholders, stubs, or TODOs.

hint src/...
--mode fix

Repair

Where the code and the spec disagree, the code is wrong.

Diagnose the root cause, make the smallest conforming change, and ship a regression test. With a hint.lock it reconciles only the blocks that drifted — and changes nothing when the code already conforms.

hint --mode fix
--mode review

Audit

Findings, never patches.

Walk the spec block by block, hunt declared anti-patterns, and report findings by severity with file ranges and minimal corrections.

hint --mode review
In practice · demo-pied-piper

A compression engine, specified before it's written.

The Pied Piper demo repo shows a whole module declared in .hint first — then built, fixed, and reviewed entirely from the compiled prompts.

01

Lay the baseline

A root _.hint declares lang TypeScript, the build pipeline, and a bad GlobalState rule every file inherits.

02

Specify the module

Companion hints define the CompressionResult entity, the compress contract, its flow, and the LossyFallback prohibition.

03

Compile & implement

hint src/compression | claude -p emits the implementation prompt; the agent writes code in dependency order with the Weissman score exact.

04

Review every PR

--mode review in CI audits each change against the same spec — the lossy fallback never lands without a flagged violation.

05

Verify, lock & reconcile

hint verify confirms every declared func, entity, and error actually landed — deterministic, no tokens — then hint lock records what shipped. Later hint diff shows which blocks a spec edit touched, and --mode fix corrects just those — the rest stays byte-for-byte.

_.hint · project root
Middle-out compression for Pied Piper. # lang TypeScript Node 22, ES modules, strict. No CommonJS. # build - npm run build to compile - npm test runs the vitest suites # bad GlobalState Never store request state in module-level variables. # dep Whitelist Only the packages in package.json. Ask before adding anything new.
Quick start

Wire it into your repo.

1 · install & register
# from your repo root npm install -g @openhint/cli hint config hint add @openhint/hintbook-software-engineer hint apply
2 · compile & ship
# implement from the spec hint src/billing/invoice.ts | claude -p # repair against the spec hint --mode fix src/billing/invoice.ts \ | claude -p # validate every spec in CI hint --dry-run 'src/**/*.hint'

Then just keep talking to your agent. hint apply writes the HINT workflow into your AGENTS.md and CLAUDE.md — so Claude Code, Codex, and Cursor call hint on their own whenever a .hint spec is relevant. No need to run it by hand.

Borders around your codebase.

Declare the architecture once. Let the agent build, fix, and review inside it — forever.