{"id":47688156,"url":"https://github.com/makfly/instant-grep","last_synced_at":"2026-04-29T14:00:54.610Z","repository":{"id":346454369,"uuid":"1189934816","full_name":"MakFly/instant-grep","owner":"MakFly","description":"Trigram-indexed regex search CLI — sub-ms code search for AI agents. 93.5% token savings.","archived":false,"fork":false,"pushed_at":"2026-04-22T23:35:14.000Z","size":711,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-23T01:30:16.481Z","etag":null,"topics":["ai-agent","cli","code-search","developer-tools","grep","rust","trigram"],"latest_commit_sha":null,"homepage":"https://instant-grep.pulseview.app","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MakFly.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["MakFly"]}},"created_at":"2026-03-23T20:11:00.000Z","updated_at":"2026-04-22T23:35:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/MakFly/instant-grep","commit_stats":null,"previous_names":["makfly/instant-grep"],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/MakFly/instant-grep","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MakFly%2Finstant-grep","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MakFly%2Finstant-grep/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MakFly%2Finstant-grep/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MakFly%2Finstant-grep/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MakFly","download_url":"https://codeload.github.com/MakFly/instant-grep/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MakFly%2Finstant-grep/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32428622,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T13:34:34.882Z","status":"ssl_error","status_checked_at":"2026-04-29T13:34:29.830Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agent","cli","code-search","developer-tools","grep","rust","trigram"],"created_at":"2026-04-02T15:03:59.891Z","updated_at":"2026-04-29T14:00:54.601Z","avatar_url":"https://github.com/MakFly.png","language":"Rust","funding_links":["https://github.com/sponsors/MakFly"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ch1 align=\"center\"\u003einstant-grep\u003c/h1\u003e\n  \u003cp align=\"center\"\u003e\n    \u003cstrong\u003eThe AI agent's search engine. Trigram-indexed regex, token-compressed git, sub-ms daemon.\u003c/strong\u003e\n  \u003c/p\u003e\n  \u003cp align=\"center\"\u003e\n    \u003ca href=\"#benchmarks\"\u003eBenchmarks\u003c/a\u003e \u0026middot;\n    \u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e \u0026middot;\n    \u003ca href=\"#token-savings\"\u003eToken Savings\u003c/a\u003e \u0026middot;\n    \u003ca href=\"#agent-integration\"\u003eAgent Integration\u003c/a\u003e \u0026middot;\n    \u003ca href=\"#how-it-works\"\u003eHow it works\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/MakFly/instant-grep/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/MakFly/instant-grep/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/MakFly/instant-grep/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/MakFly/instant-grep\" alt=\"Release\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/MakFly/instant-grep/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/MakFly/instant-grep\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/platform-macOS%20%7C%20Linux-blue\" alt=\"Platform\"\u003e\n\u003c/p\u003e\n\n---\n\n## TL;DR\n\n- **Trigram-indexed regex** that beats `ripgrep` 2–8× on warm caches with byte-identical match parity.\n- **Token-compressed CLI** (`ig git status/log/diff`, `ig read -s`, `ig ls`, …) shipped as drop-ins for AI agents.\n- **Indexes live in the XDG cache** (`~/.cache/ig/`) since v1.15.0 — your projects stay clean (no `.ig/` folder to gitignore). `find_root` also recognises `package.json`, `Cargo.toml`, `go.mod`, etc., so non-versioned projects no longer scatter stray indexes.\n- **One global daemon** since v1.16.0 — multi-tenant, single Unix socket, single systemd-user / launchd unit. Replaces the previous one-daemon-per-project design. **~14× less RAM** in real-world use (5–20 MB total instead of 60 MB × N).\n- **Two-step install on a new machine**: `curl … install.sh | bash`, then `ig daemon install`. New projects are served the moment they're queried — no preboot.\n\n```\nig                  ──── ~/.cache/ig/ ──── one daemon, one socket, all your projects\n │                       │\n ├── search/             ├── \u003chash-of-rootA\u003e/   ← lexicon.bin, postings.bin, …\n ├── git proxy           ├── \u003chash-of-rootB\u003e/\n ├── ls / read / pack    ├── daemon.sock        ← single multi-tenant socket\n └── gc / migrate        └── daemon.{pid,log}\n```\n\n---\n\n**One binary. ~5MB. Zero runtime dependencies.** `ig` replaces `grep`, `cat`, `ls`, `tree`, `find`, and `git status/log/diff` with token-optimized alternatives — built for AI coding agents (Claude Code, Codex, OpenCode, Cursor).\n\n```\n$ ig \"async fn.*Result\" src/ --stats\n\nsrc/daemon.rs\n23:    pub async fn handle_connection(stream: UnixStream) -\u003e Result\u003c()\u003e {\n\n--- stats ---\nCandidates: 4/1284 files (0.3%)\nSearch: 1.5ms\nIndex: yes\n```\n\n### The numbers (measured, not estimated)\n\n| What | Result |\n|------|--------|\n| **ig vs ripgrep 14.1.1 — wall time** (v1.11.0, 5 patterns on iautos/apps 18 GB) | **2.2× to 7.8× faster** (median 2.6× faster) |\n| **ig vs ripgrep — match parity** | **5/5 patterns identical** (file count + total matches byte-for-byte) |\n| **Daemon auto-route gain** (v1.11.0, 10-query burst) | **-15% wall, -70% user CPU** vs in-process search |\n| **Single-query latency** (warm, daemon, iautos/apps) | **2.4–8.1 ms** depending on pattern |\n| **ig vs rtk total bytes** (v1.10.0, 115 cases on a 347K-file monorepo) | **896 KB vs 1.04 MB** (ig wins) |\n| **ig vs rtk total time** (same 115 cases) | **1.74 s vs 2.88 s** (ig 40% faster) |\n| **BM25 `--top N` vs rtk** | **10/10 bytes wins**, 7/10 time wins (rtk has no index) |\n| **`--semantic` PMI vs rtk** | **5/5 bytes wins** — synonyms learned from your repo |\n| **Token savings** | **93.5% average** across 100 benchmarked commands |\n| **ig files --compact** | 176K → 149B (**-99.9%**) on a 3K-file project |\n| **git status** | 422 bytes → 25 bytes (**-94%**) |\n| **git log** | 2,499 bytes → 484 bytes (**-81%**) |\n| **Index build** | **226ms** for 1,609 files, **483ms** for 3,084 files |\n| **Symbols extracted** | **4,834** from a Laravel project, **7,702** from a monorepo |\n| **Context reduction** | 12,841 bytes → 3,828 bytes per turn (**-70%**) |\n| **Agent setup** | 8 agents configured in **one command** |\n| **Rust tests** | **438 tests** (389 bin + 49 goldens) |\n| **Integration tests** | **63/65 pass** (2 voluntary skips, 0 failures) |\n| **Commands rewritten** | **91 bins** across 42 TOML filters (v1.9.0) |\n\n### ig vs ripgrep 14.1.1 (v1.11.0, iautos/apps 18 GB, warm cache, hyperfine -N)\n\n| pattern             | ig (daemon) | rg 14.1.1 | ig faster |\n| ------------------- | ----------: | --------: | --------: |\n| `useEffect`         | 5.9 ms      | 18.3 ms   | **3.1×**  |\n| `createServer`      | 2.4 ms      | 18.8 ms   | **7.8×**  |\n| `fn\\s+\\w+_test`     | 3.5 ms      | 27.4 ms   | **7.8×**  |\n| `async function`    | 8.1 ms      | 18.2 ms   | **2.2×**  |\n| `export default`    | 6.9 ms      | 18.0 ms   | **2.6×**  |\n\n`rg` spends ~17–27 ms walking the gitignore tree and opening 3 000 candidate files. `ig`'s trigram filter cuts that to ~50–200 candidates *before* any file is touched — `User: 1.5 ms, System: 1.5 ms` average. Match counts identical on every pattern (no false positives, no missed lines).\n\n\u003e Every number on this page is measured with `wc -c` / `hyperfine` on real commands, on real projects (1,609-file Laravel app, 3,084-file monorepo, 347K-file iautos SaaS). See the [v1.10.0 benchmark artefacts](documentation/public/bench/v1.10.0/) for the older CSV + per-domain tables.\n\n## Why\n\nAI agents call CLI tools constantly. Every byte of output is a token consumed. On a $200/month Claude Code Max plan, wasted tokens = hitting rate limits sooner.\n\n`ig` solves this at two levels:\n\n1. **Search** — trigram-indexed regex search (same algorithm as [GitHub Code Search](https://github.blog/engineering/architecture-optimization/the-technology-behind-githubs-new-code-search/)). First search auto-builds the index. Subsequent searches: near-instant.\n\n2. **Token compression** — `ig git status` outputs 25 bytes instead of 422. `ig read --plain` is byte-exact with `cat`, or `-s` gives signatures-only (−95% on large code files). `ig ls` produces compact listings. Compact search mode (`IG_COMPACT=1`) caps matches + truncates long lines for −60 to −95% on `grep`/`rg`. A PreToolUse hook rewrites commands transparently — the AI agent never knows the difference.\n\n|              | ripgrep 14.1.1 | ig (CLI, in-proc) | ig (daemon, auto-route) |\n| ------------ | -------------- | ----------------- | ----------------------- |\n| iautos/apps (3K files, 18 GB) | ~18–27 ms | ~3–7 ms | **~2.4–8 ms** (auto-spawned, transparent) |\n| Approach     | Full scan      | Index + verify    | Persistent hot process  |\n\n## Installation\n\n### One-liner (recommended)\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/MakFly/instant-grep/main/install.sh | bash\n```\n\n\u003e Installs the binary and runs `ig setup` to configure all detected AI agents.\n\n### Download binaries\n\nSince **v1.13.0**, `ig` ships as two artefacts per platform — a tiny C shim (in your `PATH`) and a hidden Rust backend. Grab both from [Releases](https://github.com/MakFly/instant-grep/releases/latest):\n\n| Platform                | Shim (→ `~/.local/bin/ig`)  | Backend (→ `~/.local/share/ig/bin/ig-rust`) |\n| ----------------------- | --------------------------- | ------------------------------------------- |\n| Linux x86_64            | `ig-shim-linux-x86_64`      | `ig-backend-linux-x86_64`                   |\n| Linux ARM64             | `ig-shim-linux-aarch64`     | `ig-backend-linux-aarch64`                  |\n| macOS x86_64            | `ig-shim-macos-x86_64`      | `ig-backend-macos-x86_64`                   |\n| macOS ARM (M1/M2/M3/M4) | `ig-shim-macos-aarch64`     | `ig-backend-macos-aarch64`                  |\n\nThe shim resolves the backend through `$IG_BACKEND` → `~/.local/share/ig/bin/ig-rust` → `/usr/local/share/ig/bin/ig-rust` → first `ig-rust` on `PATH`. Use `install.sh` to do this layout automatically (recommended).\n\n### Build from source\n\n```bash\ngit clone https://github.com/MakFly/instant-grep.git\ncd instant-grep\ncargo build --release\ncp target/release/ig ~/.local/bin/\n```\n\n## Token Savings\n\n### v1.8.2 benchmarks — measured on real projects\n\nNumbers below come from a monorepo (Next.js frontend ~12 MB + Symfony/PHP backend ~5.5 MB). Every row is a single `wc -c` comparison between the raw command and its ig-rewritten equivalent.\n\n| Category | Command | Raw | ig | Savings |\n|---|---|---:|---:|---:|\n| **ls** | `ls -la` | 3,086 B | 577 B | **−81%** |\n| **ls** | `ls -laR app/` | 81,866 B | 232 B | **−99.7%** *(ig ls is a flat tree — not 1:1 with `ls -laR`)* |\n| **cat** small | `cat package.json` | 5,187 B | 5,187 B | 0% *(parity — no regression)* |\n| **cat** large code | `cat ApiExceptionSubscriber.php` → `-s` | 10,929 B | 2,138 B | **−80%** |\n| **cat** large code | `cat market-insights-actions.ts` → `-s` | 8,773 B | 339 B | **−96%** |\n| **grep/rg** dense | `rg 'public function' src/` (PHP) | 243,740 B | 14,360 B | **−94%** |\n| **grep/rg** dense | `rg 'useState' features/ app/` | 95,021 B | 15,934 B | **−83%** |\n| **grep/rg** dense | `rg 'Entity' src/` (PHP) | 122,345 B | 11,758 B | **−90%** |\n| **grep/rg** medium | `rg 'export function' app/` | 57,812 B | 21,809 B | **−62%** |\n| **grep/rg** sparse | `rg 'fn build' src/` (10 matches) | 674 B | 642 B | −5% *(physical floor)* |\n| **git** | `git status` | 732 B | 127 B | **−83%** |\n| **git** | `git log -10` | 8,861 B | 997 B | **−89%** |\n| **git** | `git diff` (large) | 26,288 B | 6,906 B | **−74%** |\n| **docker** | `docker ps` | 1,792 B | 593 B | **−67%** |\n| **docker** | `docker compose ps` | 1,792 B | 593 B | **−67%** |\n| **docker** | `docker logs` | 1,909 B | 886 B | **−54%** |\n| **JS/TS** | `jest --verbose` | 6,125 B | 910 B | **−85%** |\n| **JS/TS** | `bun test` | 3,467 B | 301 B | **−91%** |\n| **JS/TS** | `playwright test` | 3,984 B | 688 B | **−83%** |\n| **PHP** | `phpunit` | 1,340 B | 698 B | **−48%** |\n| **PHP** | `pest` | 1,220 B | 651 B | **−47%** |\n\n\u003e **How grep/rg compaction works** (`IG_COMPACT=1`, auto-set by rewrites): line truncation at 100 chars (UTF-8 safe), per-file cap of 10 matches, global cap of 200 matches with an explicit `… global cap reached` marker. Inter-file blank lines and `--` separators are dropped. Matches rtk's `--context-only` gains on dense patterns, beats rtk on sparse ones (no header overhead).\n\n### Cumulative savings (real session, 800+ commands)\n\n```\nTotal input:     7.2 MB (native command output)\nTotal output:    1.7 MB (ig compressed output)\nBytes saved:     5.5 MB (76%)\nTokens saved:    ~1,377,000 tokens\n```\n\n### Impact on Claude Code Opus 4.6 session\n\n| | Without ig | With ig | Savings |\n|---|---:|---:|---:|\n| Context per turn | 3,210 tokens | 1,104 tokens | **-66%** |\n| 50 turns context | 160,500 tokens | 55,200 tokens | **-66%** |\n| 30 tool calls | ~80,000 tokens | ~17,000 tokens | **-79%** |\n| **Total per session** | **~240,500 tokens** | **~72,200 tokens** | **-70%** |\n\n\u003e On a Max 20x plan ($200/month), this means **40-60% more messages** before hitting rate limits.\n\n### Token analytics\n\n```bash\nig gain                       # savings dashboard\nig gain --history             # individual command history\nig gain --json                # machine-readable output\nig discover                   # find missed optimization opportunities\n```\n\n### Command rewriting — full RTK parity (v1.9.0)\n\n`ig rewrite` now matches [`rtk rewrite`](https://github.com/rtk-ai/rtk) on every depth feature and exceeds it on breadth. The hook (`~/.claude/hooks/ig-guard.sh`) is a thin shell delegator — all intelligence lives in the Rust binary. Measured in a 4-round × 30-session `claude -p` benchmark, 28 / 28 piped `rg`/`grep -r`/`find -name` commands are now silently rewritten (0 `BLOCK` errors visible to the model).\n\n| Feature | `ig rewrite` | `rtk rewrite` |\n|---|:---:|:---:|\n| Thin shell hook (stdin JSON delegator) | ✅ | ✅ |\n| Pipelines (`rg pat src \\| head -20`) | ✅ | ✅ |\n| Compounds (`cargo test \u0026\u0026 ls -la`) | ✅ | ✅ |\n| ENV prefix (`RUST_LOG=debug rg …`) | ✅ | ✅ |\n| `sudo` / `env` wrappers | ✅ | ✅ |\n| Absolute binary paths (`/usr/bin/grep`) | ✅ | ✅ |\n| Git global options (`git -C path log`) | ✅ | ✅ |\n| Deny rules (`rm -rf /`, `git reset --hard`) | ✅ | ✅ |\n| Ask rules (`git push --force`) | ✅ | ✅ |\n| Dedup consecutive identical output lines | ✅ | ✅ |\n| Rewritten command categories | **91** | 72 |\n\nAll features are quote-aware: `|`/`;`/`\u0026\u0026` inside `\"…\"` or `'…'` are preserved literally.\n\n**Example rewrites** (what the agent typed → what actually runs):\n\n```\ngrep -r \"fn main\" src --include=\"*.rs\" | wc -l\n  → IG_COMPACT=1 ig \"fn main\" src | wc -l\n\nRUST_LOG=debug rg useState features/\n  → RUST_LOG=debug IG_COMPACT=1 ig \"useState\" features/\n\n/usr/bin/grep -rn pattern .\n  → IG_COMPACT=1 ig \"pattern\"\n\ngit -C /tmp/repo log --oneline\n  → ig git log --oneline\n\nfind src -type f -name \"*.rs\"\n  → ig files --glob \"*.rs\"\n\ncargo test \u0026\u0026 ls -la src\n  → ig run cargo test \u0026\u0026 ig ls src\n```\n\n### Deny/Ask safety rules\n\n`ig rewrite` protects against destructive commands:\n\n| Command | Exit code | Behavior |\n|---------|-----------|----------|\n| `git status/log/diff/show` | 0 (rewrite) | Transparently compressed |\n| `git reset --hard` | 2 (deny) | Blocked by hook |\n| `git push --force` | 3 (ask) | Rewritten but user must confirm |\n| `cat file` | 0 (rewrite) | `ig read --plain file` (byte-exact) or `-s` on large code files |\n| `python3 script.py` | 1 (passthrough) | No rewrite |\n\n## Usage\n\n### Search\n\n```bash\nig \"pattern\" .                    # auto-indexes on first run\nig -i \"todo|fixme\" .              # case-insensitive\nig \"useRouter\" . --type ts        # filter by file type\nig -C 3 \"async fn\" src/           # context lines\nig \"fetchData\" . --json           # JSON output for agents\nig \"Result\u003cT\u003e\" . --stats          # show performance stats\nig --top 10 \"pattern\" .           # BM25 ranking, keep top 10 by relevance (v1.10.0)\nig --semantic \"error\" .           # expand query with PMI-learned synonyms (v1.10.0)\n```\n\n### Compact search mode (v1.8.2+)\n\nSet `IG_COMPACT=1` (or let the PreToolUse hook do it when rewriting `grep`/`rg`) to enable aggressive output compaction:\n\n```bash\nIG_COMPACT=1 ig \"pattern\" src/    # capped, truncated, no separators\n```\n\nWhat changes:\n- Line truncation at **100 chars** (UTF-8 safe, `…` marker, match stays visible)\n- Per-file cap: **10 matches** with `… +N more` footer\n- Global cap: **200 matches** with `… global cap reached` marker\n- Inter-file blank line + `--` separators between non-contiguous matches are dropped\n\nOverride individual caps:\n```bash\nIG_LINE_MAX=80 IG_MAX_MATCHES_PER_FILE=5 IG_MAX_MATCHES_TOTAL=100 ig \"pattern\" src/\n```\n\nTypical gains on real projects: **−60 to −94%** on dense patterns (`rg 'public function' src/` on a Symfony codebase: 244 KB → 14 KB).\n\n### BM25 ranking — `--top N` (v1.10.0)\n\nRegex search returns every match in filesystem order. That's fine for a human skimming 20 hits — it's wasteful when there are 2 000 of them and only 5 actually matter. `--top N` scores each matched file with a textbook Okapi BM25 and keeps only the N highest-ranked:\n\n```bash\n$ ig --top 5 useState\napps/.../create-conversational/vehicle-edit-step-dialog.tsx\n  3: import { useState, useMemo } from \"react\";\n 73:   const [value, setValue] = useState(formData.saleMode);\n107:   const [brandId, setBrandId] = useState(formData.brand);\n…\n```\n\nScore = `idf · (tf · (k1 + 1)) / (tf + k1 · (1 − b + b · dl / avdl))` with `k1 = 1.5`, `b = 0.75`. `tf` is the match count per file, `dl` is the file byte-size, `avdl` is the mean across matches. Dense hits in short files rank first — the files where the concept is actually implemented, not the files that happen to mention it in a comment.\n\nOn iautos: `ig --top 10 \"export default\"` returns **743 bytes** of curated hits; `rtk grep \"export default\"` returns a flat-compressed 19 KB dump. Not better compression — *better content*, because rtk has no index and cannot rank.\n\n### Semantic query expansion — `--semantic` (v1.10.0)\n\nStatistical synonym expansion, **no ML model, no download**. During `ig index`, a second pass tokenises every line, counts co-occurrences in a 5-line sliding window, and persists a PMI-ranked top-10 neighbour table to `.ig/cooccurrence.bin`. At query time, `ig --semantic error` rewrites the regex to `\\b(error|catch|throw|exception|…)\\b` and lets the trigram pre-filter do the heavy lifting:\n\n```bash\n$ ig --semantic --top 5 throw\n(semantic: expanded 'throw' → got, inattendu, denied, autorisé, trouvée, manquant)\napps/packages/reader-api-vo/scripts/test-rest-e2e.ts\n 44:   throw new Error(\"HTTP server did not become ready in time\");\n…\n```\n\nThe synonyms are **learned from your own codebase** — if you have `VehicleWantedError` or `iautosPaymentException`, they'll show up in the neighbour tables alongside the common vocabulary. Levy \u0026 Goldberg ([NeurIPS 2014](https://papers.nips.cc/paper_files/paper/2014/file/feab05aa91085b7a8012516bc3533958-Paper.pdf)) proved skip-gram word2vec with negative sampling implicitly factorises the shifted-PMI matrix, so direct PMI recovers most of the neighbourhood quality of a learned embedding at a fraction of the cost.\n\nControls:\n- Disable build entirely: `IG_SEMANTIC=0 ig index`\n- Opt-out per query: just don't pass `--semantic`\n- Inspect: the stderr line `(semantic: expanded 'x' → …)` shows exactly what was added — no magic\n\nExpansion quality depends on how often a term co-occurs with others in your corpus: `throw`, `payment`, `auth`, `config` work well on iautos; rare terms may get a weak expansion or none at all.\n\n### File intelligence\n\n```bash\nig read src/main.rs               # numbered lines\nig read src/main.rs --plain       # no line numbers, byte-exact with `cat` (v1.8.2+)\nig read src/main.rs -s            # signatures only (imports + function names, -95% on large code)\nig read src/main.rs -a            # aggressive mode (strip comments, elide bodies)\nig read src/main.rs -b 500        # budget mode (500 tokens max, entropy-scored)\nig read src/main.rs -r \"payment\"  # relevance boost (keep payment-related code)\nig read src/main.rs -d            # delta mode (git-changed lines only)\nig smart .                        # 2-line summary per file\nig symbols .                      # all function/class definitions\nig context src/main.rs 42         # enclosing code block at line 42\nig ls                             # compact directory listing (-65%)\nig pack                           # generate .ig/context.md (full project map)\nig files .                        # list all files (respects .gitignore)\nig files --compact                # tree-compressed listing (÷300 vs raw)\n```\n\n### Git proxy\n\n```bash\nig git status                     # compact porcelain output (-94%)\nig git log                        # oneline + stats, 10 max (-89%)\nig git diff                       # stat first, then truncated diff (-74%)\nig git show HEAD                  # stat + compact diff (-51%)\nig git branch -a                  # passthrough (already compact)\n```\n\n### Daemon mode (sub-millisecond, multi-tenant since v1.16.0)\n\nA single global daemon serves searches for **every** indexed project on the\nmachine. One process, one socket, one systemd / launchd unit. Tenants are\nopened lazily on first query and kept in an LRU cache (default cap 32, set\n`IG_DAEMON_TENANTS_MAX` to override).\n\n```bash\nig daemon start                   # start the global daemon (foreground or backgrounded)\nig daemon status                  # PID + socket\nig daemon stop                    # SIGTERM the daemon\nig daemon install                 # systemd-user (Linux) or launchd (macOS), auto-start on login\n\nig query \"pattern\" /path/to/proj  # 0.06–1.3 ms response via the global Unix socket\n```\n\n**RAM**: ~6 MB idle, ~12 MB with 3 hot tenants, ~19 MB with 5. Compared to the\npre-v1.16.0 per-project model, this is **~14× less** in typical workstation\nuse (16 cached projects went from 995 MB to 19 MB).\n\n**Wire format**: each query carries the project root in its JSON payload\n(`{\"root\": \"/abs/path\", \"pattern\": \"...\", …}`), so the daemon dispatches\ninternally without needing per-project sockets.\n\n**Boot-time cleanup**: when v1.16.0+ starts, it SIGTERMs any leftover\nper-project daemons, removes their `/tmp/ig-*.sock` files, and takes over.\nIdempotent.\n\n### Cache management (since v1.15.0)\n\nIndexes live in `~/.cache/ig/\u003chash-of-root\u003e/` (XDG-compliant). Set\n`IG_LOCAL_INDEX=1` to fall back to `\u003croot\u003e/.ig/` for a project, or\n`IG_CACHE_DIR=/path` to relocate the whole cache.\n\n```bash\nig cache-ls                       # list every cached project (size, last_used)\nig migrate [--dry-run]            # move \u003croot\u003e/.ig/ to the XDG cache\nig gc [--days N] [--dry-run]      # drop entries whose root is gone, or unused for N days\n```\n\n**Project root detection** (`find_root`) recognises both `.git/` and project\nmarkers (`package.json`, `Cargo.toml`, `pyproject.toml`, `go.mod`,\n`deno.json`, `composer.json`, `bun.lock`, …). Searches from any subdirectory\nof a Next.js / Cargo / Go monorepo resolve to the same root → one shared\nindex, no duplicates.\n\n### Index management\n\n```bash\nig index .                        # build or rebuild\nig status .                       # show stats\nig watch .                        # auto-rebuild on file changes\n```\n\n## Agent Integration\n\n### One-shot setup\n\n```bash\nig setup                          # configure all detected agents\nig setup --dry-run                # preview without writing\n```\n\n`ig setup` detects and configures **every installed agent** automatically:\n\n| Agent | What it configures |\n|-------|--------------------|\n| **Claude Code** | 3 hook scripts + 8 hook registrations + permissions + env vars + CLAUDE.md |\n| **Codex CLI** | AGENTS.md with search instructions |\n| **OpenCode** | AGENTS.md + opencode.json instructions array |\n| **Cursor** | `~/.cursor/rules/ig-search.mdc` (alwaysApply) |\n| **GitHub Copilot** | `copilot-instructions.md` with search instructions |\n| **Windsurf** | `.windsurfrules` with search instructions |\n| **Cline** | `.clinerules` with search instructions |\n| **Gemini CLI** | Manual instructions (print-only) |\n\n**Claude Code hooks installed:**\n- `ig-guard.sh` — command rewriting + blocks `rg`/`grep -r`/`find` in favor of ig\n- `session-start.sh` — version change detection + token savings summary\n- `format.sh` — auto-format on file writes\n- Grep tool blocker, npm/npx blocker, destructive git blocker, secret detection, .env warning\n\n100% idempotent. Safe to run multiple times. `--dry-run` to preview.\n\n### For AI agent developers\n\n`ig` follows the [CLI \u003e MCP consensus](https://ejholmes.github.io/2026/02/28/mcp-is-dead-long-live-the-cli.html):\n\n- **35x fewer tokens** than MCP (4K vs 145K for equivalent tool schemas)\n- **Zero config** — just `ig --json` via Bash\n- **LLMs already know CLIs** — trained on millions of man pages\n- **Composable** — pipe to `jq`, `head`, `wc`\n\nSince v1.7.0, ig is a **complete standalone solution** for AI agent token optimization. No additional tools needed.\n\n## Benchmarks\n\n### Real projects (measured on Apple M4 Max, macOS 15.5)\n\n| Project | Files | Index build | Search | git status | Symbols |\n|---------|------:|------------|--------|------------|---------|\n| **Laravel app** | 1,609 | 226ms | 23ms | **-95%** | 4,834 |\n| **Monorepo** | 3,084 | 483ms | 50ms | **-51%** | 7,702 |\n| **Rust CLI** | 87 | 95ms | 9ms | **-84%** | 541 |\n| **TypeScript CLI** | 35 | 30ms | 6ms | **-83%** | 150 |\n\n### ig v1.6.23 Benchmark (100 commands)\n\n| Category | Raw | ig | Savings |\n|----------|-----|-----|---------|\n| Search --compact (19 patterns) | 2.3 MB | 108K | **-95%** |\n| Files --compact (14 listings) | 597K | 2.2K | **-99.6%** |\n| Read -s (10 files) | 259K | 28K | **-89%** |\n| Read -a (10 files) | 259K | 39K | **-85%** |\n| Read -b500 (10 files) | 259K | 32K | **-88%** |\n| Git (13 commands) | 60K | 32K | **-47%** |\n| ls (5 listings) | 4.3K | 758B | **-83%** |\n| **Total (100 commands)** | **3.7 MB** | **241K** | **-93.5%** |\n\n### ig vs rtk — full benchmark (v1.10.0)\n\n**115 cases across 12 domains**, run on the `iautos` SaaS monorepo (347 843 files raw, 3 146 after ig's default excludes). Methodology: 2 warm-up passes + **median of 3** wall-time runs per case. Bytes are deterministic (one measurement). Full raw data in `documentation/public/bench/v1.10.0/`.\n\n| Headline | ig 1.10.0 | rtk 0.37.2 |\n|---|---:|---:|\n| **Total bytes emitted** | **896 KB** | 1.04 MB |\n| **Total wall time** | **1.74 s** | 2.88 s |\n| **Bytes wins** | **57 / 115** | 54 / 115 *(tie 4)* |\n| **Time wins** | **80 / 115** | 27 / 115 *(tie 8)* |\n\n**ig wins on aggregate bytes and wall time simultaneously for the first time.**\n\n#### Per-domain breakdown\n\n| # | Domain | ig bytes wins | rtk bytes wins | ig time wins | rtk time wins |\n|---|---|---:|---:|---:|---:|\n| 1 | literal search | 5 | 5 | **9** | 1 |\n| 2 | regex search | 3 | **7** | **6** | 4 |\n| 3 | flag variants | **7** | 3 | **9** | 1 |\n| 4 | listing | 2 | **8** | **7** | 3 |\n| 5 | read full | 0 | **10** | **8** | 0 |\n| 6 | read signatures | **9** | 1 | **10** | 0 |\n| 7 | git proxy | **7** | 2 | **8** | 0 |\n| 8 | varied identifiers | 3 | 4 | **10** | 0 |\n| 9 | smart summaries | 4 | **6** | 0 | **10** |\n| 10 | generic proxy | 2 | **8** | 4 | 3 |\n| 11 | **`--top` BM25** | **10** | 0 | **7** | 3 |\n| 12 | **`--semantic` PMI** | **5** | 0 | 2 | 2 |\n\n#### Where rtk still wins — and why it's a trade-off, not a bug\n\n- **Read full (10/10 bytes to rtk)** — ig keeps the `   42: content` line-number prefix because it's what lets the Edit tool round-trip precisely. Dropping it saves ~15 % bytes per file and halves the utility. Deliberate.\n- **Listing / smart dir singles** — rtk's `rtk ls` emits a placeholder 8 B for top-level dirs. Fewer bytes, less information; we emit a compact listing that's still actionable.\n\n#### Where ig is categorically ahead — rtk cannot match without a persistent index\n\n- **`--top N` BM25 ranking** — 10 / 10 bytes wins. Example: `ig --top 10 \"export default\"` = 743 B; `rtk grep \"export default\"` = 19 403 B — same query, **−96 %**. rtk has no `tf` / `df` / `avdl` so it cannot rank; it can only flat-compress.\n- **`--semantic` PMI expansion** — 5 / 5 bytes wins. Example: `ig --semantic --top 5 throw` = 3 368 B with synonyms learned from the repo; `rtk grep throw` = 17 717 B of literal matches. Building a cooccurrence matrix would require rtk to ship its own index layer.\n- **Sub-ms daemon** — not in this run, but `ig daemon` serves queries at p50 = 0.7 ms through a Unix socket; rtk shells to ripgrep on every invocation.\n\n### ig v1.4.0 vs ripgrep\n\n| Pattern | ig | ripgrep | Winner |\n|---------|---|---------|--------|\n| `function` (11K files) | **33ms** | 39ms | ig 1.2x |\n| `class\\s+\\w+` (11K files) | **29ms** | 34ms | ig 1.2x |\n| `deprecated` (11K files) | **21ms** | 31ms | ig 1.5x |\n| `import` (11K files) | **24ms** | 32ms | ig 1.3x |\n\n### Daemon mode (1,001 queries)\n\n| Metric | Value |\n|--------|-------|\n| p50 | **0.71ms** |\n| p95 | 4.51ms |\n| Throughput | **2,695 QPS** (server-side) |\n\n### Scaling — ig gets faster on larger projects\n\n| Project | Files | ig | rg | Speedup |\n|---------|------:|---|---|---------|\n| Small (49) | 49 | 19ms | 21ms | 1.1x |\n| Medium (1,552) | 1,552 | 70ms | 33ms | 0.5x |\n| **Large (24,760)** | 24,760 | **627ms** | 1,490ms | **2.4x** |\n| **Linux kernel (92,585)** | 92,585 | **1,290ms** | 5,119ms | **4.0x** |\n\n\u003e On the Linux kernel (92K files), a zero-result search: **28ms with ig vs 5,279ms with rg — 189x speedup**.\n\n### Optimal codebase exploration strategy\n\nTested on a 1,609-file Laravel project — searching \"how authentication works\":\n\n| Approach | Files found | Symbols | Requests | Time |\n|----------|----------:|--------:|--------:|-----:|\n| Manual `ig \"auth\"` | 6 | 0 | 4 | ~5s |\n| Agent explorer (sequential reads) | ~35 | ~35 | 69 | ~120s |\n| **ig symbols + ig -l (optimized)** | **121** | **194** | **10** | **170ms** |\n| **Agent + ig optimized (v3)** | **121 found, 10 read** | **194** | **14** | **~60s** |\n\nThe optimal strategy: `ig symbols | grep KEYWORD` for definitions, `ig -l \"KEYWORD\"` for file discovery, then `ig read -s` (signatures only) for the key files. **700x faster** than sequential exploration.\n\n### Test suite results\n\n65 integration tests across 9 categories:\n\n| Category | Tests | Result |\n|----------|------:|--------|\n| Smoke tests | 8/8 | **100%** |\n| Performance | 8/8 | **100%** |\n| Integration | 8/8 | **100%** |\n| Stress tests | 6/6 | **100%** |\n| Token consumption | 10/10 | **100%** |\n| Agent Teams | 10/10 | **100%** |\n| Claude -p sessions | 5/5 | **100%** |\n| Agentik Team | 5/5 | **100%** |\n| Real project (Laravel) | 5/5 | **100%** |\n| **Total** | **63/65** | **100% executed** (2 voluntary skips) |\n\n## How it works\n\n### Distribution: C shim + hidden Rust backend (v1.13.0)\n\n```\n┌────────────────────────┐\n│ ~/.local/bin/ig        │   35 KB C shim, in $PATH\n│ (C shim, in PATH)      │\n└───────────┬────────────┘\n            │ hot path: argv → daemon socket (no execve)\n            │ cold path: execve($IG_BACKEND or fallback)\n            ▼\n┌──────────────────────────────────────┐\n│ ~/.local/share/ig/bin/ig-rust        │   5.1 MB Rust backend, hors $PATH\n│ (Rust backend)                       │\n└──────────────────────────────────────┘\n```\n\nA single `ig` name in your `PATH`. The shim handles the hot subcommands (`search`, `grep`, `files`, `count`) entirely in C — argv parse, root resolve, daemon socket round-trip — for sub-2 ms cold start. Cold-path subcommands (`index`, `setup`, `update`, …) `execve` the backend. Backend resolution: `$IG_BACKEND` → user share → system share → first `ig-rust` on `PATH`.\n\n### The pipeline\n\n```\nregex pattern\n    │\n    ▼\nregex-syntax::Extractor → extract literal sequences\n    │\n    ▼\nbuild_covering_ngrams() → minimal set of sparse n-grams\n    │\n    ▼\nFNV-1a hash → NgramKey (u64) → lookup in mmap'd hash table\n    │\n    ▼\nintersect posting lists → candidate file IDs\n    │\n    ▼\nparallel regex verification (rayon) → only on candidates\n    │\n    ▼\nresults (colored / JSON)\n```\n\n### Sparse n-grams\n\nTraditional trigram indexes use fixed 3-character windows. `ig` uses **variable-length sparse n-grams** based on [danlark1/sparse_ngrams](https://github.com/danlark1/sparse_ngrams) (the algorithm behind GitHub Code Search):\n\n```\nTrigrams:     23 keys → 47 candidate files\nSparse grams:  3 keys →  4 candidate files (12x better)\n```\n\n### On-disk format (v10)\n\n| File | Format | Size (1,552 files) |\n|------|--------|-------------------|\n| `metadata.bin` | bincode — file paths, mtimes, git SHA | 111 KB |\n| `lexicon.bin` | Hash table: `[NgramKey:u64, offset:u32, byte_len:u32]` | 31 MB |\n| `postings.bin` | Delta + VByte encoded, concatenated | 7.1 MB |\n\nMemory-mapped. Streaming SPIMI pipeline (128MB budget). Overlay index for incremental updates.\n\n### BM25 ranking (v1.10.0)\n\nWhen `--top N` is set, the candidate file list from the trigram intersection is scored with Okapi BM25:\n\n```\nscore(file) = idf · (tf · (k1 + 1)) / (tf + k1 · (1 − b + b · dl / avdl))\n            k1 = 1.5, b = 0.75\n            tf = match count in the file\n            dl = file byte size\n            avdl = mean dl across the result set\n```\n\nScoring happens *after* the regex verification pass (so only real matches are considered) and adds one `stat(2)` per candidate. On the 115-case bench, `--top N` never takes more than 50 ms end-to-end, even for patterns that match in 300+ files.\n\n### Semantic layer — PMI, no ML model (v1.10.0)\n\n`--semantic` piggy-backs on a second index built alongside the trigram one:\n\n```\nig index  ─┬─▶ trigram + filedata + symbols       (existing)\n            └─▶ cooccurrence.bin                    (new)\n\nig --semantic \u003cword\u003e ─▶ lookup top-6 PMI neighbours\n                     ─▶ build regex \\b(word|n1|…|n6)\\b\n                     ─▶ normal trigram+regex search\n                     ─▶ optional BM25 rerank via --top\n```\n\nDuring index build, every line is tokenised (camelCase / snake_case / acronym-aware), and co-occurrences in a 5-line sliding window are counted. At finalisation we compute count-weighted PPMI per pair:\n\n```\nPMI(a, b)     = log( p(a, b) / (p(a) · p(b)) )\nscore(a, b)   = PMI · log(count + 1)     (rejects rare-word coincidences)\n```\n\n…and persist the top-10 neighbours per token to `.ig/cooccurrence.bin` (bincode, ~1.5 MB on a 3K-file repo). Thresholds `MIN_PAIR_COUNT = 15` and `MIN_TOKEN_COUNT = 10` kill PMI's well-known low-frequency bias.\n\nTheoretical basis: Levy \u0026 Goldberg, [*Neural Word Embedding as Implicit Matrix Factorization*](https://papers.nips.cc/paper_files/paper/2014/file/feab05aa91085b7a8012516bc3533958-Paper.pdf) (NeurIPS 2014) — direct PMI is *the* objective that skip-gram word2vec with negative sampling implicitly optimises.\n\n### OpenAI embeddings — opt-in POC (v1.14.0)\n\nPMI gives you semantic *expansion* (synonyms learned from your repo) on top of literal matching. For natural-language queries that don't share any token with the target code (`\"function that cancels a Stripe subscription\"` → `unsubscribe()`), you need **dense embeddings**. v1.14.0 ships a pedagogical POC, **disabled by default at two layers**:\n\n| Layer | Mechanism | Controls |\n|---|---|---|\n| **Compile-time** | `cargo build --features embed-poc` | Whether the `embed-poc` subcommand exists in the binary at all (default: absent). |\n| **Runtime** (v1.14.2) | `ig emb on / ig emb off` | Whether it executes when present (default: off). |\n\n```bash\n# 1. Compile-time opt-in\ncargo build --release --features embed-poc      # subcommand now compiled in\nig embed-poc --help                              # visible\n\n# 2. Runtime toggle (lives in ~/.config/ig/embed.toml)\nig emb status                                    # disabled (default)\nig emb on                                        # enabled\nig emb off                                       # back to disabled\n\n# 3. Try to use embed-poc while runtime is OFF → friendly refusal\n$ ig embed-poc hello \"test\"\nError: embeddings are disabled.\nEnable with:  ig emb on\n```\n\nThe POC is intentionally tiny — JSON store, brute-force cosine, 40-line chunker — so the math is readable. **The shipped binary contains zero OpenAI client code** unless you opt in at compile-time. Even after that, the runtime toggle defaults to off so no network call ever fires by accident. Users without an API key fall back to the regular trigram path (`ig search \"pattern\"`) which is sub-ms, no network, no cost.\n\n```\nig embed-poc index ./src\n   │\n   ├─▶ chunk files (40 lines, 5 overlap)             ──▶ 768 chunks\n   ├─▶ batch-embed via OpenAI text-embedding-3-small  ──▶ 1536 floats / chunk\n   └─▶ persist to .ig/poc-embeddings.json             ──▶ ~30 MB on a 3 k-file repo\n\nig embed-poc search \"function that cancels a Stripe subscription\"\n   │\n   ├─▶ embed the query (1 OpenAI call, ~$0.0000002)\n   ├─▶ rayon par_iter cosine over the store\n   └─▶ top-N ranked (file:lines + score + preview)\n```\n\nFive subcommands, all gated behind the feature flag **and** the runtime toggle:\n- `embed-poc hello \u003ctext\u003e` — single-vector smoke test (Phase 1)\n- `embed-poc index \u003cdir\u003e` — chunk + embed + JSON store (Phase 2)\n- `embed-poc inspect [--limit N]` — human-readable store dump\n- `embed-poc search \u003cquery\u003e [--top N]` — cosine top-N\n- `embed-poc serve [--port 7877] [--ui ui/dist]` — `tiny_http` JSON server + optional React SPA\n\nPlus one always-available toggle (no feature flag required):\n- `ig emb [on|off|status]` — flip the runtime switch persisted in `~/.config/ig/embed.toml`. Fail-closed: if the config file is unreadable, embeddings stay off.\n\nWhy this is **not the default**:\n- **Cost guard.** An indexing run on a 3 k-file repo costs ~$0.05; a runaway re-index in a CI loop could rack up real money. PMI/trigram are free.\n- **Network dependency.** Each search is one round-trip to OpenAI (~200–800 ms). The trigram daemon answers in \u003c 1 ms.\n- **API-key handling.** The key lives in `~/.config/ig/config.toml` or `.env` (always gitignored, pre-commit hook blocks `sk-*` strings) — but most users don't have one and shouldn't have to.\n- **Recall is similar at this scale.** On a 3 k-file repo, well-tuned PMI + BM25 (`ig --semantic --top 10`) catches most queries that dense embeddings catch. Embeddings start to dominate at 50 k+ files / multi-language polyglot repos.\n\nThe POC stays in-tree (gated) so users curious about embedding-based search can see exactly what an embedding *is* (1 536 floats, L2-normalised, 32×48 heatmap visualisable in the SPA), measure the latency/cost themselves, and decide whether to industrialise.\n\nRead the full design + Phase 0–4 walkthrough at [`/docs/embeddings`](https://instant-grep.pulseview.app/docs/embeddings).\n\n## Architecture\n\n```\nig\n├── index/          — Sparse n-gram index (build + query + overlay)\n├── search/         — Indexed + brute-force search\n│   └── rank.rs     — BM25 ranking (--top N, v1.10.0)\n├── semantic/       — PMI cooccurrence tokenizer + builder (v1.10.0)\n├── query/          — Regex → NgramQuery conversion\n├── git.rs          — Token-compressed git proxy\n├── rewrite.rs      — Command rewriting engine (exit codes 0/1/2/3)\n├── gain.rs         — Token savings dashboard\n├── tracking.rs     — JSONL history\n├── discover.rs     — Session scanner for missed savings\n├── setup.rs        — Universal AI agent configuration\n├── scoring.rs      — Layered Semantic Compression (entropy × weight × relevance)\n├── delta.rs        — Git-aware delta reads (changed lines + enclosing context)\n├── read.rs         — Smart file reading (full + signatures)\n├── smart.rs        — 2-line file summaries + dir-aggregate mode (v1.10.0)\n├── symbols.rs      — Symbol definition extraction\n├── pack.rs         — Project context generator\n├── ls.rs           — Compact directory listing\n├── cache.rs        — XDG cache (~/.cache/ig/) + gc/migrate (v1.15.0)\n├── daemon.rs       — Single global Unix-socket server, multi-tenant LRU (v1.16.0)\n├── watch.rs        — File watcher + auto-rebuild\n└── walk.rs         — Gitignore-aware walking\n```\n\n## Credits\n\n- [danlark1/sparse_ngrams](https://github.com/danlark1/sparse_ngrams) — sparse n-gram algorithm\n- [Cursor — Fast regex search](https://cursor.com/blog/fast-regex-search) — the inspiration\n- [GitHub — The technology behind code search](https://github.blog/engineering/architecture-optimization/the-technology-behind-githubs-new-code-search/)\n- [BurntSushi](https://github.com/BurntSushi) — `regex-syntax`, `ignore`, `memchr`\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmakfly%2Finstant-grep","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmakfly%2Finstant-grep","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmakfly%2Finstant-grep/lists"}