diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..1de68b2 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,20 @@ +# GitHub Copilot Instructions + +## Use Agent Context + +When working on this project, consult the `agents.md` file for project-specific guidelines, architecture decisions, and development patterns. This file contains curated information that will help you make better decisions aligned with the project's goals and standards. + +If the file does not exist, you will need to install it, by running the following command: + +```bash +$ bundle install +$ bundle exec bake agent:context:install +``` + +This command will set up the necessary context files that help you understand the project structure, dependencies, and conventions. + +## Ignoring Files + +The `.gitignore` file is split into two sections, separated by a blank line. The first section is automatically generated, while the second section is user controlled. + +While working on pull requests, you should not add unrelated changes to the `.gitignore` file as part of the pull request. diff --git a/.github/workflows/test-external.yaml b/.github/workflows/test-external.yaml deleted file mode 100644 index 287124c..0000000 --- a/.github/workflows/test-external.yaml +++ /dev/null @@ -1,33 +0,0 @@ -name: Test External - -on: [push, pull_request] - -permissions: - contents: read - -jobs: - test: - name: ${{matrix.ruby}} on ${{matrix.os}} - runs-on: ${{matrix.os}}-latest - - strategy: - matrix: - os: - - ubuntu - - macos - - ruby: - - "3.2" - - "3.3" - - "3.4" - - steps: - - uses: actions/checkout@v4 - - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{matrix.ruby}} - bundler-cache: true - - - name: Run tests - timeout-minutes: 10 - run: bundle exec bake test:external diff --git a/.gitignore b/.gitignore index bd2467d..ee82a6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ -/.bundle +/agents.md /.context +/.bundle /pkg /gems.locked /.covered.db diff --git a/bake/agent/context.rb b/bake/agent/context.rb index d7d5ea9..d8b17c3 100644 --- a/bake/agent/context.rb +++ b/bake/agent/context.rb @@ -75,14 +75,14 @@ def install(gem: nil) end end - # Update agent.md after installing context + # Update agents.md after installing context index = Agent::Context::Index.new(@installer.context_path) - index.update_agent_md + index.update_agents_md end -# Update or create AGENT.md in the project root with context section -# This follows the AGENT.md specification for agentic coding tools -def agent_md(path = "agent.md") - index = Agent::Context::Index.new(@helper.context_path) - index.update_agent_md(path) +# Update or create AGENTS.md in the project root with context section +# This follows the AGENTS.md specification for agentic coding tools +def agents_md(path = "agents.md") + index = Agent::Context::Index.new(@installer.context_path) + index.update_agents_md(path) end diff --git a/gems.rb b/gems.rb index 70b1610..2bbcf97 100644 --- a/gems.rb +++ b/gems.rb @@ -2,6 +2,7 @@ # Released under the MIT License. # Copyright, 2025, by Shopify Inc. +# Copyright, 2025, by Samuel Williams. source "https://rubygems.org" diff --git a/lib/agent/context/index.rb b/lib/agent/context/index.rb index a36724c..b026578 100644 --- a/lib/agent/context/index.rb +++ b/lib/agent/context/index.rb @@ -12,11 +12,11 @@ module Agent # @namespace module Context - # Represents an index for managing and generating agent.md files from context files. + # Represents an index for managing and generating agents.md files from context files. # - # This class provides functionality to update or create AGENT.md files following - # the AGENT.md specification for agentic coding tools. It can parse existing - # agent.md files, update the context section, and generate new files when needed. + # This class provides functionality to update or create AGENTS.md files following + # the AGENTS.md specification for agentic coding tools. It can parse existing + # agents.md files, update the context section, and generate new files when needed. class Index # Initialize a new index instance. # @parameter context_path [String] The path to the context directory (default: ".context"). @@ -26,18 +26,18 @@ def initialize(context_path = ".context") attr :context_path - # Update or create an AGENT.md file in the project root with context section - # This follows the AGENT.md specification for agentic coding tools - def update_agent_md(agent_md_path = "agent.md") + # Update or create an AGENTS.md file in the project root with context section + # This follows the AGENTS.md specification for agentic coding tools + def update_agents_md(agents_md_path = "agents.md") context_content = generate_context_section - if File.exist?(agent_md_path) - update_existing_agent_md(agent_md_path, context_content) + if File.exist?(agents_md_path) + update_existing_agents_md(agents_md_path, context_content) else - create_new_agent_md(agent_md_path, context_content) + create_new_agents_md(agents_md_path, context_content) end - Console.debug("Updated agent.md: #{agent_md_path}") + Console.debug("Updated agents.md: #{agents_md_path}") end # Generate just the context section content (without top-level headers) @@ -100,8 +100,8 @@ def generate_context_section private - def update_existing_agent_md(agent_md_path, context_content) - content = File.read(agent_md_path) + def update_existing_agents_md(agents_md_path, context_content) + content = File.read(agents_md_path) # Find the # Agent heading agent_heading_line = find_agent_heading_line(content) @@ -123,10 +123,10 @@ def update_existing_agent_md(agent_md_path, context_content) end # Write the updated content back to file - File.write(agent_md_path, updated_content) + File.write(agents_md_path, updated_content) end - def create_new_agent_md(agent_md_path, context_content) + def create_new_agents_md(agents_md_path, context_content) content = [ "# Agent", "", @@ -134,7 +134,7 @@ def create_new_agent_md(agent_md_path, context_content) "", context_content, ].join("\n") - File.write(agent_md_path, content) + File.write(agents_md_path, content) end def find_agent_heading_line(content) diff --git a/lib/agent/context/installer.rb b/lib/agent/context/installer.rb index 45522be..abbc369 100644 --- a/lib/agent/context/installer.rb +++ b/lib/agent/context/installer.rb @@ -182,7 +182,7 @@ def ensure_gem_index(gem, gem_directory) unless File.exist?(index_path) # Generate dynamic index from gemspec index = generate_dynamic_index(gem, gem_directory) - + # Write the generated index File.write(index_path, index.to_yaml) Console.debug("Generated dynamic index for #{gem[:name]}: #{index_path}") diff --git a/post.md b/post.md index 7aaa6fa..9f77f68 100644 --- a/post.md +++ b/post.md @@ -28,11 +28,11 @@ **Claude:** "So how does this work in practice?" -**Ruby:** "Let me show you! When a developer runs `bake agent:context:install`, it scans all my installed gems for `context/` directories, copies the files to a `.context/` folder in their project, and generates an `agent.md` file that gives you a comprehensive overview." +**Ruby:** "Let me show you! When a developer runs `bake agent:context:install`, it scans all my installed gems for `context/` directories, copies the files to a `.context/` folder in their project, and generates an `agents.md` file that gives you a comprehensive overview." -**Claude:** "That sounds perfect! What does this `agent.md` file look like?" +**Claude:** "That sounds perfect! What does this `agents.md` file look like?" -**Ruby:** "It's structured and organized, following the AGENT.md specification. Here's what it generates:" +**Ruby:** "It's structured and organized, following the AGENTS.md specification. Here's what it generates:" ```markdown # Agent @@ -87,26 +87,26 @@ my-awesome-gem/ **Claude:** "This is great, but how do I actually access this information? Different AI tools expect different file names and locations." -**Ruby:** "Good question! The generated `agent.md` can be linked to whatever your tool expects:" +**Ruby:** "Good question! The generated `agents.md` can be linked to whatever your tool expects:" **For Cursor:** -Create `.cursor/rules/agent.mdc` with: +Create `.cursor/rules/agents.mdc` with: ``` markdown --- alwaysApply: true --- -Read the `agent.md` file in the project root directory for detailed context relating to this project and external dependencies. +Read the `agents.md` file in the project root directory for detailed context relating to this project and external dependencies. ``` **For GitHub Copilot:** ```bash -ln -s ../../agent.md .github/copilot-instructions.md +ln -s ../../agents.md .github/copilot-instructions.md ``` **For Claude Code:** ```bash -ln -s agent.md CLAUDE.md +ln -s agents.md CLAUDE.md ``` **Claude:** "Perfect! So developers can easily integrate this with their preferred AI tools." diff --git a/readme.md b/readme.md index 8a0c587..90eb97d 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ # Agent::Context -Provides tools for installing and managing context files from Ruby gems for AI agents, and generating `agent.md` files following the specification. +Provides tools for installing and managing context files from Ruby gems for AI agents, and generating `agents.md` files following the specification. [![Development Status](https://github.com/ioquatix/agent-context/workflows/Test/badge.svg)](https://github.com/ioquatix/agent-context/actions?workflow=Test) @@ -8,7 +8,7 @@ Provides tools for installing and managing context files from Ruby gems for AI a This gem allows you to install and manage context files from other gems. Gems can provide context files in a `context/` directory in their root, which can contain documentation, configuration examples, migration guides, and other contextual information for AI agents. -When you install context from gems, they are placed in the `.context/` directory and an `agent.md` file is generated or updated to provide a comprehensive overview for AI agents. +When you install context from gems, they are placed in the `.context/` directory and an `agents.md` file is generated or updated to provide a comprehensive overview for AI agents. ## Quick Start @@ -23,8 +23,8 @@ This workflow: - Adds the `agent-context` gem to your project. - Installs context files from all gems into `.context/`. - - Generates or updates `agent.md` with a comprehensive overview. - - Follows the specification for agentic coding tools. + - Generates or updates `agents.md` with a comprehensive overview. + - Follows the specification for agentic coding tools. ## Context @@ -32,7 +32,7 @@ This gem provides its own context files in the `context/` directory, including: - `usage.md` - Comprehensive guide for using and providing context files. -When you install context from other gems, they will be placed in the `.context/` directory and referenced in `agent.md`. +When you install context from other gems, they will be placed in the `.context/` directory and referenced in `agents.md`. ## Usage @@ -52,7 +52,7 @@ $ bundle add agent-context #### Install Context (Primary Command) -Install context from all available gems and update `agent.md`: +Install context from all available gems and update `agents.md`: ``` bash $ bake agent:context:install @@ -88,10 +88,10 @@ $ bake agent:context:show --gem async --file thread-safety ## Version Control -Both `.context/` and `agent.md` should be committed to git: +Both `.context/` and `agents.md` should be committed to git: - - `agent.md` is user-facing documentation that should be versioned. - - `.context/` files are referenced by `agent.md` and needed for AI agents to function properly. + - `agents.md` is user-facing documentation that should be versioned. + - `.context/` files are referenced by `agents.md` and needed for AI agents to function properly. - This ensures AI agents in CI have access to the full context. ## Providing Context in Your Gem @@ -125,65 +125,6 @@ files: If no `index.yaml` is provided, one will be generated automatically from your gemspec and markdown files. -## AI Tool Integration - -The generated `agent.md` file can be integrated with various AI coding tools by creating symbolic links to their expected locations: - -### Cline - -``` bash -ln -s agent.md .clinerules -``` - -### Claude Code - -``` bash -ln -s agent.md CLAUDE.md -``` - -### Cursor - -First, create the `.cursor/rules` directory: - -``` bash -mkdir -p .cursor/rules -``` - -Then create `.cursor/rules/agent.mdc` with: - -``` markdown ---- -alwaysApply: true ---- -Read the `agent.md` file in the project root directory for detailed context relating to this project and external dependencies. -``` - -This approach uses Cursor's proper front-matter format and directs the AI to consult the main `agent.md` file. - -### Gemini CLI, OpenAI Codex, OpenCode - -``` bash -ln -s agent.md AGENTS.md -``` - -### GitHub Copilot - -``` bash -ln -s ../../agent.md .github/copilot-instructions.md -``` - -### Replit - -``` bash -ln -s agent.md .replit.md -``` - -### Windsurf - -``` bash -ln -s agent.md .windsurfrules -``` - ## Releases Please see the [project releases](https://ioquatix.github.io/agent-context/releases/index) for all releases. diff --git a/releases.md b/releases.md index 363c57d..8883260 100644 --- a/releases.md +++ b/releases.md @@ -1,5 +1,9 @@ # Releases +## Unreleased + + - Rename `agent.md` -> `agents.md`. + ## v0.2.0 - Don't limit description length. diff --git a/test/agent/context/index.rb b/test/agent/context/index.rb index 6be9658..488bcb3 100644 --- a/test/agent/context/index.rb +++ b/test/agent/context/index.rb @@ -25,7 +25,7 @@ def around it "creates new AGENT.md when file doesn't exist" do index = Agent::Context::Index.new(context_path) - index.update_agent_md(agent_md_path) + index.update_agents_md(agent_md_path) expect(File.exist?(agent_md_path)).to be == true content = File.read(agent_md_path) @@ -49,7 +49,7 @@ def around File.write(agent_md_path, existing_content) index = Agent::Context::Index.new(context_path) - index.update_agent_md(agent_md_path) + index.update_agents_md(agent_md_path) content = File.read(agent_md_path) expect(content).to be(:include?, "# Agent") @@ -75,7 +75,7 @@ def around File.write(agent_md_path, existing_content) index = Agent::Context::Index.new(context_path) - index.update_agent_md(agent_md_path) + index.update_agents_md(agent_md_path) content = File.read(agent_md_path) expect(content).to be(:include?, "# Agent") @@ -100,7 +100,7 @@ def around File.write(agent_md_path, existing_content) index = Agent::Context::Index.new(context_path) - index.update_agent_md(agent_md_path) + index.update_agents_md(agent_md_path) content = File.read(agent_md_path) expect(content).to be(:include?, "# Agent") @@ -122,7 +122,7 @@ def around File.write(File.join(gem_context_path, "README.md"), readme_content) index = Agent::Context::Index.new(context_path) - index.update_agent_md(agent_md_path) + index.update_agents_md(agent_md_path) content = File.read(agent_md_path) expect(content).to be(:include?, "# Agent") @@ -154,7 +154,7 @@ def around File.write(File.join(gem_context_path, "getting-started.md"), "# Getting Started\n\nSome content.") index = Agent::Context::Index.new(context_path) - index.update_agent_md(agent_md_path) + index.update_agents_md(agent_md_path) content = File.read(agent_md_path) expect(content).to be(:include?, "### example_gem") @@ -184,7 +184,7 @@ def around File.write(agent_md_path, existing_content) index = Agent::Context::Index.new(context_path) - index.update_agent_md(agent_md_path) + index.update_agents_md(agent_md_path) content = File.read(agent_md_path) expect(content).to be(:include?, "# Agent")