@tokelang-lite/claude-code-skill 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,241 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ * Tokelang Claude Code skill — NPX installer.
4
+ *
5
+ * npx @tokelang-lite/claude-code-skill
6
+ *
7
+ * What it does (no external npm dependencies — built-in modules only):
8
+ * 1. Detect this host's platform/arch and pick the matching release artifact name.
9
+ * 2. Download that static `tokelang-cli` binary from the tokelang-cli GitHub release,
10
+ * verify it against the release's combined SHA256SUMS, mark it executable.
11
+ * 3. Assemble the plugin (skills + hooks + statusline + resolver) at
12
+ * `~/.claude/skills/tokelang/`, dropping the binary into its `bin/`.
13
+ *
14
+ * Install target = a personal-scope *skills-directory plugin*: any folder under
15
+ * `~/.claude/skills/` that has a `.claude-plugin/plugin.json` loads automatically as
16
+ * `tokelang@skills-dir` on the next session — no `claude` CLI call, no marketplace, and no
17
+ * workspace-trust gate (personal scope). It is discovered in place (not copied to a cache),
18
+ * so the binary we place in `bin/` is exactly what the hooks run.
19
+ *
20
+ * Env overrides (mainly for offline installs / the Phase-2b gate / CI):
21
+ * TOKELANG_LOCAL_BIN path to a prebuilt binary to use instead of downloading
22
+ * TOKELANG_DOWNLOAD_BASE release asset base URL (default: the tokelang-cli GitHub release)
23
+ * TOKELANG_CLI_VERSION version → release tag `v<version>` (default: package version)
24
+ * TOKELANG_INSTALL_DIR install fully somewhere else (default: $CLAUDE_CONFIG_DIR or ~/.claude → /skills/tokelang)
25
+ * Flags: --dry-run (resolve + report, touch nothing), --force (reinstall), --help.
26
+ */
27
+
28
+ 'use strict';
29
+
30
+ const fs = require('fs');
31
+ const os = require('os');
32
+ const path = require('path');
33
+ const https = require('https');
34
+ const crypto = require('crypto');
35
+
36
+ const PKG_ROOT = path.resolve(__dirname, '..');
37
+ const PKG = require(path.join(PKG_ROOT, 'package.json'));
38
+
39
+ const ARGS = process.argv.slice(2);
40
+ const DRY_RUN = ARGS.includes('--dry-run');
41
+ const FORCE = ARGS.includes('--force');
42
+
43
+ if (ARGS.includes('--help') || ARGS.includes('-h')) {
44
+ console.log(
45
+ [
46
+ 'Tokelang Claude Code skill installer',
47
+ '',
48
+ 'Usage: npx @tokelang-lite/claude-code-skill [--dry-run] [--force]',
49
+ '',
50
+ ' --dry-run Show what would happen; change nothing.',
51
+ ' --force Reinstall even if already present.',
52
+ '',
53
+ 'Installs to ~/.claude/skills/tokelang/ (override with TOKELANG_INSTALL_DIR).',
54
+ ].join('\n'),
55
+ );
56
+ process.exit(0);
57
+ }
58
+
59
+ // ---- platform → release artifact name --------------------------------------------------
60
+ // Names MUST match the skill resolver (skill bin/tokelang-cli): tokelang-cli-<os>-<arch>,
61
+ // os = `uname -s` lowercased (windows shells normalized to "windows"), arch = `uname -m`.
62
+ function resolveArtifact() {
63
+ const platform = os.platform(); // 'linux' | 'darwin' | 'win32'
64
+ const arch = os.arch(); // 'x64' | 'arm64' | ...
65
+ const table = {
66
+ 'linux:x64': 'tokelang-cli-linux-x86_64',
67
+ 'darwin:arm64': 'tokelang-cli-darwin-arm64',
68
+ 'darwin:x64': 'tokelang-cli-darwin-x86_64',
69
+ 'win32:x64': 'tokelang-cli-windows-x86_64.exe',
70
+ };
71
+ const artifact = table[`${platform}:${arch}`];
72
+ if (!artifact) {
73
+ fail(
74
+ `unsupported platform ${platform}/${arch}.\n` +
75
+ 'Supported: linux x64, macOS arm64/x64, Windows x64.\n' +
76
+ 'Build from source instead: cargo build --release -p tokelang-cli',
77
+ );
78
+ }
79
+ return artifact;
80
+ }
81
+
82
+ function fail(msg) {
83
+ console.error(`\n✗ tokelang install failed: ${msg}\n`);
84
+ process.exit(1);
85
+ }
86
+
87
+ // ---- download (follows GitHub's redirect to the asset storage host) --------------------
88
+ function download(url, redirectsLeft = 5) {
89
+ return new Promise((resolve, reject) => {
90
+ https
91
+ .get(url, { headers: { 'User-Agent': 'tokelang-installer' } }, (res) => {
92
+ const { statusCode, headers } = res;
93
+ if (statusCode >= 300 && statusCode < 400 && headers.location) {
94
+ if (redirectsLeft <= 0) return reject(new Error('too many redirects'));
95
+ res.resume();
96
+ return resolve(download(headers.location, redirectsLeft - 1));
97
+ }
98
+ if (statusCode !== 200) {
99
+ res.resume();
100
+ return reject(new Error(`HTTP ${statusCode} for ${url}`));
101
+ }
102
+ const chunks = [];
103
+ res.on('data', (c) => chunks.push(c));
104
+ res.on('end', () => resolve(Buffer.concat(chunks)));
105
+ })
106
+ .on('error', reject);
107
+ });
108
+ }
109
+
110
+ function sha256(buf) {
111
+ return crypto.createHash('sha256').update(buf).digest('hex');
112
+ }
113
+
114
+ // ---- recursive copy with a per-file filter ---------------------------------------------
115
+ function copyTree(src, dest, filter) {
116
+ const stat = fs.statSync(src);
117
+ if (stat.isDirectory()) {
118
+ fs.mkdirSync(dest, { recursive: true });
119
+ for (const entry of fs.readdirSync(src)) {
120
+ copyTree(path.join(src, entry), path.join(dest, entry), filter);
121
+ }
122
+ } else {
123
+ if (filter && !filter(src)) return;
124
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
125
+ fs.copyFileSync(src, dest);
126
+ // Preserve executability for the resolver + hook/statusline scripts.
127
+ if (src.endsWith('.sh') || path.basename(src) === 'tokelang-cli') {
128
+ fs.chmodSync(dest, 0o755);
129
+ }
130
+ }
131
+ }
132
+
133
+ async function main() {
134
+ const artifact = resolveArtifact();
135
+ const version = process.env.TOKELANG_CLI_VERSION || PKG.version;
136
+ const tag = `v${version}`;
137
+ const base =
138
+ process.env.TOKELANG_DOWNLOAD_BASE ||
139
+ `https://github.com/tokelang/tokelang-cli/releases/download/${tag}`;
140
+
141
+ const installDir =
142
+ process.env.TOKELANG_INSTALL_DIR ||
143
+ path.join(
144
+ process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude'),
145
+ 'skills',
146
+ 'tokelang',
147
+ );
148
+ const binDir = path.join(installDir, 'bin');
149
+ const binDest = path.join(binDir, artifact);
150
+
151
+ console.log(`Tokelang Claude Code skill v${PKG.version}`);
152
+ console.log(` platform : ${os.platform()}/${os.arch()} → ${artifact}`);
153
+ console.log(` binary : ${process.env.TOKELANG_LOCAL_BIN || `${base}/${artifact}`}`);
154
+ console.log(` install : ${installDir}`);
155
+
156
+ if (fs.existsSync(installDir) && !FORCE && !DRY_RUN) {
157
+ console.log(
158
+ `\n• Already installed at ${installDir}. Re-run with --force to reinstall.\n` +
159
+ ' Restart Claude Code or run /reload-plugins if it is not active yet.',
160
+ );
161
+ return;
162
+ }
163
+
164
+ // 1) Obtain + verify the binary buffer before touching the install dir.
165
+ let binBuf;
166
+ if (process.env.TOKELANG_LOCAL_BIN) {
167
+ binBuf = fs.readFileSync(process.env.TOKELANG_LOCAL_BIN);
168
+ console.log(` using local binary (${binBuf.length} bytes), skipping download/verify`);
169
+ } else if (DRY_RUN) {
170
+ console.log('\n[dry-run] would download + SHA-256 verify the binary, then assemble the plugin.');
171
+ return;
172
+ } else {
173
+ console.log('\n→ downloading binary …');
174
+ binBuf = await download(`${base}/${artifact}`).catch((e) =>
175
+ fail(`could not download ${artifact}: ${e.message}\n(is the ${tag} release published?)`),
176
+ );
177
+ console.log('→ verifying checksum …');
178
+ // The release publishes a single combined SHA256SUMS (one `<hash> <name>` line per
179
+ // artifact), not per-file .sha256 sidecars. Fetch it once and pick our artifact's line.
180
+ const sumText = await download(`${base}/SHA256SUMS`).catch((e) =>
181
+ fail(`could not download SHA256SUMS: ${e.message}`),
182
+ );
183
+ let expected = null;
184
+ for (const line of sumText.toString('utf8').split('\n')) {
185
+ const parts = line.trim().split(/\s+/);
186
+ if (parts.length < 2) continue;
187
+ const name = parts.slice(1).join(' ').replace(/^\*/, ''); // strip binary-mode '*' marker
188
+ if (name === artifact) {
189
+ expected = parts[0].toLowerCase();
190
+ break;
191
+ }
192
+ }
193
+ if (!expected) fail(`no SHA256SUMS entry for ${artifact}`);
194
+ const actual = sha256(binBuf).toLowerCase();
195
+ if (!/^[0-9a-f]{64}$/.test(expected) || expected !== actual) {
196
+ fail(`checksum mismatch for ${artifact}\n expected ${expected}\n actual ${actual}`);
197
+ }
198
+ console.log(` ok (sha256 ${actual.slice(0, 16)}…)`);
199
+ }
200
+
201
+ if (DRY_RUN) {
202
+ console.log('\n[dry-run] verified; would now write the plugin. Nothing changed.');
203
+ return;
204
+ }
205
+
206
+ // 2) Fresh assemble: clear our own dir, copy the plugin tree (resolver yes, prebuilt
207
+ // platform binaries no — those are downloaded fresh), then drop in this host's binary.
208
+ fs.rmSync(installDir, { recursive: true, force: true });
209
+ fs.mkdirSync(installDir, { recursive: true });
210
+
211
+ const PLUGIN_PARTS = [
212
+ '.claude-plugin',
213
+ 'skills',
214
+ 'hooks',
215
+ 'statusline',
216
+ 'settings.json',
217
+ 'README.md',
218
+ 'LICENSE',
219
+ ];
220
+ for (const part of PLUGIN_PARTS) {
221
+ const src = path.join(PKG_ROOT, part);
222
+ if (fs.existsSync(src)) copyTree(src, path.join(installDir, part));
223
+ }
224
+ // bin/: copy only the resolver wrapper, never any prebuilt tokelang-cli-<os>-<arch>.
225
+ copyTree(path.join(PKG_ROOT, 'bin'), binDir, (f) => path.basename(f) === 'tokelang-cli');
226
+
227
+ // 3) The downloaded/local binary for THIS host.
228
+ fs.mkdirSync(binDir, { recursive: true });
229
+ fs.writeFileSync(binDest, binBuf);
230
+ fs.chmodSync(binDest, 0o755);
231
+
232
+ console.log(`\n✓ Installed tokelang@skills-dir → ${installDir}`);
233
+ console.log('\nNext:');
234
+ console.log(' • Restart Claude Code (or run /reload-plugins) to activate it.');
235
+ console.log(' • Verify: claude plugin list (look for tokelang@skills-dir)');
236
+ console.log(' • Disable: claude plugin disable tokelang@skills-dir (or delete the folder)');
237
+ console.log('\nOptional — per-prompt INPUT compression (non-interactive):');
238
+ console.log(` alias claude='${binDest.replace(artifact, 'tokelang-cli')} wrap claude'`);
239
+ }
240
+
241
+ main().catch((e) => fail(e && e.message ? e.message : String(e)));
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@tokelang-lite/claude-code-skill",
3
+ "version": "1.0.0",
4
+ "description": "NPX installer for the Tokelang Claude Code plugin: downloads the matching static tokelang-cli binary and installs the plugin (skills + hooks + statusline) as a personal skills-directory plugin. Compresses context files and subagent prompts locally before they reach the model. Apache 2.0.",
5
+ "homepage": "https://tokelang.com",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/tokelang/claude-code-skill"
9
+ },
10
+ "license": "Apache-2.0",
11
+ "author": "Tokelang",
12
+ "type": "commonjs",
13
+ "bin": {
14
+ "tokelang-install": "install/install.js"
15
+ },
16
+ "engines": {
17
+ "node": ">=16"
18
+ },
19
+ "scripts": {
20
+ "test": "node install/install.js --dry-run"
21
+ },
22
+ "files": [
23
+ ".claude-plugin/",
24
+ "skills/",
25
+ "hooks/",
26
+ "statusline/",
27
+ "bin/tokelang-cli",
28
+ "settings.json",
29
+ "install/",
30
+ "README.md",
31
+ "LICENSE"
32
+ ],
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "keywords": [
37
+ "claude-code",
38
+ "plugin",
39
+ "tokens",
40
+ "compression",
41
+ "prompt-engineering",
42
+ "cost-reduction"
43
+ ]
44
+ }
package/settings.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "tokelang.level": "2",
3
+ "tokelang.custom": {
4
+ "subagent_input": true,
5
+ "subagent_input.depth": "lite",
6
+ "subagent_input.min_chars": 200,
7
+ "output_style": "lite"
8
+ },
9
+ "statusLine": {
10
+ "command": "${CLAUDE_PLUGIN_ROOT}/statusline/savings.sh"
11
+ },
12
+ "_comment": "Default install ships at level 2 (Balanced) per v1.0.0 build plan (Option B revision 2026-06-01). Level 2 enables subagent (Task tool) input compression + lite output style guide. NOTE: Claude Code's plugin hook contract does NOT allow user-input compression — for that, use `alias claude='tokelang-cli wrap claude'` separately. To turn the skill off entirely: set tokelang.level to 'off'. To uninstall: claude plugin uninstall tokelang. The .custom block is only used when tokelang.level is 'custom'."
13
+ }
@@ -0,0 +1,90 @@
1
+ ---
2
+ name: tokelang
3
+ description: >
4
+ Compress your context files, your subagent invocations, and your model's responses
5
+ via a style guide. Controlled by a level dial (L1 / L2 / L3) plus a semantic validator
6
+ that refuses to compress when meaning would be lost.
7
+ For real input compression (every prompt you type), use the separate `tokelang-cli wrap`
8
+ alias — Claude Code's plugin hooks cannot rewrite user input directly.
9
+ Open source under Apache 2.0. Auto-activates on session start. Disable: /tokelang-level off
10
+ ---
11
+
12
+ # Tokelang for Claude Code
13
+
14
+ This skill compresses tokens at three points where Claude Code's plugin hooks make it possible:
15
+
16
+ 1. **Context files** — your `CLAUDE.md`, agent personas, RAG headers (one-shot via `/tokelang-compress <file>`)
17
+ 2. **Subagent invocations** — the prompt argument passed to the `Task` tool gets compressed before the subagent receives it (PreToolUse hook)
18
+ 3. **Output style** — system-context injection at session start nudges the model to respond briefly (SessionStart hook)
19
+
20
+ For **user-input compression** (compressing every prompt you type), use the separate `tokelang-cli wrap` command — Claude Code's plugin hook contract is additive only and cannot rewrite user input. See the README "Wrap mode for real input compression" section for setup.
21
+
22
+ ## Why compress at all
23
+
24
+ Compressed prompts don't just save money. They make the model **think better**. From Hakim 2026 ([arXiv:2604.00025](https://arxiv.org/abs/2604.00025), "Brevity Constraints Reverse Performance Hierarchies in Language Models"):
25
+
26
+ > "Constraining large models to produce brief responses improves accuracy by 26 percentage points and reduces performance gaps by up to two-thirds. Most critically, brevity constraints completely reverse performance hierarchies on mathematical reasoning and scientific knowledge benchmarks."
27
+
28
+ The verbose English you usually write masks the model's reasoning capacity. Compression strips the parsing tax. We give you that compression automatically, with a validator that refuses to drop semantic content.
29
+
30
+ ## The level dial — what's ON by default
31
+
32
+ You install Tokelang at **Level 2 (Balanced)**. The skill side does this automatically:
33
+
34
+ | Surface | Level 2 behavior |
35
+ |---|---|
36
+ | Context files | Untouched until you run `/tokelang-compress <file>` |
37
+ | Subagent inputs (Task tool prompt) | Compressed automatically every Task invocation |
38
+ | Output style | Lite — "be concise, drop hedges and filler" injected into system context |
39
+ | **User input** | **Not touched by the skill.** Use `tokelang-cli wrap` for that. |
40
+
41
+ If even the output-style nudge feels too aggressive, dial back:
42
+
43
+ ```
44
+ /tokelang-level 1 → output style guide only; subagent compression off
45
+ /tokelang-level off → skill stays loaded but does nothing
46
+ /tokelang-level 3 → + aggressive output style
47
+ ```
48
+
49
+ The setting persists across sessions in `~/.claude/settings.json` under `"tokelang.level"`.
50
+
51
+ ## Persistence
52
+
53
+ Active every response unless you say "stop tokelang" or run `/tokelang-level off`. The skill does not "drift off" after many turns and will not silently disable itself.
54
+
55
+ The engine runs locally — your prompts do NOT leave your machine. The hosted API at tokelang.com is a separate product (used by the dashboard); the CLI bundled with this skill is fully offline-capable.
56
+
57
+ ## Validator — why nothing important gets dropped
58
+
59
+ Every compression candidate (file compression OR subagent input) passes through a semantic validator before replacing the original. The validator checks:
60
+
61
+ - **Content recall** — 0.85 minimum for context files, 0.90 minimum for subagent inputs (subagents are higher-stakes than per-turn prompts)
62
+ - **Hard zones** — negations (`not`, `never`, `only`), numeric thresholds, code blocks, URLs, file paths, regex literals, quoted strings, contract vocabulary (`shall`, `must`) — never rewritten
63
+
64
+ If the validator rejects a candidate, the original passes through unchanged. **Tokelang never compresses past what the model can still reason about.**
65
+
66
+ ## Slash commands
67
+
68
+ | Command | What it does |
69
+ |---|---|
70
+ | `/tokelang-compress <file>` | Compress a context file (CLAUDE.md, agent persona, etc.) with `.original.md` backup. Reversible via `/tokelang-restore`. |
71
+ | `/tokelang-restore <file>` | Restore a compressed file from its `.original.md` backup. |
72
+ | `/tokelang-stats` | Show savings for current session: tokens saved, % reduction, equivalent $ cost. |
73
+ | `/tokelang-level [1\|2\|3\|off]` | Change compression aggressiveness. |
74
+
75
+ ## What this skill will NOT do
76
+
77
+ - **Compress your typed input via plugin** — Claude Code's UserPromptSubmit hook is additive-only. For real input compression, use `tokelang-cli wrap` alias (one line of shell config; see README).
78
+ - **Compress tool results** — Claude Code's PostToolUse hook is additive-only. Tool results pass through to the next turn as-is.
79
+ - **Touch your output text** — the model speaks however it wants; we only nudge via style guide. No post-processing.
80
+ - **Compress sensitive content** — Task subagent prompts that look like security warnings, credentials, or irreversible actions auto-skip compression (escape hatch).
81
+ - **Hide what it's doing** — `/tokelang-stats` always tells you exactly what's been compressed and by how much. Statusline shows cumulative savings.
82
+ - **Phone home** — engine runs locally. Nothing sent to tokelang.com unless you explicitly use the hosted API.
83
+
84
+ ## Off-switch summary (so you can always disable)
85
+
86
+ Quickest: type `/tokelang-level off` in any session.
87
+ Persistent: edit `~/.claude/settings.json`, set `"tokelang.level": "off"`.
88
+ Uninstall: `claude plugin uninstall tokelang`.
89
+
90
+ There is no telemetry. There is no usage limit. The skill is yours to use, modify, or fork (Apache 2.0).
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: tokelang-compress
3
+ description: >
4
+ Compress a context file (CLAUDE.md, .cursorrules, agent persona, RAG header, etc.) in
5
+ place with an automatic .original.md backup. Uses the local Tokelang engine (OptA→MEC)
6
+ in default mode for code-dense instruction docs; validator-gated, with negations and
7
+ protected spans preserved. Reversible via /tokelang-restore.
8
+ Trigger: /tokelang-compress <filepath>
9
+ ---
10
+
11
+ # Compress a context file
12
+
13
+ Compresses a context file with the local engine's **default mode (the OptA→MEC chain)**. Config/instruction files (CLAUDE.md, `.cursorrules`, agent personas) are *code-dense*, and the engine's `context_file` mode passes them through at near-0% — so this command uses `default`, which compresses them ~17–31% while the validator preserves negations, numbers, code, URLs, and other protected spans. (`--mode context_file` is the right choice only for *prose-heavy* system prompts / RAG headers, where its higher recall floor applies without no-opping.)
14
+
15
+ The original file is preserved as `<filename>.original.md` in the same directory. You can revert any time via `/tokelang-restore <filepath>`.
16
+
17
+ ## Trigger
18
+
19
+ - `/tokelang-compress <filepath>` — explicit
20
+ - "compress my CLAUDE.md" — natural language
21
+ - "shrink this context file" — natural language
22
+
23
+ ## Process
24
+
25
+ 1. Verify the file exists and is a supported type (`.md`, `.txt`, `.rst`, or extensionless markdown). Code/config files (`.json`, `.yaml`, `.toml`, `.py`, `.rs`) are explicitly rejected — wrong target for context compression.
26
+
27
+ 2. Read the file and check size. Files <500 chars are usually not worth compressing; warn and ask before proceeding.
28
+
29
+ 3. Run the local Tokelang binary in default mode (OptA→MEC):
30
+ ```bash
31
+ "${CLAUDE_PLUGIN_ROOT}/bin/tokelang-cli" compress --mode default < <filepath>
32
+ ```
33
+ (For a prose-heavy system-prompt file rather than a code-dense instruction doc, use `--mode context_file` instead.)
34
+
35
+ 4. The engine is validator-gated: it returns the compressed form only when the content-recall floor holds and every protected span survives — negations, numbers, fenced code (byte-identical), URLs, inline code, contract vocab. If any check fails, the engine passes the **original through unchanged**, so a rejected compression simply yields the original file, never a lossy one.
36
+
37
+ 5. Write the compressed version over the original file. Save the original as `<filename>.original.md` (a Claude Code marker file — do not edit by hand).
38
+
39
+ 6. Print a summary:
40
+ ```
41
+ Compressed CLAUDE.md
42
+ Before: 1,247 tokens (cl100k_base)
43
+ After: 812 tokens
44
+ Saved: 435 tokens (35%)
45
+ Backup: CLAUDE.md.original.md
46
+ ```
47
+
48
+ ## What this command does NOT do
49
+
50
+ - Compress code files (use file type guard; rejects `.json`, `.yaml`, `.toml`, etc.)
51
+ - Auto-compress without user-initiated trigger
52
+ - Modify the file in any way other than running it through the engine
53
+ - Send file contents to the hosted API (local engine only)
54
+
55
+ ## Failure modes (and how the tool handles them)
56
+
57
+ | Situation | Behavior |
58
+ |---|---|
59
+ | File doesn't exist | Error: print path and abort |
60
+ | File is wrong type | Error: explain that context_file mode is for prose, suggest manual editing |
61
+ | File <500 chars | Warn + ask confirmation; small files yield small savings |
62
+ | Validator rejects compression | Print the failed invariant; leave original file untouched; suggest user review |
63
+ | `.original.md` already exists | Ask whether to overwrite the existing backup |
64
+
65
+ ## Example
66
+
67
+ ```
68
+ > /tokelang-compress CLAUDE.md
69
+
70
+ Reading CLAUDE.md... 1247 cl100k tokens.
71
+ Compressing in context_file mode...
72
+ Validator: recall 0.91 ✓ | headings 7/7 ✓ | code blocks 3/3 ✓ | URLs 4/4 ✓
73
+ Writing compressed file (812 tokens).
74
+ Backup saved to CLAUDE.md.original.md.
75
+
76
+ Saved 435 tokens (35%). Restore with: /tokelang-restore CLAUDE.md
77
+ ```
@@ -0,0 +1,91 @@
1
+ ---
2
+ name: tokelang-level
3
+ description: >
4
+ Change Tokelang's compression aggressiveness. L1 = output style guide only. L2 = + Task
5
+ subagent prompt compression (default on install). L3 = + aggressive output style.
6
+ "off" = skill loaded but inert. Setting persists in ~/.claude/settings.json.
7
+ For user-input compression (every prompt you type), use the separate `tokelang-cli wrap`
8
+ command — see README. Trigger: /tokelang-level [1|2|3|off]
9
+ ---
10
+
11
+ # Change compression level
12
+
13
+ Switch between four preset compression levels. Setting persists across sessions in `~/.claude/settings.json` under `"tokelang.level"`.
14
+
15
+ ## Trigger
16
+
17
+ - `/tokelang-level [1|2|3|off]` — explicit
18
+ - `/tokelang-level` (no arg) — show current level + describe each
19
+ - "turn tokelang down" / "be less aggressive" — natural language (interpret as one step down)
20
+ - "disable tokelang" / "turn it off" — natural language → set to off
21
+
22
+ ## Level matrix (revised 2026-06-01 for Option B)
23
+
24
+ | Level | Context files (slash cmd) | Subagent inputs (Task tool) | Output style guide |
25
+ |---|---|---|---|
26
+ | **L1** Safe | via `/tokelang-compress` | **off** | "lite" — be concise |
27
+ | **L2** Balanced (default install) | via `/tokelang-compress` | **on**, lite depth | "lite" — be concise |
28
+ | **L3** Aggressive | via `/tokelang-compress` | **on**, medium depth | "medium" — fragments OK, drop articles |
29
+ | **off** | via `/tokelang-compress` | **off** | **off** (no style guide injection) |
30
+
31
+ Note: `/tokelang-compress` works at every level (it's user-initiated). Level only controls the *automatic* hooks (SessionStart style guide + PreToolUse Task compression).
32
+
33
+ **For real user-input compression**, you need `tokelang-cli wrap claude` as an alias. This is outside the skill's level dial. See README "Wrap mode" section.
34
+
35
+ ## Process
36
+
37
+ 1. Parse argument. Accept `1`, `2`, `3`, `off` (case-insensitive). Other input → print usage.
38
+ 2. Read `~/.claude/settings.json`. If `"tokelang"` block missing, create it.
39
+ 3. Set `"tokelang.level"`. Save settings.
40
+ 4. Confirm:
41
+ ```
42
+ Tokelang level changed: 2 (Balanced) → 1 (Safe).
43
+ Subagent compression: OFF
44
+ Output style guide: lite (be concise)
45
+ Context-file compression: still available via /tokelang-compress
46
+ ```
47
+ 5. Hook scripts read this setting on every fire — change takes effect on the next Task invocation. No restart needed.
48
+
49
+ ## Custom level (advanced)
50
+
51
+ `~/.claude/settings.json` supports per-dial overrides via a `tokelang.custom` object. Example:
52
+
53
+ ```json
54
+ {
55
+ "tokelang.level": "custom",
56
+ "tokelang.custom": {
57
+ "subagent_input": true,
58
+ "subagent_input.depth": "medium",
59
+ "output_style": "lite"
60
+ }
61
+ }
62
+ ```
63
+
64
+ When `"tokelang.level": "custom"`, the dials in `custom` are used directly.
65
+
66
+ ## Off semantics
67
+
68
+ `"tokelang.level": "off"` keeps the skill loaded (slash commands still work, statusline still shows lifetime stats) but the hooks become no-ops. No subagent compression, no style-guide injection. Use this for sessions where you want Tokelang fully dormant without uninstalling.
69
+
70
+ To uninstall completely: `claude plugin uninstall tokelang`.
71
+
72
+ ## Example
73
+
74
+ ```
75
+ > /tokelang-level
76
+
77
+ Current: 2 (Balanced)
78
+ Subagent compression: ON (lite depth)
79
+ Output style guide: lite (be concise)
80
+
81
+ Levels:
82
+ 1 / Safe — output style only; subagent compression off
83
+ 2 / Balanced — + subagent compression (DEFAULT)
84
+ 3 / Aggressive — + medium-depth subagent + aggressive output style
85
+ off — skill loaded but inert; hooks are no-ops
86
+
87
+ For input compression (every prompt you type):
88
+ alias claude='tokelang-cli wrap claude'
89
+
90
+ Switch with: /tokelang-level <1|2|3|off|custom>
91
+ ```
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: tokelang-restore
3
+ description: >
4
+ Restore a context file from its .original.md backup created by /tokelang-compress.
5
+ Reverses any compression performed on the file.
6
+ Trigger: /tokelang-restore <filepath>
7
+ ---
8
+
9
+ # Restore a compressed file
10
+
11
+ Reverses `/tokelang-compress` by replacing the compressed file with its `.original.md` backup. The backup file is deleted after successful restoration.
12
+
13
+ ## Trigger
14
+
15
+ - `/tokelang-restore <filepath>` — explicit
16
+ - "undo tokelang on CLAUDE.md" — natural language
17
+ - "restore the original" (only if context makes the target file unambiguous) — natural language
18
+
19
+ ## Process
20
+
21
+ 1. Verify `<filepath>.original.md` exists. If not, abort with: "No backup found for <filepath>. Was this file compressed by Tokelang?"
22
+
23
+ 2. Verify `<filepath>` exists and was compressed (we expect a marker comment at the top of compressed files — TBD format).
24
+
25
+ 3. Replace `<filepath>` with the contents of `<filepath>.original.md`.
26
+
27
+ 4. Delete `<filepath>.original.md` after successful copy.
28
+
29
+ 5. Print confirmation:
30
+ ```
31
+ Restored CLAUDE.md from CLAUDE.md.original.md.
32
+ Backup deleted.
33
+ ```
34
+
35
+ ## What this command does NOT do
36
+
37
+ - Restore from arbitrary backups (only `.original.md` siblings)
38
+ - Restore files that were never compressed by Tokelang
39
+ - Auto-trigger when the model touches a compressed file (user must invoke)
40
+
41
+ ## Failure modes
42
+
43
+ | Situation | Behavior |
44
+ |---|---|
45
+ | No `.original.md` backup exists | Error: explain and abort |
46
+ | File doesn't show our compression marker | Warn: "This file may not have been compressed by Tokelang. Restore anyway? (y/n)" |
47
+ | Backup older than compressed file (modified-after-compression) | Warn: "You may have edited the compressed version since. Restore will lose your edits. Proceed? (y/n)" |
48
+ | Backup file is empty | Error: backup looks corrupted; abort |
49
+
50
+ ## Example
51
+
52
+ ```
53
+ > /tokelang-restore CLAUDE.md
54
+
55
+ Restored CLAUDE.md (1247 cl100k tokens) from CLAUDE.md.original.md.
56
+ Backup deleted.
57
+ ```