Agent skill

Update Lexicon

by woogles-io in woogles-io/liwords

Add a new edition of an existing woogles lexicon (e.g. An agent skill from woogles-io/liwords.

AGPL-3.0Auto-check passed

Install Update Lexicon

skills CLI
$ npx skills add woogles-io/liwords --skill update-lexicon -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install woogles-io/liwords update-lexicon --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/woogles-io/liwords.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/update-lexicon .claude/skills/update-lexicon && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
update-lexicon
GitHub stars
117
Token cost
~3k tokens
SKILL.md length
1,591 words
Files
5 (incl. scripts)
Skills in repo
1
Repo updated
First seen
Licence
AGPL-3.0

At a glance

Add a new edition of an existing woogles lexicon (e.g. An agent skill from woogles-io/liwords.

  • Works in 10 steps: Pin down the inputs → Build and verify the word graphs → Branch → …
  • The user says a new dictionary
  • SKILL.md covers 0. Pin down the inputs, 1. Build and verify the word…, 2. Branch and 3. Put the files in place, plus 6 more sections
  • Runs Python and Shell scripts from its folder; calls git, go and npx

What it does

Update Lexicon is an agent skill from woogles-io/liwords. Add a new edition of an existing woogles lexicon (e.g. NSF25 - NSF26, CSW21 - CSW24) from a raw word list. It builds and verifies the .kwg/.kad with kwgc, reuses or accepts a .klv2, wires the lexicon into liwords, retires the old edition, opens the PR and walks through the production rollout. Use when the user says a new dictionary, word list or lexicon version is out, or asks to update, add or obsolete a lexicon.

Its SKILL.md is about 3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 6 other files, including scripts (for example `reference/new-alphabet.md`, `reference/prod-sql.md` and `scripts/build_lexicon.py`).

It works with WebAssembly. The repository describes itself as: A site that allows people to play a crossword board game against each other. The licence is AGPL-3.0.

When your agent uses it

  • The user says a new dictionary
  • Lexicon version is out
  • Obsolete a lexicon

Example prompts

  • “/update-lexicon”

Requirements

  • Python 3
  • Node.js
  • A Bash shell
  • Docker

Workflow steps

10 steps, taken from the step headings in SKILL.md.

  1. Pin down the inputs
  2. Build and verify the word graphs
  3. Branch
  4. Put the files in place
  5. Wire NEW into liwords
  6. Tests that pin the new files
  7. Check it locally
  8. Commit and PR
  9. Production rollout (the user runs this, or you run it only with explicit approval)
  10. Cross-repo follow-ups (usually none needed; check each)

What it can do on your machine

Read from SKILL.md and the folder at commit 1a69ec9. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Ships 2 files in scripts/ (Python and Shell), which the agent can run.

    Shell commands in SKILL.md call:

    • git
    • go
    • npx
    • make
    • python3
    • npm
    • ssh

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use git, npx, npm and ssh, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Update Lexicon loads about 3k tokens when it runs. Until then it costs about 109 tokens; SKILL.md has 1,591 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~109
When it runs · the whole SKILL.md, loaded when a task matches
~3k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.

SKILL.md

The full file from woogles-io/liwords at commit 1a69ec9, republished under its AGPL-3.0 licence (© woogles-io). 1,591 words, ~3,004 tokens.

Download SKILL.mdSave it as .claude/skills/update-lexicon/SKILL.md (or your agent's skills folder). This skill also uses 4 other files; get the full folder from GitHub.
name
update-lexicon
description
Add a new edition of an existing woogles lexicon (e.g. NSF25 -> NSF26, CSW21 -> CSW24) from a raw word list. It builds and verifies the .kwg/.kad with kwgc, reuses or accepts a .klv2, wires the lexicon into liwords, retires the old edition, opens the PR and walks through the production rollout. Use when the user says a new dictionary, word list or lexicon version is out, or asks to update, add or obsolete a lexicon.

Updating a lexicon on woogles

This covers a new edition of a lexicon whose alphabet woogles already supports. A brand-new alphabet or letter distribution (for example Slovene in PR #1952 and #1955) is a different, multi-repo job. See reference/new-alphabet.md and stop to plan it with the user before touching anything.

Work carefully. The repo usually has unrelated untracked files, and the old edition's files are still needed by existing games. Several steps affect production and must never be done without explicit approval.

Throughout, OLD is the edition being replaced (e.g. NSF25), NEW is the new one (e.g. NSF26), and WASM=liwords-ui/public/wasm/2024. data/lexica/gaddag is a symlink to WASM, so local dev and CI read the same files.

0. Pin down the inputs

Work these out before building, and confirm them with the user in one message:

InputHow to decide
Word list pathGiven by the user. Look at it first: head, line count, encoding, case, and whether there's a second column (definitions).
NEW code<FAMILY><2-digit year>, following the existing ones (ls $WASM). A file named nsf2026.txt becomes NSF26.
OLD codeThe family's current entry in AllowedNewGameLexica (pkg/entity/lexica.go).
Alphabettilemapping.ProbableLetterDistributionName prefix map in word-golib, e.g. NSF → norwegian. It must exist in pkg/memento/letterdistributions/ and as a kwgc tileset. If either is missing, this isn't a version update.
Leaves (.klv2)Reuse OLD.klv2 (copied as NEW.klv2) unless the user supplies new leaves. Same for super-OLD.klv2 if it exists.
Length windowmin 2 (no 1-tile plays exist). Max 15, or 21 if super-OLD.klv2 exists (that lexicon is also played on the 21x21 SuperCrosswordGame board).
Obsolete OLD?Default yes: OLD leaves new-game lists but stays loadable (see step 3).

Earlier editions were not always filtered. NSF25.kwg contains 1-letter words and words up to 33 letters, so a big "fewer words" number compared with OLD's raw count is expected and not a problem. The diff below only compares words inside the length window.

1. Build and verify the word graphs

bash
cd ~/code/kwgc && make   # only if ./kwgc is missing or stale
python3 .claude/skills/update-lexicon/scripts/build_lexicon.py \
  --input <wordlist> --name NEW --alphabet <alphabet> \
  --prev $WASM/OLD.kwg --max-len <15|21> \
  --out <scratchpad>/NEW

The script normalizes the list: NFC, uppercase, first column only, duplicates removed. It stops if any character is outside the alphabet, drops words outside the length window, and builds NEW.kwg and NEW.kad with kwgc. It then reads them back and checks them exactly:

  • DAWG half of the kwg = the kept word set
  • .kad = the set of per-word sorted-tile anagram keys
  • GADDAG half of the kwg = every reverse(prefix)?suffix entry for every word

It also writes report.json, dropped.txt, added.txt and removed.txt (diff against OLD inside the length window). kwgc exits 0 even when it fails, so rely on the script's checks, never on kwgc's exit code.

Show the user a summary and wait for an OK before going on. Include: raw / kept / dropped (short, long, invalid) counts, the 1-letter words dropped, the blank-only word count (words using zero-count tiles such as Q/X/Z/Ä/Ö/Ü in Norwegian are valid and stay in), added and removed counts with examples, and the file sizes next to OLD's. Stop and ask if:

  • any check failed
  • --drop-invalid was needed
  • removed > ~2% of OLD, or added is far outside normal edition-to-edition churn
  • the kwg is much bigger or smaller than OLD's

2. Branch

Start from an up-to-date master on a new branch: git fetch && git checkout -b NEW-lexicon origin/master && git branch --unset-upstream. Without the unset, the branch tracks master. The working tree usually has unrelated untracked files (plans, binaries, test JSON). Never git add -A or git add .. Stage paths explicitly.

3. Put the files in place

Copy into $WASM: NEW.kwg, NEW.kad, NEW.klv2 (from OLD.klv2 or the supplied file), and super-NEW.klv2 if OLD has a super table. Check with md5 that the copies match their sources.

Never delete, rename or overwrite OLD's files. Existing games, annotated games, the analyzer, and macondo's download-on-demand (it fetches from $WASM on GitHub master) all load lexica by name.

4. Wire NEW into liwords

Grep for every mention first: git grep -n 'OLD' -- ':!*.kwg' ':!*.kad' ':!*.klv2' ':!*_pb*'. The usual edits (compare with commit ddb1199d for NSF25 and PR #1381 for CSW24):

  • pkg/entity/lexica.go: in AllowedNewGameLexica, replace OLD with NEW. This list is the only thing stopping new games on OLD.
  • liwords-ui/src/shared/lexica.ts: rename the AllLexica entry's key, code, and matchName if it's versioned. Update shortDescription, and the longDescription copyright year if it has one. Do not touch lexiconCodeToInternalRatingName or InternalRatingNameToProfileRatingName: ratings are keyed by family (NSF* → NSF21), so players keep their rating across editions. pkg/entity/ratings.go transformLexiconName is the same, so leave it alone.
  • liwords-ui/src/shared/lexicon_display.tsx:
    • lexiconOrder: replace OLD with NEW.
    • puzzleLexica: replace OLD if it's there.
    • historicalLexica: add OLD, so annotated games and GCG imports can still use it.
  • liwords-ui/src/wasm/loader.ts: add NEW.kad, NEW.klv2, NEW.kwg (and super-NEW.klv2) in sorted position. Keep OLD's entries. The browser loader needs a klv2 next to every kwg.
  • liwords-ui/src/lobby/seek_form.tsx: the stored-form migration switch should send OLD and every older edition to NEW. Merge them into one case group; don't just add a new case, or older editions stay pointed at OLD.
  • liwords-ui/src/App.tsx puzzleLexicon migration: same, if the family is a puzzle lexicon.
  • English only: the definition fallbacks in liwords-ui/src/utils/hooks/definitions.tsx, and any defaults like pkg/league/season_start.go, liwords-ui/src/leagues/admin.tsx, pkg/broadcasts/obs.go, db/migrations/*broadcasts* defaults, and sought_game_interactions.test.ts.
  • Anything else the grep turns up. For each hit, decide whether it means "the current edition" (update it) or "that exact edition" (leave it). Test fixtures, GCGs and CGPs almost always mean the exact edition.

Do not regenerate protos, bump go.mod, or touch letter distributions for a version update.

5. Tests that pin the new files

Add a test in pkg/cwgame/lexicon_test.go next to TestCSW15IsNotALaterEdition / TestNSF26IsNotAnEarlierEdition, using the lexiconHasWord helper there. It asserts that a few words from added.txt are present and a few from removed.txt are absent. Pick 2–3 of each, 2–15 tiles long, using only non-zero-count tiles. Also assert a dropped 1-letter and a >max-len word are absent, and check the reverse against OLD. This catches a wrong or mislabeled file being copied in.

In pkg/entity/lexica_test.go, add OLD to the historical list in TestHistoricalLexicaCannotStartGames.

Show full SKILL.md (618 more words)Show less

6. Check it locally

bash
go build ./pkg/... && source local.env && go test ./pkg/cwgame/ ./pkg/entity/
cd liwords-ui && npx prettier --write <changed files> && npx tsc && npx vitest run src/lobby

If tsc or vitest complain about missing modules or native bindings, the local node_modules is stale: run npm ci (it doesn't change the lockfile) and retry. Don't blame the lexicon change.

Optional but worth it: start the app, open the browser analyzer or WordSmog in NEW, and check that a word from added.txt is accepted.

7. Commit and PR

Stage only the files you touched, plus the new binaries. Commit, then ask before pushing. PR body:

  • source list (file name and date), NEW code, alphabet
  • the build summary: kept count, dropped counts and why, the three check results, added and removed counts with a few examples
  • klv2 provenance (reused from OLD, or new)
  • "Before merging" and "After merging" rollout checklists (step 8)

8. Production rollout (the user runs this, or you run it only with explicit approval)

Order matters, because the API's word service only picks up kwgs that exist when it starts.

Before merging:

  1. Copy the files to the EFS data volume with scripts/deploy_to_efs.sh NEW OLD. It does a dry run by default: it lists the local md5s, shows OLD's files on the volume, and flags any NEW target that already exists. Show the user that output, then run it with --apply only once they approve. The script never overwrites anything. The volume is mounted at /mnt/efs on woogles-wg (ssh woogles-wg, as ec2-user, which owns the files), with data under /mnt/efs/data:
    • lexica/gaddag/2024/: NEW.kwg, NEW.kad, NEW.klv2, super-NEW.klv2. This is what the API, the bot and the analysis workers read. The 2024 is the KWG path prefix; it's not lexica/gaddag/.
    • strategy/NEW/leaves.klv2 (+ super-leaves.klv2): the legacy leaves folder. Every current lexicon has one, identical to its gaddag klv2.
    • lexica/NEW.wmp: the word map (step 2). Not handled by the script.
    • lexica/words/NEW.txt: optional definitions (WORD\tdefinition, LC_ALL=C sorted). There isn't one for NSF. Not handled by the script.
    • The klv2 matters. Without NEW.klv2 on disk, macondo doesn't download it: it silently borrows the family default's leaves from defaultForLexicon in macondo dataloaders/strategy.go (NSF → NSF23), which is an older table.
  2. If the alphabet has ≤32 letters, build a word map for macondo with go run ./cmd/make_all_wmps -lexica NEW in macondo and put it on the volume. Norwegian and Polish have 33 letters, so skip it for them.

After the deploy: 3. Restart the macondo bot. It also serves WordSmog natively, from NEW.kad; there is no wolges_awsm service any more. 4. Clubs whose default is an old edition: before writing the PR, check whether there are any. Run the read-only query in reference/prod-sql.md with bin/proddb -c "<SELECT>" (it opens an SSH tunnel to the prod DB; SELECT only). If there are none (NSF26 had none), skip this step: no migration, no SQL. If there are some, add a migration to the PR (./gen_migration.sh <name>, which needs docker, or create the two files by hand with a UTC YYYYMMDDHHmm prefix; see 202402150312_default_club_settings_nwl23 for the pattern). Match with an explicit list of editions, never LIKE 'CSW%': that would also catch CSW24X. 5. List, but don't change, leagues (settings->>'lexicon') and unfinished tournaments still on OLD, and ask the user what to do with them. Running events keep their lexicon. Leagues use their settings at the next season start. 6. Smoke test: a rated game against a bot in NEW, playing a word from added.txt; WordSmog; the browser analyzer; a word lookup.

9. Cross-repo follow-ups (usually none needed; check each)

  • macondo: dataloaders/strategy.go defaultForLexicon (the family's fallback leaves), and cmd/make_all_wmps/main.go defaultLexica, which must mirror AllowedNewGameLexica. Suggest a small PR if either still names an older edition.
  • kwgc / word-golib / MinMacondoVersion (pkg/analysis/service.go): only for a new alphabet.
  • Wiki: if anything in this process changed, update Adding-a-new-lexicon-(2026) in the liwords wiki (a separate git repo, liwords.wiki.git), and this skill.

© woogles-io, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 4 other files (scripts) in .claude/skills/update-lexicon of woogles-io/liwords.

  • SKILL.md
  • reference/new-alphabet.md
  • reference/prod-sql.md
  • scripts/build_lexicon.py
  • scripts/deploy_to_efs.sh

Open the folder on GitHubat commit 1a69ec9

Compare with similar skills

Update Lexicon next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Update Lexicon compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Update Lexicon this skillwoogles-io/liwords117—~3kAutomated safety check: PassAGPL-3.0
RuView CLI, API and WASMruvnet/RuView97k—~1.2kAutomated safety check: NotesMIT
Nginx To Higress Migrationhigress-group/higress9.5k—~3.9kAutomated safety check: PassApache-2.0
Update V86felixrieseberg/windows9524k—~1.7kAutomated safety check: PassCustom licence
Dotlottie WebLottieFiles/dotlottie-web892—~3.5kAutomated safety check: PassMIT
Adding Internal API RouteTriliumNext/Trilium38k—~3.3kAutomated safety check: PassAGPL-3.0

Similar skills

  • Covers the RuView `wifi-densepose` command line binary, its Axum REST API and the WebAssembly builds for browsers and ESP32, for embedding or scripting RuView.

    97k GitHub stars~1.2k tokensUpdated today
    Backend & APIsAuto-check: notes
  • Nginx To Higress Migration

    higress-group/higress

    Migrate from ingress-nginx to Higress in Kubernetes environments.

    9.5k GitHub stars~3.9k tokensUpdated 2 days ago
    DevOps & CloudAuto-check passed
  • Update V86

    felixrieseberg/windows95

    Build and install v86 (wasm + libv86.js + BIOS) into windows95.

    24k GitHub stars~1.7k tokensUpdated 1 mo ago
    Testing & QAAuto-check passed
  • Dotlottie Web

    LottieFiles/dotlottie-web

    Implement Lottie animations using dotLottie runtimes (@lottiefiles/dotlottie-web and @lottiefiles/dotlottie-react).

    892 GitHub stars~3.5k tokensUpdated 4 days ago
    Media & CreativeAuto-check passed
  • Adding Internal API Route

    TriliumNext/Trilium

    A skill your agent uses when adding, moving, or wiring an internal REST endpoint in Trilium (a new /api/ route) — choosing between a core-shared handler (packages/trilium-core/src/routes/index.ts…

    38k GitHub stars~3.3k tokensUpdated today
    Testing & QAAuto-check passed
  • Client Request Signature Reversal

    awarexone/Agentic-Bug-Hunter

    Recovers a client-side request signature or anti-bot token just far enough to replay blocked requests in bug bounty testing, starting from a captured packet.

    5.3k GitHub stars~4.7k tokensUpdated yesterday
    SecurityAuto-check passed

Works with

Questions about Update Lexicon

What does Update Lexicon do?

Add a new edition of an existing woogles lexicon (e.g. An agent skill from woogles-io/liwords. Update Lexicon is an agent skill from woogles-io/liwords.g.

When should I use Update Lexicon?

Update Lexicon fits situations like: the user says a new dictionary; lexicon version is out; obsolete a lexicon.

How do I install Update Lexicon in Claude Code?

Run `npx skills add woogles-io/liwords --skill update-lexicon -a claude-code`. Or copy the skill folder (.claude/skills/update-lexicon in woogles-io/liwords) into .claude/skills/update-lexicon in your project. Claude Code loads it when a task matches its description.

How do I install Update Lexicon in Codex?

Run `npx skills add woogles-io/liwords --skill update-lexicon -a codex`. Or copy the skill folder (.claude/skills/update-lexicon in woogles-io/liwords) into .agents/skills/update-lexicon in your project. Codex loads it when a task matches its description.

Can I use Update Lexicon in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add woogles-io/liwords --skill update-lexicon -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/update-lexicon, .gemini/skills/update-lexicon, .github/skills/update-lexicon and .opencode/skills/update-lexicon in your project.

What does Update Lexicon need to run?

Going by SKILL.md and its folder, Update Lexicon needs Python and a shell for the scripts in its folder and the command-line tools its instructions call (git, go, npx, make, python3 and npm). Our summary lists: Python 3; Node.js; A Bash shell; Docker.

Does Update Lexicon access the network?

SKILL.md contains no URLs. Its commands use git, npx, npm and ssh, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Update Lexicon safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.

What licence does Update Lexicon use?

Update Lexicon is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Update Lexicon use?

About 3k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Update Lexicon?

Skills that share tags, products or a category with Update Lexicon: RuView CLI, API and WASM (ruvnet/RuView, 97k stars), Nginx To Higress Migration (higress-group/higress, 9.5k stars), Update V86 (felixrieseberg/windows95, 24k stars) and Dotlottie Web (LottieFiles/dotlottie-web, 892 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Update Lexicon?

woogles-io (a GitHub organization) maintains it in woogles-io/liwords, which has 117 GitHub stars. The repository was last updated on October 11, 2026.

Source: woogles-io/liwords on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.