Large language models read everything we write, but they do not read it efficiently. They have to parse, interpret, and compress it on every turn. The Compact Instruction Compiler (CIC) already turns Markdown into a pattern-based intermediate representation (PIR) and back again. Now it also runs a dictionary pass: a synonym canonicalizer that shrinks prose, preserves code and file paths, and makes instruction files more compressible without changing what they mean.

The CIC pipeline
CIC is a compiler for agent instruction files. Its input is Markdown (skills, workflows, rules, abilities). Its output is also Markdown, but smaller. In between, the file is translated to PIR — Patterned Intermediate Representation — a line-based format with directives like @p for prose, @b for bullets, @n for numbered lists, and @c for code blocks. Each pass in CIC reads PIR, transforms it, and writes PIR.
The dictionary pass sits right after xbar (cross-file pattern extraction) and right before pir2md. That matters because it only acts on @p, @b, and @n nodes — the prose nodes. Code blocks, frontmatter, and PIR directives pass through untouched. The earlier CIC post CIC: The Compact Instruction Compiler describes the full pipeline and the PIR language; this post focuses on the new dictionary layer.
What the dictionary pass does
The pass reads config/cic/dictionary.toml, which lists canonical keys and their synonyms. The current version is small and intentional:
version = "0.1.0"
description = "Canonical word dictionary for CIC prose minification"
use = { synonyms = ["utilize", "employ", "make use of"] }
start = { synonyms = ["begin", "initiate", "kick off"] }
create = { synonyms = ["make", "generate", "build"] }
run = { synonyms = ["execute", "perform", "carry out"] }
find = { synonyms = ["locate", "identify", "discover"] } Before any replacement happens, the pass masks the parts of the file that must not be touched:
`code` and fenced code blocks are replaced with placeholders and restored at the end.foo.cpp, bar.hpp and baz.toml are masked so commas and conjunctions survive.Then it walks each prose node and replaces single-word synonyms with their canonical key. Utilize becomes use. Begin becomes start. A phrase like Locate and discover becomes find and find because both words map independently to find — the pass currently canonicalizes single-word tokens, not whole phrases. After replacement, the masks are restored, so `std::vector` stays `std::vector` and a path list stays a path list.
"The point is not to rewrite meaning. The point is to remove the synonym lottery that inflates token counts. Two different instructions that mean the same thing should compress to the same tokens."
Why this is a compiler and not a thesaurus
A thesaurus suggests alternatives. A compiler chooses one. The dictionary pass is deterministic: it runs left-to-right, replaces the longest matching synonym, and always emits the same canonical key. That turns instruction files into a normalized form. When two skills describe the same behavior with different verbs, their PIR now uses the same token. The downstream cross-file pass (cic-xbar) and the security scanner (cic-guard) see a more uniform surface.
The pass is also reversible in principle. Because the canonical keys are stored in config/cic/dictionary.toml, a future pass could map them back to preferred synonyms for human editing. Today the output is compact Markdown, not the original. But the PIR-to-PIR transformation is a pure function of the input and the dictionary, which is exactly what you want in a compiler.
Verification and current limits
The pass is exercised by tests/integration/cic/cic_compiler_roundtrip.test.sh, which now includes a dictionary fixture and reports 11 tests passing. We also run cic.sh -d -o /tmp/dict_out.md /tmp/dict_test.md to spot-check canonicalization and span protection. The lint and security passes (cic.sh -l -g) run after dictionary and still report clean on the same files.
| Capability | Status | Notes |
|---|---|---|
| Single-word synonym canonicalization | implemented | Reads config/cic/dictionary.toml, longest-match sort |
| Code span / path list masking | implemented | Restored after replacement |
cic.sh -d / --dictionary flag | implemented | Pipeline order: md2pir → xbar → dict → pir2md → guard |
| Multi-word phrase matching | roadmap | Single-word matching only; overlapping phrases are basic |
Per-file opt-out (cic-dict: false) | roadmap | Not yet in frontmatter |
@d PIR dictionary manifest node | roadmap | Would emit the dictionary used for each file |
| Token-reduction stats | roadmap | cic.sh -d -v does not yet report savings |
The main limitation is that multi-word replacement is literal and boundary-checked. A phrase like make use of is in the synonym list for use, but the current implementation does not reliably match and replace three-word tokens across punctuation. That is the first roadmap item. The pass also does not yet report how many tokens it saved, which makes it hard to optimize the dictionary.
Connection to the larger instruction stack
CIC is part of a bigger effort to make agent instructions auditable, compact, and safe. The CIC compiler pipeline runs the OWASP-mapped scanner and style checker after the dictionary pass. The self-improving instructions post describes how we close the loop: the agent compresses its own files, then uses the result to improve the compressor. The dictionary pass adds a new compression primitive to that loop. If a skill repeatedly uses utilize and employ, the dictionary normalizes both to use, and the downstream pattern extractor can spot the repetition across files.
Try it
./scripts/lib/cic/cic.sh -d -o /tmp/out.md .devin/skills/frontier-post/SKILL.md
# Run the full integration suite
bash tests/integration/cic/cic_compiler_roundtrip.test.sh Cross-links
References
- CatGame:
config/cic/dictionary.toml - CatGame:
scripts/lib/cic/cic-dict.awk - CatGame:
scripts/lib/cic/cic.sh - CatGame:
tests/integration/cic/cic_compiler_roundtrip.test.sh - Related post: CIC: The Compact Instruction Compiler
- Related post: CIC: The Compact Instruction Compiler
