You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rebased onto current main and reworked so the additions match the
current architecture rather than the stale base this branch was written
against. The original revision documented the retired Windsurf
integration and a CLI-managed `context_file` field that no longer
exists (context files are now owned by the opt-in agent-context
extension), and described the manifest at the wrong path with a
non-existent API.
This version keeps all current AGENTS.md content unchanged and adds four
onboarding-focused sections, verified against the code:
- Quickstart — Add a New Integration in 5 Steps (links into the existing
step-by-step section; notes context files are extension-owned)
- IntegrationManifest — File Tracking (correct path
.specify/integrations/<key>.manifest.json and real API:
record_file / record_existing / hash-guarded uninstall)
- Error Handling and Debugging (symptom/cause/fix table + debug tips)
- Contribution Checklist
Purely additive (+88 lines, no deletions); all internal anchors resolve.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: AGENTS.md
+88Lines changed: 88 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,6 +10,20 @@ The toolkit supports multiple AI coding assistants, allowing teams to use their
10
10
11
11
---
12
12
13
+
## Quickstart — Add a New Integration in 5 Steps
14
+
15
+
If you are new to the codebase and want to add support for a new AI agent, here is the shortest path from zero to a working integration:
16
+
17
+
1.**Choose a base class** — most agents only need `MarkdownIntegration`. See [Choose a base class](#1-choose-a-base-class).
18
+
2.**Create a subpackage** — add `src/specify_cli/integrations/<package_dir>/__init__.py` with the required `key`, `config`, and `registrar_config` fields.
19
+
3.**Register it** — add one import and one `_register()` call in `src/specify_cli/integrations/__init__.py` (both alphabetical).
20
+
4.**Write a test file** — create `tests/integrations/test_integration_<key>.py` (hyphens in the key become underscores in the filename).
21
+
5.**Run and verify** — use `specify init --integration <key>` to exercise the full install/uninstall cycle.
22
+
23
+
Each step is expanded under [Adding a New Integration](#adding-a-new-integration). Note that agent **context files** (`CLAUDE.md`, `AGENTS.md`, …) are **not** handled by the integration — that is owned by the opt-in `agent-context` extension; see [Context file behavior](#4-context-file-behavior).
24
+
25
+
---
26
+
13
27
## Integration Architecture
14
28
15
29
Each AI agent is a self-contained **integration subpackage** under `src/specify_cli/integrations/<key>/`. The subpackage exposes a single class that declares all metadata and inherits setup/teardown logic from a base class. Built-in integrations are then instantiated and added to the global `INTEGRATION_REGISTRY` by `src/specify_cli/integrations/__init__.py` via `_register_builtins()`.
@@ -34,6 +48,30 @@ The registry is the **single source of truth for Python integration metadata**.
34
48
35
49
---
36
50
51
+
## IntegrationManifest — File Tracking
52
+
53
+
`manifest.py` provides the `IntegrationManifest` class, which records every file an integration installs. This record is what makes uninstall reliable and safe.
54
+
55
+
### How it works
56
+
57
+
`setup()` receives an `IntegrationManifest` and writes files through it rather than touching the filesystem directly:
58
+
59
+
```python
60
+
# Produce a new file and record its hash for later verification.
# Adopt a pre-existing file the integration is now responsible for.
64
+
manifest.record_existing(".vscode/settings.json")
65
+
```
66
+
67
+
The manifest is persisted at `.specify/integrations/<key>.manifest.json` (one per integration, keyed by `key`) and stores a SHA-256 hash per file. When the user runs `specify integration uninstall <key>`, `teardown()` delegates to `manifest.uninstall()`, which removes only files whose current hash still matches the recorded value — so files the user later edited by hand are skipped, not clobbered (pass `force=True` to remove them anyway).
68
+
69
+
### Why this matters
70
+
71
+
Without hash-tracked manifests, uninstall would either remove files it should not (destructive) or leave orphans behind (messy). If you write a custom `setup()`, route **every** file you create through `manifest.record_file(...)` (or `record_existing(...)` for files you adopt) so uninstall can reason about them.
72
+
73
+
---
74
+
37
75
## Adding a New Integration
38
76
39
77
### 1. Choose a base class
@@ -511,4 +549,54 @@ Disclosure is **continuous**, not a one-time event. A single AI-disclosure parag
| CLI check fails for a `requires_cli: True` agent | `key` does not match the executable name | Set `key` to the exact name `shutil.which(key)` must resolve (e.g. `"cursor-agent"`, not `"cursor"`) |
561
+
| Command files have the wrong argument syntax | Wrong `args` value in `registrar_config` | Use `$ARGUMENTS` for Markdown agents, `{{args}}` for TOML/YAML agents, or the agent's custom placeholder |
562
+
| `ModuleNotFoundError` on a brand-new subpackage under pytest only | Ambient interpreter with a stale editable `.pth` | Run inside this tree's own venv (see Common Pitfall 6) |
563
+
| Uninstall leaves files behind, or skips files you expected removed | Files not recorded via the manifest, or their hash changed after install | Route every created file through `manifest.record_file(...)`; user-edited files are intentionally skipped unless `force=True` |
564
+
| Context file (`CLAUDE.md`, etc.) not updated | Expecting the CLI to manage it | Context files are owned by the opt-in `agent-context` extension, not the integration — see [Context file behavior](#4-context-file-behavior) |
565
+
566
+
### Debugging Tips
567
+
568
+
**Inspect the manifest** to see what an installed integration tracks:
569
+
570
+
```bash
571
+
cat .specify/integrations/<key>.manifest.json
572
+
```
573
+
574
+
**Verify a CLI tool is detected** before debugging a `requires_cli` agent:
575
+
576
+
```bash
577
+
which <key># Should print the executable path if installed
578
+
```
579
+
580
+
**Verify the installed output structure** after `specify init`:
581
+
582
+
```bash
583
+
find my-project/<folder> -type f
584
+
```
585
+
586
+
---
587
+
588
+
## Contribution Checklist
589
+
590
+
Before opening or merging an integration PR, confirm the following:
591
+
592
+
-[ ] Added the integration subpackage under `src/specify_cli/integrations/<package_dir>/`.
593
+
-[ ] Registered it (import **and**`_register()`) in `src/specify_cli/integrations/__init__.py`, both alphabetical.
594
+
-[ ] Added or updated tests in `tests/integrations/test_integration_<key>.py`.
595
+
-[ ] Verified the install/uninstall flow with `specify init --integration <key>`.
596
+
-[ ] Did **not** add `context_file` handling to the CLI (that belongs to the `agent-context` extension).
597
+
-[ ] Updated devcontainer files if the agent needs a VS Code extension or CLI install step.
598
+
-[ ] Updated this guide or other relevant docs if the integration has special setup or limitations.
599
+
600
+
---
601
+
514
602
*This documentation should be updated whenever new integrations are added to maintain accuracy and completeness.*
0 commit comments