Metadata-Version: 2.4
Name: ziplex
Version: 0.6.1
Summary: Which tests does this change affect? A zero-config, incremental dependency graph (Python/TS/JS/Go) for CI test selection, editor hooks and coding agents (MCP).
Author: rim
License: MIT License
        
        Copyright (c) 2026 rim
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/taerim0/Ziplex
Project-URL: Repository, https://github.com/taerim0/Ziplex
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Documentation
Classifier: Topic :: Software Development :: Libraries
Classifier: Environment :: Console
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: tree-sitter
Requires-Dist: tree-sitter-python
Requires-Dist: tree-sitter-java
Requires-Dist: tree-sitter-typescript
Requires-Dist: tree-sitter-lua
Requires-Dist: tree-sitter-go
Requires-Dist: tree-sitter-cpp
Requires-Dist: tree-sitter-rust
Requires-Dist: tree-sitter-c-sharp
Requires-Dist: tree-sitter-php
Requires-Dist: tree-sitter-ruby
Requires-Dist: tree-sitter-bash
Requires-Dist: tree-sitter-mlua
Requires-Dist: tree-sitter-language-pack
Requires-Dist: tiktoken
Requires-Dist: pathspec
Requires-Dist: python-dotenv
Requires-Dist: requests
Requires-Dist: mcp
Requires-Dist: flask
Requires-Dist: pywebview
Requires-Dist: watchdog
Requires-Dist: ruamel.yaml
Requires-Dist: tomli; python_version < "3.11"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Dynamic: license-file

<img src="docs/images/logo.png" alt="Ziplex logo" width="96" height="96">

# Ziplex

**English** | [한국어](README_ko.md)

**Which tests does this change affect, and what depends on this file? Ziplex answers from a zero-config dependency graph — for your CI, your editor hook and your coding agent.**

Ziplex parses a project with Tree-sitter and resolves imports the way the toolchain does — relative/index files, tsconfig `paths` aliases, pnpm/npm workspace packages and their `exports`, Python packages, re-exports, `conftest.py` and package `__init__.py` files, Go packages — into one graph across languages. It keeps that graph in an incremental local index (no LLM, no network, no API key) and answers from it in milliseconds.

> ⚠️ Under active development. Interfaces may still change.

---

## Where it helps

- **Running only the tests a change can affect** — locally (`pytest $(ziplex impact --format paths)`) or on every pull request ([CI template](docs/ci/impacted-tests.yml)). Measured on 99 real commits of repos Ziplex was never tuned on: recall 0.976, or 0.988 without the imports pytest itself makes ([eval](eval/README.md)). It falls back to the full suite whenever a targeted run isn't safe.
- **Giving a coding agent the impact answers grep can't produce in one step** — `ziplex-mcp` answers "which tests cover this change", "what is transitively affected", "how does A reach B". On held-out repos, Claude Code with it spent 57% less and finished 55% faster on those questions, at the same accuracy ([EXPERIMENTS #15](docs/EXPERIMENTS.md)).
- **Polyglot and monorepo codebases** — a TypeScript frontend, a Python backend and shared workspace packages resolve into one graph, with no per-language tool to configure.
- **An editor hook** — after Claude Code edits a file, one line tells it how many files depend on it and which tests to run.

Honest scope: for a direct "who imports X" question a single grep is already enough (the MCP costs ~12% more there), and in small, local bug fixes agents gained nothing measurable from it ([EXPERIMENTS #16](docs/EXPERIMENTS.md)). The value is in transitive impact and test selection.

## Quick start

```bash
pip install ziplex                      # or: pipx install ziplex
cd your-project
ziplex impact                           # tests affected by your uncommitted changes
pytest $(ziplex impact --format paths)  # run just those (prints nothing -> full suite when unsure)
ziplex deps src/app.py --in --depth 2   # who depends on a file, by hop
ziplex install claude --hook            # register the MCP server + post-edit hook with Claude Code
```

The first command builds `.ziplex/index.db` (gitignored automatically; django's 5,700 files take ~10s, later updates under a second). More in [Graph index](#graph-index-deps-impacted-tests-editor-hook), [MCP server](#mcp-server) and the [CI template](docs/ci/impacted-tests.yml).

## Packing a project into aif.json (optional)

Ziplex can also pack a project into `aif.json`: per-file summaries (structural, or written by an LLM you choose), inferred coding rules, a project guide and the relationship graph, reviewable in a GUI before it's saved. Useful for pasting a project's shape into a chat with no tool access; for agents that have tools, the graph commands above are what measurably helps ([EXPERIMENTS](docs/EXPERIMENTS.md) #1-#9).

### Pack quick start

```bash
pip install ziplex        # or: pipx install ziplex (isolated env, PATH handled for you automatically)
# or: venv\Scripts\activate && pip install -e . from a clone
ziplex-gui
```

A native window opens: pick a project folder with the folder picker, check off which files to include (or just accept the safe default), and pack — no flags to remember. Want to try it before committing to an API key? Check "no LLM" and you get a real `aif.json` from structural summaries alone — no signup, no network call. Uncheck it (with a `GEMINI_API_KEY` in `.env`, or another provider picked on the Options page) for real AI-written summaries, inferred coding rules, and a project guide instead. Packing pauses for review before anything's saved, and browsing a project you've already packed works the same way — see [GUI](#gui) for the full walkthrough.

> **`ziplex`/`ziplex-gui` command not found after installing?** [pipx](https://pipx.pypa.io/) avoids this by design — it installs into its own isolated environment and puts that on your PATH automatically (`pipx ensurepath`, then restart your terminal). With plain `pip install ziplex` on Windows, if you don't have write access to your global Python's `site-packages` (common without admin rights), pip silently falls back to a per-user install whose `Scripts` folder often isn't on PATH — you'll usually see a `WARNING: The script ziplex.exe is installed in '...' which is not on PATH` line scroll by during install. Fix: either switch to `pipx install ziplex`, or add that printed folder (typically `%APPDATA%\Python\Python3XX\Scripts`) to your user PATH yourself and open a new terminal.

Prefer the terminal — scripting, CI, or an environment with no GUI?

<details>
<summary>CLI quick start</summary>

**Try it right now — no API key, no signup, no network call:**

```bash
ziplex pack ./your-project/ --auto --no-llm
```

This runs the full pipeline (Tree-sitter compression, dependency graph, tech-stack detection) and writes a real `aif.json` — summaries are just a structural listing of each file's own signatures instead of an LLM-written description. See what that looks like on your own project before deciding whether the AI-written version is worth an API key.

Liked it? Add a `.env` with `GEMINI_API_KEY=...` (optionally `GEMINI_MODEL=...` too — see [Tech stack](#tech-stack)), drop `--no-llm`, and get real AI-written summaries plus inferred coding rules and a project guide:

```bash
ziplex pack ./your-project/                        # full pipeline, interactive
ziplex pack ./your-project/ --auto --auto-correct  # fully non-interactive (CI, scripted runs)
```

`--auto` (skip interactive file selection) and `--auto-correct` (skip interactive correction) are independent, so any combination of the two works. Re-running `pack` on a project you've packed before only re-summarizes files that actually changed (by content hash) — everything else reuses its previous summary instead of another LLM call.

</details>

<details>
<summary>Every <code>pack</code> flag</summary>

| Flag | Effect |
|---|---|
| `--auto` | Skip interactive file selection, include everything safe |
| `--auto-correct` | Skip interactive correction, auto-accept whatever the LLM produced |
| `-o, --output <path>` | Custom output path (writes `<path>` + sibling `.detail.json`/`.cache.json`) |
| `--no-cache` | Force-resummarize every file, ignoring any previous pack found on disk |
| `--include <patterns>` | Only pack files matching these comma-separated globs, on top of `.ziplex.json` (below) |
| `--ignore <patterns>` | Additionally exclude these comma-separated globs, on top of `.ziplex.json` |
| `--max-tokens N` (+ `--max-tokens-model M`) | CI guard: exit code 1 if the packed payload exceeds `N` tokens for model `M` (default GPT-4o) |
| `--no-llm` | No `GEMINI_API_KEY`/network at all — structural summaries only, `rules`/AI guide skipped |
| `--lang en\|ko` | Language every summary/rule/AI guide is *written in* (default/recommended `en`) — independent of what language your code or comments are in |

</details>

<details>
<summary>Other AI providers (OpenAI-compatible, Ollama, LM Studio, Claude)</summary>

Gemini is the default, but every LLM-calling step (summaries, coding rules, the project guide) can run through a different provider instead — set `LLM_PROVIDER` (env var, for CLI/CI use) or pick one on the GUI's [Options page](#gui) (takes effect on the very next pack, no restart needed):

| Provider | `LLM_PROVIDER` | Config |
|---|---|---|
| Gemini (default) | `gemini` | `GEMINI_API_KEY`, optional `GEMINI_MODEL` |
| OpenAI-compatible — real OpenAI, Ollama, LM Studio, vLLM, OpenRouter, Groq, llama.cpp's server, ... | `openai` | `OPENAI_API_KEY` (often unneeded for a local server), `OPENAI_BASE_URL`, `OPENAI_MODEL` |
| Claude (Anthropic) | `claude` | `ANTHROPIC_API_KEY` (or `CLAUDE_API_KEY`), optional `CLAUDE_MODEL` |

A local model (Gemma, Llama, Mistral, ...) served through Ollama or LM Studio is just the `openai` provider pointed at that server — `OPENAI_BASE_URL=http://localhost:11434/v1` (Ollama) or `http://localhost:1234/v1` (LM Studio), `OPENAI_MODEL` set to whatever name that server expects, no API key needed either way. The GUI's Options page has one-click presets for both.

</details>

### Config file

`ziplex init ./your-project/` scaffolds `.ziplex.json` in the target project (not in Ziplex's own repo) so `include`/`ignore` glob patterns don't need retyping on every `pack`:

```jsonc
// your-project/.ziplex.json
{
  "include": ["src/**/*.py", "*.md"],  // empty = everything not ignored (default)
  "ignore": ["**/*.generated.*"]        // extra patterns beyond DEFAULT_IGNORE/.gitignore
}
```

`--include`/`--ignore` CLI flags add to this file's patterns rather than replacing them. Every subcommand that previews what `pack` would collect (`collect`, `tree`, `tokens`, `search`, `freshness`) reads the same file, so none of them drift out of sync with what a real `pack` on that project would actually see. Worth committing alongside the project the same way `aif.json`/`detail.json` already can (see Team use below) — it documents how that project gets packed.

<details>
<summary>Every command</summary>

Forgot the list? A bare `ziplex` (no subcommand) prints this same table, English text and all — the one part of this CLI that isn't Korean.

| Command | Description |
|---|---|
| `pack <path>` | Full pipeline — `ziplex-gui` is the same thing without the flags |
| `init <path>` | Scaffold `.ziplex.json` (`include`/`ignore` glob patterns) in the target project |
| `collect <path>` | File collection + security scan only |
| `tokens <path>` | Token count, before/after compression |
| `tree <path>` | Dependency tree only |
| `search <path> <pattern>` | Regex search across all safe files (`--context N`, `--ignore-case`) |
| `detail <name>.detail.json <file-key>` | Partial read of one file's compressed body (`--start`/`--end`) |
| `freshness <path> <name>.cache.json` | Hash-check `aif.json` against the files on disk — no LLM calls |
| `skill <name>.json` | Export as a Claude Agent Skill (`.claude/skills/<slug>/`) — no MCP server needed |
| `link <name>.json <file> <target>` / `unlink ...` | Add/remove a dependency edge on an already-saved `aif.json`, without re-running `pack` |
| `settings` / `settings set <key> <value>` | View or change `~/.ziplex/settings.json` — output folder, LLM provider/API key/model; the CLI counterpart of the GUI's Options page |
| `checkpoint` / `checkpoint clean [<path>\|--all]` | List or delete leftover checkpoint files from an interrupted `pack` |
| `doctor [<path>]` | Environment check — Python version, active LLM provider/API key, secretlint, leftover checkpoints; no LLM call |
| `signatures \| dependencies \| api \| compress \| debug <file>` | Run one extraction step on a single file |

`ziplex --version` (also `ziplex-gui --version`/`ziplex-mcp --version`) prints the installed version.

</details>

## How it works

Ziplex collects a project's files (skipping build artifacts and anything `.gitignore`d), security-scans them for secrets, and parses the safe ones with Tree-sitter to pull out signatures, imports, and API routes. Function bodies get compressed down to a single marker; an LLM then writes a one-line summary per file plus project-wide coding rules and an AI-facing guide. A human reviews and edits all of that — only low-confidence summaries get flagged, not every file — before the final `aif.json` (small, loaded up front) and its heavier sibling `detail.json` (full compressed body, fetched on demand) are saved.

## Output format

A pack produces three files, each read differently:

| File | Contains | Read when |
|---|---|---|
| `aif.json` | Project guide, coding rules, token stats, one summary + confidence score per file, the full dependency graph | Every time — small enough to load up front |
| `<name>.detail.json` | The full compressed source, per file | On demand, when a summary alone isn't enough (`get_detail`, the GUI's detail view) |
| `<name>.cache.json` | A content-hash of every packed file | Never by a human — internal bookkeeping for `check_freshness` and incremental re-pack |

```jsonc
// aif.json — small, loaded up front
{
  "project": {
    "name": "...", "prompt": "...",
    "tech_stack": [{ "manifest": "package.json", "language": "JavaScript/TypeScript", "package_manager": "npm", "dependencies": ["react", "..."], "dependencies_truncated": false }],
    "security_scan": { "flagged": 0, "included_anyway": 0, "excluded": 0 },
    "format_notes": "..."  // fixed legend explaining confidence/⋮---- to a reader with no other Ziplex context
  },
  "rules": ["..."],
  "folders": { "src": { "summary": "..." } },  // one sentence per folder describing its role
  "tokens": { "GPT-4o": { "original": 3100, "compressed": 749, "saved_pct": 75.8 } },
  "files": { "src/App.tsx": { "summary": "...", "confidence": 0.83 } },
  "relationships": { "src/App.tsx": { "internal": ["..."], "external": ["react"] } }
}
```

```jsonc
// out.detail.json — heavier, fetched only when a file actually needs a closer look
{
  "src/App.tsx": { "compressed": "import React ...\n    ⋮----\nexport default App" }
}
```

```jsonc
// out.cache.json — internal bookkeeping, not meant for an AI to read; a
// content-hash snapshot of what was packed, for check_freshness to diff
// against later
{
  "src/App.tsx": "3b1c2e...(sha256)"
}
```

## Features

- **Multi-language, structure-aware compression** — Python, Java, TypeScript, JavaScript, Lua, GDScript, Go, C++, Rust, C#, PHP, Ruby, Bash via Tree-sitter, plus dedicated JSON/YAML/Markdown/plain-text/Dockerfile compressors, all preserving structure while cutting tokens. Works on any collection of local files with cross-file relationships, not just git repos — game mods and asset projects included.
- **Security scanning built in** — every file is checked for secrets (`secretlint`, regex fallback) before it ever enters the pipeline.
- **Human-in-the-loop, but it scales** — every LLM output (summaries, rules, project guide, dependency tree) is reviewable and editable, or skippable entirely with `--auto-correct`. Only low-confidence summaries get flagged for review — review time doesn't grow with project size.
- **Three ways to consume the result** — an [MCP server](#mcp-server) for Claude Code/Cursor/etc., a local [GUI](#gui) for packing and browsing without a terminal, or a [Claude Agent Skill export](#claude-agent-skill-export) that needs no server at all.
- **Cheap to keep current** — incremental re-pack only re-summarizes files that actually changed (content hash), retries with backoff on LLM flakiness, and checkpoints a failed run instead of restarting from scratch.
- **Bring your own LLM** — Gemini by default, or switch to any OpenAI-compatible endpoint (real OpenAI, Ollama, LM Studio, vLLM, OpenRouter, ...) or Claude directly, via `LLM_PROVIDER` or the GUI's Options page — including a fully local setup with no API key or network call at all (see [Other AI providers](#pack-quick-start)).
- **No API key required, if you want** — `pack --no-llm` skips every LLM call and still produces structural summaries, dependency graphs, and tech-stack detection. Scope any pack with `.ziplex.json`/`--include`/`--ignore`, and guard CI budgets with `--max-tokens`.

## Testing

```bash
pip install -e ".[dev]"   # adds pytest on top of the base install
pytest
```

Covers the deterministic core — compressors, the Tree-sitter extractor, the collector's ignore/binary-file filtering, the dependency-graph operations (`build_tree`/`has_cycle`/`move_file`), and the pure `aif`-editing API — plus a full `pack()` run against a network-free `MockProvider` instead of Gemini, exercising checkpointing, parallel summaries, and token counting end to end without the cost or latency of a real LLM call.

Want to smoke-test `pack` against a real project without waiting on Gemini? `LLM_PROVIDER=mock ziplex pack <project> --auto --auto-correct` runs the whole pipeline network-free in under a second.

## Graph index: deps, impacted tests, editor hook

No pack and no LLM needed: these commands keep an incremental dependency-graph index in `<project>/.ziplex/index.db` (a disposable cache, gitignored automatically) and answer from it. The project defaults to the current directory.

```bash
ziplex index [--check]                        # build/refresh the index; --check exits 1 if anything changed
ziplex deps src/app.py                        # what it imports (with line numbers)
ziplex deps src/app.py --in --depth 2         # who depends on it, by hop
ziplex impact                                 # tests affected by your uncommitted changes (= --diff worktree)
pytest $(ziplex impact --format paths)        # run just those tests
ziplex path src/app.py src/db.py              # shortest import chain
ziplex install claude --hook                  # register the MCP server + a post-edit hook with Claude Code
```

`impact --format paths` prints nothing when a targeted run isn't safe (a build/config/lockfile changed, or a file was deleted), so the `pytest $(...)` line above falls back to the whole suite; the reason goes to stderr. `--format commands` prints ready-to-run `pytest`/`jest`/`go test` commands instead.

With `--hook`, `ziplex install claude` adds a `PostToolUse` entry (`ziplex-hook`) to `<project>/.claude/settings.json`. After Claude edits a file it tells Claude, in one short line, how many files depend on it and which tests to run. It never blocks, stays silent in projects without an index, and repeats at most once per file per 10 minutes. `--dry-run` shows the command and the settings diff without changing anything.

## MCP server

`ziplex-mcp` gives Claude Code, Cursor or any MCP client the same live graph as the commands above -- no pack needed, refreshed from disk before every call.

```bash
claude mcp add ziplex -- ziplex-mcp --project /abs/path/to/project   # or: ziplex install claude
```

| Tool | What it answers |
|---|---|
| `graph_overview(scope?)` | Hubs, import cycles, folder layering, unresolved relative imports -- start here in an unfamiliar repo |
| `who_depends_on(files, depth?, include_mentions?)` | Who imports these files (with the import line), or everything transitively affected, by hop |
| `dependencies_of(files, external?)` | What these files import, resolved to files (aliases, workspaces, Python packages, Go packages) |
| `impacted_tests(files?, diff?)` | Tests affected by a change or a git diff, with the import chain and a ready-to-run command |
| `dependency_path(source, target)` | The shortest import chain between two files |

Answers are compact text (tens to a few hundred tokens), and the five tool definitions cost ~720 tokens per session. Paths can be repo-relative, absolute or a unique suffix (`query_service.py`).

**Legacy mode.** `ziplex-mcp --aif <name>.json [--project .]` (or `--legacy-tools`) serves the previous ten tools over a packed `aif.json` instead (`get_overview`, `list_files`, `get_folders`, `get_relationships`, `get_graph_summary`, `get_dependents`, `get_blast_radius`, `get_detail`, `check_freshness`, `search_project`), so existing registrations keep working.

## GUI

A local, single-user GUI for two situations: packing a project without touching a terminal, and browsing an already-packed project somewhere Claude Code (or MCP generally) isn't available but a browser-based AI chat is.

```bash
ziplex-gui                                            # native window (pywebview)
ziplex-gui --aif out.json --project ./your-project/   # prefill the landing page
ziplex-gui --no-window                                # plain browser tab instead
```

### Packing a project

![Pack: project setup — folder, output path, and packing language](docs/images/en/gui-pack-select.png)

Pick a project folder with the native folder picker, check off which files to include (the same safe/dangerous split `collect`'s security scan produces), pick the packing language (`pack --lang`'s GUI equivalent — what language summaries/rules/the AI guide are *written in*, separate from the topbar's own display-language toggle), optionally check "no LLM" (`pack --no-llm`'s GUI equivalent), and watch the pack run in the background.

### Reviewing before anything is saved

![Pack: review project guide, rules, and folder/per-file summaries](docs/images/en/gui-pack-review.png)

Analysis pauses for review before anything is saved: edit the project name, guide, rules, and folder/per-file summaries (only the low-confidence ones are flagged, same triage the CLI uses).

### Dependency graph & relationship editing

![Dependency tree and relationship editor](docs/images/en/gui-relationships.png)

The dependency graph opens as a collapsible whole-tree overview first — click a file's name once you've spotted one worth fixing to drop into an edit view for just that file, linking or unlinking individual edges (a file with more than one real parent keeps its other references intact). The Relationships page (for a project already packed) reuses this same whole-tree-then-edit-one-file flow, so a relationship noticed after the fact can be fixed without re-running the pipeline.

### Browsing an already-packed project

![Overview page for a packed project](docs/images/en/gui-overview.png)

The same overview/files/relationships/detail/search views the MCP server exposes, as web pages instead of MCP tool calls. Each page has a Copy button; the intended flow is looking around here and pasting what's useful into a separate AI chat by hand, not the GUI talking to that chat itself.

**Debugging in a plain web chat (no file access, no MCP)**: paste `aif.json`'s content once at the start of the conversation — it's small on purpose, just summaries and relationships, meant to be pasted whole. Once the AI points at a suspect file from those summaries/relationships, don't paste the rest of `detail.json` too — open that one file's page here and hit its own Copy button (or run `ziplex detail <name>.detail.json <file-key>` for just a line range of a large file) and paste only that into the same chat. The AI now has that file's full compressed source without you ever handing over anything for the files it didn't ask about.

### Options page

![Options page: output folder, AI provider](docs/images/en/gui-options.png)

The default output folder new packs save to, and which AI provider every pack uses (Gemini / OpenAI-compatible / Claude — see [Other AI providers](#pack-quick-start)), with one-click presets for Ollama's and LM Studio's default local ports so a fully local setup needs no typed URL. Display language and light/dark theme live in the topbar itself instead (two small toggles next to the nav links) — a display-only chrome preference, not something worth a trip to a separate page for.

Binds to `127.0.0.1` only — no `--host` flag, no way to expose it to a network.

## Claude Agent Skill export

A third way to reach a packed project, alongside the MCP server and the GUI — for when Claude Code is available but registering an MCP server isn't (or is more setup than the moment calls for):

```bash
ziplex skill .ziplex/my-project.json               # writes .claude/skills/my-project/
ziplex skill .ziplex/my-project.json -o some/dir    # custom output directory
```

Generates a [Claude Agent Skill](https://code.claude.com/docs/en/skills) — `SKILL.md` plus `references/overview.md`/`files.md`/`relationships.md`/`detail.json` — that Claude Code discovers and progressively loads on its own once it sits under `.claude/skills/`, no server process required. Unlike [repomix](https://repomix.com/guide/agent-skills-generation)'s equivalent `--skill-generate` feature, `references/files.md` never embeds full raw source — it stays to summaries and confidence scores, exactly what `aif.json` itself already restricts to; the *compressed* body only ships as `references/detail.json`. Committing the generated directory works the same way committing `aif.json`/`detail.json` does (see Team use below) — it's just files.

## Team use

Ziplex packs one person's local snapshot — there's no shared server or live sync. That doesn't rule out team use, though: `aif.json`/`detail.json`/`cache.json` are just files, so a team can commit them to the project's own repo the same way any other generated-but-versioned artifact works.

- Whoever runs `pack` after a meaningful change commits the refreshed output alongside their code change.
- Everyone else's copy is only as current as the last commit that touched it — `check_freshness` (or `get_overview`/`list_files` with `project_path` passed, see above) tells them whether their working copy has drifted from what's committed, without re-`pack`ing just to find out.
- This is a convention, not a feature Ziplex enforces or coordinates: no merge/conflict resolution, and no defined "who wins" if two people repack independently before either commits. If it does conflict, don't hand-resolve the JSON — see [merge-conflicts.md](docs/team/merge-conflicts.md) for the recommended fix (clear the conflict, re-`pack`, review); [`gitattributes`](docs/team/gitattributes) keeps these files collapsed in GitHub's PR diff view.

**CI gate (optional):** `ziplex freshness <project> <name>.cache.json` exits non-zero when the committed output has drifted — no LLM calls, no `GEMINI_API_KEY`, just a hash comparison. Wire it into a PR check ([template](docs/ci/freshness-gate.yml)) to catch a stale, un-re-reviewed `aif.json` before it merges, without automating `pack` itself (which costs real LLM calls and skips human review — left as a manual step on purpose).

## Tech stack

Python 3.10+ · [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) (Python/Java/TypeScript/JavaScript/Lua/GDScript/Go/C++/Rust/C#/PHP/Ruby/Bash grammars, GDScript via `tree-sitter-language-pack`) · [tiktoken](https://github.com/openai/tiktoken) · [ruamel.yaml](https://yaml.readthedocs.io/) · plain REST via `requests` against Gemini (`gemini-flash-latest` by default, overridable via `GEMINI_MODEL`), any OpenAI-compatible endpoint (real OpenAI, Ollama, LM Studio, vLLM, OpenRouter, ...), or Claude — see [Other AI providers](#pack-quick-start) · [MCP](https://modelcontextprotocol.io/) · Flask · pywebview · `secretlint` · `pathspec`

## License

[MIT](LICENSE)
