agentpack-cli 0.1.24__tar.gz → 0.1.26__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentpack_cli-0.1.26/.gitignore +33 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/PKG-INFO +15 -7
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/README.md +14 -6
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/pyproject.toml +1 -1
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/__init__.py +1 -1
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/application/pack_service.py +51 -2
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/claude_cmd.py +1 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/diff.py +7 -1
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/doctor.py +74 -1
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/explain.py +52 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/hook_cmd.py +116 -7
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/init.py +56 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/pack.py +24 -3
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/scan.py +7 -1
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/stats.py +156 -2
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/status.py +34 -3
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/summarize.py +7 -1
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/watch.py +1 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/config.py +12 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/context_pack.py +2 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/scanner.py +4 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/data/agentpack.md +5 -4
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/installers/antigravity.py +8 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/installers/codex.py +2 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/installers/cursor.py +9 -4
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/installers/windsurf.py +4 -2
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/renderers/markdown.py +3 -2
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/session/state.py +2 -0
- agentpack_cli-0.1.24/.gitignore +0 -21
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/LICENSE +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/adapters/__init__.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/adapters/antigravity.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/adapters/base.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/adapters/claude.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/adapters/codex.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/adapters/cursor.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/adapters/detect.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/adapters/generic.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/adapters/windsurf.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/analysis/__init__.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/analysis/dependency_graph.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/analysis/go_imports.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/analysis/java_imports.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/analysis/js_ts_imports.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/analysis/python_imports.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/analysis/ranking.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/analysis/rust_imports.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/analysis/symbols.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/analysis/tests.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/application/__init__.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/cli.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/__init__.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/_shared.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/benchmark.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/install.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/mcp_cmd.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/monitor.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/commands/quickstart.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/__init__.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/bootstrap.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/cache.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/diff.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/git.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/git_hooks.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/global_install.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/ignore.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/merkle.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/models.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/redactor.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/snapshot.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/token_estimator.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/core/vscode_tasks.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/installers/__init__.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/installers/claude.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/integrations/__init__.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/integrations/git_hooks.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/integrations/global_install.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/integrations/vscode_tasks.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/mcp_server.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/renderers/__init__.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/renderers/compact.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/renderers/receipts.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/session/__init__.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/summaries/__init__.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/summaries/base.py +0 -0
- {agentpack_cli-0.1.24 → agentpack_cli-0.1.26}/src/agentpack/summaries/offline.py +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.egg-info/
|
|
4
|
+
dist/
|
|
5
|
+
build/
|
|
6
|
+
.eggs/
|
|
7
|
+
*.egg
|
|
8
|
+
|
|
9
|
+
.venv/
|
|
10
|
+
venv/
|
|
11
|
+
env/
|
|
12
|
+
|
|
13
|
+
# agentpack:start
|
|
14
|
+
# AgentPack generated context/cache (safe to ignore)
|
|
15
|
+
.agentpack/cache/
|
|
16
|
+
.agentpack/snapshots/
|
|
17
|
+
.agentpack/context*
|
|
18
|
+
.agentpack/metrics.jsonl
|
|
19
|
+
.agentpack/pack_metadata.json
|
|
20
|
+
.agentpack/activity.log
|
|
21
|
+
.agentpack/.gitignore
|
|
22
|
+
.agentpack/.mcp_reminded
|
|
23
|
+
.agentpack/session.json
|
|
24
|
+
.agentpack/task.md
|
|
25
|
+
.agentpack/benchmark_results.jsonl
|
|
26
|
+
.agent/skills/agentpack/
|
|
27
|
+
# agentpack:end
|
|
28
|
+
|
|
29
|
+
.pytest_cache/
|
|
30
|
+
.mypy_cache/
|
|
31
|
+
.ruff_cache/
|
|
32
|
+
|
|
33
|
+
*.dist-info/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentpack-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.26
|
|
4
4
|
Summary: Task-aware context packing for AI coding agents — Claude, Cursor, Windsurf, Codex, and Antigravity
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -44,7 +44,7 @@ Description-Content-Type: text/markdown
|
|
|
44
44
|
[](https://opensource.org/licenses/MIT)
|
|
45
45
|
[](https://github.com/vishal2612200/agentpack/actions/workflows/ci.yml)
|
|
46
46
|
|
|
47
|
-
> **Status: alpha (v0.1.
|
|
47
|
+
> **Status: alpha (v0.1.25).** Works, tested, used in real sessions. Python and JavaScript/TypeScript are the best-supported languages. Not yet validated across a wide range of repos. API may change before 1.0.
|
|
48
48
|
>
|
|
49
49
|
> **Platform note:** macOS and Linux are fully supported. Windows support is not yet implemented (git hooks use POSIX shell; the Claude Code session hooks use `python3`/`rm -f`). Contributions welcome.
|
|
50
50
|
|
|
@@ -377,7 +377,7 @@ Configures:
|
|
|
377
377
|
- `CLAUDE.md` — tells Claude to read the context pack before each task
|
|
378
378
|
- `.claude/settings.json` — two hooks:
|
|
379
379
|
- `SessionStart`: clears injection sentinel so first prompt gets context
|
|
380
|
-
- `UserPromptSubmit`: runs `agentpack hook` — detects repo changes via `root_hash`, triggers background repack using your prompt as task. With MCP: emits Option-B hint (~100 tokens, task + top files). Without MCP: emits capped fallback (top 8 files, ≤3k chars)
|
|
380
|
+
- `UserPromptSubmit`: runs `agentpack hook` — detects repo changes via `root_hash`, detects clear task switches, updates `.agentpack/task.md`, and triggers background repack using your prompt as task. With MCP: emits Option-B hint (~100 tokens, task + top files). Without MCP: emits capped fallback (top 8 files, ≤3k chars)
|
|
381
381
|
|
|
382
382
|
After this, context is injected automatically into every Claude Code session. No `/agentpack` command needed — it just happens.
|
|
383
383
|
|
|
@@ -388,7 +388,7 @@ agentpack install --agent cursor
|
|
|
388
388
|
```
|
|
389
389
|
|
|
390
390
|
Configures:
|
|
391
|
-
- `.cursorrules` — rule: read `.agentpack/context.md`
|
|
391
|
+
- `.cursorrules` — rule: write current task, run `agentpack pack --task auto`, then read `.agentpack/context.md`
|
|
392
392
|
- `.cursor/rules/agentpack.mdc` — `alwaysApply: true` rule (Cursor v0.43+)
|
|
393
393
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
394
394
|
- `.vscode/tasks.json` — "AgentPack: Repack context" in Command Palette + `runOn: folderOpen`
|
|
@@ -400,7 +400,7 @@ agentpack install --agent windsurf
|
|
|
400
400
|
```
|
|
401
401
|
|
|
402
402
|
Configures:
|
|
403
|
-
- `.windsurfrules` — rule: read `.agentpack/context.md`
|
|
403
|
+
- `.windsurfrules` — rule: write current task, run `agentpack pack --task auto`, then read `.agentpack/context.md`
|
|
404
404
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
405
405
|
- `.vscode/tasks.json` — "AgentPack: Repack context" in Command Palette + `runOn: folderOpen`
|
|
406
406
|
|
|
@@ -411,7 +411,7 @@ agentpack install --agent codex
|
|
|
411
411
|
```
|
|
412
412
|
|
|
413
413
|
Configures:
|
|
414
|
-
- `AGENTS.md` — tells Codex to read the context pack before each task
|
|
414
|
+
- `AGENTS.md` — tells Codex to write current task, repack, and read the context pack before each task
|
|
415
415
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
416
416
|
|
|
417
417
|
### Antigravity
|
|
@@ -422,7 +422,7 @@ agentpack install --agent antigravity
|
|
|
422
422
|
|
|
423
423
|
Configures:
|
|
424
424
|
- `.agent/skills/agentpack/SKILL.md` — AgentPack context as a Skill; Antigravity activates it automatically for coding tasks
|
|
425
|
-
- `GEMINI.md` — registers the agentpack skill reference
|
|
425
|
+
- `GEMINI.md` — registers the agentpack skill reference and task-switch protocol
|
|
426
426
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
427
427
|
- `.vscode/tasks.json` — "AgentPack: Repack context" in Command Palette + `runOn: folderOpen`
|
|
428
428
|
|
|
@@ -642,6 +642,7 @@ agentpack init --share-cache # commit cache/ to git for team sharing
|
|
|
642
642
|
|
|
643
643
|
Creates:
|
|
644
644
|
```
|
|
645
|
+
.gitignore # patched idempotently with AgentPack generated artifacts
|
|
645
646
|
.agentignore # gitignore-style file exclusion rules
|
|
646
647
|
.agentpack/
|
|
647
648
|
config.toml # configuration (safe to commit)
|
|
@@ -1062,6 +1063,10 @@ include_tests = true
|
|
|
1062
1063
|
include_configs = true
|
|
1063
1064
|
include_receipts = true
|
|
1064
1065
|
|
|
1066
|
+
[hooks]
|
|
1067
|
+
task_switch_detection = true
|
|
1068
|
+
task_switch_min_terms = 1
|
|
1069
|
+
|
|
1065
1070
|
[agents.claude]
|
|
1066
1071
|
output = ".agentpack/context.claude.md"
|
|
1067
1072
|
patch_claude_md = true
|
|
@@ -1114,8 +1119,11 @@ Works like `.gitignore`. Default rules exclude:
|
|
|
1114
1119
|
.agentignore ✓ commit
|
|
1115
1120
|
.agentpack/config.toml ✓ commit
|
|
1116
1121
|
.agentpack/cache/ ✓ commit if --share-cache (recommended for teams)
|
|
1122
|
+
.agentpack/.gitignore ✗ gitignored
|
|
1117
1123
|
.agentpack/snapshots/ ✗ gitignored
|
|
1118
1124
|
.agentpack/context.* ✗ gitignored
|
|
1125
|
+
.agentpack/task.md ✗ gitignored (local current task)
|
|
1126
|
+
.agent/skills/agentpack/ ✗ gitignored (generated Antigravity context)
|
|
1119
1127
|
```
|
|
1120
1128
|
|
|
1121
1129
|
---
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://github.com/vishal2612200/agentpack/actions/workflows/ci.yml)
|
|
7
7
|
|
|
8
|
-
> **Status: alpha (v0.1.
|
|
8
|
+
> **Status: alpha (v0.1.25).** Works, tested, used in real sessions. Python and JavaScript/TypeScript are the best-supported languages. Not yet validated across a wide range of repos. API may change before 1.0.
|
|
9
9
|
>
|
|
10
10
|
> **Platform note:** macOS and Linux are fully supported. Windows support is not yet implemented (git hooks use POSIX shell; the Claude Code session hooks use `python3`/`rm -f`). Contributions welcome.
|
|
11
11
|
|
|
@@ -338,7 +338,7 @@ Configures:
|
|
|
338
338
|
- `CLAUDE.md` — tells Claude to read the context pack before each task
|
|
339
339
|
- `.claude/settings.json` — two hooks:
|
|
340
340
|
- `SessionStart`: clears injection sentinel so first prompt gets context
|
|
341
|
-
- `UserPromptSubmit`: runs `agentpack hook` — detects repo changes via `root_hash`, triggers background repack using your prompt as task. With MCP: emits Option-B hint (~100 tokens, task + top files). Without MCP: emits capped fallback (top 8 files, ≤3k chars)
|
|
341
|
+
- `UserPromptSubmit`: runs `agentpack hook` — detects repo changes via `root_hash`, detects clear task switches, updates `.agentpack/task.md`, and triggers background repack using your prompt as task. With MCP: emits Option-B hint (~100 tokens, task + top files). Without MCP: emits capped fallback (top 8 files, ≤3k chars)
|
|
342
342
|
|
|
343
343
|
After this, context is injected automatically into every Claude Code session. No `/agentpack` command needed — it just happens.
|
|
344
344
|
|
|
@@ -349,7 +349,7 @@ agentpack install --agent cursor
|
|
|
349
349
|
```
|
|
350
350
|
|
|
351
351
|
Configures:
|
|
352
|
-
- `.cursorrules` — rule: read `.agentpack/context.md`
|
|
352
|
+
- `.cursorrules` — rule: write current task, run `agentpack pack --task auto`, then read `.agentpack/context.md`
|
|
353
353
|
- `.cursor/rules/agentpack.mdc` — `alwaysApply: true` rule (Cursor v0.43+)
|
|
354
354
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
355
355
|
- `.vscode/tasks.json` — "AgentPack: Repack context" in Command Palette + `runOn: folderOpen`
|
|
@@ -361,7 +361,7 @@ agentpack install --agent windsurf
|
|
|
361
361
|
```
|
|
362
362
|
|
|
363
363
|
Configures:
|
|
364
|
-
- `.windsurfrules` — rule: read `.agentpack/context.md`
|
|
364
|
+
- `.windsurfrules` — rule: write current task, run `agentpack pack --task auto`, then read `.agentpack/context.md`
|
|
365
365
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
366
366
|
- `.vscode/tasks.json` — "AgentPack: Repack context" in Command Palette + `runOn: folderOpen`
|
|
367
367
|
|
|
@@ -372,7 +372,7 @@ agentpack install --agent codex
|
|
|
372
372
|
```
|
|
373
373
|
|
|
374
374
|
Configures:
|
|
375
|
-
- `AGENTS.md` — tells Codex to read the context pack before each task
|
|
375
|
+
- `AGENTS.md` — tells Codex to write current task, repack, and read the context pack before each task
|
|
376
376
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
377
377
|
|
|
378
378
|
### Antigravity
|
|
@@ -383,7 +383,7 @@ agentpack install --agent antigravity
|
|
|
383
383
|
|
|
384
384
|
Configures:
|
|
385
385
|
- `.agent/skills/agentpack/SKILL.md` — AgentPack context as a Skill; Antigravity activates it automatically for coding tasks
|
|
386
|
-
- `GEMINI.md` — registers the agentpack skill reference
|
|
386
|
+
- `GEMINI.md` — registers the agentpack skill reference and task-switch protocol
|
|
387
387
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
388
388
|
- `.vscode/tasks.json` — "AgentPack: Repack context" in Command Palette + `runOn: folderOpen`
|
|
389
389
|
|
|
@@ -603,6 +603,7 @@ agentpack init --share-cache # commit cache/ to git for team sharing
|
|
|
603
603
|
|
|
604
604
|
Creates:
|
|
605
605
|
```
|
|
606
|
+
.gitignore # patched idempotently with AgentPack generated artifacts
|
|
606
607
|
.agentignore # gitignore-style file exclusion rules
|
|
607
608
|
.agentpack/
|
|
608
609
|
config.toml # configuration (safe to commit)
|
|
@@ -1023,6 +1024,10 @@ include_tests = true
|
|
|
1023
1024
|
include_configs = true
|
|
1024
1025
|
include_receipts = true
|
|
1025
1026
|
|
|
1027
|
+
[hooks]
|
|
1028
|
+
task_switch_detection = true
|
|
1029
|
+
task_switch_min_terms = 1
|
|
1030
|
+
|
|
1026
1031
|
[agents.claude]
|
|
1027
1032
|
output = ".agentpack/context.claude.md"
|
|
1028
1033
|
patch_claude_md = true
|
|
@@ -1075,8 +1080,11 @@ Works like `.gitignore`. Default rules exclude:
|
|
|
1075
1080
|
.agentignore ✓ commit
|
|
1076
1081
|
.agentpack/config.toml ✓ commit
|
|
1077
1082
|
.agentpack/cache/ ✓ commit if --share-cache (recommended for teams)
|
|
1083
|
+
.agentpack/.gitignore ✗ gitignored
|
|
1078
1084
|
.agentpack/snapshots/ ✗ gitignored
|
|
1079
1085
|
.agentpack/context.* ✗ gitignored
|
|
1086
|
+
.agentpack/task.md ✗ gitignored (local current task)
|
|
1087
|
+
.agent/skills/agentpack/ ✗ gitignored (generated Antigravity context)
|
|
1080
1088
|
```
|
|
1081
1089
|
|
|
1082
1090
|
---
|
|
@@ -16,6 +16,7 @@ from agentpack.core import git
|
|
|
16
16
|
from agentpack.core.context_pack import select_files, save_pack_metadata
|
|
17
17
|
from agentpack.core.models import ContextPack, DependencyGraph, FileInfo, ScanResult, SelectedFile, Receipt
|
|
18
18
|
from agentpack.core.token_estimator import estimate_tokens
|
|
19
|
+
from agentpack.renderers.markdown import render_generic
|
|
19
20
|
from agentpack.analysis.ranking import (
|
|
20
21
|
score_files,
|
|
21
22
|
extract_keyword_weights,
|
|
@@ -193,6 +194,7 @@ class PackPlanner:
|
|
|
193
194
|
previous_snapshot=previous_snap,
|
|
194
195
|
include_globs=cfg.project.include_globs or None,
|
|
195
196
|
exclude_globs=cfg.project.exclude_globs or None,
|
|
197
|
+
always_skip_paths=AdapterRegistry.generated_output_paths(root, cfg),
|
|
196
198
|
)
|
|
197
199
|
phase_times["scan"] = time.perf_counter() - t0
|
|
198
200
|
|
|
@@ -255,7 +257,7 @@ class AdapterRegistry:
|
|
|
255
257
|
"""Maps agent names to adapter instances; extensible without touching PackService."""
|
|
256
258
|
|
|
257
259
|
@staticmethod
|
|
258
|
-
def
|
|
260
|
+
def _factories(cfg: Any) -> dict[str, Any]:
|
|
259
261
|
from agentpack.adapters.antigravity import AntigravityAdapter
|
|
260
262
|
from agentpack.adapters.claude import ClaudeAdapter
|
|
261
263
|
from agentpack.adapters.codex import CodexAdapter
|
|
@@ -263,15 +265,33 @@ class AdapterRegistry:
|
|
|
263
265
|
from agentpack.adapters.windsurf import WindsurfAdapter
|
|
264
266
|
from agentpack.adapters.generic import GenericAdapter
|
|
265
267
|
|
|
266
|
-
|
|
268
|
+
return {
|
|
267
269
|
"antigravity": lambda: AntigravityAdapter(),
|
|
268
270
|
"claude": lambda: ClaudeAdapter(cfg.agents.claude.output),
|
|
269
271
|
"cursor": lambda: CursorAdapter(cfg.agents.generic.output),
|
|
270
272
|
"windsurf": lambda: WindsurfAdapter(cfg.agents.generic.output),
|
|
271
273
|
"codex": lambda: CodexAdapter(cfg.agents.generic.output),
|
|
274
|
+
"generic": lambda: GenericAdapter(cfg.agents.generic.output),
|
|
272
275
|
}
|
|
276
|
+
|
|
277
|
+
@staticmethod
|
|
278
|
+
def get(agent: str, cfg: Any) -> Any:
|
|
279
|
+
from agentpack.adapters.generic import GenericAdapter
|
|
280
|
+
|
|
281
|
+
adapters = AdapterRegistry._factories(cfg)
|
|
273
282
|
return adapters.get(agent, lambda: GenericAdapter(cfg.agents.generic.output))()
|
|
274
283
|
|
|
284
|
+
@staticmethod
|
|
285
|
+
def generated_output_paths(root: Path, cfg: Any) -> set[str]:
|
|
286
|
+
paths: set[str] = set()
|
|
287
|
+
for factory in AdapterRegistry._factories(cfg).values():
|
|
288
|
+
try:
|
|
289
|
+
out_path = factory().output_path(root)
|
|
290
|
+
paths.add(str(out_path.relative_to(root)).replace("\\", "/"))
|
|
291
|
+
except (OSError, ValueError):
|
|
292
|
+
continue
|
|
293
|
+
return paths
|
|
294
|
+
|
|
275
295
|
|
|
276
296
|
class PackService:
|
|
277
297
|
"""Materializes a plan from PackPlanner into a written context file."""
|
|
@@ -319,6 +339,7 @@ class PackService:
|
|
|
319
339
|
|
|
320
340
|
t0 = time.perf_counter()
|
|
321
341
|
out_path = adapter.write(pack_obj, root)
|
|
342
|
+
_write_canonical_context(pack_obj, root, out_path)
|
|
322
343
|
plan.phase_times["render"] = time.perf_counter() - t0
|
|
323
344
|
|
|
324
345
|
save_snapshot(plan.current_snap, root)
|
|
@@ -333,6 +354,7 @@ class PackService:
|
|
|
333
354
|
token_estimate=packed_tokens,
|
|
334
355
|
freshness=freshness,
|
|
335
356
|
freshness_warnings=freshness_warnings,
|
|
357
|
+
selected_files=_selected_file_metadata(plan.selected),
|
|
336
358
|
)
|
|
337
359
|
excluded_receipts = [r for r in plan.receipts if r.action == "excluded"]
|
|
338
360
|
# Budget-cut: files that scored OK but didn't fit — more useful signal than "score too low"
|
|
@@ -368,6 +390,33 @@ class PackService:
|
|
|
368
390
|
)
|
|
369
391
|
|
|
370
392
|
|
|
393
|
+
def _write_canonical_context(pack: ContextPack, root: Path, out_path: Path) -> None:
|
|
394
|
+
"""Keep .agentpack/context.md fresh even when the target agent writes elsewhere."""
|
|
395
|
+
canonical_path = root / ".agentpack" / "context.md"
|
|
396
|
+
try:
|
|
397
|
+
if out_path.resolve() == canonical_path.resolve():
|
|
398
|
+
return
|
|
399
|
+
except OSError:
|
|
400
|
+
if out_path == canonical_path:
|
|
401
|
+
return
|
|
402
|
+
canonical_path.parent.mkdir(parents=True, exist_ok=True)
|
|
403
|
+
canonical_path.write_text(render_generic(pack), encoding="utf-8")
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def _selected_file_metadata(selected: list[SelectedFile]) -> list[dict[str, Any]]:
|
|
407
|
+
return [
|
|
408
|
+
{
|
|
409
|
+
"path": sf.path,
|
|
410
|
+
"mode": sf.include_mode,
|
|
411
|
+
"score": round(sf.score, 1),
|
|
412
|
+
"why": sf.reasons[0] if sf.reasons else "",
|
|
413
|
+
"reasons": sf.reasons,
|
|
414
|
+
"tokens": _sf_tokens(sf),
|
|
415
|
+
}
|
|
416
|
+
for sf in selected
|
|
417
|
+
]
|
|
418
|
+
|
|
419
|
+
|
|
371
420
|
def _sf_tokens(sf: SelectedFile) -> int:
|
|
372
421
|
if sf.content:
|
|
373
422
|
return estimate_tokens(sf.content)
|
|
@@ -30,6 +30,7 @@ def register(app: typer.Typer) -> None:
|
|
|
30
30
|
state.last_refresh_at = _now_iso()
|
|
31
31
|
state.refresh_count += 1
|
|
32
32
|
state.last_task_hash = _file_hash(root / TASK_FILE)
|
|
33
|
+
state.last_resolved_agent = state.agent
|
|
33
34
|
save_session(root, state)
|
|
34
35
|
log_activity(root, f"claude cmd — {result['files']} files, {result['tokens']:,} tokens")
|
|
35
36
|
else:
|
|
@@ -8,6 +8,7 @@ from agentpack.core.ignore import load_spec
|
|
|
8
8
|
from agentpack.core.scanner import scan
|
|
9
9
|
from agentpack.core.snapshot import build_snapshot, load_snapshot
|
|
10
10
|
from agentpack.core.diff import diff_snapshots
|
|
11
|
+
from agentpack.application.pack_service import AdapterRegistry
|
|
11
12
|
from agentpack.commands._shared import console, _root
|
|
12
13
|
|
|
13
14
|
|
|
@@ -19,7 +20,12 @@ def register(app: typer.Typer) -> None:
|
|
|
19
20
|
cfg = load_config(root)
|
|
20
21
|
ignore_spec = load_spec(root / cfg.project.ignore_file)
|
|
21
22
|
|
|
22
|
-
scan_result = scan(
|
|
23
|
+
scan_result = scan(
|
|
24
|
+
root,
|
|
25
|
+
ignore_spec,
|
|
26
|
+
cfg.context.max_file_tokens,
|
|
27
|
+
always_skip_paths=AdapterRegistry.generated_output_paths(root, cfg),
|
|
28
|
+
)
|
|
23
29
|
current = build_snapshot(scan_result.packable)
|
|
24
30
|
previous = load_snapshot(root)
|
|
25
31
|
result = diff_snapshots(previous, current)
|
|
@@ -16,6 +16,7 @@ from agentpack.integrations.global_install import (
|
|
|
16
16
|
_detect_rc_file,
|
|
17
17
|
)
|
|
18
18
|
from agentpack.commands._shared import console, _root
|
|
19
|
+
from agentpack.core.context_pack import load_pack_metadata
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
def register(app: typer.Typer) -> None:
|
|
@@ -104,11 +105,11 @@ def register(app: typer.Typer) -> None:
|
|
|
104
105
|
return
|
|
105
106
|
|
|
106
107
|
config_path = root / ".agentpack" / "config.toml"
|
|
107
|
-
context_path = root / ".agentpack" / "context.claude.md"
|
|
108
108
|
if not config_path.exists():
|
|
109
109
|
console.print(f" [yellow]![/] Not initialized in {root} — run: agentpack init")
|
|
110
110
|
else:
|
|
111
111
|
console.print(" [green]✓[/] .agentpack/config.toml present")
|
|
112
|
+
context_path = _latest_context_path(root)
|
|
112
113
|
if context_path.exists():
|
|
113
114
|
import time
|
|
114
115
|
age = time.time() - context_path.stat().st_mtime
|
|
@@ -216,6 +217,16 @@ def register(app: typer.Typer) -> None:
|
|
|
216
217
|
if not _local_has_mcp and not _global_has_mcp:
|
|
217
218
|
console.print(" [yellow]![/] MCP server not registered — mcp__agentpack__* tools unavailable")
|
|
218
219
|
|
|
220
|
+
# --- Release hygiene ---
|
|
221
|
+
console.print("\n[bold]Release hygiene[/]")
|
|
222
|
+
findings = _release_hygiene_findings(root)
|
|
223
|
+
if findings:
|
|
224
|
+
for finding in findings:
|
|
225
|
+
console.print(f" [yellow]![/] {finding}")
|
|
226
|
+
ok = False
|
|
227
|
+
else:
|
|
228
|
+
console.print(" [green]✓[/] no generated release-noise files staged or untracked")
|
|
229
|
+
|
|
219
230
|
# --- Slash command ---
|
|
220
231
|
console.print("\n[bold]Slash command (/agentpack)[/]")
|
|
221
232
|
local_cmd = root / ".claude" / "commands" / "agentpack.md"
|
|
@@ -244,6 +255,23 @@ def _check_agent_file(root: Path, filename: str, agent: str) -> None:
|
|
|
244
255
|
console.print(f" [dim]-[/] {filename} not present (optional)")
|
|
245
256
|
|
|
246
257
|
|
|
258
|
+
def _latest_context_path(root: Path) -> Path:
|
|
259
|
+
meta = load_pack_metadata(root)
|
|
260
|
+
if meta and meta.get("context_path"):
|
|
261
|
+
candidate = root / str(meta["context_path"])
|
|
262
|
+
if candidate.exists():
|
|
263
|
+
return candidate
|
|
264
|
+
for rel in (
|
|
265
|
+
".agentpack/context.md",
|
|
266
|
+
".agentpack/context.claude.md",
|
|
267
|
+
".agent/skills/agentpack/SKILL.md",
|
|
268
|
+
):
|
|
269
|
+
candidate = root / rel
|
|
270
|
+
if candidate.exists():
|
|
271
|
+
return candidate
|
|
272
|
+
return root / ".agentpack" / "context.md"
|
|
273
|
+
|
|
274
|
+
|
|
247
275
|
def _source_checkout_warning(
|
|
248
276
|
root: Path,
|
|
249
277
|
package_file: Path,
|
|
@@ -268,6 +296,51 @@ def _source_checkout_warning(
|
|
|
268
296
|
)
|
|
269
297
|
|
|
270
298
|
|
|
299
|
+
_RELEASE_NOISE_PREFIXES = (
|
|
300
|
+
".agent/",
|
|
301
|
+
".agentpack/",
|
|
302
|
+
".claude/worktrees/",
|
|
303
|
+
".codex/",
|
|
304
|
+
".cursor/",
|
|
305
|
+
".vscode/",
|
|
306
|
+
)
|
|
307
|
+
_RELEASE_NOISE_FILES = {".coverage"}
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def _release_hygiene_findings(root: Path) -> list[str]:
|
|
311
|
+
"""Flag local generated artifacts that should not be staged or released."""
|
|
312
|
+
try:
|
|
313
|
+
result = subprocess.run(
|
|
314
|
+
["git", "status", "--short"],
|
|
315
|
+
cwd=root,
|
|
316
|
+
capture_output=True,
|
|
317
|
+
text=True,
|
|
318
|
+
timeout=5,
|
|
319
|
+
)
|
|
320
|
+
except (OSError, subprocess.TimeoutExpired):
|
|
321
|
+
return ["could not inspect git status for release hygiene"]
|
|
322
|
+
if result.returncode != 0:
|
|
323
|
+
return []
|
|
324
|
+
|
|
325
|
+
noisy: list[str] = []
|
|
326
|
+
for raw in result.stdout.splitlines():
|
|
327
|
+
if not raw.strip():
|
|
328
|
+
continue
|
|
329
|
+
status = raw[:2].strip() or "modified"
|
|
330
|
+
path = raw[3:].strip()
|
|
331
|
+
if " -> " in path:
|
|
332
|
+
path = path.rsplit(" -> ", 1)[1]
|
|
333
|
+
norm = path.replace("\\", "/")
|
|
334
|
+
if norm in _RELEASE_NOISE_FILES or any(norm.startswith(prefix) for prefix in _RELEASE_NOISE_PREFIXES):
|
|
335
|
+
noisy.append(f"{status} {norm}")
|
|
336
|
+
|
|
337
|
+
if not noisy:
|
|
338
|
+
return []
|
|
339
|
+
sample = ", ".join(noisy[:8])
|
|
340
|
+
extra = f", ... {len(noisy) - 8} more" if len(noisy) > 8 else ""
|
|
341
|
+
return [f"generated/local artifacts present: {sample}{extra}"]
|
|
342
|
+
|
|
343
|
+
|
|
271
344
|
def _print_summary(ok: bool) -> None:
|
|
272
345
|
console.print("")
|
|
273
346
|
if ok:
|
|
@@ -10,6 +10,7 @@ from agentpack.core.context_pack import select_files
|
|
|
10
10
|
from agentpack.commands._shared import console, _root
|
|
11
11
|
from agentpack.commands.pack import _resolve_task
|
|
12
12
|
from agentpack.core.config import load_config, ScoringWeights
|
|
13
|
+
from agentpack.analysis.ranking import extract_keyword_weights, generic_task_term_ratio, _GENERIC_TASK_TERMS
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
def _resolve_signal_weight(reason: str, weights: ScoringWeights) -> float:
|
|
@@ -111,6 +112,50 @@ def _print_file_detail(
|
|
|
111
112
|
console.print()
|
|
112
113
|
|
|
113
114
|
|
|
115
|
+
def _noise_report(task: str, plan: object) -> list[str]:
|
|
116
|
+
keyword_weights = extract_keyword_weights(task)
|
|
117
|
+
generic_terms = sorted(term for term in keyword_weights if term in _GENERIC_TASK_TERMS)
|
|
118
|
+
specific_terms = sorted(term for term in keyword_weights if term not in _GENERIC_TASK_TERMS)
|
|
119
|
+
selected = list(plan.selected) # type: ignore[attr-defined]
|
|
120
|
+
summary_count = sum(1 for sf in selected if sf.include_mode == "summary")
|
|
121
|
+
filename_count = sum(1 for sf in selected if "filename keyword match" in sf.reasons)
|
|
122
|
+
symbol_count = sum(1 for sf in selected if "symbol keyword match" in sf.reasons)
|
|
123
|
+
excluded = [r for r in plan.receipts if r.action == "excluded"] # type: ignore[attr-defined]
|
|
124
|
+
summary_cap = sum(1 for r in excluded if r.reason == "summary cap reached")
|
|
125
|
+
score_floor = sum(1 for r in excluded if r.reason == "summary score below floor")
|
|
126
|
+
|
|
127
|
+
lines = [
|
|
128
|
+
"## Pack noise report",
|
|
129
|
+
"",
|
|
130
|
+
f"- generic task ratio: {generic_task_term_ratio(task):.0%}",
|
|
131
|
+
f"- generic terms: {', '.join(generic_terms) if generic_terms else '(none)'}",
|
|
132
|
+
f"- specific terms: {', '.join(specific_terms) if specific_terms else '(none)'}",
|
|
133
|
+
f"- selected summaries: {summary_count}/{len(selected)}",
|
|
134
|
+
f"- filename-match selections: {filename_count}/{len(selected)}",
|
|
135
|
+
f"- symbol-match selections: {symbol_count}/{len(selected)}",
|
|
136
|
+
f"- excluded by summary cap: {summary_cap}",
|
|
137
|
+
f"- excluded by weak summary score: {score_floor}",
|
|
138
|
+
"",
|
|
139
|
+
"### Sharpen task wording",
|
|
140
|
+
"",
|
|
141
|
+
]
|
|
142
|
+
if generic_terms:
|
|
143
|
+
lines.append("- Replace broad terms with subsystem, file, or symptom words.")
|
|
144
|
+
lines.append(f"- Broad terms driving matches: {', '.join(generic_terms[:8])}.")
|
|
145
|
+
else:
|
|
146
|
+
lines.append("- Task terms are already specific; inspect changed files or score weights next.")
|
|
147
|
+
if summary_count and selected and summary_count / len(selected) >= 0.7:
|
|
148
|
+
lines.append("- Try `--mode minimal` for edit work, or add exact module/file names.")
|
|
149
|
+
if filename_count and selected and filename_count / len(selected) >= 0.6:
|
|
150
|
+
lines.append("- Filename matches dominate; add behavior words that appear inside target files.")
|
|
151
|
+
return lines
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _print_noise_report(task: str, plan: object) -> None:
|
|
155
|
+
for line in _noise_report(task, plan):
|
|
156
|
+
console.print(line)
|
|
157
|
+
|
|
158
|
+
|
|
114
159
|
def register(app: typer.Typer) -> None:
|
|
115
160
|
@app.command()
|
|
116
161
|
def explain(
|
|
@@ -120,6 +165,7 @@ def register(app: typer.Typer) -> None:
|
|
|
120
165
|
since: Optional[str] = typer.Option(None, "--since", help="Git ref to compare against (e.g. HEAD~1, main)."),
|
|
121
166
|
file: Optional[str] = typer.Option(None, "--file", help="Show detailed score breakdown for a specific file."),
|
|
122
167
|
omitted: bool = typer.Option(False, "--omitted", is_flag=True, help="Show top-10 excluded files and why."),
|
|
168
|
+
why_noisy: bool = typer.Option(False, "--why-noisy", is_flag=True, help="Explain broad task terms and noisy selection signals."),
|
|
123
169
|
) -> None:
|
|
124
170
|
"""Explain which files would be selected and why, without writing a context file."""
|
|
125
171
|
if mode not in ("minimal", "balanced", "deep"):
|
|
@@ -199,6 +245,12 @@ def register(app: typer.Typer) -> None:
|
|
|
199
245
|
console.print()
|
|
200
246
|
return
|
|
201
247
|
|
|
248
|
+
if why_noisy:
|
|
249
|
+
console.print(f"\n[bold]Task:[/] [cyan]{resolved_task}[/] [dim]mode={mode} budget={plan.budget:,}[/]\n")
|
|
250
|
+
_print_noise_report(resolved_task, plan)
|
|
251
|
+
console.print()
|
|
252
|
+
return
|
|
253
|
+
|
|
202
254
|
console.print(f"\n[bold]Task:[/] [cyan]{resolved_task}[/] [dim]mode={mode} budget={plan.budget:,}[/]\n")
|
|
203
255
|
|
|
204
256
|
console.print("[bold]Top selected files (ranked):[/]")
|