Skip to content

Instantly share code, notes, and snippets.

@kaushikgopal
Created March 23, 2026 21:23
Show Gist options
  • Select an option

  • Save kaushikgopal/48646acde54f7661f2833aa68266d944 to your computer and use it in GitHub Desktop.

Select an option

Save kaushikgopal/48646acde54f7661f2833aa68266d944 to your computer and use it in GitHub Desktop.
Makefile for wiring AI tools (Claude, Codex, OpenCode, Gemini) to a shared AGENTS.md repo
ROOT := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
dir ?=
GRAY := \033[1;30m
NC := \033[0m
.PHONY: help setup setup-user setup-project setup-project-here
help:
@printf "%b\n" "$(GRAY)Targets:$(NC)"
@printf "%b\n" "$(GRAY) make setup-user$(NC)"
@printf "%b\n" "$(GRAY) make setup-project dir=/path/to/repo$(NC)"
@printf "%b\n" "$(GRAY) make setup-project-here # run from target repo with: make -f /path/to/aikado/Makefile setup-project-here$(NC)"
setup: setup-user
setup-user:
@printf "%b\n" "$(GRAY)••••••• setting up agent symlinks$(NC)"
@# legacy cleanup
@if [ -L "$(HOME)/.ai" ] || [ -e "$(HOME)/.ai" ]; then \
printf "%b\n" "$(GRAY)••••••• removing legacy $(HOME)/.ai$(NC)"; \
rm -rf "$(HOME)/.ai"; \
fi
@if [ -L "$(HOME)/.agents" ]; then \
printf "%b\n" "$(GRAY)••••••• removing legacy $(HOME)/.agents symlink$(NC)"; \
rm "$(HOME)/.agents"; \
fi
@# global agent paths
@mkdir -p "$(HOME)/.agents"
@ln -sfn "$(ROOT)/skills" "$(HOME)/.agents/skills"
@ln -sfn "$(ROOT)/AGENTS.md" "$(HOME)/AGENTS.md"
@printf "%b\n" "$(GRAY)••••••• symlinked $(ROOT)/AGENTS.md -> $(HOME)/AGENTS.md$(NC)"
@printf "%b\n" "$(GRAY)••••••• symlinked $(ROOT)/skills -> $(HOME)/.agents/skills$(NC)"
@# opencode
@mkdir -p "$(HOME)/.config/opencode"
@ln -sfn "$(ROOT)/config/opencode/opencode.json" "$(HOME)/.config/opencode/opencode.json"
@ln -sfn "$(ROOT)/config/opencode/tui.json" "$(HOME)/.config/opencode/tui.json"
@rm -rf "$(HOME)/.config/opencode/agents"
@ln -sfn "$(ROOT)/agents" "$(HOME)/.config/opencode/agents"
@rm -rf "$(HOME)/.config/opencode/plugins"
@ln -sfn "$(ROOT)/config/opencode/plugins" "$(HOME)/.config/opencode/plugins"
@rm -rf "$(HOME)/.config/opencode/themes"
@ln -sfn "$(ROOT)/config/opencode/themes" "$(HOME)/.config/opencode/themes"
@# claude
@if [ -L "$(HOME)/.claude" ]; then \
printf "%b\n" "$(GRAY)••••••• removing legacy $(HOME)/.claude symlink$(NC)"; \
rm "$(HOME)/.claude"; \
fi
@mkdir -p "$(HOME)/.claude"
@ln -sfn "$(ROOT)/CLAUDE.md" "$(HOME)/.claude/CLAUDE.md"
@printf "%b\n" "$(GRAY)••••••• symlinked $(ROOT)/CLAUDE.md -> $(HOME)/.claude/CLAUDE.md$(NC)"
@rm -rf "$(HOME)/.claude/agents"
@ln -sfn "$(ROOT)/agents" "$(HOME)/.claude/agents"
@rm -rf "$(HOME)/.claude/commands"
@ln -sfn "$(ROOT)/commands" "$(HOME)/.claude/commands"
@rm -rf "$(HOME)/.claude/skills"
@ln -sfn "$(ROOT)/skills" "$(HOME)/.claude/skills"
@ln -sfn "$(ROOT)/config/claude/settings.json" "$(HOME)/.claude/settings.json"
@ln -sfn "$(ROOT)/config/claude/statusline.sh" "$(HOME)/.claude/statusline.sh"
@rm -rf "$(HOME)/.claude/hooks"
@ln -sfn "$(ROOT)/config/claude/hooks" "$(HOME)/.claude/hooks"
@# codex
@mkdir -p "$(HOME)/.codex"
@if [ ! -f "$(HOME)/.codex/config.toml" ]; then \
cp "$(ROOT)/config/codex/config.toml" "$(HOME)/.codex/config.toml"; \
printf "%b\n" "$(GRAY)••••••• copied starter Codex config to $(HOME)/.codex/config.toml$(NC)"; \
else \
printf "%b\n" "$(GRAY)••••••• leaving existing $(HOME)/.codex/config.toml in place$(NC)"; \
fi
@rm -rf "$(HOME)/.codex/agents"
@ln -sfn "$(ROOT)/config/codex/agents" "$(HOME)/.codex/agents"
@rm -rf "$(HOME)/.codex/prompts"
@ln -sfn "$(ROOT)/commands" "$(HOME)/.codex/prompts"
@ln -sfn "$(ROOT)/AGENTS.md" "$(HOME)/.codex/AGENTS.md"
@printf "%b\n" "$(GRAY)••••••• agent setup complete$(NC)"
setup-project:
@if [ -z "$(dir)" ]; then \
printf "%b\n" "$(GRAY)usage: make setup-project dir=/path/to/repo$(NC)"; \
exit 1; \
fi
@project_input='$(dir)'; \
case "$$project_input" in \
~) project_input="$$HOME" ;; \
~/*) project_input="$$HOME/$${project_input#~/}" ;; \
esac; \
project_dir="$$(cd "$$project_input" && pwd)"; \
printf "%b\n" "$(GRAY)••••••• setting up agent structure in $$project_dir $(NC)"; \
: "root instruction files"; \
if [ ! -f "$$project_dir/AGENTS.md" ]; then \
touch "$$project_dir/AGENTS.md"; \
printf "%b\n" "$(GRAY)••••••• created AGENTS.md $(NC)"; \
fi; \
if [ ! -f "$$project_dir/CLAUDE.md" ]; then \
printf "See @AGENTS.md\n" > "$$project_dir/CLAUDE.md"; \
printf "%b\n" "$(GRAY)••••••• created CLAUDE.md -> @AGENTS.md $(NC)"; \
fi; \
: "project agent directories"; \
mkdir -p \
"$$project_dir/.agents/agents" \
"$$project_dir/.agents/skills" \
"$$project_dir/.agents/commands" \
"$$project_dir/.agents/tasks" \
"$$project_dir/.claude" \
"$$project_dir/.codex" \
"$$project_dir/.opencode" \
"$$project_dir/.gemini"; \
: "fold legacy scratch directories into .agents/tasks when possible"; \
for legacy_dir in "$$project_dir/.agents/plans" "$$project_dir/.agents/tmp"; do \
if [ -d "$$legacy_dir" ]; then \
find "$$legacy_dir" -mindepth 1 -maxdepth 1 -exec mv -n {} "$$project_dir/.agents/tasks/" \; 2>/dev/null; \
if rmdir "$$legacy_dir" 2>/dev/null; then \
printf "%b\n" "$(GRAY)••••••• folded $${legacy_dir##*/} into .agents/tasks $(NC)"; \
else \
printf "%b\n" "$(GRAY)••••••• left $$legacy_dir in place; resolve name conflicts in .agents/tasks manually $(NC)"; \
fi; \
fi; \
done; \
: "tool-specific links"; \
rm -rf "$$project_dir/.claude/agents"; \
ln -sfn ../.agents/agents "$$project_dir/.claude/agents"; \
rm -rf "$$project_dir/.claude/commands"; \
ln -sfn ../.agents/commands "$$project_dir/.claude/commands"; \
rm -rf "$$project_dir/.claude/skills"; \
ln -sfn ../.agents/skills "$$project_dir/.claude/skills"; \
rm -rf "$$project_dir/.opencode/agents"; \
ln -sfn ../.agents/agents "$$project_dir/.opencode/agents"; \
rm -rf "$$project_dir/.codex/prompts"; \
ln -sfn ../.agents/commands "$$project_dir/.codex/prompts"; \
printf '{"context":{"fileName":["AGENTS.md"]}}\n' > "$$project_dir/.gemini/settings.json"; \
: "gitignore entries"; \
if ! grep -qxF ".agents/tasks/**" "$$project_dir/.gitignore" 2>/dev/null; then \
printf ".agents/tasks/**\n" >> "$$project_dir/.gitignore"; \
printf "%b\n" "$(GRAY)••••••• added .agents/tasks/** to .gitignore $(NC)"; \
fi; \
printf "%b\n" "$(GRAY)••••••• agent project setup complete in $$project_dir $(NC)"
# Run this target from inside the repo you want to initialize:
# cd ~/dev/oss/project-xxx
# make -f /path/to/aikado/Makefile setup-project-here
setup-project-here:
@$(MAKE) -f "$(lastword $(MAKEFILE_LIST))" setup-project dir=.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment