AI Coding Instructions
Reusable coding instructions, agent skills, custom agents, and prompt templates for AI coding agents.
ai/
├── common/ # shared — same files read as-is by every tool
│ ├── instructions/*.instructions.md # general + per-language/platform, one copy each
│ ├── skills/<name>/SKILL.md
│ └── config/direnv-skate.sh # shared — tool-agnostic, not Claude/Copilot-specific
├── copilot/
│ ├── agents/<name>.md # Copilot-only — alias-based tools, disable-model-invocation
│ └── config/mcp.json # Copilot-only — VS Code workspace MCP template (${env:VAR} expansion)
└── claude/
├── agents/<name>.md # Claude Code-only — real tool names
├── skills/<name>/SKILL.md # Claude Code-only skills — not mirrored to Copilot
└── config/ # Claude Code-only — settings.json (permissions.deny) + mcp.json (${VAR} expansion)The applyTo frontmatter on instruction files is a Copilot-specific glob-scoping mechanism, but it's inert, harmless text to every other consumer (Claude Code's @import just inlines raw file content; Codex/AGENTS.md is plain text) — so there's exactly one copy of each instruction file, used as-is everywhere. Only agents/ needs a real per-tool split, since Copilot and Claude Code parse genuinely different, type-checked frontmatter schemas there.
Four kinds of content: instructions (always-on guidance), skills (workflows loaded only when relevant — avoids bloating context), agents (specialist personas with restricted tools), config (settings/MCP templates for scoping permissions and secrets — see Secrets & Permission Scoping).
NOTE
See the dotfiles repo for a real-world example of scripting this setup end-to-end (personal Claude/Copilot settings, MCP servers) as part of a full machine bootstrap.
Quick Start
One-liner — bootstraps instructions + skills for both tools at once:
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/shell/setup-ai-agent.sh" | bash -s -- -t bothUse -t claude or -t copilot to set up just one, -p <preset> for a stack-specific instruction set (javascript, python, kubernetes, go), -a to also install agents, -g for personal/global instead of repo setup, -c (with -g -t copilot) to also populate Copilot CLI's personal file, or -r to safely run rtk init -g --copilot without losing existing content (see RTK below). See setup-ai-agent.sh or run it with -h for details.
Or do it by hand, one curl at a time:
Claude Code
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/general.instructions.md" \
-o "CLAUDE.md"
for skill in code-review repository-audit commit-message pull-request; do
mkdir -p ".claude/skills/${skill}"
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/skills/${skill}/SKILL.md" \
-o ".claude/skills/${skill}/SKILL.md"
doneGitHub Copilot
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/general.instructions.md" \
-o ".github/copilot-instructions.md"
for skill in code-review repository-audit commit-message pull-request; do
mkdir -p ".github/skills/${skill}"
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/skills/${skill}/SKILL.md" \
-o ".github/skills/${skill}/SKILL.md"
doneThat's a working baseline for either tool. See the sections below for scoped per-language instructions, personal/global setup, custom agents, and every other option.
Claude Code
Repo setup
Claude Code reads CLAUDE.md at the repository root. Point it at the general instructions, then append whichever scoped files match the repo's stack:
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/general.instructions.md" \
-o "CLAUDE.md"
# then append the scoped files relevant to this repo, e.g.:
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/docker.instructions.md" \
>> "CLAUDE.md"The
applyTofrontmatter at the top of each file is inert text to Claude Code — it just gets read as part of the prompt, no parsing/scoping applied.
See Available Instructions for the full list of scoped files.
Personal instructions (user profile)
Claude Code always reads ~/.claude/CLAUDE.md for every repo — no settings/opt-in flag required (unlike Copilot's chat.instructionsFilesLocations). Since Claude Code has no applyTo-style scoping, only tool-agnostic, always-relevant guidance belongs here — the General Development instructions fit, the language/platform-scoped ones don't.
Use CLAUDE.md's @path/to/file import syntax to compose it alongside other personal files rather than overwriting the whole thing:
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/general.instructions.md" \
-o "${HOME}/.claude/general-instructions.md"
echo "@general-instructions.md" >> "${HOME}/.claude/CLAUDE.md"Skills
Claude Code reads skills from .claude/skills/ (repo) or ~/.claude/skills/ (personal, applies to every repo — no opt-in needed). The ai/common/skills/*/SKILL.md files are already in Claude's native format (no conversion needed):
# Repo
for skill in code-review repository-audit commit-message pull-request; do
mkdir -p ".claude/skills/${skill}"
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/skills/${skill}/SKILL.md" \
-o ".claude/skills/${skill}/SKILL.md"
done
# Personal (swap the target dir)
for skill in code-review repository-audit commit-message pull-request; do
mkdir -p "${HOME}/.claude/skills/${skill}"
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/skills/${skill}/SKILL.md" \
-o "${HOME}/.claude/skills/${skill}/SKILL.md"
done- Automatic: Claude Code detects when a skill is relevant and loads it (based on
descriptionin frontmatter) - Explicit: Include the skill name with a
/prefix in your prompt:/code-review analyze the auth module
Custom Agents
Claude Code subagents live in .claude/agents/<name>.md. The frontmatter differs from Copilot's agent format — tools: lists actual tool names instead of aliases, and there's no disable-model-invocation flag (Claude Code auto-delegates based on description, or you invoke the agent by name). Canonical source: ai/claude/agents/.
Some agents also tune model: and effort: for cost/quality — cheaper model: haiku for mechanical, low-risk work; effort: high (same model, more reasoning) for analysis where missing a real bug/vuln is costly. code-reviewer also preloads the code-review skill via skills: [code-review] instead of duplicating its checklist inline, so the two can't drift out of sync. These fields are Claude Code-only — Copilot's agent schema doesn't have model/effort/skills in the same shape, so ai/copilot/agents/ intentionally doesn't mirror them.
| Name | Description | Model / Effort |
|---|---|---|
| Code Reviewer | Read-only code review specialist (preloads code-review skill) | effort: high |
| Security Auditor | Security-focused vulnerability analysis | effort: high |
| Refactorer | Improves structure while preserving behavior | default |
| Test Writer | Generates tests following project conventions | model: haiku |
| Doc Writer | Generates and updates documentation from code | model: haiku |
| Migration Assistant | Dependency upgrades and framework migrations | default |
| IaC Reviewer | Reviews Terraform, K8s, Docker, CI/CD configs | effort: high |
| Copilot tool alias | Claude Code tool name(s) |
|---|---|
read | Read, Glob |
search | Grep, Glob |
edit | Edit, Write |
execute | Bash |
web | WebFetch, WebSearch |
agent | Task |
todo | TodoWrite |
# Repo
mkdir -p .claude/agents
for agent in code-reviewer security-auditor refactorer test-writer doc-writer migration-assistant iac-reviewer; do
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/claude/agents/${agent}.md" \
-o ".claude/agents/${agent}.md"
done
# Personal (swap the target dir) — applies to every repo, no opt-in needed
mkdir -p "${HOME}/.claude/agents"
for agent in code-reviewer security-auditor refactorer test-writer doc-writer migration-assistant iac-reviewer; do
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/claude/agents/${agent}.md" \
-o "${HOME}/.claude/agents/${agent}.md"
doneClaude-only Skills
Some skills are Claude Code-specific — either because they lean on Claude Code-only mechanisms, or because they're deliberately not worth mirroring to Copilot (e.g. they'd duplicate a capability Copilot already ships natively). These live in ai/claude/skills/ instead of ai/common/skills/, same SKILL.md format, just not distributed to ai/copilot/.
| Name | Description |
|---|---|
| Systematic Debugging | Reproduce → isolate → one hypothesis at a time, for bugs that resist a quick fix |
# Repo
mkdir -p .claude/skills/systematic-debugging
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/claude/skills/systematic-debugging/SKILL.md" \
-o ".claude/skills/systematic-debugging/SKILL.md"
# Personal (swap the target dir) — applies to every repo, no opt-in needed
mkdir -p "${HOME}/.claude/skills/systematic-debugging"
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/claude/skills/systematic-debugging/SKILL.md" \
-o "${HOME}/.claude/skills/systematic-debugging/SKILL.md"NOTE
Before reaching for a third-party skill pack (e.g. Superpowers-style marketplaces), check whether Claude Code already ships the capability natively — verify, simplify, security-review, loop, and schedule are built in as of this writing. Adding a whole marketplace on top duplicates those and is Claude-only anyway, so it fits this same ai/claude/skills/ model better than a blanket import — cherry-pick the specific workflow you're missing instead.
GitHub Copilot
VS Code
How it works
GitHub Copilot in VS Code reads instructions from several locations, including your home directory for skills:
| File/Folder | Purpose |
|---|---|
.github/copilot-instructions.md | Global workspace prompt — always active |
AGENTS.md, CLAUDE.md | Cross-tool alias — always active |
.github/instructions/*.instructions.md | Scoped — activated by applyTo glob |
.github/skills/<name>/SKILL.md | Agent skills (repo) — on demand |
~/.copilot/skills/<name>/SKILL.md | Agent skills (personal) — on demand, enabled by default |
~/.claude/skills/<name>/SKILL.md | Agent skills (personal, Claude alias) — on demand, enabled by default |
.github/agents/<name>.md | Custom agents — selectable from the agent picker |
.github/prompts/*.prompt.md | Prompt files — reusable templates |
Setup
Option 1 — General instructions only (quickest)
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/general.instructions.md" \
-o ".github/copilot-instructions.md"The
applyTofrontmatter at the top is harmless here —.github/copilot-instructions.mdisn't glob-scoped, it's always active regardless, so the 3-line header is just inert text.
Option 2 — Scoped instructions (recommended for multi-tech repos)
mkdir -p .github/instructions
INSTRUCTIONS="javascript docker kubernetes github-actions"
for name in $INSTRUCTIONS; do
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/${name}.instructions.md" \
-o ".github/instructions/${name}.instructions.md"
doneOption 3 — Full setup (instructions + skills + agents)
# Instructions
mkdir -p .github/instructions
for name in general javascript docker kubernetes github-actions; do
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/${name}.instructions.md" \
-o ".github/instructions/${name}.instructions.md"
done
# Skills
for skill in code-review repository-audit commit-message pull-request; do
mkdir -p ".github/skills/${skill}"
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/skills/${skill}/SKILL.md" \
-o ".github/skills/${skill}/SKILL.md"
done
# Agents
mkdir -p .github/agents
for agent in code-reviewer security-auditor; do
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/copilot/agents/${agent}.md" \
-o ".github/agents/${agent}.md"
doneSee Recommended setup by project type for stack-specific presets.
Personal instructions (user profile)
Create *.instructions.md files in ~/.copilot/instructions/ to apply personal conventions to all your workspaces. They are not enabled by default — opt in via chat.instructionsFilesLocations in your user settings.json:
mkdir -p ~/.copilot/instructions
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/general.instructions.md" \
-o "${HOME}/.copilot/instructions/general.instructions.md"Then enable in user settings.json (Cmd+Shift+P → "Open User Settings (JSON)"):
{
"chat.instructionsFilesLocations": {
".github/instructions": true,
"~/.copilot/instructions": true
}
}Configure via settings.json
All customization features can be enabled and relocated via settings. The workspace .vscode/settings.json applies to the project; your user settings.json applies globally.
{
// ── Instructions ─────────────────────────────────────────────────────────
// Where to look for *.instructions.md files (supports ~ expansion)
"chat.instructionsFilesLocations": {
".github/instructions": true, // workspace (default on)
".claude/rules": true, // workspace, Claude format
"~/.copilot/instructions": true, // personal — opt in to enable
"~/.claude/rules": true // personal, Claude format — opt in
},
"chat.includeApplyingInstructions": true, // auto-include files with matching applyTo
"chat.useAgentsMdFile": true, // AGENTS.md always-on
"chat.useClaudeMdFile": true, // CLAUDE.md always-on
// ── Skills ───────────────────────────────────────────────────────────────
// All four locations enabled by default
"chat.useAgentSkills": true,
"chat.agentSkillsLocations": {
".github/skills": true, // workspace
".claude/skills": true, // workspace, Claude alias
"~/.copilot/skills": true, // personal (default on)
"~/.claude/skills": true // personal, Claude alias (default on)
},
// ── Agents ───────────────────────────────────────────────────────────────
// Add personal agents location (not enabled by default)
"chat.agentFilesLocations": {
".github/agents": true, // workspace (default on)
"~/.copilot/agents": true // personal — add to enable
},
// ── Prompts ──────────────────────────────────────────────────────────────
"chat.promptFilesLocations": {
".github/prompts": true // workspace (default on)
},
// ── Per-feature instructions (commit, PR, review) ────────────────────────
// Note: codeGeneration.instructions is deprecated since VS Code 1.102
// use *.instructions.md files with applyTo: "**" instead
"github.copilot.chat.commitMessageGeneration.instructions": [
{ "file": ".github/instructions/commit-message.instructions.md" }
],
"github.copilot.chat.pullRequestDescriptionGeneration.instructions": [
{ "file": ".github/instructions/pull-request.instructions.md" }
],
"github.copilot.chat.reviewSelection.instructions": [
{ "file": ".github/instructions/code-review.instructions.md" }
],
// ── Monorepo ─────────────────────────────────────────────────────────────
// Discover instructions/skills/agents from parent folder when opening a subfolder
"chat.useCustomizationsInParentRepositories": false
}Git workflow instructions (commit + PR)
mkdir -p .github/instructions
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/commit-message.instructions.md" \
-o ".github/instructions/commit-message.instructions.md"
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/pull-request.instructions.md" \
-o ".github/instructions/pull-request.instructions.md"
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/code-review.instructions.md" \
-o ".github/instructions/code-review.instructions.md"CLI
Copilot CLI reads from both the repository and your home directory. Personal config in ~/.copilot/ is loaded every session across all repos.
| File | Scope |
|---|---|
~/.copilot/copilot-instructions.md | Personal (all sessions, all repos) |
~/.copilot/skills/<name>/SKILL.md | Personal skills (all repos) |
.github/copilot-instructions.md | Repository |
.github/skills/<name>/SKILL.md | Repository skills |
AGENTS.md, Copilot.md, GEMINI.md, CODEX.md | Repository (cross-tool aliases) |
Personal setup (applies to all repos)
# Personal instructions — always loaded in every Copilot CLI session
mkdir -p ~/.copilot
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/general.instructions.md" \
-o "${HOME}/.copilot/copilot-instructions.md"
# Personal skills — available everywhere
for skill in code-review repository-audit commit-message pull-request; do
mkdir -p "${HOME}/.copilot/skills/${skill}"
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/skills/${skill}/SKILL.md" \
-o "${HOME}/.copilot/skills/${skill}/SKILL.md"
doneKey CLI commands
| Command | Purpose |
|---|---|
/skills list | List available skills |
/skills info | Detail about a skill |
/skills reload | Reload after adding skills mid-session |
/plan | Create an implementation plan before coding |
/review | Review current changes |
/delegate | Offload work to cloud agent |
/model | Switch model mid-session |
/context | Show context window usage |
/fleet | Break task into parallel subtasks |
/clear or /new | Reset context between unrelated tasks |
Allowed tools
Pre-configure tool permissions via CLI flags:
copilot --allow-tool='shell(git:*)' --deny-tool='shell(git push)'Common patterns: shell(git:*), shell(npm run:*), shell(bun:*), write.
Agents
Agents define specialist personas with their own instructions and restricted tool access. Canonical source: ai/copilot/agents/.
| Name | Description | Tools |
|---|---|---|
| Code Reviewer | Read-only code review specialist | read, search |
| Security Auditor | Security-focused vulnerability analysis | read, search |
| Refactorer | Improves structure while preserving behavior | edit, search, read |
| Test Writer | Generates tests following project conventions | edit, search, read, execute |
| Doc Writer | Generates and updates documentation from code | edit, search, read |
| Migration Assistant | Dependency upgrades and framework migrations | edit, search, read, execute, web |
| IaC Reviewer | Reviews Terraform, K8s, Docker, CI/CD configs | read, search |
Setup (repository)
mkdir -p .github/agents
for agent in code-reviewer security-auditor refactorer test-writer doc-writer migration-assistant iac-reviewer; do
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/copilot/agents/${agent}.md" \
-o ".github/agents/${agent}.md"
doneSetup (personal — VS Code only)
Personal agents are supported in VS Code via chat.agentFilesLocations. Copilot CLI does not support a personal agents directory.
mkdir -p ~/.copilot/agents
for agent in code-reviewer security-auditor refactorer test-writer doc-writer migration-assistant iac-reviewer; do
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/copilot/agents/${agent}.md" \
-o "${HOME}/.copilot/agents/${agent}.md"
doneEnable in user settings.json:
{
"chat.agentFilesLocations": {
".github/agents": true,
"~/.copilot/agents": true
}
}Using agents
- VS Code: Select the agent from the agent dropdown in the Chat panel
- Copilot CLI: Copilot auto-delegates to an agent when it detects a matching task (unless
disable-model-invocation: true) - Cloud agent: Agents are available when assigned to a task on GitHub
Agent configuration
Agent files support these YAML frontmatter properties:
---
description: What the agent does (required)
tools: ["read", "search"] # Restrict available tools (omit for all)
model: claude-sonnet-4-5 # Override model (optional)
disable-model-invocation: false # If true, must be manually selected
---Tool aliases: read, edit, search, execute (shell), web, agent, todo.
Reference
Available Instructions
All of these live in ai/common/instructions/ and are used as-is by Copilot, Claude Code, and Codex/AGENTS.md — pick the ones relevant to what you're setting up (General Development always applies; add scoped ones for the languages/platforms actually in the repo).
| Name | Description | Instruction Name | Type |
|---|---|---|---|
| General Development | Universal development practices | general | General |
| Code Review | Code review guidelines (lightweight) | code-review | Review |
| Commit Message | Conventional Commits format | commit-message | Git |
| Pull Request | PR description best practices | pull-request | Git |
| JavaScript/TypeScript | Scoped to JS/TS files (incl. Bun) | javascript | Language |
| Go | Scoped to Go files | go | Language |
| Bash/Shell | Scoped to shell scripts | shell | Language |
| Python | Scoped to Python files (FastAPI) | python | Language |
| TypeScript Monorepo | Complete TS monorepo setup | ts-monorepo | Architecture |
| Docker | Scoped to Dockerfiles | docker | Platform |
| Kubernetes/Helm | Scoped to K8s YAML files | kubernetes | Platform |
| GitHub Actions | Scoped to workflow files | github-actions | CI/CD |
| Terraform/IaC | Scoped to Terraform files | terraform | Platform |
Available Skills
Skills are folders of instructions loaded on demand when the agent detects they're relevant to a task. All live in ai/common/skills/ — same format works for Copilot and Claude Code.
| Name | Description | Skill Name |
|---|---|---|
| Code Review | Full review methodology with language checks & decision framework | code-review |
| Repository Audit | Comprehensive repo analysis (quality, security, performance, DevOps) | repository-audit |
| Commit Message | Conventional Commits generation | commit-message |
| Pull Request | PR description generation | pull-request |
commit-message, pull-request, and repository-audit also carry Claude Code-only frontmatter for perf/scope: allowed-tools grants narrowly-scoped tool calls (e.g. Bash(git diff *)) without a permission prompt while the skill is active, model: haiku (commit-message only) switches the session to a cheaper/faster model for that one formulaic turn, and effort: high (repository-audit) asks for more thorough reasoning on a task that's explicitly meant to be exhaustive. VS Code's Copilot schema doesn't recognize these fields — it flags them as an unsupported-attribute hint and ignores them, the same way it already ignores unrelated fields — so the shared file stays a no-op-safe superset rather than forking per tool.
See the Claude Code and Copilot sections above for setup commands and for the available custom agents (agent tables live there since the frontmatter schema is tool-specific). Claude-only skills (not mirrored to Copilot) are listed separately under Claude-only Skills.
Discovery order by tool
Each tool has its own discovery model. Repository-level settings take precedence over personal ones.
| Tool | Repo instructions | Skills | Personal |
|---|---|---|---|
| Claude Code | CLAUDE.md, .claude/skills/ | .claude/skills/ | ~/.claude/CLAUDE.md, ~/.claude/skills/ |
| VS Code Chat | .github/copilot-instructions.md, .github/instructions/, AGENTS.md, CLAUDE.md | .github/skills/, .claude/skills/, ~/.copilot/skills/*, ~/.claude/skills/* | ~/.copilot/instructions/†, ~/.claude/rules/†, ~/.claude/CLAUDE.md |
| Copilot CLI | .github/copilot-instructions.md, .github/skills/, AGENTS.md | .github/skills/, ~/.copilot/skills/ | ~/.copilot/copilot-instructions.md |
| GitHub cloud agent | .github/copilot-instructions.md, .github/instructions/, AGENTS.md | — | — |
| OpenAI Codex | AGENTS.md, CODEX.md | — | — |
* Enabled by default in VS Code via chat.agentSkillsLocations. † Opt-in — add to chat.instructionsFilesLocations to enable.
Alias files (AGENTS.md, CLAUDE.md, Copilot.md, GEMINI.md, CODEX.md) provide cross-tool compatibility — most modern coding agents recognize them.
Token-Efficient Terminal Commands (RTK)
rtk is a CLI proxy that filters/compresses terminal command output (git, tests, build/lint, containers, GitHub CLI, AWS, IaC, package managers, 100+ commands total) before it reaches the model context, cutting token usage by 60-90%.
Install the auto-rewrite hook — this is the only setup that guarantees every supported command gets rewritten, since it intercepts the shell tool call itself instead of relying on the model to remember to type rtk:
# Install (macOS/Linux)
brew install rtk
# or: curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh
# Enable the hook for your tool
rtk init -g --copilot # GitHub Copilot (VS Code + CLI)
rtk init -g # Claude Code (default agent)None of the instruction files in ai/common/instructions/ embed RTK guidance as prompt text — the hook is the only mechanism relied on. general.instructions.md just points to this section.
NOTE
The auto-rewrite hook only intercepts shell/terminal tool calls. Built-in editor tools (e.g. VS Code's file read/search tools) are never rewritten by the hook — they're a separate, already token-efficient code path.
WARNING
rtk init -g --copilot overwrites ~/.copilot/copilot-instructions.md entirely with just its own RTK block — it does not merge into existing content. If you've already set up custom personal instructions there (see Copilot — Personal setup), running it directly will wipe them. Use setup-ai-agent.sh's -r flag instead — it backs up your existing content, runs the real installer, and merges the two back together (safe to re-run, never duplicates the block):
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/shell/setup-ai-agent.sh" | bash -s -- -rrtk init -g (Claude Code, no --copilot flag) doesn't have this problem — it writes to its own separate file and is imported via @RTK.md, not baked into CLAUDE.md directly.
Sanity-checking hook coverage — run rtk discover occasionally; it scans recent session history for commands rtk already supports but that weren't rewritten (rtk gain shows the reverse: what's already been saved). Two things it reports are not live problems: commands from sessions that predate the hook being installed, and the handful of commands rtk doesn't support yet at all (check its unhandled-commands list against rtk-ai/rtk issues before assuming the hook itself is broken).
Secrets & Permission Scoping
Neither tool lets you allowlist which ambient shell env vars get inherited by the agent — that can only be enforced at the OS/process level (a wrapper script, a container, or per-project loaders like direnv). What both tools do support natively:
1. Never hardcode secrets in MCP config — reference them instead.
Both tools expand env vars inline, just with different syntax:
| Tool | Syntax | Where it works |
|---|---|---|
| Claude Code | ${VAR} / ${VAR:-default} | command, args, env, url, headers in .mcp.json / ~/.claude.json |
| Copilot (VS Code) | ${env:VAR} | Same fields, in .vscode/mcp.json / user mcp.json |
If the var is unset and there's no default, the literal ${VAR} is left in place and the tool warns at startup — so a missing secret fails loudly instead of silently sending an empty string. Templates: ai/claude/config/mcp.json, ai/copilot/config/mcp.json.
# Claude Code — project-scoped MCP config (git-safe as long as it only ever contains ${VAR} references, never literal values)
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/claude/config/mcp.json" -o ".mcp.json"
# Copilot — VS Code workspace MCP config
mkdir -p .vscode
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/copilot/config/mcp.json" -o ".vscode/mcp.json"NOTE
Claude Code's MCP scopes: project (.mcp.json, committed, shared) is for config only — keep it to ${VAR} references. Local and user scope (both inside ~/.claude.json, never committed) are where an actual secret value belongs if you'd rather set it directly than export it from the shell. Mixing the two up is how a real token ends up committed.
2. Deny reads/edits of secret files, regardless of what's in the prompt.
permissions.deny in .claude/settings.json blocks the Read/Edit tools from ever touching matching paths — it's enforced by the harness, not by the model remembering not to look. Template: ai/claude/config/settings.json.
mkdir -p .claude
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/claude/config/settings.json" -o ".claude/settings.json"{
"permissions": {
"deny": [
"Read(.env)", "Read(**/.env.*)", "Read(**/*.pem)", "Read(**/*.key)", "Read(**/secrets/**)",
"Edit(.env)", "Edit(**/.env.*)", "Edit(**/*.pem)", "Edit(**/*.key)", "Edit(**/secrets/**)",
"Bash(skate list *)"
]
}
}WARNING
Read/Edit denies only gate those two tools. They do not stop the Bash tool from running cat .env — Bash permission rules match command prefixes (e.g. Bash(git push:*)), not arbitrary file content, so there's no generic blanket block for shell access to a secret file. If a repo's Bash access needs to be untrusted around secrets, the real boundary is not putting the secret in a file/env var the agent's shell can reach in the first place (see direnv note below), not a permission rule.
What Bash denies are reliable for is blocking a specific known-dangerous subcommand by name — e.g. Bash(skate list *) above blocks skate's "dump every stored secret" command while leaving skate get <key> (fetch one named secret) untouched. This is verified to hold even in auto-approved/bypass-permissions modes (deny rules are checked first, per-subcommand, even inside compound/piped commands) — worth doing for any secret manager's equivalent of "list/dump everything," not just skate.
Copilot/VS Code has no equivalent to permissions.deny today — the closest is not exporting secrets into the ambient environment a Copilot session inherits, plus ordinary .gitignore hygiene.
3. Prefer .claude/settings.local.json (gitignored) over .claude/settings.json (committed) for anything personal — e.g. a locally-relaxed permission or a machine-specific env value. Team-wide defaults like the deny rules above belong in the committed file; anything you wouldn't want a teammate to inherit belongs in the local one.
4. Scope ambient secrets per-project with direnv, instead of exporting everything to every shell. A single shell-profile file that exports every secret you own (common pattern: one env.sh sourced from .zshrc) means every shell — including any agent's Bash tool — inherits all of them, regardless of what the current project actually needs. direnv scopes exports to the current directory instead, loading them on cd in and unloading them on cd out. Paired with a secret manager (e.g. skate), a project only ever declares the specific secrets it needs:
# ~/.config/direnv/direnvrc — fetch once, add the source line once
mkdir -p ~/.config/direnv
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/config/direnv-skate.sh" \
-o ~/.config/direnv/direnv-skate.sh
echo 'source "$HOME/.config/direnv/direnv-skate.sh"' >> ~/.config/direnv/direnvrc
# .envrc in a given project — declares only what that project needs
use skate ARGOCD_API_TOKEN=argocd_api_token CONTEXT7_API_KEY=context7_api_keydirenv allow (required once per directory before it'll load) is itself a safety feature — a .envrc can't silently start exporting things just because you cd'd into a repo you don't fully trust yet.
NOTE
This scopes ambient exposure — what ends up in env, what an agent might echo/log by accident — it does not stop an agent with Bash access from running skate get <any-key> directly. It's a least-privilege default, not a hard boundary against a deliberately-instructed agent; pair it with the permissions.deny rules above, not instead of them.
Recommended setup by project type
JavaScript / TypeScript
mkdir -p .github/instructions
for name in javascript docker github-actions; do
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/${name}.instructions.md" \
-o ".github/instructions/${name}.instructions.md"
donePython (FastAPI)
mkdir -p .github/instructions
for name in python docker github-actions; do
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/${name}.instructions.md" \
-o ".github/instructions/${name}.instructions.md"
doneKubernetes / DevOps
mkdir -p .github/instructions
for name in kubernetes docker github-actions terraform shell; do
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/${name}.instructions.md" \
-o ".github/instructions/${name}.instructions.md"
doneGo
mkdir -p .github/instructions
for name in go docker github-actions; do
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/${name}.instructions.md" \
-o ".github/instructions/${name}.instructions.md"
doneFor Claude Code, curl the same files and cat/append them into CLAUDE.md instead (see Claude Code — Repo setup).
AGENTS.md (OpenAI Codex / GitHub Copilot coding agent)
AGENTS.md at the repository root is read by OpenAI Codex and any agent following the AGENTS.md convention:
curl -fsSL "https://raw.githubusercontent.com/this-is-tobi/tools/main/ai/common/instructions/general.instructions.md" \
-o "AGENTS.md"Troubleshooting
Instructions not applied (GitHub Copilot)
- File must be in
.github/(or.github/instructions/for scoped files) - Scoped files must end in
.instructions.md - Reload VS Code after adding new files or changing settings
- Check
applyTofrontmatter — patterns are glob-style and case-sensitive:
---
applyTo: "**/*.{js,ts}"
---Skills not loading
- Skill files must be named exactly
SKILL.md(case-sensitive) - Each skill needs its own subdirectory under
.github/skills/(or.claude/skills/for Claude Code) - YAML frontmatter must include
nameanddescription - Use
/skills listin Copilot CLI to verify discovery - Use
/skills reloadafter adding skills mid-session
Instruction file too large
Split the content across multiple scoped files. Each one is only loaded when its applyTo pattern matches the file being edited (Copilot) or when you choose to include it (Claude Code). For task-specific workflows, convert to skills instead — they're only loaded when relevant.