From citadel
Monitors working directory for file changes and @citadel: markers via git diff polling against baseline commit, auto-triggering skills via /do. For automatic batch reactions; not one-off tasks.
npx claudepluginhub sethgammon/citadel --plugin citadelThis skill uses the workspace's default tool permissions.
Use when the user wants automatic reactions to file changes or marker comments (`@citadel:`).
Performs code reviews on uncommitted git changes or latest commits, auto-generates and inserts CHANGELOG entries if missing, runs lints, and proactively fixes P0-P1-P2 issues.
Automatically detects issue references in git commit messages and artifacts, updates GitHub/Gitea issues with progress comments, closures, labels, and blocker notifications.
Manages Claude Code repository hooks for adding, configuring, troubleshooting, enabling/disabling, and enforcing rules. Delegates to docs-management for official documentation.
Share bugs, ideas, or general feedback.
Use when the user wants automatic reactions to file changes or marker comments (@citadel:).
Do NOT use for one-off file inspection or tasks that need human judgment per file.
Use when: running a file sentinel that triggers a skill or command automatically when watched paths change. Don't use when: monitoring CI status on a PR (use /pr-watch); running a one-shot verification check (use /verify).
/watch start does NOT call CronCreate by default. Only pass --remote
to use Anthropic's routine system, and only after explicit user confirmation.
CronCreate counts against the 15 routine runs / 24h cap — at the default
5-minute interval a watch exhausts the quota in under an hour.
/watch start (no --remote flag)CronCreate. Leave cronId: null in state.status: "watching".Watch state created: .planning/watch-state.json
Baseline: {commit hash, first 7 chars}
To start real-time watching, run in a separate terminal:
npm run watch:local
For cloud-persistent polling (machine off, user away):
/watch start --remote (uses CronCreate, counts against 15/day cap)
/watch start --remoteOnly when --remote is explicitly passed:
CronCreate, which counts against your 15 routine
runs / 24h quota. At a 5-minute interval this exhausts the quota in under
an hour. Continue? (y/N)"CronCreate.| Command | Behavior |
|---|---|
/watch start | Default: create state, prompt user to run npm run watch:local |
/watch start --remote | Use CronCreate polling (counts against 15/day quota — requires confirmation) |
/watch start --interval {N}m | Set poll interval for --remote mode (default: 5m) |
/watch stop | Stop watching, tear down cron |
/watch status | Show watch state, last scan time, pending actions |
/watch scan | Run a single scan now (manual trigger) |
.planning/watch-state.json if it existsstatus is "watching":
/watch stop first, then continuegit rev-parse HEAD to get the current commit hashlastScanTime, skip commit-based diffing)lastScanCommitCronCreate:
interval: "{N}m" (default: 5m)
command: "/watch scan"
Save the cron ID in the state file.
Write .planning/watch-state.json:
{
"status": "watching",
"lastScanCommit": "abc1234",
"lastScanTime": null,
"interval": "5m",
"cronId": "{id from step 3 or null}",
"pendingActions": [],
"processedMarkers": [],
"stats": {
"scansRun": 0,
"markersFound": 0,
"intakeItemsCreated": 0,
"skillsDispatched": 0
}
}
Watch started.
Interval: every {N}m
Baseline: {commit hash, first 7 chars}
State: .planning/watch-state.json
.planning/watch-state.json. If missing or not "watching": "No watch is active."CronDelete: {cronId} — if cronId is missing or deletion fails, continue."status": "stopped", "cronId": null. Preserve all other fields.Watch stopped.
Scans completed: {stats.scansRun}
Markers found: {stats.markersFound}
Intake items created: {stats.intakeItemsCreated}
Skills dispatched: {stats.skillsDispatched}
.planning/watch-state.json missing: "No watch configured. Use /watch start to begin."pendingActions non-empty, list each: [{action}] {file}:{line} -- {description}.planning/watch-state.jsonlastScanCommit from git rev-parse HEAD and status: "watching".Git mode (primary):
git diff --name-only {lastScanCommit} HEAD (committed changes)git diff --name-only (unstaged) and git diff --name-only --cached (staged)Fallback mode (no git):
find . -newer {timestamp_file} -type fnode_modules/, .git/, .planning/, dist/, build/If no files changed: update lastScanTime and stats.scansRun, exit early.
Search changed files for:
| Pattern | Languages |
|---|---|
// @citadel: {action} {description} | JS, TS, Go, Rust, C, Java |
# @citadel: {action} {description} | Python, Shell, YAML, Ruby |
/* @citadel: {action} {description} */ | CSS, multi-line C-style |
<!-- @citadel: {action} {description} --> | HTML, Markdown |
Action-to-skill mapping:
| Action | Skill |
|---|---|
review | /review |
test | /test-gen |
fix | /systematic-debugging |
document | /doc-gen |
refactor | /refactor |
todo | intake item |
Unknown actions become intake items with the action preserved as metadata.
Deduplication: Compare against processedMarkers (stored as "{file}:{line}:{action}"). Skip already-processed markers. Remove from processedMarkers when the file is modified again.
| File pattern | Auto-action |
|---|---|
*.test.*, *.spec.*, __tests__/* | Queue: "run tests" intake item |
*.md in docs/ or project root | Queue: "doc staleness check" intake item |
src/**/*.ts, src/**/*.tsx | Queue: "changed source" intake item |
package.json, tsconfig.json | Queue: "config change" intake item (high priority) |
For each new marker:
/do {action} in {file} at line {line}: {description}processedMarkers, increment stats.skillsDispatchedBatch limit: Dispatch at most 5 per scan. Queue overflow in pendingActions.
Filename: watch-{timestamp}-{index}.md in .planning/intake/
---
source: watch
priority: {normal|high}
created: {ISO timestamp}
---
# {brief description}
File: {file path}
Change type: {new|modified|deleted}
Classification: {test change|doc change|source change|config change|marker overflow}
{If marker: Action: {action}, Description: {description}}
Detected by /watch scan at {ISO timestamp}.
Before writing, check for duplicates (glob .planning/intake/watch-*, grep for file path).
lastScanCommit: git rev-parse HEADlastScanTime: current ISO timestampstats.scansRun, stats.markersFoundpendingActions and processedMarkersManual scan:
Scan complete.
Files changed: {N}
Markers found: {new} ({total} total)
Actions dispatched: {N} (batch limit: 5)
Intake items: {N} written to .planning/intake/
Pending actions: {N}
Cron poll: silent.
.planning/intake/ for /autopilot./do — never invokes skills directly./daemon can start a watch alongside a campaign.init-project.js triggers a scan if state is "watching"..planning/ missing: Create on first scan.
Not a git repo: Fall back to timestamp detection; warn once.
No files changed: Update stats, exit silently.
Unknown action: Treat as intake item, preserve raw action.
Deleted file: Skip marker scanning; write intake item noting deletion.
Large diff (100+ files): Cap at 50 per scan, queue rest.
Binary files: Skip during marker scanning.
Corrupted state: Reset to defaults, preserve processedMarkers if readable.
CronCreate not available: Warn and suggest manual /watch scan.
Scan overlap: Skip if lastScanTime within last 60 seconds.
Marker removed: Remove stale entries from processedMarkers on each scan.
Disclosure: "Starting file watch on [paths]. Triggers [skill] on change. Stop with Ctrl+C."
Reversibility: amber — runs sentinel that triggers other skills on file change; triggered skills may modify files; stop with Ctrl+C and run /watch stop
Trust gates:
/watch start: Output confirmation block. No HANDOFF./watch stop: Output stop summary with lifetime stats./watch scan (manual): Output scan report with counts./watch scan (cron): Silent./watch status: Output current state.