Metadata-Version: 2.5
Name: focuspack
Version: 0.2.0
Summary: Focus-driven, budget-aware codebase context packager for LLMs
Project-URL: Homepage, https://github.com/maqbulansari/focuspack
Project-URL: Repository, https://github.com/maqbulansari/focuspack
Project-URL: Issues, https://github.com/maqbulansari/focuspack/issues
Project-URL: Documentation, https://github.com/maqbulansari/focuspack#readme
Author: focuspack contributors
License-Expression: MIT
License-File: LICENSE
Keywords: ast-analysis,chatgpt,claude,cli,codebase-to-prompt,context-engineering,gemini,llm,prompt-caching,token-budget
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Requires-Dist: click>=8.1.0
Requires-Dist: pathspec>=0.11.0
Requires-Dist: rich>=13.0.0
Provides-Extra: all
Requires-Dist: pyperclip>=1.8.2; extra == 'all'
Requires-Dist: tiktoken>=0.5.0; extra == 'all'
Provides-Extra: clipboard
Requires-Dist: pyperclip>=1.8.2; extra == 'clipboard'
Provides-Extra: dev
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.4.0; extra == 'dev'
Provides-Extra: tiktoken
Requires-Dist: tiktoken>=0.5.0; extra == 'tiktoken'
Description-Content-Type: text/markdown

<div align="center">

# 🎯 focuspack

**Focus-driven, budget-aware codebase context packager for LLMs**

[![CI](https://github.com/maqbulansari/focuspack/actions/workflows/ci.yml/badge.svg)](https://github.com/maqbulansari/focuspack/actions)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
[![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)

*Don't dump blindly. Pack the exact slice of code your LLM needs with AST contracts, semantic roles, and adaptive token budgets.*

[Quick Start](#-quick-start) • [Why focuspack?](#-why-focuspack) • [How Budgeting Works](#-adaptive-multi-stage-budget-engine) • [Comparison](#-competitive-comparison) • [CLI Reference](#-cli-reference) • [Product Charter](CHARTER.md) • [Contributing](#-contributing)

---

</div>

## 💡 Why focuspack?

Static file dumpers (like Repomix or code2prompt) suffer from a fundamental blind spot: **they treat codebases as flat buckets of files**. If you run them on a project, they dump dozens of files into a 100k+ token monolith.

### The Attention Breakdown (Lost in the Middle)
Transformer research proves that as context length grows, reasoning accuracy plummets in the middle 60–80% of the prompt. Dumping 80 irrelevant files dilutes attention heads, causing missed edge cases, hallucinated methods, and sluggish completions.

### What LLMs Actually Need
1. **High Signal-to-Noise:** The file you are actively modifying in **FULL**.
2. **Contract-First Dependencies:** When an LLM calls helper functions or imports classes, it rarely needs hundreds of lines of internal implementation. It only needs the **interface contract** (class hierarchy, method signatures, argument types, return annotations, and docstrings).
3. **Adaptive Token Fitting:** When constrained by a token budget (e.g., `--budget 8k` or `--budget 32k`), context tools must intelligently tier and adapt code—**without sacrificing the target file you asked to inspect**.
4. **Semantic Role Labeling:** Tagging files with `role="focus_target"` vs `role="dependency_contract"` explicitly instructs the model what it is asked to modify versus what is an immutable external API.

---

## ⚡ Competitive Comparison

How `focuspack` compares against flat dumpers and other context tools under constrained budgets:

| Capability | Flat Dumpers (Repomix) | codesurf | ctxeng | 🎯 focuspack |
| :--- | :---: | :---: | :---: | :---: |
| **Selection Model** | Flat / Dump All (globs) | Focus Path | Focus Path | **Focus-Driven Graph** (`-F`) |
| **Dependency Awareness** | ❌ None | ⚠️ Path heuristic | ❌ None | ✅ **AST Import Graph (BFS)** |
| **Target Preservation under Budget** | N/A (no budget fitting) | ❌ **Drops target file** at low budgets | ❌ **Truncates mid-line** | ✅ **Preserves target; compresses tiered** |
| **Budget Enforcement** | ❌ Exit code 1 check only | Silent file omission | String slicing | ✅ **4-Stage Adaptive Optimizer** |
| **AST Interface Skeletons** | Global `--compress` flag | Regex-based | ❌ None | ✅ **Python AST + JS/TS outline** |
| **Semantic Role Tags** | ❌ `<file path="...">` | ❌ None | ❌ None | ✅ `<file role="focus_target\|dependency_contract">` |
| **Task / Mission Framing** | ❌ Raw dump | ❌ None | ❌ None | ✅ `--task bugfix\|review\|refactor` |
| **Runtime Requirement** | ⚠️ Node.js / NPM (`npx`) | Python | Python | ✅ **Zero-Node Pure Python** (`pip`, `uvx`) |

---

## 🧠 Adaptive Multi-Stage Budget Engine

When you supply `--budget <size>` (e.g. `--budget 8k` or `--budget 32k`), `focuspack` does **not** naively truncate text or silently drop your primary target. It executes a multi-stage optimization pipeline:

```
[All Repo Files]
       │
       ▼  Stage 1: Peripheral Pruning
[Focus Target (FULL) + Contracts (FULL)]
       │
       ▼  Stage 2: Contract Skeletonization
[Focus Target (FULL) + Contracts (AST Skeletons)]
       │
       ▼  Stage 3: Contract Docstring Stripping (AST Transformer)
[Focus Target (FULL) + Contracts (Minimal AST)]
       │
       ▼  Stage 4: Target Method Body Compression (AST)
[Focus Target (Signatures + Compressed Methods) + Contracts]
       │
       ▼  (Optional: --strict-budget)
[Guaranteed Fit or Non-Zero Exit Code]
```

1. **Stage 1 — Peripheral Pruning:** Unrelated modules, documentation files (`README.md`, `LICENSE`), and peripheral assets are omitted from file contents while preserving repository architecture in the directory tree.
2. **Stage 2 — Dependency Contract Skeletons:** Directly imported dependencies are converted into AST interface contracts. Method bodies are replaced with `...`, preserving class definitions, type hints, and docstrings.
3. **Stage 3 — Clean AST Docstring Stripping:** If further reduction is required, contract docstrings are cleanly removed using an `ast.NodeTransformer` without corrupting code or leaving loose strings.
4. **Stage 4 — Large Target Method Compression:** If the focus target alone exceeds the budget, verbose internal method bodies are compressed to `...` while preserving public interfaces, arguments, return types, and docstrings.
5. **Strict Budget Mode (`--strict-budget`):** In CI/CD pipelines or automated workflows, `--strict-budget` guarantees an exit code `1` if even Stage 4 cannot satisfy the requested limit.

---

## 🚀 Quick Start

### Installation

```bash
# Install via pip
pip install focuspack

# Or run instantly with uvx / pipx without installing
uvx focuspack
```

### Common Workflows

```bash
# 1. Target a specific file — packages auth.py in FULL and its imported dependencies as Skeletons:
focuspack --focus src/auth/service.py

# 2. Fit adaptively within an 8k or 32k token window:
focuspack -F src/auth/service.py --budget 8k

# 3. Add an automated debugging mission and copy straight to clipboard:
focuspack -F src/payment.py --task bugfix --copy

# 4. Package git-modified files + their connected contracts:
focuspack diff --copy

# 5. Enforce strict budget gating in CI scripts:
focuspack -F src/api.py --budget 16k --strict-budget
```

---

## 📦 Output Format (Claude & LLM Optimized)

By default, `focuspack` generates semantic XML structured for Anthropic Claude 3.5/3.7, OpenAI GPT-4o, and Google Gemini:

```xml
<documents>
  <context_manifest>
    <tool>focuspack v0.2.0</tool>
    <token_budget total_allowed="8000" tokens_used="6420" utilization="80.2%" status="fits"/>
    <role_counts focus_targets="1" dependency_contracts="3"/>
  </context_manifest>

  <directory_structure>
  src/
  ├── auth/
  │   └── service.py  [FOCUS]
  └── db/
      └── client.py   [CONTRACT]
  </directory_structure>

  <files>
    <file index="1" path="src/auth/service.py" role="focus_target" mode="full" tokens="3420">
      <document_content>
        <!-- Full implementation code of the focus target -->
      </document_content>
    </file>

    <file index="2" path="src/db/client.py" role="dependency_contract" mode="skeleton" tokens="380">
      <document_content>
        <!-- AST Contract: classes, methods, type hints, docstrings without bodies -->
      </document_content>
    </file>
  </files>

  <task_instruction>
    You are a principal debugging engineer. Analyze the enclosed focus targets and their dependency contracts...
  </task_instruction>
</documents>
```

*(Also supports `--format markdown`, `--format json`, and `--format plain`).*

---

## 🛡️ Secret & Credential Scanning

`focuspack` automatically scans and redacts sensitive credentials before code is packaged or copied:
- **API Keys & Tokens:** OpenAI (`sk-...`), Anthropic (`sk-ant-...`), GitHub tokens (`ghp_...`, `github_pat_...`), Slack tokens.
- **Cloud Credentials:** AWS Access Keys (`AKIA...`), AWS Secret Keys.
- **Database Connection Strings:** Complete password redaction across `postgres://`, `mysql://`, `mongodb://`, `redis://`, and `mssql://` URLs.
- **Private Keys:** RSA, SSH, and generic PEM private keys.

---

## 📖 CLI Reference

```text
Usage: focuspack [OPTIONS] COMMAND [ARGS]...

Options:
  -v, --version  Show version and exit.
  --help         Show this message and exit.

Commands:
  pack     Package focused codebase context optimized for LLMs.
  analyze  Inspect repository dependency graph, token metrics, and largest files.
  diff     Package only git-changed files + their connected dependency contracts.
  init     Create a .focuspack.json configuration file.
```

### `focuspack pack` Options

| Option | Flag | Description | Default |
| :--- | :--- | :--- | :--- |
| `--focus` | `-F` | File(s) or directories to focus on (kept in Full; dependencies become Contracts) | `None` |
| `--depth` | `-d` | Dependency traversal depth (1 = direct imports, 2 = 2 hops) | `1` |
| `--budget` | `-b` | Token budget (e.g. `8k`, `32k`, `64k`). Adaptively tiers files to fit | `None` |
| `--strict-budget` | | Exit with non-zero error code if output exceeds requested budget | `False` |
| `--include-peripherals` | | Keep peripheral/unrelated files in output even when focus targets are active | `False` |
| `--task` | `-t` | Task prompt template (`bugfix`, `review`, `refactor`, `explain`, `test`) | `None` |
| `--format` | `-f` | Output format (`xml`, `markdown`, `json`, `plain`) | `xml` |
| `--mode` | `-m` | Compression mode (`auto`, `full`, `skeleton`) | `auto` |
| `--copy` | `-c` | Copy output directly to system clipboard | `False` |
| `--stdout` | | Stream output directly to stdout | `False` |
| `--diff` | | Focus on git uncommitted/staged changes + connected contracts | `False` |
| `--output` | `-o` | Output file path | `context.<format>` |
| `--no-redact-secrets` | | Disable automated secret redaction | `False` |
| `--tree / --no-tree` | | Include directory tree diagram | `True` |
| `--quiet` | `-q` | Suppress console UI | `False` |

---

## ⚙️ Configuration

Generate a configuration file with:

```bash
focuspack init
```

Creates `.focuspack.json`:

```json
{
  "output_format": "xml",
  "mode": "auto",
  "token_budget": 32000,
  "focus_depth": 1,
  "focus_targets": [],
  "max_size": "500kb",
  "exclude": [
    "docs/build/**",
    "scratch/**"
  ],
  "respect_gitignore": true,
  "redact_secrets": true,
  "include_tree": true
}
```

---

## 🤝 Contributing

Contributions, issues, and feature requests are welcome!
Please review our **[Product Charter (CHARTER.md)](CHARTER.md)** to ensure proposals align with our core mission, and see [CONTRIBUTING.md](CONTRIBUTING.md) for local dev setup.

1. Fork the repo & clone locally
2. Create your branch (`git checkout -b feature/awesome-feature`)
3. Install dependencies (`pip install -e ".[dev,all]"`)
4. Run tests (`pytest`)
5. Open a Pull Request verifying alignment with the Charter


---

## 📄 License

Distributed under the MIT License. See [LICENSE](LICENSE) for details.
