admin: Add AI coding assistant configuration (#2122)
Adds agent configuration supporting Claude Code, Cursor, GitHub Copilot, OpenAI Codex, and Opencode. A single AGENTS.md and contents of .agents subdirectory serve as the canonical source for instructions, skills, and other things that can be used across multiple tools. A script can be invoked by users to do the local setup of links or references to allow them to use a particular tool: `.agents/setup-agent TOOL` Currently supported tools by this script include Claude Code, Codex, Cursor, GitHub Copilot, and OpenCode. This initial commit includes two skills that I wrote and have used for the last couple monthly releases: release-notes-update and prepare-patch-release. I assume that we will add more over time as we discover tasks that we want to make standard skill automation for. Assisted-by: Claude Code / claude-sonnet-4-6 The AGENTS.md, Claude skills, and general scheme are entirely from me. I used Claude to help me establish the setup script for the other tools I don't happen to use. This basic structure was first prototyped on OIIO and then copied to OSL. Signed-off-by: Larry Gritz <lg@larrygritz.com>
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
# Ignore skills that might be installed locally by a developer, to prevent
|
||||
# cluttering the output of `git status` and prevent people from accidentally
|
||||
# checking in locally installed skills.
|
||||
skills/*
|
||||
|
||||
# But don't ignore the ones that belong to this project and are checked in. As
|
||||
# we add skills that we intend to commit and make available to all project
|
||||
# developers, they must be individually added here if they don't start with
|
||||
# "osl-".
|
||||
!skills/osl-*/
|
||||
!skills/prepare-patch-release/
|
||||
!skills/release-notes-update/
|
||||
Executable
+313
@@ -0,0 +1,313 @@
|
||||
#!/usr/bin/env bash
|
||||
# .agents/setup-agent — Set up AI coding tool integration for this repository.
|
||||
#
|
||||
# Creates the tool-specific symlinks and config files needed to use the shared
|
||||
# resources in AGENTS.md and .agents/ with your preferred AI coding assistant.
|
||||
# Run "setup-agent <tool>" once after cloning; re-running is always safe.
|
||||
#
|
||||
# The canonical project instructions live in AGENTS.md (root) and skills live
|
||||
# in .agents/skills/<name>/SKILL.md. Everything tool-specific is either a
|
||||
# symlink into those locations, or a thin wrapper that references them.
|
||||
# Tool-specific directories (.claude/, .cursor/, etc.) are git-ignored so that
|
||||
# each developer runs this script for the tool they actually use.
|
||||
#
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# TOOL STRATEGIES (update this section when tool conventions change)
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
#
|
||||
# CLAUDE CODE
|
||||
# Reads: .claude/CLAUDE.md (project) or CLAUDE.md (root) — NOT AGENTS.md natively.
|
||||
# If Anthropic eventually adds native AGENTS.md support, the
|
||||
# .claude/CLAUDE.md wrapper can be retired.
|
||||
# Skills: .claude/skills/ (each subdirectory is a skill)
|
||||
# Setup: Write .claude/CLAUDE.md containing "@AGENTS.md" (Claude's include
|
||||
# syntax), symlink .claude/skills -> ../.agents/skills.
|
||||
# Docs: https://docs.anthropic.com/en/docs/claude-code/memory
|
||||
# https://docs.anthropic.com/en/docs/claude-code/skills
|
||||
#
|
||||
# OPENAI CODEX
|
||||
# Reads: AGENTS.md natively — no wrapper needed.
|
||||
# Skills: .agents/skills/ natively, and also .codex/skills/ as a fallback.
|
||||
# Setup: Symlink .codex/skills -> ../.agents/skills so either path works.
|
||||
# Docs: https://developers.openai.com/codex/guides/agents-md
|
||||
# https://developers.openai.com/codex/skills
|
||||
#
|
||||
# CURSOR
|
||||
# Reads: .cursor/rules/*.mdc files — does NOT read AGENTS.md natively.
|
||||
# If Cursor adds native AGENTS.md support, the rules symlink can be
|
||||
# retired.
|
||||
# Skills: Cursor uses a different slash-command mechanism; .agents/skills/
|
||||
# are not directly usable today, but the convention may change.
|
||||
# Setup: Symlink .cursor/rules/project.mdc -> ../../AGENTS.md so Cursor
|
||||
# picks up our instructions as a project rule.
|
||||
# Docs: https://docs.cursor.com/context/rules-for-ai
|
||||
# https://docs.cursor.com/cmdk/overview
|
||||
#
|
||||
# OPENCODE
|
||||
# Reads: AGENTS.md natively — no wrapper needed.
|
||||
# Skills: Documented to read .agents/skills/ natively, but in practice also
|
||||
# requires .opencode/commands/<name>.md symlinks (as of 2025-05).
|
||||
# Remove the per-command symlinks once opencode reliably finds
|
||||
# .agents/skills/ on its own.
|
||||
# Setup: Symlink .opencode/skills -> ../.agents/skills (future-proof),
|
||||
# plus individual .opencode/commands/<name>.md -> skill SKILL.md
|
||||
# files (current workaround).
|
||||
# Docs: https://opencode.ai/docs/configuration
|
||||
# https://opencode.ai/docs/skills
|
||||
#
|
||||
# GITHUB COPILOT
|
||||
# Reads: AGENTS.md natively (VS Code Copilot ≥ 1.99 / GitHub Copilot Chat).
|
||||
# Also reads .github/copilot-instructions.md as a fallback for older
|
||||
# clients or non-VS Code surfaces.
|
||||
# Skills: .agents/skills/ natively supported.
|
||||
# Setup: Symlink .github/copilot-instructions.md -> ../AGENTS.md so older
|
||||
# clients also receive our instructions. Remove once all Copilot
|
||||
# surfaces reliably pick up AGENTS.md directly.
|
||||
# Docs: https://code.visualstudio.com/docs/copilot/customization/custom-instructions
|
||||
# https://docs.github.com/en/copilot/concepts/about-prompting-copilot
|
||||
# https://docs.github.com/en/copilot/concepts/agents/about-agent-skills
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
SKILLS_DIR=".agents/skills"
|
||||
SUPPORTED_TOOLS="claude codex cursor opencode copilot"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: .agents/setup-agent <tool|all|clear|list> [tool...]
|
||||
|
||||
Commands:
|
||||
<tool> [...] Set up one or more tools
|
||||
all Set up all supported tools
|
||||
clear Remove all tool-specific setup created by this script
|
||||
clear <tool> Remove setup for one specific tool
|
||||
list List supported tools
|
||||
|
||||
Supported tools: $SUPPORTED_TOOLS
|
||||
|
||||
Examples:
|
||||
.agents/setup-agent claude
|
||||
.agents/setup-agent claude cursor
|
||||
.agents/setup-agent all
|
||||
.agents/setup-agent clear
|
||||
.agents/setup-agent clear opencode
|
||||
EOF
|
||||
}
|
||||
|
||||
rel() { echo "${1#"$REPO_ROOT"/}"; }
|
||||
|
||||
# Create a symlink only if the path doesn't already exist.
|
||||
# Silent if the link already points to the correct target.
|
||||
safe_symlink() {
|
||||
local link="$1" target="$2"
|
||||
if [ -L "$link" ] && [ "$(readlink "$link")" = "$target" ]; then
|
||||
return 0
|
||||
elif [ -e "$link" ] || [ -L "$link" ]; then
|
||||
echo " SKIP (already exists): $(rel "$link")"
|
||||
return 0
|
||||
fi
|
||||
mkdir -p "$(dirname "$link")"
|
||||
ln -s "$target" "$link"
|
||||
echo " LINK: $(rel "$link") -> $target"
|
||||
}
|
||||
|
||||
# Write a file only if the path doesn't already exist.
|
||||
safe_write() {
|
||||
local file="$1"
|
||||
shift
|
||||
local content="$*"
|
||||
if [ -e "$file" ]; then
|
||||
echo " SKIP (already exists): $(rel "$file")"
|
||||
return 0
|
||||
fi
|
||||
mkdir -p "$(dirname "$file")"
|
||||
printf '%s\n' "$content" > "$file"
|
||||
echo " FILE: $(rel "$file")"
|
||||
}
|
||||
|
||||
# Remove a symlink only if it still points to the expected target.
|
||||
safe_remove_symlink() {
|
||||
local link="$1" expected_target="$2"
|
||||
[ ! -L "$link" ] && return 0
|
||||
if [ "$(readlink "$link")" = "$expected_target" ]; then
|
||||
rm "$link"
|
||||
echo " REMOVED: $(rel "$link")"
|
||||
else
|
||||
echo " SKIP (modified, not removing): $(rel "$link")"
|
||||
fi
|
||||
}
|
||||
|
||||
# Remove a file only if its content still matches what we wrote.
|
||||
safe_remove_file() {
|
||||
local file="$1"
|
||||
shift
|
||||
local expected="$*"
|
||||
[ ! -f "$file" ] || [ -L "$file" ] && return 0
|
||||
if [ "$(cat "$file")" = "$expected" ]; then
|
||||
rm "$file"
|
||||
echo " REMOVED: $(rel "$file")"
|
||||
else
|
||||
echo " SKIP (modified, not removing): $(rel "$file")"
|
||||
fi
|
||||
}
|
||||
|
||||
try_rmdir() { rmdir "$1" 2>/dev/null && echo " RMDIR: $(rel "$1")" || true; }
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Common (tool-agnostic project setup)
|
||||
#------------------------------------------------------------------------------
|
||||
setup_common() {
|
||||
echo "Setting up common project infrastructure..."
|
||||
# specs/ at the project root is a symlink into docs/dev/specs/ so that
|
||||
# speckit bash scripts find the directory where they expect it, while the
|
||||
# actual specs are committed under docs/dev/specs/ and are not cluttered
|
||||
# at the project root for developers who don't use agents.
|
||||
safe_symlink "$REPO_ROOT/specs" "docs/dev/specs"
|
||||
}
|
||||
clear_common() {
|
||||
echo "Removing common project infrastructure..."
|
||||
safe_remove_symlink "$REPO_ROOT/specs" "docs/dev/specs"
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Claude Code (.claude/)
|
||||
#------------------------------------------------------------------------------
|
||||
setup_claude() {
|
||||
echo "Setting up Claude Code..."
|
||||
safe_write "$REPO_ROOT/.claude/CLAUDE.md" "@AGENTS.md"
|
||||
safe_symlink "$REPO_ROOT/.claude/skills" "../.agents/skills"
|
||||
safe_write "$REPO_ROOT/.claude/.gitignore" "settings.local.json"
|
||||
}
|
||||
clear_claude() {
|
||||
echo "Removing Claude Code setup..."
|
||||
safe_remove_file "$REPO_ROOT/.claude/CLAUDE.md" "@AGENTS.md"
|
||||
safe_remove_symlink "$REPO_ROOT/.claude/skills" "../.agents/skills"
|
||||
safe_remove_file "$REPO_ROOT/.claude/.gitignore" "settings.local.json"
|
||||
try_rmdir "$REPO_ROOT/.claude"
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# OpenAI Codex (.codex/)
|
||||
#------------------------------------------------------------------------------
|
||||
setup_codex() {
|
||||
echo "Setting up OpenAI Codex..."
|
||||
safe_symlink "$REPO_ROOT/.codex/skills" "../.agents/skills"
|
||||
safe_write "$REPO_ROOT/.codex/.gitignore" "*.log"
|
||||
}
|
||||
clear_codex() {
|
||||
echo "Removing OpenAI Codex setup..."
|
||||
safe_remove_symlink "$REPO_ROOT/.codex/skills" "../.agents/skills"
|
||||
safe_remove_file "$REPO_ROOT/.codex/.gitignore" "*.log"
|
||||
try_rmdir "$REPO_ROOT/.codex"
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Cursor (.cursor/)
|
||||
#------------------------------------------------------------------------------
|
||||
setup_cursor() {
|
||||
echo "Setting up Cursor..."
|
||||
safe_symlink "$REPO_ROOT/.cursor/rules/project.mdc" "../../AGENTS.md"
|
||||
safe_write "$REPO_ROOT/.cursor/.gitignore" "$(printf 'composer/\nchat/')"
|
||||
}
|
||||
clear_cursor() {
|
||||
echo "Removing Cursor setup..."
|
||||
safe_remove_symlink "$REPO_ROOT/.cursor/rules/project.mdc" "../../AGENTS.md"
|
||||
safe_remove_file "$REPO_ROOT/.cursor/.gitignore" "$(printf 'composer/\nchat/')"
|
||||
try_rmdir "$REPO_ROOT/.cursor/rules"
|
||||
try_rmdir "$REPO_ROOT/.cursor"
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Opencode (.opencode/)
|
||||
#------------------------------------------------------------------------------
|
||||
OPENCODE_GITIGNORE="$(printf 'node_modules\npackage.json\npackage-lock.json\nbun.lock')"
|
||||
|
||||
setup_opencode() {
|
||||
echo "Setting up Opencode..."
|
||||
safe_symlink "$REPO_ROOT/.opencode/skills" "../.agents/skills"
|
||||
safe_write "$REPO_ROOT/.opencode/.gitignore" "$OPENCODE_GITIGNORE"
|
||||
# Individual command links (needed in practice despite docs implying otherwise)
|
||||
for skill_dir in "$REPO_ROOT/$SKILLS_DIR"/*/; do
|
||||
[ -d "$skill_dir" ] || continue
|
||||
local skill_name
|
||||
skill_name="$(basename "$skill_dir")"
|
||||
safe_symlink "$REPO_ROOT/.opencode/commands/${skill_name}.md" \
|
||||
"../../$SKILLS_DIR/${skill_name}/SKILL.md"
|
||||
done
|
||||
}
|
||||
clear_opencode() {
|
||||
echo "Removing Opencode setup..."
|
||||
safe_remove_symlink "$REPO_ROOT/.opencode/skills" "../.agents/skills"
|
||||
safe_remove_file "$REPO_ROOT/.opencode/.gitignore" "$OPENCODE_GITIGNORE"
|
||||
for skill_dir in "$REPO_ROOT/$SKILLS_DIR"/*/; do
|
||||
[ -d "$skill_dir" ] || continue
|
||||
local skill_name
|
||||
skill_name="$(basename "$skill_dir")"
|
||||
safe_remove_symlink "$REPO_ROOT/.opencode/commands/${skill_name}.md" \
|
||||
"../../$SKILLS_DIR/${skill_name}/SKILL.md"
|
||||
done
|
||||
try_rmdir "$REPO_ROOT/.opencode/commands"
|
||||
try_rmdir "$REPO_ROOT/.opencode"
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# GitHub Copilot (.github/copilot-instructions.md)
|
||||
# Copilot natively reads AGENTS.md, but also checks copilot-instructions.md.
|
||||
#------------------------------------------------------------------------------
|
||||
setup_copilot() {
|
||||
echo "Setting up GitHub Copilot..."
|
||||
safe_symlink "$REPO_ROOT/.github/copilot-instructions.md" "../AGENTS.md"
|
||||
}
|
||||
clear_copilot() {
|
||||
echo "Removing GitHub Copilot setup..."
|
||||
safe_remove_symlink "$REPO_ROOT/.github/copilot-instructions.md" "../AGENTS.md"
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Dispatch
|
||||
#------------------------------------------------------------------------------
|
||||
run_tool() {
|
||||
local action="$1" tool="$2"
|
||||
case "$tool" in
|
||||
claude) "${action}_claude" ;;
|
||||
codex) "${action}_codex" ;;
|
||||
cursor) "${action}_cursor" ;;
|
||||
opencode) "${action}_opencode" ;;
|
||||
copilot) "${action}_copilot" ;;
|
||||
*)
|
||||
echo "Unknown tool: $tool (supported: $SUPPORTED_TOOLS)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
[ $# -eq 0 ] && { usage; exit 0; }
|
||||
|
||||
case "$1" in
|
||||
all)
|
||||
setup_common
|
||||
for t in $SUPPORTED_TOOLS; do run_tool setup "$t"; done
|
||||
;;
|
||||
clear)
|
||||
shift
|
||||
if [ $# -eq 0 ]; then
|
||||
for t in $SUPPORTED_TOOLS; do run_tool clear "$t"; done
|
||||
clear_common
|
||||
else
|
||||
for t in "$@"; do run_tool clear "$t"; done
|
||||
fi
|
||||
;;
|
||||
list)
|
||||
echo "Supported tools: $SUPPORTED_TOOLS"
|
||||
;;
|
||||
-h|--help|help)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
setup_common
|
||||
for t in "$@"; do run_tool setup "$t"; done
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
name: prepare-patch-release
|
||||
description: Do all the tasks needed for a patch release of the project.argument-hint: [new-version]
|
||||
---
|
||||
|
||||
Do all the tasks needed for a patch release of the project. These patch
|
||||
releases generally happen on the first day of every month.
|
||||
|
||||
Arguments: `$ARGUMENTS`
|
||||
- First argument (optional): the version of the upcoming release we are
|
||||
preparing. If omitted, find the most recent tag on this branch, and the
|
||||
new version will update the third portion of the version. It might be
|
||||
either a version number (like `3.1.4.0`) or a tag (like `v3.1.4.0`).
|
||||
|
||||
Hint: The numeric "version" is a four-part numeric deignation with the pattern
|
||||
`MAJOR.MINOR.PATCH.TWEAK`. The "version tag" is usually the numeric version
|
||||
with a "v" prepended, for example, `v3.1.4.0`.
|
||||
|
||||
## Steps and Checklist
|
||||
|
||||
- [ ] Determine the version of the new release.
|
||||
- [ ] Update the main @CMakeLists.txt.
|
||||
- [ ] Use the "release-notes-update" skill to update @CHANGES.md.
|
||||
- [ ] Review the release notes to ensure that the changes do not deprecate any
|
||||
API calls or break API or ABI backward-compatibility, or remove support
|
||||
for any dependency or toolchain versions. If you think these rules are
|
||||
being violated, ask for confirmation.
|
||||
- [ ] Review @README.md for changes.
|
||||
- [ ] Review @INSTALL.md for changes.
|
||||
- [ ] Review @CREDITS.md for changes.
|
||||
- [ ] Review @SECURITY.md for changes.
|
||||
|
||||
## Steps to determine the versions of the last and new releases.
|
||||
|
||||
1. **Determine the previous tag** if not provided by looking at the
|
||||
most recent git tag in the current branch, and deducing the 4-part
|
||||
version number from that.
|
||||
2. The assumed new version for a patch release has the same major and minor
|
||||
numbers, the patch number is incremented by one since the last tag, and the
|
||||
tweak number is "0".
|
||||
3. If no optional version was present in the arguments, use the assumed new
|
||||
version.
|
||||
4. If a version was supplied in the arguments, double check that it differs
|
||||
from the last tag as explained above. If it does not, ask for verification
|
||||
that the version requested is correct before proceeding.
|
||||
|
||||
## Steps to update CMakeLists.txt
|
||||
|
||||
1. In the main @CMakeLists.txt, alter the version to that of the new release,
|
||||
if it isn't already the same.
|
||||
2. For a patch release, ensure that `${PROJECT_NAME}_SUPPORTED_RELEASE` should
|
||||
be set to ON. In main (not yet a supported release) it shold be OFF. If you
|
||||
find these to not be as expected, ask for confirmation of whether to fix.
|
||||
3. For a patch release, `PROJECT_VERSEION_RELEASE_TYPE` should be set to empty
|
||||
(""). In main, it will typically be "dev", "beta", or other designations.
|
||||
If you find these to not be as expected, ask for confirmation of whether to
|
||||
fix.
|
||||
|
||||
## Reviewing README.md
|
||||
|
||||
If this release added support for any new image file formats, be sure that
|
||||
README.md mentions them in its list of image formats supported.
|
||||
|
||||
## Reviewing INSTALL.md
|
||||
|
||||
If any of the new commits (as described in the release notes for this version)
|
||||
appear to add dependencies, or add support for new versions of dependencies,
|
||||
be sure that INSTALL.md is updated to include that dependency (if not already
|
||||
listed among the required and optional dependencies), and reflects the latest
|
||||
version that we claim to support.
|
||||
|
||||
Double check @externalpackages.cmake and ensure that any minimum required
|
||||
versions of dependencies that cmake will enforce match the oldest versions
|
||||
of those dependencies as documentd in INSTALL.md.
|
||||
|
||||
## Reviewing CREDITS.md
|
||||
|
||||
The @CREDITS.md file lists all known contributors to the project, sorted alpha
|
||||
by first name. In cases where an author's actual name is unknown, we use the
|
||||
GitHub userid.
|
||||
|
||||
Ensure that any authors referenced in the new release notes for the version we
|
||||
are releasing are inserted in the credit list, if they are not already
|
||||
present. You don't need to check older versions, we presume those have already
|
||||
been included.
|
||||
|
||||
## Reviewing SECURITY.md
|
||||
|
||||
The @SECURITY.md file lists which versions are currently supported at what
|
||||
levels, and lists all previously-fixed SVE's or security advisories. Be sure
|
||||
to check this file in older branches (the last two releases, say), and if you
|
||||
are preparing a patch release, also check in main and more recent (higher
|
||||
numbered) releases for more recently modified SECURITY.md, and be sure that
|
||||
this branch gets amended with any information that seems to have been updated
|
||||
more recently in those other branches. Check whichever is newer of the local
|
||||
and remote copy of that branch, since the local one may have had release notes
|
||||
or its version in CMakeLists.txt updated, but not yet pushed to GitHub.
|
||||
|
||||
|
||||
## Reference
|
||||
|
||||
- Full release procedures: `docs/dev/RELEASING.md`
|
||||
- Steps for updating release notes: `release-notes-update/SKILL.md`
|
||||
@@ -0,0 +1,217 @@
|
||||
---
|
||||
name: release-notes-update
|
||||
description: Generate or update release notes for a patch, minor, or major release, or just to update main. Run git-cliff, organize and edit the output per project conventions, and insert into CHANGES.md.
|
||||
argument-hint: [patch|minor|major|main] [prev-tag]
|
||||
---
|
||||
|
||||
Generate release notes for an OSL release.
|
||||
|
||||
Arguments: `$ARGUMENTS`
|
||||
- First argument (optional): release type — `patch` (default), `minor`, `major`, or `main`.
|
||||
- Second argument (optional): previous release tag (e.g. `v3.1.2.0`). If omitted, find the most recent tag automatically. If the release type is `main`, instead of a tag, look for the last commit at which the CHANGES.md file was updated.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Determine the previous tag** if not provided:
|
||||
```
|
||||
git describe --tags --abbrev=0
|
||||
```
|
||||
or look at recent tags: `git tag --sort=-version:refname | head -10`.
|
||||
However, if the "release type" is `main`, instead of a tag, just find
|
||||
the commit at which CHANGES.md was last updated.
|
||||
|
||||
2. **Run git-cliff** to get raw commit data:
|
||||
```
|
||||
git cliff -c src/doc/cliff.toml <prev-tag>..HEAD > /tmp/cliff-out.md
|
||||
```
|
||||
Read `/tmp/cliff-out.md` to see the raw output.
|
||||
|
||||
3. **Read CHANGES.md** to see the current top of the file and understand where to insert.
|
||||
|
||||
4. **Format the release notes** according to the release type:
|
||||
|
||||
### For patch releases:
|
||||
|
||||
Follow the skeleton in `docs/dev/Changes-skeleton-patch.md`:
|
||||
|
||||
```
|
||||
Release X.Y.Z.W (Month DD, YYYY) -- compared to X.Y.Z.W-1
|
||||
---------------------------------------------------------
|
||||
- *category*: Description. [#NNNN](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/NNNN) (by author)
|
||||
```
|
||||
|
||||
Rules:
|
||||
- **Remove** the section headings git-cliff generates; patch notes are a flat
|
||||
list.
|
||||
- **Add conventional commit prefixes** to any "uncategorized" entries (those
|
||||
lacking a `feat:`, `fix:`, etc. prefix).
|
||||
- **Reorder** entries logically: feature enhancements first, then bug fixes,
|
||||
then build/CI fixes, then internal changes, then test improvements, then
|
||||
docs/admin.
|
||||
- **Omit** entries that are purely internal and too minor to matter to users.
|
||||
Ask for confirmation about entries you propose to omit.
|
||||
- Prefer to use author's actual name if known. If the name cannot be found,
|
||||
the GitHub userid can be used instead.
|
||||
- Omit the author if it is the project leader, Larry Gritz, unless he is not
|
||||
the dominant author (at least 75% of commits) in this release.
|
||||
- Keep entries to one line each. Be terse but informative.
|
||||
- Use the format `*subsystem*:` for the category prefix (e.g., back end target
|
||||
such as `*optix*:` or `*batch*:`, utility like `*testrender*:` or
|
||||
`*osltoy*:`, class or API category like `*ShadingSystem*:`, or topic
|
||||
category such as `*build*:`, `*ci*:`, `*docs*:`).
|
||||
- We aim to make patch releases on the first day of each month. If we are
|
||||
within a few days of a month end, list the date as the beginning of the
|
||||
upcoming month. Ask for confirmation that this is the planned release date.
|
||||
|
||||
|
||||
### For minor or major releases:
|
||||
|
||||
Follow the skeleton in `docs/dev/Changes-skeleton-major.md`. Sections:
|
||||
|
||||
```
|
||||
Release X.Y.0.0 (Month, YYYY) -- compared to X.Y-1
|
||||
--------------------------------------------------
|
||||
|
||||
### New minimum dependencies, toolchain, and compatibility changes:
|
||||
### ✏️ OSL Language, standard library, and oslc compiler (for shader writers):
|
||||
### ⛰️ API changes and new ShadingSystem features (for renderer writers):
|
||||
### ☀️ testshade/testrender/osltoy improvements
|
||||
### 🐛/🔧 Internals: fixes, improvements, and developer concerns
|
||||
### 🏗 Build/test/CI and platform ports
|
||||
* CMake build system and scripts:
|
||||
* Dependency and platform support:
|
||||
* Testing and Continuous integration (CI) systems:
|
||||
### 📚 Notable documentation changes:
|
||||
### 🏢 Project Administration
|
||||
### 🤝 Contributors
|
||||
```
|
||||
|
||||
Note that the section outline may already be present, in which case you
|
||||
only need to fit items into the existing category outline.
|
||||
|
||||
Rules:
|
||||
- Group commits into sections; within each section, cluster related items together.
|
||||
- When needed, expand terse one-liners into enough prose that users understand what changed and why it matters.
|
||||
- For `feat:` commits, make sure the feature is explained sufficiently — don't just copy the commit subject.
|
||||
- For `api:` or `api!:` commits, clearly call out what changed in the public API.
|
||||
- Include PR links and author attribution for every entry.
|
||||
- The notes should "tell the story" of the release, not just be a dump of commit subjects.
|
||||
- We aim to make major/minor releases approximately in October 1 of each year. If the anticipted release date is already in the file, don't change it. If it is not present, ask for confirmation of the planned release date.
|
||||
|
||||
### For updating release notes in main:
|
||||
|
||||
Rules:
|
||||
- Generally, follow the rules for "major/minor releases", except as noted in other items below.
|
||||
- Don't apply a new skeleton of category listings unless they are not present for the upcoming release.
|
||||
|
||||
5. **Insert the formatted notes** into `CHANGES.md` in the appropriate place (as detailed below). Leave the existing content intact.
|
||||
- When updating `main` or preparing a `major` or `minor` release, insert the updates in the top section for the upcoming major/minor release. Insert a new set of category sections only if it's not already present.
|
||||
- When doing a `patch` release, insert the changes immediately above the last patch release of that branch, so that CHANGES.md lists releases in descending numerical (version) order.
|
||||
- When porting a set of release notes from a release branch into main, or from an older (obsolete) release branch to the current release branch, insert it into the right place to maintain overall descending order.
|
||||
|
||||
6. **Double check that the notes are adequately descriptive.** (See more
|
||||
detailed description of this step below.)
|
||||
|
||||
7. **Forward-port release notes from release branches if needed**
|
||||
|
||||
8. **Show a summary** of what was inserted and ask the user to review before finalizing.
|
||||
|
||||
## Forward-porting release notes
|
||||
|
||||
Release notes may have been generated independently in main, and release
|
||||
branches. When updating one branch, we ensure that any changes from older
|
||||
branches have been incorporated.
|
||||
|
||||
- When preparing `patch` release notes, check the CHANGES.md file in the
|
||||
"dev-X.(Y-1)" branch for the previous minor release family to identify any
|
||||
X.(Y-1).Z patch release notes that are not reflected in the current release
|
||||
notes that we are updating.
|
||||
- When updating `main` or doing a `major` or `minor` release, check the
|
||||
CHANGES.md file in both the "dev-X.(Y-1)" and "dev-X.(Y-2)" branches.
|
||||
Check whichever is newer of the local and remote copy of that branch, since
|
||||
the local one may have had release notes or its version in CMakeLists.txt
|
||||
updated, but not yet pushed to GitHub.
|
||||
- If any patch releases are present in the older dev branches checked, insert
|
||||
the release notes for those patch releases into the right positions in the
|
||||
current release notes that we are updating.
|
||||
- If a change is forward-ported in this manner and the same PR is an update in
|
||||
the current set of changes we are updating as our main task, document that
|
||||
in the current set of notes using the following convention: in the line of
|
||||
the notes, the explanation of the version where it appears should reflect
|
||||
the first version of all branches where it appeared, for example, `(3.2.0.0,
|
||||
3.1.3.0, 3.0.8.0)` to indicate that the patch was added to each of those
|
||||
versions. The versions should be listed in descending order.
|
||||
|
||||
## Useful abbreviations for category labels
|
||||
|
||||
| Abbrev | Meaning |
|
||||
|--------|---------|
|
||||
| build | CMake/build system |
|
||||
| deps | Changes to accommodate dependency or toolchain changes |
|
||||
| ci | CI/GitHub Actions |
|
||||
| docs | documentation |
|
||||
| int | internal/refactor |
|
||||
| test | testsuite or unit tests |
|
||||
| HEADER.h | Developer utilities in a public header file |
|
||||
|
||||
## Combining PRs into single entries
|
||||
|
||||
To be more concise and easier to read, within a release's notes, related
|
||||
PRs/commits can be combined into a single bullet-point line, which would look
|
||||
like
|
||||
```
|
||||
- *category*: Combined Description. [#NNNN1](URL) (by author1) [#NNNN2](URL2) (by author2) [#NNNN2](URL2) (by author2)
|
||||
|
||||
```
|
||||
if fully combined, or if explained one by one,
|
||||
```
|
||||
- *category*: Description 1 [#NNNN1](URL) (by author1), amendment 2, [#NNNN2](URL2) (by author2), amendment 3, [#NNNN3](URL3) (by author3)
|
||||
```
|
||||
Choose the fully combined or explained one by one based on which is more clear
|
||||
to the reader.
|
||||
|
||||
If the authors are all the same, only have the author designation at the end.
|
||||
|
||||
Here are the cases where it's ok to combine commits in this way:
|
||||
- If it is clear that multiple PRs are part of the same feature or fix,
|
||||
consisting of an initial commit, and subsequent smaller changes or
|
||||
continuations of the same topic.
|
||||
- An initial commit, and a subsequent commit that is obviously a fix to a bug
|
||||
in the initial commit.
|
||||
- "CI" changes that all only add new cases to the test matrix.
|
||||
- "CI" changes that all only fix spontaneous breakages in the GitHub runners.
|
||||
- "Build" changes that are all just minor updates to versions of dependencies
|
||||
that we support or test against.
|
||||
|
||||
Some more examples of combined commit messages:
|
||||
|
||||
```
|
||||
- feat: Add GPS metadata functionality for TIFF [PR1](PR URL 1) [PR2](PR URL 2) [PR3](PR URL 3) (by author).
|
||||
- ci: New CI variants for MSVS 2026 [PR1](PR URL 1) (by author1), VFX Platform 2027 [PR2](PR URL 2) (by author2).
|
||||
- ci: Various fixes for unexpected changes to GitHub Actions runners [PR1](PR URL 1), [PR2](PR URL 2) (by author)
|
||||
- build: Added support for gcc 15 [PR1](PR URL 1) (by author1), OpenEXR 3.5.1 [PR2](PR URL 2) (by author2), libtiff 4.8 [PR3](PR URL 3) (by author3).
|
||||
```
|
||||
|
||||
Always ask for confirmation before combining commits in this manner. Confirm
|
||||
separately for each proposed combination of a group of multiple original
|
||||
commits into a single commit. Give the user the opportunity to revise the
|
||||
combined description or request other changes for the grouping.
|
||||
|
||||
## Double check that the notes are adequately descriptive
|
||||
|
||||
For newly added items for this release, read the short descriptions provided
|
||||
by git-cliff, double check them against the full commit messages to be sure
|
||||
the one-line summary is adequate. If the summary is misleading, too brief and
|
||||
leaving out the fact that an important thing was changed, or not adequately
|
||||
capturing the scope of changes, feel free to propose an alternate wording that
|
||||
will make it more clear to readers what changed as a result of the PR. Ask for
|
||||
confirmation on these and explain why you felt the one-line description wasn't
|
||||
enough.
|
||||
|
||||
## Reference
|
||||
|
||||
Full release procedures: `docs/dev/RELEASING.md`
|
||||
Patch skeleton: `docs/dev/Changes-skeleton-patch.md`
|
||||
Major skeleton: `docs/dev/Changes-skeleton-major.md`
|
||||
Example good patch notes: https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/releases/tag/v1.15.2.0
|
||||
Example good major/minor notes: https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/releases/tag/v1.15.0.0
|
||||
@@ -11,3 +11,11 @@ build
|
||||
.vscode
|
||||
.envrc
|
||||
.DS_Store
|
||||
|
||||
# AI coding tool directories — generated locally by .agents/setup-agent
|
||||
.claude/
|
||||
.codex/
|
||||
.cursor/
|
||||
.opencode/
|
||||
.github/copilot-instructions.md
|
||||
/specs
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
# OSL Agent Guide
|
||||
|
||||
This file provides guidance to coding assistants when working with code in
|
||||
this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Open Shading Language (OSL) is a production shading language for VFX/animation
|
||||
renderers, maintained by the Academy Software Foundation. It compiles `.osl`
|
||||
shader source to `.oso` bytecode, then JIT-compiles via LLVM to native code at
|
||||
render time. C++17 codebase.
|
||||
|
||||
|
||||
## Repo map
|
||||
|
||||
**Core libraries**
|
||||
|
||||
- `src/liboslcomp/` — Shader compiler. Flex/Bison lexer+parser → AST → `.oso`
|
||||
bytecode. Entry point: `oslcomp.h`
|
||||
- `src/liboslexec/` — Shader execution engine. Loads `.oso`, optimizes shader
|
||||
groups, JIT-compiles to native via LLVM. Key files: `backendllvm.cpp`,
|
||||
`llvm_gen.cpp`, `llvm_ops.cpp`, `instance.cpp`. Contains `wide/`
|
||||
subdirectory for SIMD batched execution (SSE2/AVX/AVX-512)
|
||||
- `src/liboslquery/` — Query compiled shader metadata and parameters
|
||||
- `src/liboslnoise/` — Noise function implementations
|
||||
- `src/libbsdl/` — BSDF/closure library
|
||||
|
||||
**Command line tools**
|
||||
|
||||
- `src/oslc/` — Compiler CLI (`oslc`)
|
||||
- `src/oslinfo/` — Shader info query tool (`oslinfo`)
|
||||
- `src/testshade/` — Test harness that executes shaders on rectangular arrays
|
||||
of points, saves output as images.
|
||||
- `src/testrender/` — Minimal path-tracing renderer demonstrating OSL
|
||||
integration.
|
||||
- `src/osltoy/` — Qt-based GUI shader editor (optional)
|
||||
|
||||
**Public APIs/headers**
|
||||
|
||||
Headers in `src/include/OSL/`: `oslexec.h`, `oslcomp.h`, `oslquery.h`, `rendererservices.h` (abstract interface renderers must implement).
|
||||
|
||||
Namespaces:
|
||||
- `OSL` (outer), `OSL::pvt` (private implementation of internal-only utilities)
|
||||
- Versioned inner namespace: `v{MAJOR}_{MINOR}`
|
||||
|
||||
|
||||
## Build and verification
|
||||
|
||||
Common build commands via the Makefile convenience wrapper:
|
||||
```bash
|
||||
make # configure, build, install (Release)
|
||||
make debug # debug build
|
||||
make clean # wipe build dir (needed when switching branches/modes)
|
||||
make clang-format # format all source files
|
||||
make test # full testsuite
|
||||
make test TEST=<pattern> # subset matching regex
|
||||
```
|
||||
|
||||
Or directly with cmake:
|
||||
```bash
|
||||
cmake -B build -S .
|
||||
cmake --build build --target install
|
||||
ctest --test-dir build -R <pattern> --output-on-failure
|
||||
```
|
||||
|
||||
By default, builds into `./build` and installs into `./dist`.
|
||||
|
||||
## Testsuite notes
|
||||
|
||||
- Test output lands in `build/testsuite/<testname>/`; references in
|
||||
`testsuite/<testname>/ref/`
|
||||
- Read `testsuite/TESTSUITE-README.md` before updating references or
|
||||
diagnosing failures
|
||||
- For platform-specific diffs, add a variant ref (e.g. `out-win.txt`) rather
|
||||
than overwriting
|
||||
- Be conservative loosening image diff thresholds — use the minimum needed
|
||||
- Check uploaded CI artifacts before changing references when local
|
||||
reproduction is unclear
|
||||
|
||||
## Code formatting and file conventions
|
||||
|
||||
- `clang-format` enforced (`.clang-format`); CI rejects non-conforming code —
|
||||
run `make clang-format` before committing
|
||||
- Lines ~80 cols; ASCII only in code and comments; `#pragma once` for headers
|
||||
- New files: standard copyright + SPDX notice
|
||||
- `CamelCase` classes, `snake_case` locals, `ALL_CAPS` macros, `m_foo` private
|
||||
members
|
||||
- 3 blank lines between free functions/classes; 1 between class methods; max 1
|
||||
blank line inside a function body
|
||||
- `//` for regular comments; `///` Doxygen for public API
|
||||
- If a file has a strong local style, imitate that.
|
||||
|
||||
|
||||
## C++ guidelines
|
||||
|
||||
- Error handling: prefer `bool` returns, explicit status propagation, and
|
||||
`errorfmt()`-style reporting — not exceptions — consistent with the
|
||||
surrounding subsystem
|
||||
- Preserve API, ABI, and behavior compatibility unless the task explicitly
|
||||
requires a break
|
||||
- For hot paths: no hidden allocation in inner loops or parallel regions;
|
||||
precompute outside hot paths
|
||||
|
||||
|
||||
## OIIO utility types (prefer over raw C++ equivalents)
|
||||
|
||||
The [OpenImageIO](http://github.com/AcademySoftwareFoundation/OpenImageIO) (OIIO) project is a key dependency of OSL and the two projects are co-developed. Many utilities shared by both projects live in OpenImageIO.
|
||||
|
||||
Prefer C++17 `std` and Imath types except as noted below. Avoid introducing
|
||||
new third-party dependencies without a strong reason. Rely liberally on these
|
||||
classes and headers from OIIO:
|
||||
|
||||
- `OIIO::TypeDesc` - light-weight description of simple types (aliased
|
||||
as `OSL::TypeDesc`)
|
||||
- `OIIO::ustring` and `OIIO::ustringhash` - light-weight unique string heavily
|
||||
used in OSL. (Aliased as `OSL::ustring` and `OSL::ustringhash`).
|
||||
- `OIIO::string_view` — non-owning string/`char*` (like `std::string_view`).
|
||||
Aliased as `OSL::string_view`.
|
||||
- `OIIO::span` / `OIIO::cspan` — non-owning contiguous data (like
|
||||
`std::span`); use instead of pointer+length pairs. Aliased as `OSL::span`
|
||||
and `OSL::cspan`.
|
||||
- `OpenImageIO/strutil.h` : string processing utilities
|
||||
- `OIIO::Strutil::print()` , also aliased as `OSL::print` — string
|
||||
formatting/output; **never** use `printf` or `<<` streams
|
||||
- `OpenImageIO/fmath.h` — fast/safe math, avoids NaN/Inf
|
||||
- `OIIO::Filesystem::*` in `OpenImageIO/filesystem.h` — file/directory
|
||||
utilities
|
||||
- `OpenImageIO/simd.h` — SIMD helpers
|
||||
- `OpenImageIO/parallel.h` — parallel loops, etc.
|
||||
- `OpenImageIO/unittest.h` — unit test macros
|
||||
|
||||
|
||||
## Safe programming in C++
|
||||
|
||||
- Try to avoid passing raw pointers as function arguments.
|
||||
- Use `std::unique_ptr` and `std::shared_ptr` rather than raw pointers when
|
||||
ownership must be expressed.
|
||||
- Prefer `OSL::string_view` when passing non-mutable strings or C-style
|
||||
`char*` strings.
|
||||
- Prefer `OSL::span` rather than passing raw pointers + a separate length, or
|
||||
passing a raw pointer with an implied (but not explicitly passed) length.
|
||||
`OSL::cspan` is a synonmym when the underlying data is const/non-mutable.
|
||||
`OSL::span<std::byte>` or `OSL::cspan<std::byte>` can be used to represent
|
||||
contiguous untyped data. These are our equivalent of C++ `std::span`.
|
||||
- Use these guidelines always for new code, but do not churn existing code
|
||||
just to "modernize" it.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Compilation Pipeline
|
||||
|
||||
OSL source → (Flex/Bison) → AST → (liboslcomp) → `.oso` bytecode → (liboslexec) → LLVM IR → JIT native code
|
||||
|
||||
|
||||
## Code Style
|
||||
|
||||
- clang-format config in `.clang-format` (WebKit-based, 80-char line limit, 4-space indent)
|
||||
- Run `make clang-format` before submitting changes
|
||||
|
||||
## Key Dependencies
|
||||
|
||||
- **LLVM 14+** (JIT compilation), **OpenImageIO 2.5+** (textures, image I/O, utilities), **Imath 3.1+** (math types), **Flex/Bison** (parser generation), **pybind11** (Python bindings, optional)
|
||||
|
||||
## Commits and PRs
|
||||
|
||||
- Keep PRs narrow and easy to review.
|
||||
- Prefix format: `type(subsystem): message` — subsystem is optional but helpful.
|
||||
- Valid types: `fix:`, `feat:`, `perf:`, `api:`, `int:`, `build:`, `test:`,
|
||||
`ci:`, `docs:`, `refactor:`, `style:`, `admin:`, `revert:`.
|
||||
- Add a subsystem tag when it helps, e.g. `fix(exr):` or `perf(IBA):`.
|
||||
- Write commit messages and PR descriptions that explain why the change is
|
||||
needed, what behavior changes, and any non-obvious implementation choices.
|
||||
|
||||
## Spec-driven design
|
||||
|
||||
Feature specifications live in `docs/dev/specs/` (not at the project root).
|
||||
When using speckit commands (`/speckit-specify`, `/speckit-plan`, etc.), always
|
||||
use `docs/dev/specs/` as the base directory for all spec paths, overriding any
|
||||
default of `specs/`. When creating a new spec, set `SPECIFY_FEATURE_DIRECTORY`
|
||||
to `docs/dev/specs/<NNN-feature-name>` and write that path to
|
||||
`.specify/feature.json`.
|
||||
|
||||
The speckit bash scripts expect a `specs/` directory at the project root. A
|
||||
symlink satisfies this without committing speckit infrastructure to the repo.
|
||||
This symlink is set up by the setup-agents script, and is not committed to
|
||||
the repo. All saved specs live in `docs/dev/specs`.
|
||||
|
||||
## AI policy
|
||||
|
||||
Refer to `docs/dev/AI_Policy.md`.
|
||||
|
||||
See `docs/dev/AI_Policy.md`. Key rule: if AI assistance contributed materially
|
||||
to a patch, the commit must include `Assisted-by: <TOOL> / <MODEL>`. The human
|
||||
author is responsible for understanding, testing, and defending all changes.
|
||||
|
||||
## References
|
||||
|
||||
- `CONTRIBUTING.md` : general contribution guidelines and recap of coding
|
||||
conventions.
|
||||
@@ -82,6 +82,26 @@ High-level summary:
|
||||
Please do read the whole [Policy on AI Coding Assistants](docs/dev/AI_Policy.md)
|
||||
for all the details.
|
||||
|
||||
The repository includes configuration for several AI coding assistants
|
||||
(Claude Code, Cursor, GitHub Copilot, OpenAI Codex, Opencode). Much of this
|
||||
uses symbolic links to keep a single source of truth in `AGENTS.md`. **Windows
|
||||
users** must enable symlink support before cloning or the agent integrations
|
||||
will silently malfunction:
|
||||
|
||||
1. Enable [Windows Developer Mode](https://learn.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development)
|
||||
2. `git config --global core.symlinks true`
|
||||
3. Then clone (or re-clone) the repository.
|
||||
|
||||
The repository supports several AI coding assistants (Claude Code, Cursor,
|
||||
GitHub Copilot, OpenAI Codex, Opencode). After cloning, run the setup script
|
||||
for whichever tool(s) you use:
|
||||
|
||||
```
|
||||
.agents/setup-agent claude # or: cursor, codex, opencode, copilot, all
|
||||
```
|
||||
|
||||
See [docs/dev/Agentic_Coding.md](docs/dev/Agentic_Coding.md) for details.
|
||||
|
||||
|
||||
Contributor License Agreement (CLA) and Intellectual Property
|
||||
-------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
# Ignore temporary specs that may be ephemeral or local to an individual
|
||||
# developer, to prevent cluttering the output of `git status` and prevent
|
||||
# people from accidentally checking in specs that are only meant for them.
|
||||
specs/*
|
||||
|
||||
# But don't ignore the ones that belong to this project and are checked in. As
|
||||
# we add specs that we intend to commit and make available to all project
|
||||
# developers, they must be individually added here.
|
||||
!specs/002-backend-cpp
|
||||
@@ -0,0 +1,57 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
<!-- Copyright Contributors to the OpenImageIO Project. -->
|
||||
|
||||
# Agentic coding / coding assistants
|
||||
|
||||
Please start by reading [our policy on using "AI" coding
|
||||
assistsants](AI_Policy.md).
|
||||
|
||||
|
||||
## Multi-tool setup
|
||||
|
||||
We aim to allow people to use whatever agentic or coding assistant tools they
|
||||
want. The repository ships with a setup script that configures tool-specific
|
||||
files locally for whichever assistant(s) you use.
|
||||
|
||||
### Generic: `AGENTS.md` and `.agents/`
|
||||
|
||||
As much as possible, we use identical instructions and files across all coding
|
||||
assistants.
|
||||
|
||||
`AGENTS.md` is the main file providing overall repo-specific instructions and
|
||||
context to agents. Many coding agents already read this file directly; for
|
||||
those that don't, the setup script creates the necessary links or wrappers.
|
||||
|
||||
`.agents/skills/` is where shared skill files live. Many tools find skills
|
||||
here automatically; for those that need them elsewhere, the setup script
|
||||
creates the appropriate links.
|
||||
|
||||
### Running the setup script
|
||||
|
||||
After cloning, run `.agents/setup-agent <tool>` for the tool(s) you use:
|
||||
|
||||
```
|
||||
.agents/setup-agent claude # Claude Code
|
||||
.agents/setup-agent cursor # Cursor
|
||||
.agents/setup-agent codex # OpenAI Codex
|
||||
.agents/setup-agent opencode # Opencode
|
||||
.agents/setup-agent copilot # GitHub Copilot
|
||||
.agents/setup-agent all # all of the above
|
||||
```
|
||||
|
||||
The script is idempotent — running it multiple times is safe. To undo:
|
||||
|
||||
```
|
||||
.agents/setup-agent clear # remove all tool setup
|
||||
.agents/setup-agent clear claude # remove setup for one tool
|
||||
```
|
||||
|
||||
Tool-specific directories (`.claude/`, `.cursor/`, `.codex/`, `.opencode/`,
|
||||
`.github/copilot-instructions.md`) are created locally only and are listed in
|
||||
`.gitignore`. Each developer runs the script for the tool they use; nothing
|
||||
tool-specific is committed to the repository.
|
||||
|
||||
The script header contains per-tool documentation (what each tool reads
|
||||
natively, what requires setup, and links to relevant docs) — consult it when
|
||||
adding support for a new tool or updating the strategy for an existing one.
|
||||
|
||||
Reference in New Issue
Block a user