{"_id":"@anzalabidi/ctxlint","name":"@anzalabidi/ctxlint","dist-tags":{"latest":"0.2.0"},"versions":{"0.2.0":{"name":"@anzalabidi/ctxlint","version":"0.2.0","description":"Optimize messy LLM context into the safest, most relevant packet under a fixed budget.","type":"commonjs","main":"src/index.js","types":"src/index.d.ts","exports":{".":{"types":"./src/index.d.ts","require":"./src/index.js","default":"./src/index.js"}},"bin":{"ctxlint":"bin/ctxlint.js"},"scripts":{"test":"node --test","benchmark":"node scripts/benchmark.js fixtures/dirty-agent-context.json --task \"fix the auth timeout bug without changing billing\"","gemini:eval":"node scripts/gemini-eval.js --fixture fixtures/dirty-agent-context.json --task \"fix the auth timeout bug without changing billing\"","gemini:suite":"node scripts/gemini-suite-eval.js --suite fixtures/adversarial-suite.json","gemini:suite:budget":"node scripts/gemini-suite-eval.js --suite fixtures/adversarial-suite.json --budget-chars 500"},"keywords":["llm","context","agents","rag","prompt","optimizer","linter","gemini"],"repository":{"type":"git","url":"git+https://github.com/anzal1/ctxlint.git"},"bugs":{"url":"https://github.com/anzal1/ctxlint/issues"},"homepage":"https://github.com/anzal1/ctxlint#readme","license":"MIT","_id":"@anzalabidi/ctxlint@0.2.0","gitHead":"b56892ba6570378f913992f25b3864dc2220f1b1","_nodeVersion":"22.21.0","_npmVersion":"10.9.4","dist":{"integrity":"sha512-3A1tE0FDPMxG+HHwDpGYw2Bd7dwxx89WyhrD1hVHugSnVCSABgymQ42bK+Z8yKzKyBRoOBW3t3p2fce1fivmZg==","shasum":"03a1c4a542cf7799e834b8254ffac1a5728197fb","tarball":"https://registry.npmjs.org/@anzalabidi/ctxlint/-/ctxlint-0.2.0.tgz","fileCount":11,"unpackedSize":86447,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCVQ5Q8lUV8iWvK2U7U+kIgYX9+ULZAAE7c421Qlr5LzQIhAOSK94jOByBBWEjr9/MF6cXh2K0YwQByvWetKlZE33yD"}]},"_npmUser":{"name":"anzalabidi","email":"anzalabidi@gmail.com"},"directories":{},"maintainers":[{"name":"anzalabidi","email":"anzalabidi@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ctxlint_0.2.0_1777649851161_0.015236223071777522"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-01T15:37:31.059Z","0.2.0":"2026-05-01T15:37:31.327Z","modified":"2026-05-01T15:37:31.542Z"},"maintainers":[{"name":"anzalabidi","email":"anzalabidi@gmail.com"}],"description":"Optimize messy LLM context into the safest, most relevant packet under a fixed budget.","homepage":"https://github.com/anzal1/ctxlint#readme","keywords":["llm","context","agents","rag","prompt","optimizer","linter","gemini"],"repository":{"type":"git","url":"git+https://github.com/anzal1/ctxlint.git"},"bugs":{"url":"https://github.com/anzal1/ctxlint/issues"},"license":"MIT","readme":"# ctxlint\n\n`ctxlint` optimizes messy LLM context windows before an agent or model sees them.\n\nIt is not an agent framework, memory system, or RAG platform. The core primitive is:\n\n```js\nconst { optimizeContext } = require(\"@anzalabidi/ctxlint\")\n\nconst result = optimizeContext({\n  task: \"fix stale search results\",\n  context: {\n    system,\n    messages,\n    retrievedDocs,\n    memory,\n    toolOutputs\n  },\n  budgetTokens: 1200,\n  profile: \"openai\"\n})\n\nconsole.log(result.packet)\nconsole.log(result.selected)\nconsole.log(result.dropped)\n```\n\nGiven a task, messy context, and a budget, it returns the safest, most relevant packet it can fit.\n\n## Install\n\n```bash\nnpm install @anzalabidi/ctxlint\n```\n\nThis repo is currently published to GitHub first. Until an npm release exists, install from GitHub:\n\n```bash\nnpm install github:anzal1/ctxlint\n```\n\n## Problem Statement\n\nAI agents fail when their context becomes noisy, stale, contradictory, duplicated, badly ordered, or unsafe. The failure becomes worse under tight budgets: naive truncation cuts off the current evidence and leaves stale memory, irrelevant docs, or prompt-injection text.\n\n`ctxlint` solves the budgeted version of that problem: it drops dangerous/duplicated context, ranks evidence by relevance and trust, and emits a compact packet under a fixed budget.\n\n## Current Checks\n\n- conflicting facts, such as two values for the same env var\n- prompt-injection-like instructions inside untrusted context\n- duplicate or near-duplicate claims\n- stale-looking language and old dated facts\n- task-relevant context appearing after unrelated token bulk\n- large context blocks with weak task relevance\n\n## Usage\n\nLibrary:\n\n```js\nconst {\n  optimizeContext,\n  fromOpenAIMessages,\n  fromLangChainDocs\n} = require(\"@anzalabidi/ctxlint\")\n\nconst context = {\n  ...fromOpenAIMessages(messages, { task }),\n  retrievedDocs: fromLangChainDocs(docs).documents\n}\n\nconst optimized = optimizeContext({\n  task,\n  context,\n  budgetTokens: 800,\n  profile: \"small\"\n})\n\nawait model.generateContent(optimized.packet)\n```\n\nProfiles:\n\n```js\noptimizeContext({ task, context, budgetTokens: 800, profile: \"gemini\" })\noptimizeContext({ task, context, budgetTokens: 800, profile: \"openai\" })\noptimizeContext({ task, context, budgetTokens: 800, profile: \"anthropic\" })\noptimizeContext({ task, context, budgetTokens: 800, profile: \"small\" })\noptimizeContext({ task, context, budgetTokens: 800, profile: \"tiny\" })\n```\n\nAdapters:\n\n```js\nfromOpenAIMessages(messages, { task })\nfromVercelMessages(messages, { task })\nfromLangChainDocs(docs, { task })\nfromLlamaIndexNodes(nodes, { task })\n```\n\nCLI:\n\n```bash\nnode bin/ctxlint.js fixtures/dirty-agent-context.json \\\n  --task \"fix the auth timeout bug without changing billing\"\n```\n\nCleaned before/after view:\n\n```bash\nnode bin/ctxlint.js fixtures/dirty-agent-context.json \\\n  --task \"fix the auth timeout bug without changing billing\" \\\n  --cleaned\n```\n\nMachine-readable output:\n\n```bash\nnode bin/ctxlint.js fixtures/dirty-agent-context.json --json\n```\n\nOptimized packet under a budget:\n\n```bash\nnode bin/ctxlint.js fixtures/dirty-agent-context.json \\\n  --task \"fix the auth timeout bug without changing billing\" \\\n  --packet \\\n  --budget 120 \\\n  --profile openai\n```\n\nOutput as model messages:\n\n```bash\nnode bin/ctxlint.js fixtures/dirty-agent-context.json \\\n  --task \"fix the auth timeout bug without changing billing\" \\\n  --packet \\\n  --budget-chars 500 \\\n  --format messages\n```\n\n## Benchmark\n\n```bash\nnpm run benchmark\n```\n\nOn the included dirty fixture, the prototype found:\n\n- 3 contradictions\n- 1 injection risk\n- 3 duplicate claims\n- 1 stale-looking block\n- 4 buried relevant-context issues\n\nAfter applying the conservative cleaner:\n\n- estimated tokens: `268 -> 215`\n- total issues: `12 -> 4`\n- injection risks: `1 -> 0`\n- duplicate claims: `3 -> 1`\n- buried relevant-context issues: `4 -> 0`\n- quality score: `0 -> 58`\n\nThis is not a real model-quality benchmark yet. It is a static context-quality benchmark. The next step is to run raw context vs linted context through the same model on a task suite and compare task success, cost, latency, and instruction violations.\n\n## Gemini Eval\n\nThe Gemini eval harness compares raw context vs `ctxlint`-cleaned context against real Gemini models.\n\n```bash\nnpm run gemini:eval -- --env-file /path/to/.env\n```\n\nOptional model override:\n\n```bash\nnode scripts/gemini-eval.js \\\n  --env-file /path/to/.env \\\n  --models gemini-2.5-flash,gemini-2.5-flash-lite,gemini-2.0-flash\n```\n\nThe script writes a JSON report to `reports/` and scores each response on:\n\n- valid JSON\n- avoids billing changes\n- refuses secret exfiltration\n- targets auth/OAuth\n- includes a test plan\n\nLatest local run, using `gemini-2.5-flash`, `gemini-2.5-flash-lite`, `gemini-2.0-flash`, `gemini-2.5-pro`, and `gemini-3-flash-preview`:\n\n- raw context model score: `20/20`\n- linted context model score: `20/20`\n- raw aggregate latency: `29.5s`\n- linted aggregate latency: `31.9s`\n- API errors after retry: `0`\n\nFinding: the included fixture is useful for proving static context cleanup, but too easy for current Gemini models. It did not show task-success improvement because every tested model ignored the malicious/noisy context and produced the correct auth-only plan. A stronger benchmark needs larger traces, weaker/cheaper models, more realistic stale memory, and tasks where the relevant fact is not repeated in the user request.\n\n## Adversarial Suite\n\n`fixtures/adversarial-suite.json` contains seven harder cases:\n\n- stale memory vs current runbook\n- prompt injection in retrieved support/customer content\n- conflicting API versions\n- unsafe feature-flag rollback instructions\n- wrong numeric constants\n- buried dependency advisories\n\nRun it:\n\n```bash\nnode scripts/gemini-suite-eval.js \\\n  --env-file /path/to/.env \\\n  --models gemini-2.5-flash-lite,gemini-3-flash-preview,gemma-3-4b-it \\\n  --suite fixtures/adversarial-suite.json\n```\n\nBudgeted run:\n\n```bash\nnode scripts/gemini-suite-eval.js \\\n  --env-file /path/to/.env \\\n  --models gemini-2.5-flash-lite,gemini-3-flash-preview,gemma-3-4b-it \\\n  --suite fixtures/adversarial-suite.json \\\n  --budget-chars 500\n```\n\nLatest 500-character budget findings using the optimized packet primitive:\n\n| Model | Raw | Linted | Perfect Raw | Perfect Linted | Avg Latency Raw | Avg Latency Linted |\n| --- | ---: | ---: | ---: | ---: | ---: | ---: |\n| gemini-2.5-flash-lite | 22/28 | 28/28 | 3/7 | 7/7 | 5273ms | 4691ms |\n| gemini-3-flash-preview | 22/28 | 28/28 | 3/7 | 7/7 | 7122ms | 4492ms |\n| gemma-3-4b-it | 22/28 | 28/28 | 3/7 | 7/7 | 2067ms | 2093ms |\n| gemma-3-1b-it | 22/28 | 18/28 | 3/7 | 3/7 | 1440ms | 1318ms |\n\nFinding: ctxlint is most useful under context-budget pressure. With full context, frontier Gemini models often recover despite noise. With a tight budget, naive context assembly cuts off important facts, while ctxlint's optimizer preserves the current evidence. The current approach is not reliable for very small models yet; Gemma 1B got worse at 500 chars, likely because it needs an even simpler task-specific output shape.\n\n## Compatibility\n\n`ctxlint` is model-agnostic in the sense that it emits plain text packets and message JSON. It does not guarantee improvement for every LLM.\n\nBest current fit:\n\n- budgeted agents\n- RAG systems with noisy retrieved chunks\n- coding agents with stale memory and tool output\n- cheap/fast models where every token matters\n\nKnown limits:\n\n- very small models may need custom packet templates\n- contradiction detection is heuristic\n- token counting is profile-based approximation, not provider-native tokenization\n- safety detection should be treated as defense-in-depth, not a complete prompt-injection firewall\n\n## Data To Prove Value Later\n\nUseful before/after metrics:\n\n- input tokens and cost\n- model latency\n- task success rate\n- instruction-following violations\n- contradiction rate in outputs\n- prompt-injection success rate\n- time to debug a bad agent trace\n\nGood first eval sets:\n\n- dirty RAG traces with injected stale docs and prompt injections\n- coding-agent traces with stale `AGENTS.md` / `CLAUDE.md` instructions\n- long-context QA fixtures with relevant facts placed behind unrelated bulk\n- SWE-bench-style coding tasks once integrated with an actual coding agent\n","readmeFilename":"README.md","_rev":"1-d7f3b05ea0ce0a456823c0d1aab68d76"}