feat(cursor): add symlink management for markdown commands and cleanup of stale symlinks

- Implemented symlink creation for all markdown files in cursor/commands to ~/.cursor/commands.
- Added a cleanup function to remove stale symlinks in ~/.cursor/commands that no longer point to existing files.
- Updated the configuration process to include cleanup of stale symlinks when setting up the cursor editor.
This commit is contained in:
Jim Myhrberg
2025-12-19 11:53:42 +00:00
parent 06126dba31
commit 9b66fffa4b
2 changed files with 321 additions and 3 deletions

View File

@@ -0,0 +1,265 @@
---
source: https://github.com/RayFernando1337/llm-cursor-rules/blob/main/generate-agents.md
---
# Task: Analyze this codebase and generate a hierarchical AGENTS.md structure
## Context & Principles
You are going to help me create a **hierarchical AGENTS.md system** for this codebase. This is critical for AI coding agents to work efficiently with minimal token usage.
### Core Principles
1. **Root AGENTS.md is LIGHTWEIGHT** - Only universal guidance, links to sub-files
2. **Nearest-wins hierarchy** - Agents read the closest AGENTS.md to the file being edited
3. **JIT (Just-In-Time) indexing** - Provide paths/globs/commands, NOT full content
4. **Token efficiency** - Small, actionable guidance over encyclopedic documentation
5. **Sub-folder AGENTS.md files have MORE detail** - Specific patterns, examples, commands
## Your Process
### Phase 1: Repository Analysis
First, analyze the codebase structure and provide me with:
1. **Repository type**: Monorepo, multi-package, or simple single project?
2. **Primary technology stack**: Languages, frameworks, key tools
3. **Major directories/packages** that should have their own AGENTS.md:
- Apps (e.g., `apps/web`, `apps/api`, `apps/mobile`)
- Services (e.g., `services/auth`, `services/transcribe`)
- Packages/libs (e.g., `packages/ui`, `packages/shared`)
- Workers/jobs (e.g., `workers/queue`, `workers/cron`)
4. **Build system**: pnpm/npm/yarn workspaces? Turborepo? Lerna? Or simple?
5. **Testing setup**: Jest, Vitest, Playwright, pytest? Where are tests?
6. **Key patterns to document**:
- Code organization patterns
- Important conventions (naming, styling, commits)
- Critical files that serve as good examples
- Anti-patterns to avoid
Present this as a **structured map** before generating any AGENTS.md files.
---
### Phase 2: Generate Root AGENTS.md
Create a **lightweight root AGENTS.md** (~100-200 lines max) that includes:
#### Required Sections
**1. Project Snapshot** (3-5 lines)
- Repo type (monorepo/simple)
- Primary tech stack
- Note that sub-packages have their own AGENTS.md files
**2. Root Setup Commands** (5-10 lines)
- Install dependencies (root level)
- Build all
- Typecheck all
- Test all
**3. Universal Conventions** (5-10 lines)
- Code style (TypeScript strict? Prettier? ESLint?)
- Commit format (Conventional Commits?)
- Branch strategy
- PR requirements
**4. Security & Secrets** (3-5 lines)
- Never commit tokens
- Where secrets go (.env patterns)
- PII handling if applicable
**5. JIT Index - Directory Map** (10-20 lines)
Structure like:
```
## JIT Index (what to open, not what to paste)
### Package Structure
- Web UI: `apps/web/` → [see apps/web/AGENTS.md](apps/web/AGENTS.md)
- API: `apps/api/` → [see apps/api/AGENTS.md](apps/api/AGENTS.md)
- Auth service: `services/auth/` → [see services/auth/AGENTS.md](services/auth/AGENTS.md)
- Shared packages: `packages/**/` → [see packages/README.md for details]
### Quick Find Commands
- Search for a function: `rg -n "functionName" apps/** packages/**`
- Find a component: `rg -n "export.*ComponentName" apps/web/src`
- Find API routes: `rg -n "export const (GET|POST)" apps/api`
```
**6. Definition of Done** (3-5 lines)
- What must pass before a PR is ready
- Minimal checklist
---
### Phase 3: Generate Sub-Folder AGENTS.md Files
For EACH major package/directory identified in Phase 1, create a **detailed AGENTS.md** that includes:
#### Required Sections
**1. Package Identity** (2-3 lines)
- What this package/app/service does
- Primary tech/framework for THIS package
**2. Setup & Run** (5-10 lines)
- Install command (if different from root)
- Dev server command
- Build command
- Test command
- Lint/typecheck commands
**3. Patterns & Conventions** (10-20 lines)
**THIS IS THE MOST IMPORTANT SECTION**
- File organization rules (where things go)
- Naming conventions specific to this package
- Preferred patterns with **file examples**:
```
- ✅ DO: Use functional components like `src/components/Button.tsx`
- ❌ DON'T: Use class components like `src/legacy/OldButton.tsx`
- ✅ Forms: Copy pattern from `src/components/forms/ContactForm.tsx`
- ✅ API calls: Use `src/lib/api/client.ts` wrapper, see example in `src/hooks/useUser.ts`
```
**4. Touch Points / Key Files** (5-10 lines)
Point to the most important files to understand this package:
```
- Auth logic: `src/auth/provider.tsx`
- API client: `src/lib/api.ts`
- Types: `src/types/index.ts`
- Config: `src/config.ts`
```
**5. JIT Index Hints** (5-10 lines)
Specific search commands for this package:
```
- Find a React component: `rg -n "export function .*" src/components`
- Find a hook: `rg -n "export const use" src/hooks`
- Find route handlers: `rg -n "export async function (GET|POST)" src/app`
- Find tests: `find . -name "*.test.ts"`
```
**6. Common Gotchas** (3-5 lines, if applicable)
- "Auth requires `NEXT_PUBLIC_` prefix for client-side use"
- "Always use `@/` imports for absolute paths"
- "Database migrations must be run before tests: `pnpm db:migrate`"
**7. Pre-PR Checks** (2-3 lines)
Package-specific command to run before creating a PR:
```
pnpm --filter @repo/web typecheck && pnpm --filter @repo/web test && pnpm --filter @repo/web build
```
---
### Phase 4: Special Considerations
For each AGENTS.md file, also consider:
**A. Design System / UI Package**
If there's a design system or UI library:
```markdown
## Design System
- Components: `packages/ui/src/components/**`
- Use design tokens from `packages/ui/src/tokens.ts` (never hardcode colors)
- See component gallery: `pnpm --filter @repo/ui storybook`
- Examples:
- Buttons: Copy `packages/ui/src/components/Button/Button.tsx`
- Forms: Copy `packages/ui/src/components/Input/Input.tsx`
```
**B. Database / Data Layer**
If there's a database service:
```markdown
## Database
- ORM: Prisma / Drizzle / TypeORM
- Schema: `prisma/schema.prisma`
- Migrations: `pnpm db:migrate`
- Seed: `pnpm db:seed`
- **NEVER** run migrations in tests; use `test-db` script
- Connection: via `src/lib/db.ts` singleton
```
**C. API / Backend Service**
```markdown
## API Patterns
- REST routes: `src/routes/**/*.ts`
- Auth middleware: `src/middleware/auth.ts` (apply to protected routes)
- Validation: Use Zod schemas in `src/schemas/**`
- Error handling: All errors thrown as `ApiError` from `src/lib/errors.ts`
- Example endpoint: See `src/routes/users/get.ts` for full pattern
```
**D. Testing Package**
```markdown
## Testing
- Unit tests: `*.test.ts` colocated with source
- Integration tests: `tests/integration/**`
- E2E tests: `tests/e2e/**` (Playwright)
- Run single test: `pnpm test -- path/to/file.test.ts`
- Coverage: `pnpm test:coverage` (aim for >80%)
- Mock external APIs using `src/test/mocks/**`
```
---
## Output Format
Provide the files in this order:
1. **Analysis Summary** (from Phase 1)
2. **Root AGENTS.md** (complete, ready to copy)
3. **Each Sub-Folder AGENTS.md** (one at a time, with file path)
For each file, use this format:
```
---
File: `AGENTS.md` (root)
---
[full content here]
---
File: `apps/web/AGENTS.md`
---
[full content here]
---
File: `services/auth/AGENTS.md`
---
[full content here]
```
---
## Constraints & Quality Checks
Before generating, verify:
- [ ] Root AGENTS.md is under 200 lines
- [ ] Root links to all sub-AGENTS.md files
- [ ] Each sub-file has concrete examples (actual file paths)
- [ ] Commands are copy-paste ready (no placeholders unless unavoidable)
- [ ] No duplication between root and sub-files
- [ ] JIT hints use actual patterns from the codebase (ripgrep, find, glob)
- [ ] Every "✅ DO" has a real file example
- [ ] Every "❌ DON'T" references a real anti-pattern or legacy file
- [ ] Pre-PR checks are single copy-paste commands

59
siren
View File

@@ -44,9 +44,19 @@ define_settings() {
STATIC_SYMLINKS["harper-ls/file_dictionaries"]="$(harper_config_dir)/file_dictionaries"
STATIC_SYMLINKS["harper-ls/ignored_lints"]="$(harper_config_dir)/ignored_lints"
# Conditionally add `mcp.json` for Cursor.
# Conditionally add symlinks for Cursor.
if [[ "${SETUP_EDITOR}" == "cursor" ]]; then
STATIC_SYMLINKS["cursor/mcp.json"]="${HOME}/.cursor/mcp.json"
# Symlink all markdown files from cursor/commands/ to ~/.cursor/commands/
local cmd_file
for cmd_file in "${SCRIPT_DIR}/cursor/commands/"*.md; do
if [[ -f "${cmd_file}" ]]; then
local filename
filename="$(basename "${cmd_file}")"
STATIC_SYMLINKS["cursor/commands/${filename}"]="${HOME}/.cursor/commands/${filename}"
fi
done
fi
}
@@ -420,6 +430,42 @@ symlink_static_config() {
done
}
# Private function: Remove stale symlinks in ~/.cursor/commands that point to
# files in cursor/commands/ that no longer exist.
cleanup_stale_cursor_commands() {
local cursor_commands_dir="${HOME}/.cursor/commands"
local source_commands_dir="${SCRIPT_DIR}/cursor/commands"
# Skip if the target directory doesn't exist.
if [[ ! -d "${cursor_commands_dir}" ]]; then
return
fi
local link
for link in "${cursor_commands_dir}"/*; do
# Skip if glob didn't match anything (returns literal pattern).
[[ -e "${link}" || -L "${link}" ]] || continue
# Skip if not a symlink.
if [[ ! -L "${link}" ]]; then
continue
fi
# Get the symlink target.
local target
target="$(readlink "${link}")"
# Check if the symlink points to our source directory.
if [[ "${target}" == "${source_commands_dir}/"* ]]; then
# If the target file no longer exists, remove the symlink.
if [[ ! -e "${target}" ]]; then
info "Removing stale symlink: ${link}"
rm -f "${link}"
fi
fi
done
}
# Find the editor CLI command.
#
# Returns: Editor command path via `STDOUT`.
@@ -1131,8 +1177,9 @@ install_extension() {
fi
# Try direct installation first; fall back to downloading `*.vsix` if needed.
if ! install_extension_direct "${editor_cmd}" "${extension}" \
"${target_version}" "${force_install}"; then
if [ -n "$FORCE_DOWNLOAD_VSX" ] ||
! install_extension_direct "${editor_cmd}" "${extension}" \
"${target_version}" "${force_install}"; then
local latest_version
if [[ "${use_latest}" != "false" ]]; then
@@ -1214,6 +1261,12 @@ do_static_config() {
do_config() {
symlink_editor_config
symlink_static_config
# Clean up stale symlinks for Cursor commands.
if [[ "${SETUP_EDITOR}" == "cursor" ]]; then
cleanup_stale_cursor_commands
fi
info "Symlink setup complete!"
}