agentpack-cli 0.3.0__tar.gz → 0.3.1__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.
Files changed (93) hide show
  1. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/.gitignore +5 -1
  2. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/PKG-INFO +29 -10
  3. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/README.md +28 -9
  4. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/pyproject.toml +1 -1
  5. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/__init__.py +1 -1
  6. agentpack_cli-0.3.1/src/agentpack/commands/init.py +408 -0
  7. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/install.py +6 -11
  8. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/pack.py +1 -1
  9. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/data/agentpack.md +1 -1
  10. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/mcp_server.py +1 -1
  11. agentpack_cli-0.3.0/src/agentpack/commands/init.py +0 -186
  12. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/LICENSE +0 -0
  13. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/adapters/__init__.py +0 -0
  14. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/adapters/antigravity.py +0 -0
  15. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/adapters/base.py +0 -0
  16. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/adapters/claude.py +0 -0
  17. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/adapters/codex.py +0 -0
  18. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/adapters/cursor.py +0 -0
  19. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/adapters/detect.py +0 -0
  20. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/adapters/generic.py +0 -0
  21. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/adapters/windsurf.py +0 -0
  22. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/__init__.py +0 -0
  23. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/dependency_graph.py +0 -0
  24. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/go_imports.py +0 -0
  25. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/java_imports.py +0 -0
  26. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/js_ts_imports.py +0 -0
  27. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/monorepo.py +0 -0
  28. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/python_imports.py +0 -0
  29. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/ranking.py +0 -0
  30. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/repo_map.py +0 -0
  31. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/role_inference.py +0 -0
  32. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/rust_imports.py +0 -0
  33. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/symbols.py +0 -0
  34. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/task_classifier.py +0 -0
  35. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/analysis/tests.py +0 -0
  36. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/application/__init__.py +0 -0
  37. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/application/pack_service.py +0 -0
  38. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/cli.py +0 -0
  39. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/__init__.py +0 -0
  40. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/_shared.py +0 -0
  41. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/benchmark.py +0 -0
  42. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/claude_cmd.py +0 -0
  43. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/diff.py +0 -0
  44. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/doctor.py +0 -0
  45. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/explain.py +0 -0
  46. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/hook_cmd.py +0 -0
  47. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/mcp_cmd.py +0 -0
  48. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/monitor.py +0 -0
  49. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/quickstart.py +0 -0
  50. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/repair.py +0 -0
  51. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/scan.py +0 -0
  52. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/stats.py +0 -0
  53. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/status.py +0 -0
  54. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/summarize.py +0 -0
  55. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/tune.py +0 -0
  56. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/commands/watch.py +0 -0
  57. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/__init__.py +0 -0
  58. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/bootstrap.py +0 -0
  59. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/cache.py +0 -0
  60. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/config.py +0 -0
  61. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/context_pack.py +0 -0
  62. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/diff.py +0 -0
  63. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/git.py +0 -0
  64. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/git_hooks.py +0 -0
  65. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/global_install.py +0 -0
  66. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/ignore.py +0 -0
  67. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/merkle.py +0 -0
  68. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/models.py +0 -0
  69. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/redactor.py +0 -0
  70. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/scanner.py +0 -0
  71. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/snapshot.py +0 -0
  72. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/token_estimator.py +0 -0
  73. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/core/vscode_tasks.py +0 -0
  74. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/installers/__init__.py +0 -0
  75. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/installers/antigravity.py +0 -0
  76. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/installers/claude.py +0 -0
  77. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/installers/codex.py +0 -0
  78. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/installers/cursor.py +0 -0
  79. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/installers/windsurf.py +0 -0
  80. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/integrations/__init__.py +0 -0
  81. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/integrations/agents.py +0 -0
  82. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/integrations/git_hooks.py +0 -0
  83. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/integrations/global_install.py +0 -0
  84. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/integrations/vscode_tasks.py +0 -0
  85. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/renderers/__init__.py +0 -0
  86. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/renderers/compact.py +0 -0
  87. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/renderers/markdown.py +0 -0
  88. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/renderers/receipts.py +0 -0
  89. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/session/__init__.py +0 -0
  90. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/session/state.py +0 -0
  91. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/summaries/__init__.py +0 -0
  92. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/summaries/base.py +0 -0
  93. {agentpack_cli-0.3.0 → agentpack_cli-0.3.1}/src/agentpack/summaries/offline.py +0 -0
@@ -12,6 +12,8 @@ env/
12
12
 
13
13
  # agentpack:start
14
14
  # AgentPack generated context/cache (safe to ignore)
15
+ .agentpack/*
16
+ !.agentpack/config.toml
15
17
  .agentpack/cache/
16
18
  .agentpack/snapshots/
17
19
  .agentpack/context*
@@ -23,9 +25,11 @@ env/
23
25
  .agentpack/session.json
24
26
  .agentpack/task.md
25
27
  .agentpack/benchmark_results.jsonl
28
+ .agentignore
26
29
  .agent/skills/agentpack/
30
+ .vscode/tasks.json
31
+ GEMINI.md
27
32
  # agentpack:end
28
-
29
33
  .pytest_cache/
30
34
  .mypy_cache/
31
35
  .ruff_cache/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentpack-cli
3
- Version: 0.3.0
3
+ Version: 0.3.1
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
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
45
45
  [![CI](https://github.com/vishal2612200/agentpack/actions/workflows/ci.yml/badge.svg)](https://github.com/vishal2612200/agentpack/actions/workflows/ci.yml)
46
46
 
47
- > **Status: alpha (v0.3.0).** Works, tested, used in real sessions. Python and JavaScript/TypeScript are the best-supported languages. Public benchmark proof exists for the current suite, but broader repo coverage is still growing. API may change before 1.0.
47
+ > **Status: alpha (v0.3.1).** Works, tested, used in real sessions. Python and JavaScript/TypeScript are the best-supported languages. Public benchmark proof exists for the current suite, but broader repo coverage is still growing. 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
 
@@ -80,11 +80,30 @@ AgentPack is useful when a repo is too large to paste, but a blank agent session
80
80
  ## Install
81
81
 
82
82
  ```bash
83
- pip install agentpack-cli
83
+ pipx install agentpack-cli
84
84
  agentpack --version
85
85
  ```
86
86
 
87
- Requires Python 3.10+. The PyPI package is `agentpack-cli`; the command is `agentpack`.
87
+ Requires Python 3.10+. The PyPI package is `agentpack-cli`; the command is `agentpack`. Use `pipx` for normal installs because many macOS/Linux Python distributions block global `pip install` with PEP 668's `externally-managed-environment` error. If you prefer `pip`, install inside a virtual environment.
88
+
89
+ Install `pipx` with your OS package manager first if needed:
90
+
91
+ ```bash
92
+ # macOS
93
+ brew install pipx
94
+
95
+ # Ubuntu/Debian
96
+ sudo apt install pipx
97
+
98
+ # Fedora
99
+ sudo dnf install pipx
100
+
101
+ # Arch
102
+ sudo pacman -S python-pipx
103
+
104
+ # Then ensure pipx apps are on PATH
105
+ pipx ensurepath
106
+ ```
88
107
 
89
108
  JavaScript-heavy teams can install the npm wrapper:
90
109
 
@@ -454,7 +473,7 @@ jobs:
454
473
  with:
455
474
  python-version: "3.12"
456
475
 
457
- - run: pip install agentpack-cli
476
+ - run: python -m pip install agentpack-cli
458
477
 
459
478
  - name: Generate context pack
460
479
  run: |
@@ -767,7 +786,7 @@ Uses `watchdog` if installed, falls back to polling. Context is refreshed whenev
767
786
 
768
787
  Install watchdog for better performance:
769
788
  ```bash
770
- pip install "agentpack-cli[watch]"
789
+ pipx inject agentpack-cli watchdog
771
790
  ```
772
791
 
773
792
  ---
@@ -789,7 +808,7 @@ Requires an initialized project (`agentpack init`). Refreshes context, prints th
789
808
  Run AgentPack as an MCP server — exposes context packing as tools that Claude Code (and any MCP-compatible agent) can call directly.
790
809
 
791
810
  ```bash
792
- pip install "agentpack-cli[mcp]"
811
+ pipx inject agentpack-cli "agentpack-cli[mcp]"
793
812
  agentpack mcp
794
813
  ```
795
814
 
@@ -1464,9 +1483,9 @@ Post-0.3 release focus: broader real-repo proof, npm publish reliability, and co
1464
1483
  ## Optional dependencies
1465
1484
 
1466
1485
  ```bash
1467
- pip install "agentpack-cli[watch]" # watchdog faster file watching for agentpack watch
1468
- pip install "agentpack-cli[mcp]" # mcp — expose agentpack as MCP server tools
1469
- pip install "agentpack-cli[all]" # watch + mcp
1486
+ pipx inject agentpack-cli watchdog # faster file watching for agentpack watch
1487
+ pipx inject agentpack-cli "agentpack-cli[mcp]" # expose agentpack as MCP server tools
1488
+ pipx inject agentpack-cli "agentpack-cli[all]" # watch + mcp
1470
1489
  ```
1471
1490
 
1472
1491
  ---
@@ -5,7 +5,7 @@
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
6
  [![CI](https://github.com/vishal2612200/agentpack/actions/workflows/ci.yml/badge.svg)](https://github.com/vishal2612200/agentpack/actions/workflows/ci.yml)
7
7
 
8
- > **Status: alpha (v0.3.0).** Works, tested, used in real sessions. Python and JavaScript/TypeScript are the best-supported languages. Public benchmark proof exists for the current suite, but broader repo coverage is still growing. API may change before 1.0.
8
+ > **Status: alpha (v0.3.1).** Works, tested, used in real sessions. Python and JavaScript/TypeScript are the best-supported languages. Public benchmark proof exists for the current suite, but broader repo coverage is still growing. 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
 
@@ -41,11 +41,30 @@ AgentPack is useful when a repo is too large to paste, but a blank agent session
41
41
  ## Install
42
42
 
43
43
  ```bash
44
- pip install agentpack-cli
44
+ pipx install agentpack-cli
45
45
  agentpack --version
46
46
  ```
47
47
 
48
- Requires Python 3.10+. The PyPI package is `agentpack-cli`; the command is `agentpack`.
48
+ Requires Python 3.10+. The PyPI package is `agentpack-cli`; the command is `agentpack`. Use `pipx` for normal installs because many macOS/Linux Python distributions block global `pip install` with PEP 668's `externally-managed-environment` error. If you prefer `pip`, install inside a virtual environment.
49
+
50
+ Install `pipx` with your OS package manager first if needed:
51
+
52
+ ```bash
53
+ # macOS
54
+ brew install pipx
55
+
56
+ # Ubuntu/Debian
57
+ sudo apt install pipx
58
+
59
+ # Fedora
60
+ sudo dnf install pipx
61
+
62
+ # Arch
63
+ sudo pacman -S python-pipx
64
+
65
+ # Then ensure pipx apps are on PATH
66
+ pipx ensurepath
67
+ ```
49
68
 
50
69
  JavaScript-heavy teams can install the npm wrapper:
51
70
 
@@ -415,7 +434,7 @@ jobs:
415
434
  with:
416
435
  python-version: "3.12"
417
436
 
418
- - run: pip install agentpack-cli
437
+ - run: python -m pip install agentpack-cli
419
438
 
420
439
  - name: Generate context pack
421
440
  run: |
@@ -728,7 +747,7 @@ Uses `watchdog` if installed, falls back to polling. Context is refreshed whenev
728
747
 
729
748
  Install watchdog for better performance:
730
749
  ```bash
731
- pip install "agentpack-cli[watch]"
750
+ pipx inject agentpack-cli watchdog
732
751
  ```
733
752
 
734
753
  ---
@@ -750,7 +769,7 @@ Requires an initialized project (`agentpack init`). Refreshes context, prints th
750
769
  Run AgentPack as an MCP server — exposes context packing as tools that Claude Code (and any MCP-compatible agent) can call directly.
751
770
 
752
771
  ```bash
753
- pip install "agentpack-cli[mcp]"
772
+ pipx inject agentpack-cli "agentpack-cli[mcp]"
754
773
  agentpack mcp
755
774
  ```
756
775
 
@@ -1425,9 +1444,9 @@ Post-0.3 release focus: broader real-repo proof, npm publish reliability, and co
1425
1444
  ## Optional dependencies
1426
1445
 
1427
1446
  ```bash
1428
- pip install "agentpack-cli[watch]" # watchdog faster file watching for agentpack watch
1429
- pip install "agentpack-cli[mcp]" # mcp — expose agentpack as MCP server tools
1430
- pip install "agentpack-cli[all]" # watch + mcp
1447
+ pipx inject agentpack-cli watchdog # faster file watching for agentpack watch
1448
+ pipx inject agentpack-cli "agentpack-cli[mcp]" # expose agentpack as MCP server tools
1449
+ pipx inject agentpack-cli "agentpack-cli[all]" # watch + mcp
1431
1450
  ```
1432
1451
 
1433
1452
  ---
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentpack-cli"
3
- version = "0.3.0"
3
+ version = "0.3.1"
4
4
  description = "Task-aware context packing for AI coding agents — Claude, Cursor, Windsurf, Codex, and Antigravity"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -1,3 +1,3 @@
1
1
  """AgentPack — task-aware context packing for AI coding agents."""
2
2
 
3
- __version__ = "0.3.0"
3
+ __version__ = "0.3.1"
@@ -0,0 +1,408 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from dataclasses import dataclass
5
+ from pathlib import Path
6
+ from typing import Optional
7
+
8
+ import typer
9
+
10
+ from agentpack.core.config import DEFAULT_CONFIG, CONFIG_TEMPLATE
11
+ from agentpack.core.ignore import DEFAULT_AGENTIGNORE
12
+ from agentpack.commands._shared import console, _root
13
+ from agentpack.integrations.agents import check_agent_integration, install_agent_integration
14
+ from agentpack.session.state import load_session, create_session, SESSION_FILE, TASK_FILE
15
+
16
+ _GITIGNORE_START = "# agentpack:start"
17
+ _GITIGNORE_END = "# agentpack:end"
18
+ _INIT_MODES = ("minimal", "balanced", "deep")
19
+ _INIT_AGENTS = ("auto", "claude", "cursor", "windsurf", "codex", "antigravity", "generic")
20
+ _AGENT_GITIGNORE_ENTRIES = {
21
+ "cursor": (".vscode/tasks.json",),
22
+ "windsurf": (".vscode/tasks.json",),
23
+ "antigravity": (".agent/skills/agentpack/", ".vscode/tasks.json", "GEMINI.md"),
24
+ }
25
+
26
+
27
+ @dataclass
28
+ class InitResult:
29
+ path: str
30
+ action: str
31
+
32
+
33
+ @dataclass
34
+ class InitHealth:
35
+ label: str
36
+ ok: bool
37
+ detail: str
38
+
39
+
40
+ def _repo_gitignore_entries(share_cache: bool = False, agent: str = "generic") -> list[str]:
41
+ entries = [
42
+ ".agentpack/*",
43
+ "!.agentpack/config.toml",
44
+ ]
45
+ if share_cache:
46
+ entries.extend(["!.agentpack/cache/", "!.agentpack/cache/**"])
47
+ else:
48
+ entries.append(".agentpack/cache/")
49
+ entries.extend(
50
+ [
51
+ ".agentpack/snapshots/",
52
+ ".agentpack/context*",
53
+ ".agentpack/metrics.jsonl",
54
+ ".agentpack/pack_metadata.json",
55
+ ".agentpack/activity.log",
56
+ ".agentpack/.gitignore",
57
+ ".agentpack/.mcp_reminded",
58
+ ".agentpack/session.json",
59
+ ".agentpack/task.md",
60
+ ".agentpack/benchmark_results.jsonl",
61
+ ".agentignore",
62
+ ]
63
+ )
64
+ entries.extend(_AGENT_GITIGNORE_ENTRIES.get(agent, ()))
65
+ return entries
66
+
67
+
68
+ def _repo_gitignore_block(share_cache: bool = False, agent: str = "generic") -> str:
69
+ return (
70
+ f"{_GITIGNORE_START}\n"
71
+ "# AgentPack generated context/cache (safe to ignore)\n"
72
+ + "\n".join(_repo_gitignore_entries(share_cache, agent))
73
+ + "\n"
74
+ f"{_GITIGNORE_END}\n"
75
+ )
76
+
77
+
78
+ def _agentpack_gitignore_content(share_cache: bool = False) -> str:
79
+ entries = []
80
+ if not share_cache:
81
+ entries.append("cache/")
82
+ entries.extend(
83
+ [
84
+ "snapshots/",
85
+ "context.*",
86
+ "metrics.jsonl",
87
+ "pack_metadata.json",
88
+ "activity.log",
89
+ ".mcp_reminded",
90
+ "session.json",
91
+ "task.md",
92
+ "benchmark_results.jsonl",
93
+ ]
94
+ )
95
+ return "\n".join(entries) + "\n"
96
+
97
+
98
+ def _backup_file(path: Path) -> Path:
99
+ backup = path.with_name(f"{path.name}.bak")
100
+ index = 1
101
+ while backup.exists():
102
+ backup = path.with_name(f"{path.name}.bak.{index}")
103
+ index += 1
104
+ backup.write_text(path.read_text(encoding="utf-8"), encoding="utf-8")
105
+ return backup
106
+
107
+
108
+ def _write_text(root: Path, path: Path, content: str, *, force: bool = False, backups: list[InitResult] | None = None) -> str:
109
+ existed = path.exists()
110
+ if existed and path.read_text(encoding="utf-8") == content:
111
+ return "unchanged"
112
+ if force and existed and backups is not None:
113
+ backup = _backup_file(path)
114
+ backups.append(InitResult(str(backup.relative_to(root)), "created"))
115
+ path.parent.mkdir(parents=True, exist_ok=True)
116
+ path.write_text(content, encoding="utf-8")
117
+ return "updated" if existed else "created"
118
+
119
+
120
+ def _patch_repo_gitignore(root: Path, share_cache: bool = False, agent: str = "generic", *, force: bool = False, backups: list[InitResult] | None = None) -> str:
121
+ gitignore = root / ".gitignore"
122
+ block = _repo_gitignore_block(share_cache, agent)
123
+ if not gitignore.exists():
124
+ gitignore.write_text(block, encoding="utf-8")
125
+ return "created"
126
+
127
+ content = gitignore.read_text(encoding="utf-8")
128
+ start = content.find(_GITIGNORE_START)
129
+ end = content.find(_GITIGNORE_END)
130
+ if start != -1 and end != -1 and end >= start:
131
+ end += len(_GITIGNORE_END)
132
+ replacement = block.rstrip()
133
+ updated = content[:start].rstrip() + "\n\n" + replacement + "\n" + content[end:].lstrip("\n")
134
+ if updated == content:
135
+ return "unchanged"
136
+ if force and backups is not None:
137
+ backup = _backup_file(gitignore)
138
+ backups.append(InitResult(str(backup.relative_to(root)), "created"))
139
+ gitignore.write_text(updated, encoding="utf-8")
140
+ return "updated"
141
+
142
+ prefix = content.rstrip() + "\n\n" if content.strip() else ""
143
+ if force and backups is not None:
144
+ backup = _backup_file(gitignore)
145
+ backups.append(InitResult(str(backup.relative_to(root)), "created"))
146
+ gitignore.write_text(prefix + block, encoding="utf-8")
147
+ return "updated"
148
+
149
+
150
+ def _install_agent_integration(root, agent: str) -> dict[str, str]:
151
+ """Install repo-local agent integration files after `agentpack init`."""
152
+ return install_agent_integration(root, agent)
153
+
154
+
155
+ def _print_agent_integration_results(results: dict[str, str]) -> None:
156
+ for key, action in results.items():
157
+ if action == "unchanged":
158
+ continue
159
+ if key.startswith("git:"):
160
+ console.print(f"[green].git/hooks/{key[4:]} {action}[/]")
161
+ elif key == "vscode:tasks":
162
+ console.print(f"[green].vscode/tasks.json {action}[/]")
163
+ else:
164
+ console.print(f"[green]{key} {action}[/]")
165
+
166
+
167
+ def _validate_init_options(agent: str, mode: str | None, budget: int) -> None:
168
+ if agent not in _INIT_AGENTS:
169
+ console.print(f"[yellow]Unknown agent: {agent}. Supported: {', '.join(_INIT_AGENTS)}[/]")
170
+ raise typer.Exit(1)
171
+ if mode is not None and mode not in _INIT_MODES:
172
+ console.print(f"[yellow]Unknown mode: {mode}. Supported: {', '.join(_INIT_MODES)}[/]")
173
+ raise typer.Exit(1)
174
+ if budget < 0:
175
+ console.print("[yellow]Budget must be 0 or greater.[/]")
176
+ raise typer.Exit(1)
177
+
178
+
179
+ def _resolve_init_agent(root: Path, agent: str, *, force: bool = False) -> str:
180
+ if agent != "auto":
181
+ return agent
182
+ existing_session = load_session(root)
183
+ if existing_session is not None and not force:
184
+ return existing_session.agent
185
+ from agentpack.adapters.detect import detect_agent
186
+
187
+ return detect_agent(root)
188
+
189
+
190
+ def _agent_integration_paths(agent: str) -> tuple[str, ...]:
191
+ if agent == "claude":
192
+ return ("CLAUDE.md", ".claude/settings.json", ".mcp.json")
193
+ if agent == "cursor":
194
+ return (".cursorrules", ".cursor/rules/agentpack.mdc", ".vscode/tasks.json")
195
+ if agent == "windsurf":
196
+ return (".windsurfrules", ".vscode/tasks.json")
197
+ if agent == "codex":
198
+ return ("AGENTS.md", ".codex/hooks.json")
199
+ if agent == "antigravity":
200
+ return ("GEMINI.md", ".vscode/tasks.json")
201
+ return ()
202
+
203
+
204
+ def _backup_existing_paths(root: Path, paths: tuple[str, ...], backups: list[InitResult]) -> None:
205
+ for rel in paths:
206
+ path = root / rel
207
+ if path.exists() and path.is_file():
208
+ backup = _backup_file(path)
209
+ backups.append(InitResult(str(backup.relative_to(root)), "created"))
210
+
211
+
212
+ def _planned_action(path: Path, expected: str | None = None) -> str:
213
+ if not path.exists():
214
+ return "create"
215
+ if expected is None:
216
+ return "update"
217
+ try:
218
+ return "unchanged" if path.read_text(encoding="utf-8") == expected else "update"
219
+ except OSError:
220
+ return "update"
221
+
222
+
223
+ def _print_dry_run(root: Path, agent: str, share_cache: bool, mode: str | None, budget: int) -> None:
224
+ console.print("[bold yellow]Dry run — no files will be changed.[/]\n")
225
+ items = [
226
+ InitResult(".agentpack/", "ensure"),
227
+ InitResult(".agentpack/snapshots/", "ensure"),
228
+ InitResult(".agentpack/cache/", "ensure"),
229
+ InitResult(".agentpack/.gitignore", _planned_action(root / ".agentpack" / ".gitignore")),
230
+ InitResult(".gitignore", _planned_action(root / ".gitignore")),
231
+ InitResult(".agentpack/config.toml", _planned_action(root / ".agentpack" / "config.toml")),
232
+ InitResult(".agentignore", _planned_action(root / ".agentignore", DEFAULT_AGENTIGNORE)),
233
+ InitResult(SESSION_FILE, _planned_action(root / SESSION_FILE)),
234
+ InitResult(TASK_FILE, _planned_action(root / TASK_FILE)),
235
+ ]
236
+ for rel in _agent_integration_paths(agent):
237
+ items.append(InitResult(rel, _planned_action(root / rel)))
238
+ _print_init_summary("Dry Run", items)
239
+ console.print(f" Agent: {agent}")
240
+ console.print(f" Mode: {mode or DEFAULT_CONFIG.context.default_mode}")
241
+ console.print(f" Budget: {budget or DEFAULT_CONFIG.context.default_budget:,}")
242
+ console.print(f" Share cache: {'yes' if share_cache else 'no'}")
243
+
244
+
245
+ def _print_init_summary(title: str, results: list[InitResult]) -> None:
246
+ console.print(f"\n[bold]{title}[/]")
247
+ grouped: dict[str, list[str]] = {}
248
+ for result in results:
249
+ grouped.setdefault(result.action, []).append(result.path)
250
+ for action in ("created", "updated", "unchanged", "skipped", "ensure", "create", "update"):
251
+ paths = grouped.get(action)
252
+ if not paths:
253
+ continue
254
+ console.print(f" {action}: {', '.join(paths)}")
255
+
256
+
257
+ def _init_health(root: Path, agent: str) -> list[InitHealth]:
258
+ checks = [
259
+ InitHealth(".gitignore", (root / ".gitignore").exists(), "repo ignore file present"),
260
+ InitHealth(".agentpack/config.toml", (root / ".agentpack" / "config.toml").exists(), "config file present"),
261
+ InitHealth(".agentignore", (root / ".agentignore").exists(), "agent ignore file present"),
262
+ InitHealth(SESSION_FILE, (root / SESSION_FILE).exists(), "session file present"),
263
+ InitHealth(TASK_FILE, (root / TASK_FILE).exists(), "task file present"),
264
+ ]
265
+ try:
266
+ from agentpack.core.config import load_config
267
+
268
+ load_config(root)
269
+ checks.append(InitHealth("config", True, "loads successfully"))
270
+ except Exception as exc:
271
+ checks.append(InitHealth("config", False, f"failed to load: {exc}"))
272
+ for check in check_agent_integration(root, agent):
273
+ checks.append(InitHealth(check.label, check.ok, check.detail))
274
+ return checks
275
+
276
+
277
+ def _print_health(root: Path, agent: str) -> None:
278
+ console.print("\n[bold]Init health[/]")
279
+ for check in _init_health(root, agent):
280
+ marker = "[green]✓[/]" if check.ok else "[yellow]![/]"
281
+ console.print(f" {marker} {check.label}: {check.detail}")
282
+
283
+
284
+ def register(app: typer.Typer) -> None:
285
+ @app.command()
286
+ def init(
287
+ force: bool = typer.Option(False, "--force", help="Overwrite existing files."),
288
+ mode: Optional[str] = typer.Option(None, "--mode", help="Default pack mode (minimal|balanced|deep)."),
289
+ budget: int = typer.Option(0, "--budget", help="Default token budget (0 = keep default 25000)."),
290
+ yes: bool = typer.Option(False, "--yes", "-y", help="Skip interactive prompts, use defaults."),
291
+ silent: bool = typer.Option(False, "--silent", help="Suppress all output (for use in hooks/scripts)."),
292
+ share_cache: bool = typer.Option(False, "--share-cache", help="Commit summary cache to git (recommended for teams)."),
293
+ agent: str = typer.Option("auto", "--agent", help="Target agent (auto|claude|cursor|windsurf|codex|antigravity|generic)."),
294
+ dry_run: bool = typer.Option(False, "--dry-run", help="Show what would change without writing files."),
295
+ health_check: bool = typer.Option(True, "--health-check/--no-health-check", help="Verify init outputs after setup."),
296
+ ) -> None:
297
+ """Initialize AgentPack in the current directory.
298
+
299
+ One-time setup. After this, just run `agentpack watch` — no other commands needed.
300
+ """
301
+ if silent:
302
+ yes = True
303
+ console.quiet = True
304
+ _validate_init_options(agent, mode, budget)
305
+ root = _root()
306
+ resolved_agent = _resolve_init_agent(root, agent, force=force)
307
+ if dry_run:
308
+ _print_dry_run(root, resolved_agent, share_cache, mode, budget)
309
+ return
310
+
311
+ results: list[InitResult] = []
312
+ backups: list[InitResult] = []
313
+ agentpack_dir = root / ".agentpack"
314
+ agentpack_existed = agentpack_dir.exists()
315
+ snapshots_existed = (agentpack_dir / "snapshots").exists()
316
+ cache_existed = (agentpack_dir / "cache").exists()
317
+ agentpack_dir.mkdir(exist_ok=True)
318
+ (agentpack_dir / "snapshots").mkdir(exist_ok=True)
319
+ (agentpack_dir / "cache").mkdir(exist_ok=True)
320
+ results.extend(
321
+ [
322
+ InitResult(".agentpack/", "unchanged" if agentpack_existed else "created"),
323
+ InitResult(".agentpack/snapshots/", "unchanged" if snapshots_existed else "created"),
324
+ InitResult(".agentpack/cache/", "unchanged" if cache_existed else "created"),
325
+ ]
326
+ )
327
+
328
+ gitignore = agentpack_dir / ".gitignore"
329
+ if not gitignore.exists() or force:
330
+ action = _write_text(root, gitignore, _agentpack_gitignore_content(share_cache), force=force, backups=backups)
331
+ results.append(InitResult(".agentpack/.gitignore", action))
332
+ else:
333
+ results.append(InitResult(".agentpack/.gitignore", "unchanged"))
334
+
335
+ gitignore_action = _patch_repo_gitignore(root, share_cache=share_cache, agent=resolved_agent, force=force, backups=backups)
336
+ results.append(InitResult(".gitignore", gitignore_action))
337
+
338
+ config_path_file = agentpack_dir / "config.toml"
339
+ if not config_path_file.exists() or force:
340
+ cfg = DEFAULT_CONFIG.model_copy(deep=True)
341
+
342
+ # Interactive mode selection
343
+ if not yes and mode is None and sys.stdin.isatty():
344
+ console.print("\n[bold]Choose default pack mode:[/]")
345
+ console.print(" [cyan]1[/] minimal — changed files + configs only (fastest, fewest tokens)")
346
+ console.print(" [cyan]2[/] balanced — + deps, tests, summaries [bold](recommended)[/]")
347
+ console.print(" [cyan]3[/] deep — + docs, more full files (most context)")
348
+ choice = typer.prompt("Mode", default="2")
349
+ mode_map = {"1": "minimal", "2": "balanced", "3": "deep",
350
+ "minimal": "minimal", "balanced": "balanced", "deep": "deep"}
351
+ cfg.context.default_mode = mode_map.get(choice.strip(), "balanced")
352
+ elif mode in ("minimal", "balanced", "deep"):
353
+ cfg.context.default_mode = mode
354
+
355
+ if budget > 0:
356
+ cfg.context.default_budget = budget
357
+
358
+ config_toml = CONFIG_TEMPLATE.replace(
359
+ 'default_mode = "balanced"',
360
+ f'default_mode = "{cfg.context.default_mode}"',
361
+ )
362
+ if budget > 0:
363
+ config_toml = config_toml.replace(
364
+ "default_budget = 25000",
365
+ f"default_budget = {cfg.context.default_budget}",
366
+ )
367
+ action = _write_text(root, config_path_file, config_toml, force=force, backups=backups)
368
+ results.append(InitResult(".agentpack/config.toml", action))
369
+ else:
370
+ results.append(InitResult(".agentpack/config.toml", "unchanged"))
371
+
372
+ ignore_path = root / ".agentignore"
373
+ if not ignore_path.exists() or force:
374
+ action = _write_text(root, ignore_path, DEFAULT_AGENTIGNORE, force=force, backups=backups)
375
+ results.append(InitResult(".agentignore", action))
376
+ else:
377
+ results.append(InitResult(".agentignore", "unchanged"))
378
+
379
+ # Bootstrap session so `agentpack watch` works immediately — no separate `session start` needed
380
+ from agentpack.core.config import load_config
381
+ resolved_mode = load_config(root).context.default_mode
382
+ existing_session = load_session(root)
383
+ if existing_session is None or force:
384
+ create_session(root, agent=resolved_agent, mode=resolved_mode)
385
+ results.append(InitResult(SESSION_FILE, "created" if existing_session is None else "updated"))
386
+ results.append(InitResult(TASK_FILE, "created" if existing_session is None else "updated"))
387
+ else:
388
+ results.append(InitResult(SESSION_FILE, "unchanged"))
389
+ results.append(InitResult(TASK_FILE, "unchanged"))
390
+
391
+ if force:
392
+ _backup_existing_paths(root, _agent_integration_paths(resolved_agent), backups)
393
+ integration_results = _install_agent_integration(root, resolved_agent)
394
+ for key, action in integration_results.items():
395
+ if key.startswith("git:"):
396
+ results.append(InitResult(f".git/hooks/{key[4:]}", action))
397
+ elif key == "vscode:tasks":
398
+ results.append(InitResult(".vscode/tasks.json", action))
399
+ else:
400
+ results.append(InitResult(key, action))
401
+
402
+ if backups:
403
+ _print_init_summary("Backups", backups)
404
+ _print_init_summary("Init Summary", results)
405
+ if health_check:
406
+ _print_health(root, resolved_agent)
407
+ console.print(f"\n[bold green]AgentPack initialized.[/] [dim]agent={resolved_agent} mode={resolved_mode}[/]")
408
+ console.print("Run [bold]agentpack watch[/] to start auto-refreshing context.")
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import sys
4
3
  from pathlib import Path
5
4
 
6
5
  import typer
@@ -129,16 +128,12 @@ def register(app: typer.Typer) -> None:
129
128
  if result.returncode == 0:
130
129
  console.print("[green]agentpack installed globally.[/] Available as `agentpack` in any shell.")
131
130
  else:
132
- console.print("[yellow]pipx install failed. Trying pip install --user...[/]")
133
- result2 = sp.run(
134
- [sys.executable, "-m", "pip", "install", "--user", "agentpack-cli"],
135
- capture_output=True,
136
- text=True,
137
- )
138
- if result2.returncode != 0:
139
- console.print(f"[red]Install failed:[/] {result2.stderr[:200]}")
140
- raise typer.Exit(1)
141
- console.print("[green]Installed via pip --user.[/]")
131
+ console.print("[red]pipx install failed.[/]")
132
+ console.print(result.stderr[:300])
133
+ console.print("Install pipx with your OS package manager, then retry: [bold]pipx ensurepath && pipx install agentpack-cli[/]")
134
+ console.print("Examples: [bold]brew install pipx[/], [bold]sudo apt install pipx[/], [bold]sudo dnf install pipx[/], [bold]sudo pacman -S python-pipx[/].")
135
+ console.print("Avoid global [bold]pip3 install[/] on system-managed Python; PEP 668 may block it.")
136
+ raise typer.Exit(1)
142
137
  elif pipx and dry_run:
143
138
  console.print("[dim]Would run: pipx install agentpack-cli[/]")
144
139
 
@@ -259,7 +259,7 @@ def _pack_watch(
259
259
  from watchdog.events import FileSystemEventHandler
260
260
  except ImportError:
261
261
  console.print("[red]watchdog is required for --watch mode.[/]")
262
- console.print("Install it: [bold]pip install watchdog[/]")
262
+ console.print("Install it: [bold]pipx inject agentpack-cli watchdog[/]")
263
263
  raise typer.Exit(1)
264
264
 
265
265
  root = _root()
@@ -82,7 +82,7 @@ Then read `.agentpack/context.claude.md` in full.
82
82
  ### Step 1: Check agentpack is installed
83
83
 
84
84
  ```bash
85
- agentpack --help 2>/dev/null || pip install agentpack-cli
85
+ agentpack --help 2>/dev/null || pipx install agentpack-cli
86
86
  ```
87
87
 
88
88
  ### Step 2: Initialize if not already done
@@ -419,7 +419,7 @@ def serve() -> None:
419
419
  except ImportError:
420
420
  print(
421
421
  "mcp package required for MCP server. "
422
- "Install: pip install 'agentpack-cli[mcp]'",
422
+ "Install: pipx inject agentpack-cli 'agentpack-cli[mcp]'",
423
423
  file=sys.stderr,
424
424
  )
425
425
  sys.exit(1)
@@ -1,186 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import sys
4
- from typing import Optional
5
-
6
- import typer
7
-
8
- from agentpack.core.config import DEFAULT_CONFIG, CONFIG_TEMPLATE
9
- from agentpack.core.ignore import DEFAULT_AGENTIGNORE
10
- from agentpack.commands._shared import console, _root
11
- from agentpack.integrations.agents import install_agent_integration
12
- from agentpack.session.state import load_session, create_session, SESSION_FILE, TASK_FILE
13
-
14
- _GITIGNORE_START = "# agentpack:start"
15
- _GITIGNORE_END = "# agentpack:end"
16
-
17
-
18
- def _repo_gitignore_block(share_cache: bool = False) -> str:
19
- cache_line = "" if share_cache else ".agentpack/cache/\n"
20
- return (
21
- f"{_GITIGNORE_START}\n"
22
- "# AgentPack generated context/cache (safe to ignore)\n"
23
- f"{cache_line}"
24
- ".agentpack/snapshots/\n"
25
- ".agentpack/context*\n"
26
- ".agentpack/metrics.jsonl\n"
27
- ".agentpack/pack_metadata.json\n"
28
- ".agentpack/activity.log\n"
29
- ".agentpack/.gitignore\n"
30
- ".agentpack/.mcp_reminded\n"
31
- ".agentpack/session.json\n"
32
- ".agentpack/task.md\n"
33
- ".agentpack/benchmark_results.jsonl\n"
34
- ".agent/skills/agentpack/\n"
35
- f"{_GITIGNORE_END}\n"
36
- )
37
-
38
-
39
- def _patch_repo_gitignore(root, share_cache: bool = False) -> str:
40
- gitignore = root / ".gitignore"
41
- block = _repo_gitignore_block(share_cache)
42
- if not gitignore.exists():
43
- gitignore.write_text(block, encoding="utf-8")
44
- return "created"
45
-
46
- content = gitignore.read_text(encoding="utf-8")
47
- start = content.find(_GITIGNORE_START)
48
- end = content.find(_GITIGNORE_END)
49
- if start != -1 and end != -1 and end >= start:
50
- end += len(_GITIGNORE_END)
51
- replacement = block.rstrip()
52
- updated = content[:start].rstrip() + "\n\n" + replacement + "\n" + content[end:].lstrip("\n")
53
- if updated == content:
54
- return "unchanged"
55
- gitignore.write_text(updated, encoding="utf-8")
56
- return "updated"
57
-
58
- prefix = content.rstrip() + "\n\n" if content.strip() else ""
59
- gitignore.write_text(prefix + block, encoding="utf-8")
60
- return "updated"
61
-
62
-
63
- def _install_agent_integration(root, agent: str) -> dict[str, str]:
64
- """Install repo-local agent integration files after `agentpack init`."""
65
- return install_agent_integration(root, agent)
66
-
67
-
68
- def _print_agent_integration_results(results: dict[str, str]) -> None:
69
- for key, action in results.items():
70
- if action == "unchanged":
71
- continue
72
- if key.startswith("git:"):
73
- console.print(f"[green].git/hooks/{key[4:]} {action}[/]")
74
- elif key == "vscode:tasks":
75
- console.print(f"[green].vscode/tasks.json {action}[/]")
76
- else:
77
- console.print(f"[green]{key} {action}[/]")
78
-
79
-
80
- def register(app: typer.Typer) -> None:
81
- @app.command()
82
- def init(
83
- force: bool = typer.Option(False, "--force", help="Overwrite existing files."),
84
- mode: Optional[str] = typer.Option(None, "--mode", help="Default pack mode (minimal|balanced|deep)."),
85
- budget: int = typer.Option(0, "--budget", help="Default token budget (0 = keep default 25000)."),
86
- yes: bool = typer.Option(False, "--yes", "-y", help="Skip interactive prompts, use defaults."),
87
- silent: bool = typer.Option(False, "--silent", help="Suppress all output (for use in hooks/scripts)."),
88
- share_cache: bool = typer.Option(False, "--share-cache", help="Commit summary cache to git (recommended for teams)."),
89
- agent: str = typer.Option("auto", "--agent", help="Target agent (auto|claude|cursor|windsurf|codex|antigravity|generic)."),
90
- ) -> None:
91
- """Initialize AgentPack in the current directory.
92
-
93
- One-time setup. After this, just run `agentpack watch` — no other commands needed.
94
- """
95
- if silent:
96
- yes = True
97
- console.quiet = True
98
- root = _root()
99
- agentpack_dir = root / ".agentpack"
100
- agentpack_dir.mkdir(exist_ok=True)
101
- (agentpack_dir / "snapshots").mkdir(exist_ok=True)
102
- (agentpack_dir / "cache").mkdir(exist_ok=True)
103
-
104
- gitignore = agentpack_dir / ".gitignore"
105
- if not gitignore.exists() or force:
106
- # With --share-cache, cache/ is committed so teammates skip the summarize step
107
- cache_line = "" if share_cache else ".agentpack/cache/\n"
108
- gitignore.write_text(
109
- f"{cache_line}.agentpack/snapshots/\n.agentpack/context.*\n.agentpack/metrics.jsonl\n"
110
- )
111
- console.print("[green]Created[/] .agentpack/.gitignore")
112
- if share_cache:
113
- console.print(" [dim]cache/ not gitignored — commit it so teammates skip agentpack summarize[/]")
114
- else:
115
- console.print("[dim]Skipped[/] .agentpack/.gitignore (exists)")
116
-
117
- gitignore_action = _patch_repo_gitignore(root, share_cache=share_cache)
118
- if gitignore_action == "created":
119
- console.print("[green]Created[/] .gitignore [dim](AgentPack generated artifacts ignored)[/]")
120
- elif gitignore_action == "updated":
121
- console.print("[green]Updated[/] .gitignore [dim](AgentPack generated artifacts ignored)[/]")
122
- else:
123
- console.print("[dim]Skipped[/] .gitignore (AgentPack block unchanged)")
124
-
125
- config_path_file = agentpack_dir / "config.toml"
126
- if not config_path_file.exists() or force:
127
- cfg = DEFAULT_CONFIG.model_copy(deep=True)
128
-
129
- # Interactive mode selection
130
- if not yes and mode is None and sys.stdin.isatty():
131
- console.print("\n[bold]Choose default pack mode:[/]")
132
- console.print(" [cyan]1[/] minimal — changed files + configs only (fastest, fewest tokens)")
133
- console.print(" [cyan]2[/] balanced — + deps, tests, summaries [bold](recommended)[/]")
134
- console.print(" [cyan]3[/] deep — + docs, more full files (most context)")
135
- choice = typer.prompt("Mode", default="2")
136
- mode_map = {"1": "minimal", "2": "balanced", "3": "deep",
137
- "minimal": "minimal", "balanced": "balanced", "deep": "deep"}
138
- cfg.context.default_mode = mode_map.get(choice.strip(), "balanced")
139
- elif mode in ("minimal", "balanced", "deep"):
140
- cfg.context.default_mode = mode
141
-
142
- if budget > 0:
143
- cfg.context.default_budget = budget
144
-
145
- config_toml = CONFIG_TEMPLATE.replace(
146
- 'default_mode = "balanced"',
147
- f'default_mode = "{cfg.context.default_mode}"',
148
- )
149
- if budget > 0:
150
- config_toml = config_toml.replace(
151
- "default_budget = 25000",
152
- f"default_budget = {cfg.context.default_budget}",
153
- )
154
- config_path_file.parent.mkdir(parents=True, exist_ok=True)
155
- config_path_file.write_text(config_toml)
156
- console.print(f"[green]Created[/] .agentpack/config.toml [dim](mode: {cfg.context.default_mode}, budget: {cfg.context.default_budget:,})[/]")
157
- else:
158
- console.print("[dim]Skipped[/] .agentpack/config.toml (exists)")
159
-
160
- ignore_path = root / ".agentignore"
161
- if not ignore_path.exists() or force:
162
- ignore_path.write_text(DEFAULT_AGENTIGNORE)
163
- console.print("[green]Created[/] .agentignore")
164
- else:
165
- console.print("[dim]Skipped[/] .agentignore (exists)")
166
-
167
- # Bootstrap session so `agentpack watch` works immediately — no separate `session start` needed
168
- from agentpack.core.config import load_config
169
- resolved_mode = load_config(root).context.default_mode
170
- existing_session = load_session(root)
171
- resolved_agent = agent
172
- if existing_session is None or force:
173
- from agentpack.adapters.detect import detect_agent
174
- resolved_agent = agent if agent != "auto" else detect_agent(root)
175
- create_session(root, agent=resolved_agent, mode=resolved_mode)
176
- console.print(f"[green]Created[/] {SESSION_FILE} [dim]agent={resolved_agent} mode={resolved_mode}[/]")
177
- console.print(f"[green]Created[/] {TASK_FILE} [dim]edit to set your task[/]")
178
- else:
179
- console.print(f"[dim]Skipped[/] {SESSION_FILE} (exists)")
180
- if agent == "auto":
181
- resolved_agent = existing_session.agent
182
-
183
- _print_agent_integration_results(_install_agent_integration(root, resolved_agent))
184
-
185
- console.print("\n[bold green]AgentPack initialized.[/]")
186
- console.print("Run [bold]agentpack watch[/] to start auto-refreshing context.")
File without changes