Skip to content

[Feature] Extract agent context updates into an agent-context extension #2398

Description

@mnriem

Problem Statement

Agent context file management (<!-- SPECKIT START --> / <!-- SPECKIT END --> marker injection into coding agent context files like CLAUDE.md, .github/copilot-instructions.md, etc.) is hardcoded into IntegrationBase in src/specify_cli/integrations/base.py. This tightly couples context file manipulation to every setup() / teardown() call, with no way for users to opt out or customize the markers.

The shared dispatcher scripts documented in AGENTS.md (update-agent-context.sh / .ps1) and per-integration thin wrappers are not implemented.

Proposed Solution

Create a bundled agent-context extension under extensions/agent-context/ that owns all coding agent context file update behavior. Ship as opt-out (enabled by default) initially, flip to opt-in at 0.11.0.

Key design: All agent context configuration flows through init-options.json. Each integration already writes context_file there. This work adds context_markers alongside it, so both the Python layer and the extension's shell scripts read from a single source of truth — no case statements, no agent-key→file mappings, and markers become user-configurable.

init-options.json schema addition

{
  "context_file": ".claude/instructions.md",
  "context_markers": {
    "start": "<!-- SPECKIT START -->",
    "end": "<!-- SPECKIT END -->"
  }
}
  • context_file — already written today (no change)
  • context_markers.start / .end — new; defaults populated from IntegrationBase.CONTEXT_MARKER_START / CONTEXT_MARKER_END at init time
  • Users who want custom markers edit init-options.json directly

Scope of Work

1. Persist markers to init-options.json

Update the writers in src/specify_cli/__init__.py:

  • specify init (~line 1406–1420): add context_markers to init_opts, populated from IntegrationBase.CONTEXT_MARKER_START / CONTEXT_MARKER_END
  • specify integration install (_update_init_options_for_integration, ~line 2183–2200): same
  • specify integration uninstall (~line 2239–2246 and ~line 2276): pop context_markers alongside context_file

2. Make Python context methods read from init-options.json

Update src/specify_cli/integrations/base.py:

  • upsert_context_section() (~line 479–555): read markers from init-options.json instead of self.CONTEXT_MARKER_START / self.CONTEXT_MARKER_END. Fall back to class constants when init-options.json is absent or missing the field.
  • remove_context_section() (~line 557–608): same treatment
  • Keep class constants as defaults (not removed), but they become the fallback, not the authority.

3. Create extensions/agent-context/ extension package

extensions/agent-context/
├── extension.yml          # id: agent-context, name: "Coding Agent Context"
├── README.md              # Title: "Coding Agent Context Extension"
├── commands/
│   └── speckit.agent-context.update.md
└── scripts/
    ├── bash/
    │   └── update-agent-context.sh
    └── powershell/
        └── update-agent-context.ps1
  • extension.yml: id: agent-context, name: "Coding Agent Context", author: spec-kit-core, bundled: true
  • Hook into lifecycle points (e.g., after_specify, after_plan) to auto-update context when plan path changes
  • Command speckit.agent-context.update for manual invocation
  • Scripts read context_file and context_markers from init-options.json — fully generic, zero agent-specific logic
  • README and catalog description should clearly state this manages coding agent context/instruction files

4. Make setup() / teardown() conditional on extension

In IntegrationBase, gate calls to upsert_context_section() and remove_context_section() on whether the agent-context extension is enabled. When disabled, no context file manipulation occurs.

5. Register in extension catalog

Add to extensions/catalog.json:

{
  "agent-context": {
    "name": "Coding Agent Context",
    "id": "agent-context",
    "version": "1.0.0",
    "description": "Manages coding agent context/instruction files (e.g., CLAUDE.md, copilot-instructions.md) with project-specific plan references and configurable markers",
    "author": "spec-kit-core",
    "repository": "https://github.com/github/spec-kit",
    "bundled": true,
    "tags": ["agent", "context", "core"]
  }
}

6. Update AGENTS.md

  • Remove the per-integration thin wrapper script documentation (update-context.sh / update-context.ps1 templates) — that pattern is superseded by the single extension script reading init-options.json
  • Remove references to shared dispatcher scripts at scripts/bash/ and scripts/powershell/ — they now live inside the extension
  • Document the init-options.json-driven approach

7. Update tests

  • Add tests/extensions/test_extension_agent_context.py
  • Test custom markers: write non-default markers to init-options.json, verify upsert_context_section() and remove_context_section() respect them
  • Test backwards compat: missing context_markers in init-options.json → falls back to class constant defaults
  • Test extension disabled: setup() / teardown() skip context file operations
  • Existing tests with hardcoded marker assertions continue to pass

Acceptance Criteria

  • context_markers is written to .specify/init-options.json during specify init and specify integration install
  • upsert_context_section() and remove_context_section() read markers from init-options.json, falling back to class constants
  • Custom markers in init-options.json are respected by both Python and shell script paths
  • extensions/agent-context/ exists with valid extension.yml, README, commands, and scripts
  • Extension scripts read from init-options.json — no agent-specific logic
  • extensions/catalog.json includes agent-context with bundled: true
  • IntegrationBase.setup() / teardown() skip context file operations when agent-context extension is disabled
  • specify init my-project --integration claude still produces the same CLAUDE.md content (backwards compatible)
  • specify extension disable agent-context prevents context file creation/modification
  • AGENTS.md updated: per-integration wrapper docs removed, init-options.json approach documented
  • All existing tests pass; new extension-specific tests added
  • Targeted for opt-in flip at 0.11.0

Additional Context

  • Reference implementation: extensions/git/ — bundled, opt-out, with commands + hooks + scripts + config
  • Current version: 0.8.2.dev0
  • 30+ integrations have context_file set; the refactor must be backwards compatible
  • Markers are defined only in IntegrationBase (line 92–93 of base.py), never overridden by any subclass
  • No per-integration wrapper scripts exist today (directories are empty) — nothing to remove, just the AGENTS.md documentation describing them

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions