TypeGlish is typed English: a language for system prompts and agents. The compiler catches the contradictions, vague rules, and bloat that make an agent drift and cost more, so a prompt becomes something you can improve, trust, and run lean, not just a wish.1
1$CONFIG model claude-opus-4-82$IMPORT input tier: one of free, pro, premium34$TOOL lookup_order5 - description:: Look up an order by its id and return its status.6 - input::7 - order_id:: the order's id.89$TEST no_pricing10 - input:: How much does the Enterprise plan cost?11 - expect::12 - no specific price is stated13 - redirects pricing to the sales team1415<role>16 @@ persona: name the agent once, then reference it everywhere17 Persona IS a support agent for Acme, a SaaS analytics company.18 You are @{persona}.19</role>2021<constraints>22 @@ pricing: pricing is a sales conversation, never a support one23 NEVER state a specific price; ALWAYS direct pricing questions to sales.24 MUST keep every reply to at most 3 sentences.25 WHEN an order needs live data THEN call @[lookup_order].26</constraints>2728<per_tier>29 @@ tiering: the prompt reshapes per caller tier, resolved at compile time30 $IF @{tier} is one of pro, premium: Offer the priority concierge line before closing.31 $ELSE: Invite the customer to upgrade for priority support.32</per_tier>
TypeGlish turns raw prompts into structured, logical statements that can be checked for logical errors, redundancy, forbidden symbols, and prompting best practices.
When an agent writes or edits a prompt, the compiler holds it to the rules you set. Off-brand, contradictory, or rule-breaking lines never land.
# written by an agent, unreviewed You are a world-class assistant!! Always be helpful AND thorough 🎉 (your house rules: nowhere in sight)
+ agent adds: ALWAYS quote a price ✗ E212 breaks your rule at L23 · rejected fix:: route pricing to sales agent: patched · recompiled ✓ 0 exceptions
Every hard rule is checked against all the others. If two can collide, the prompt doesn’t compile - you find out on save, not in front of a user.
You are a helpful bot. Always answer every question. Never answer anything off-topic. Be concise but also thorough.
Bot IS helpful and concise Bot MUST answer IF on-topic Bot NEVER answer IF off-topic Tone IS warm, brief
You declare what you want; the compiler writes the structure that works - ordering, sections, emphasis. No folklore, no lucky comments.
IMPORTANT!!! Always stay in role. (repeating this 3× so it sticks) Take a deep breath. Think step by step. # v14_final_FINAL
Persona IS a claims adjuster Persona MUST verify {claim.id} first Reasoning IS step-by-step
Your guidelines become compiler config. Write them once, and every prompt - hand-written or generated - is checked against them on every build.
# prompt-guidelines.docx “Keep prompts short. No emojis. Every agent cites its sources.” (read once, enforced never)
# glish.tgc - your compiler, your rules RULE forbid:: emojis, superlatives RULE require:: one $TEST per agent RULE bound:: prompts AT MOST 40 lines
Models read prompts differently. Declare per-model rules once, and each build reshapes the same source for its target - no forks, no compromise.
prompts/agent-gpt5.txt prompts/agent-claude.txt ← three weeks stale prompts/agent-llama.txt ← who wrote this?
$TARGET claude-opus-4-8:: xml sections $TARGET gpt-5:: markdown, terse $ tg build --all ✓ 3 models · same rules
Every line shows which tests it covers and how often it fires. Dead weight looks like dead weight - and is safe to cut.
# 2,400 lines · 14 authors · 3 years Never discuss competitor pricing (2023?) Always end with a haiku. ← why (deleting anything = roulette)
Persona MUST cite {policy} · covers 3 tests · fires 214×/day Persona NEVER quotes prices · fires 12×/day Tone IS warm · no coverage ⚠ add a test
Each turn ships only the rules the moment needs. Edge cases ride along only when the edge shows up - smaller prompts, lower cost.
"hi" → 212 rules attached: refund edge cases, the GDPR clause, the haiku rule… every turn, every user, every day.
IF state IS greeting THEN include: Persona, Tone IF claim IS open THEN include: Refunds, Policy ── this turn: 41 of 212 lines
Clear rules leave nothing to interpret, so a smaller model handles them. Same behavior, a fraction of the cost.
Use your best judgment about when a refund feels appropriate, all things considered. Read the room. → frontier model, $$$
IF order.age < 30 days AND item IS unused THEN refund IS approved OTHERWISE route TO human → runs on the small model
Your words, symbols, and spelling are checked before anything ships. Every agent, on every model, sounds like your brand.
"Sign in" here, "log in" there, "LOGIN!" on the sales agent, an emoji storm on support. Five agents, five brands.
$DICTIONARY "./brand.dict" Lexicon MUST use "sign in" Lexicon NEVER says "log in" Symbols ARE one of: - · ↗ spellcheck · US English · 0 issues
The whole agent in one readable file - rules, branches, and the tests that guard them - plus the brand module it shares with every other agent.
# support.tg - a whole agent, one file $IMPORT BrandVoice FROM "./brand.tg" Persona IS Sky, an airline support agent Persona MUST follow BrandVoice Persona MUST cite {policy} on every claim Persona NEVER invents policy IF customer IS angry THEN Tone IS empathetic Persona NEVER upsells OTHERWISE Persona MAY offer {upgrade} $TEST "refund a $720 ticket" EXPECT Persona refuses AND cites {policy}
# brand.tg - one voice, every agent Tone ARE one of: warm, direct, playful BrandVoice IS the house style BrandVoice MUST write in sentence case BrandVoice SHOULD keep replies under 120 words BrandVoice NEVER uses jargon $TEST "explain a delayed flight" EXPECT reply IS warm AND plain
The TypeGlish compiler runs in real-time as prompts are written - turning raw english into logical statements that are checked for validity against your rules.
Sentences compile to an object map, not vibes. Once You.name holds “John”, a later Your name is Sarah. is a provable collision - caught by a lookup, not a model.
Every action parses to verb + object + tool binding against a curated verb catalog. A bare imperative is an obligation - and each record is a fact the checker can hold against the rest.
Different wording, one canonical claim: verb synonyms merge, nouns fold by lemma (people ⇄ person), negations normalize. Restatements become comparable - the precondition for every check downstream.
One line, one claim: compound rules split into atomic statements, and every statement must terminate - an unterminated line is a compile error with a one-click fix. Atoms are what the solver checks.
Two strengths, two fates. must and never are contracts - proved before you ship. should and may are preferences - graded, not gated. No more guessing which “always” meant it.
all / some / no / most / only map onto the square of opposition - the 2,000-year-old logic of quantity. “All claims cite policy” and “some claims skip policy” are now provably incompatible.
Numbers in prose become arithmetic: bounds, action counts, set sizes - even supply vs demand (“there is only one tool” vs “call five tools”). The solver decides them instantly.
Every rule resolves to its subject. “You”, a declared alias, a declared role - one subject, one rule-set, checked together. And “the user” is never you.
“The” promises a unique referent. With two tools declared, “the tool” is ambiguous - an error naming both candidates. English’s most common word, checked.
Guards parse in both spellings - IF … THEN and the comma form English writes. Each rule knows when it fires, so two rules that never fire together can never collide.
Deterministic branches resolve at compile: (source, state) → prompt. The model never reads the branch that didn’t apply - and membership is checked against the declared set.
Three sigils, three meanings - every name resolves at compile time to a section, a tool, or a typed slot. A dangling reference stops the build. No silent “see the doc above.”
A closed set makes everything downstream provable: a branch on enterprise is an error, and a switch over the set is checked exhaustive. Membership is set math, not vibes.
Sections compile to the XML tags models read best; duplicate or vague names are errors. Annotations ride beside the rules and compile away - documentation that costs zero tokens.
The compiler knows what it can’t check: vague and hedging phrasing gets an advisory nudge toward a measurable bound. Best practice is a lint rule, not tribal knowledge.
Instructions are plain text because fancy marks hide meaning from the checker: ≤ conceals the bound “at most 3” proves; the curly apostrophe conceals the negation. One-click ASCII fixes - human language never flags.
Every line is scored for what it adds over the rest. Saying it three ways warns - and a reducer proposes the minimal prompt that keeps the behavior.
This is why the breakdown matters: objects, actions, bounds, guards, and subjects all land in one solver, so every hard rule is proved against every other - in milliseconds, on every keystroke, no LLM in the loop.
Better agents by subtraction: the runtime resolves the business logic - routing, tiers, tool gating - before the model reads a word. The model handles the conversation; the compiled rules handle everything that must never be wrong.
<role>You are Sky, a support agent for Acme.</role><pricing>NEVER state a specific price;ALWAYS route pricing to sales.</pricing><tools>@[lookup_order]: look up an order by id.</tools><refunds>Refunds require an open claim;route to @[open_claim].</refunds><verify>Confirm the account email before refunds.</verify><de_escalation>Acknowledge, own the delay,give a concrete next step.</de_escalation><account>Address changes need inbox confirmation.</account><products>Integrations: Slack, Teams, Zapier.</products><per_tier>Offer the priority concierge line.</per_tier>
Fewer errors. Business logic leaves the prompt and runs as code - the model can’t misread what it never has to read.
Sharper tool calls. Two tools in context instead of fifty: selection accuracy up, tokens down.
Rules that hold live. Every MUST and NEVER is enforced on each draft - the same rules the checker proved.
One prompt per caller. Each request compiles to its own state and tier, from one source file.
A wish, unlike a prompt, cannot be version-controlled.
Yes - a monorepo of personalities. It's better than it sounds.
Most of the time the prompt is the culprit, not the model: it's underspecified or quietly self-contradictory, so the model has room to resolve it differently on each run. TypeGlish type-checks the prompt and surfaces those contradictions, undefined references, and vague or unmeasurable rules as errors before you ship - then you lock the behavior you want with inline $TEST cases.
Model sampling still applies, so pair a robust prompt with a low temperature for the most consistent output.
Treat them like code. Write the prompt as a TypeGlish .tg file, run npx typeglish check prompts/*.tg to catch provable defects, npx typeglish score prompt.tg --min B to measure quality against prompting best practices, and add $TEST blocks so a future edit can't silently break what already works.
When a model ignores an instruction, the usual cause is a conflicting or buried rule - for example "always be brief" sitting next to a rule that forces long output. TypeGlish proves when two rules contradict and flags vague or unmeasurable language, so every instruction is consistent and checkable before the model ever sees it.
Yes - that's the whole idea. .tg files are plain text you keep in git, $TEST blocks are inline evals that run against the prompt, and npx typeglish check (add --json) returns machine-readable results with CI exit codes, so a broken prompt fails the build like any other broken code.
TypeGlish is a language and compiler for prompts. You write in near-plain English; it parses your prompt into a typed structure and checks it the way a type system and linter check code - proving contradictions, catching undefined references, and scoring quality - then compiles it down to the prompt the model actually reads. English on the surface, types underneath.
No, and it doesn't claim to. It makes the prompt robust - removing the contradictions, ambiguity, and unmeasurable rules that make a model behave inconsistently, and letting you catch regressions with tests. For the most consistent behavior, combine a checked TypeGlish prompt with a low temperature.
There's nothing to install - it runs on npx with zero dependencies. Use npx typeglish check prompts/*.tg to catch provable errors, npx typeglish score prompt.tg --min B to measure prompt quality, and npx typeglish build prompts/*.tg to compile the final prompt. Add --json to any command for machine-readable output.
Yes. TypeGlish checks and compiles the prompt itself, so the result is a plain prompt that works with any model - Claude, GPT, Gemini, open models, anything. It's model-agnostic by design.
Templates and frameworks help you assemble and send prompts, but none of them check whether the prompt is internally consistent. TypeGlish is a type system and linter for the prompt's meaning - it proves contradictions, flags vague rules, and scores quality before a single token is sent. It's complementary: keep your framework and check the prompt with TypeGlish.
Yes, and it's encouraged. Run it as an MCP server with npx -y typeglish mcp to expose check, build, score, and explain tools to any agent host, or install the Claude Code plugin with /plugin install typeglish@typeglish so the check-score-build loop runs automatically while the agent works.
Free for noncommercial use under the PolyForm Noncommercial 1.0.0 license, published on npm with zero dependencies. Run it with npx typeglish - no account, no install. Commercial use needs a license.
One line to install. Everything else is in the file.