Thanks for your interest in making AI-assisted coding more token-efficient! Whether it's a bug fix, a new tool, or a documentation tweak — contributions are welcome.
- Issues — Bug reports and feature requests
- Discussions — Questions and ideas
- Changelog — Run
tl-changelogto see what's changed
git clone https://github.com/edimuj/tokenlean.git
cd tokenlean
npm link # Makes all tl-* commands available globallyVerify it works:
tl-structure --helpbin/ # CLI entry points (tl-*.mjs)
src/
output.mjs # Common flags (-l, -t, -j, -q, -h), formatting, token estimation
project.mjs # File categorization, language detection, skip/important logic
cache.mjs # LRU disk cache with git-based invalidation
traverse.mjs # Fast file traversal with symlink protection
config.mjs # Config file loading (.tokenleanrc.json)
shell.mjs # Safe git/rg wrappers (spawnSync, no shell injection)
generic-lang.mjs # Regex-based symbol/import extraction for non-JS/TS languages
skills/
claude/ # Claude Code skill variants
codex/ # Codex skill variants
Every tool follows the same pattern. Here's the recipe:
Create bin/tl-<name>.mjs:
#!/usr/bin/env node
// Prompt info for tl-prompt
if (process.argv.includes('--prompt')) {
console.log(JSON.stringify({
name: 'tl-<name>',
desc: 'One-line description',
when: 'before-read', // or: before-modify, searching, utility
example: 'tl-<name> src/'
}));
process.exit(0);
}
import {
createOutput,
parseCommonArgs,
COMMON_OPTIONS_HELP
} from '../src/output.mjs';
import { findProjectRoot } from '../src/project.mjs';
const HELP = `
tl-<name> - One-line description
Usage: tl-<name> [path] [options]
Options:
${COMMON_OPTIONS_HELP}
Examples:
tl-<name> src/ # Do the thing
`;
const args = process.argv.slice(2);
const options = parseCommonArgs(args);
if (options.help) {
console.log(HELP);
process.exit(0);
}
const projectRoot = findProjectRoot();
const out = createOutput(options);
// Your logic here...
out.print();Add to package.json bin section:
"tl-<name>": "bin/tl-<name>.mjs"chmod +x bin/tl-<name>.mjsnpm link
tl-<name> --help
tl-<name> src/
tl-<name> src/ --json- Add to the appropriate table in
README.md - Add to the tools table in
CLAUDE.md
These aren't suggestions — they're the rules of the game:
- Minimal dependencies — One optional dep (node-html-markdown for tl-browse), otherwise Node.js built-ins only.
- Single purpose — Each tool does one thing well. If it does two things, it's two tools.
- Token-conscious — Every byte of output matters. No verbose explanations, no decorative borders.
- Fast — No heavy parsing, no AST analysis, no external services (unless that's the tool's purpose).
- ES modules — Use
.mjsextension,import/exportsyntax. - Common flags — All tools support
-l(limit lines),-t(limit tokens),-j(JSON),-q(quiet),-h(help).
We practice what we preach — keep it lean:
- No TypeScript (we're a CLI tool, not a library)
- No test framework (test manually, keep it simple)
- Use
gitCommand()/rgCommand()fromsrc/shell.mjsfor all git/rg calls (safespawnSyncwith array args, no shell) - Only use
execSyncfor pipe commands or non-git/rg tools whereshell.mjsdoesn't apply - Handle errors gracefully — a tool should never crash with an unhandled exception
- Fork & branch — Create a branch from
main - Keep it focused — One feature or fix per PR
- Test manually — Run your tool against a real project
- Update docs — README, CLAUDE.md
- Open a PR — Describe what and why (not how — the code shows how)
Open an issue with:
- The command you ran
- What you expected
- What actually happened
- Your Node.js version (
node --version)
Got an idea for a new tool? Open a feature request. The best suggestions include:
- What problem it solves for AI agents
- How many tokens it saves compared to the alternative
- A concrete example of input and output
By contributing, you agree that your contributions will be licensed under the MIT License.