
Imperatives
- 296 installs
- 1 repo stars
- Updated May 26, 2026
- camacho/ai-skills
imperatives is a Claude Code skill from camacho/ai-skills that authors and enforces imperative-style agent directives so sessions follow fixed execution rules, guardrails, and step order across repos.
About
imperatives is an agent-governance skill in camacho/ai-skills that teaches Claude to write and apply imperative directives—must-run steps, forbidden actions, and ordered workflows—that persist across coding sessions and repositories. Instead of soft suggestions, imperatives frames rules as non-negotiable commands agents must follow before editing files, running shell commands, or opening pull requests. Platform and developer-experience teams reach for imperatives when standardizing Claude Code behavior for monorepos, regulated environments, or shared agent playbooks. The skill complements CLAUDE.md and hook systems by making execution order and guardrails explicit enough for automated enforcement.
- Defines non-negotiable agent directives
- Standardizes imperative instruction patterns
- Reduces ambiguous or skipped agent steps
- Pairs with camacho/ai-skills workflow skills
- Improves repeatability across repositories
Imperatives by the numbers
- 296 all-time installs (skills.sh)
- Ranked #2,276 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
npx skills add https://github.com/camacho/ai-skills --skill imperativesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 296 |
|---|---|
| repo stars | ★ 1 |
| Last updated | May 26, 2026 |
| Repository | camacho/ai-skills ↗ |
How do you enforce non-negotiable rules in Claude Code?
Author and enforce imperative-style agent directives so Claude Code sessions follow non-negotiable execution rules, guardrails, and step order across repos.
Who is it for?
Developer-platform teams standardizing Claude Code behavior with mandatory steps and guardrails across multiple repositories.
Skip if: Solo experiments where informal chat instructions are enough and no shared agent policy must be enforced.
When should I use this skill?
A developer asks to write imperative agent rules, enforce guardrails, or standardize Claude Code execution order across repos.
What you get
Imperative directive blocks, guardrail specs, and ordered agent execution steps checked into repo config.
- Imperative directive files
- Guardrail specifications
Files
/imperatives
Extract atomic imperatives (MUST/SHOULD/MAY) from markdown instruction files into JSONL.
Usage
/imperatives # default: ai-workspace/rules/*.md + AGENTS.md
/imperatives .claude/rules/*.md # specific globs
/imperatives --output imperatives.jsonl # write to fileSteps
1. Resolve files. Default: ai-workspace/rules/*.md and AGENTS.md. Expand globs to absolute paths. Zero matches → error, stop.
2. Pass 1 — Script extraction (fast, deterministic).
node --import tsx "${SKILL_DIR}/scripts/extract-imperatives.ts" <files...> --output /tmp/imperatives-pass1.jsonl${SKILL_DIR} = this skill's base directory (shown in the "Base directory for this skill:" header above). Keyword-based: catches RFC 2119 terms + imperative verbs. ~80% coverage, <1s.
3. Pass 2 — Subagent reasoning (catches implicit imperatives). For each file, dispatch a subagent to identify imperatives the regex missed — contextual rules, implicit constraints, prose-embedded obligations.
Subagent prompt:
Read <file>. Here are the imperatives already extracted by the script for this file:```
<pass 1 JSONL lines where source.file matches>
```
Identify additional imperative statements the regex missed. Look for:
- Implicit obligations hidden in prose (e.g., "The workflow is a menu, not a pipeline" implies MUST NOT enforce order)
- Contextual constraints (e.g., section context that makes a statement imperative)
- Conditional rules not triggered by keyword patterns
>
For each new imperative found, output one JSON line (same schema — id, level, polarity, subject, predicate, when, source, tool_scope, tags, raw).
Do NOT duplicate entries already in pass 1. If none found, output nothing.
Use subagent_type: "explorer" (Haiku) for most files. If a file had zero pass-1 imperatives OR contains dense prose (>50 lines without a keyword match), escalate that file to Sonnet for deeper reasoning.
4. Merge passes. Concatenate pass 1 + pass 2 outputs. Deduplicate by raw text. Write final output to --output <path> or present inline.
5. Present summary. Report in a table:
- Total count (pass 1 baseline + pass 2 additions)
- Breakdown by
levelandtool_scope - Files with zero imperatives after both passes
- Pass 2 additions highlighted separately
6. Downstream callers. If invoked by /policy-algebra or /distill, return the JSONL path directly — skip the summary.
Failure modes
| Condition | Behavior |
|---|---|
| No files matched | Error message. Stop. |
| File not found | Script warns on stderr, continues with remaining files. |
| Zero imperatives | Report zero. Not an error. |
| Script exits non-zero | Surface stderr to user. |
Cross-tool notes
- Codex / Cursor: run the script directly — it's tool-agnostic.
#!/usr/bin/env -S node --import tsx
// extract-imperatives.ts — Extract atomic imperatives from markdown into JSONL.
// Run from this skill: node --import tsx "${SKILL_DIR}/scripts/extract-imperatives.ts" <files...> [--output <path>]
// Or: "${SKILL_DIR}/scripts/extract-imperatives.ts" <files...> (if chmod +x and tsx installed)
import { readFileSync, writeFileSync } from "node:fs";
import { basename, relative } from "node:path";
const args = process.argv.slice(2);
if (args.includes("--help") || args.length === 0) {
console.log(`Usage: node --import tsx "\${SKILL_DIR}/scripts/extract-imperatives.ts" <files...> [--output <path>]
Extracts imperative statements from markdown files and outputs JSONL.
Options:
--output <path> Write JSONL to file instead of stdout
--help Show this help
Examples:
node --import tsx "\${SKILL_DIR}/scripts/extract-imperatives.ts" .claude/rules/*.md AGENTS.md
node --import tsx "\${SKILL_DIR}/scripts/extract-imperatives.ts" --output out.jsonl ai-workspace/rules/*.md`);
process.exit(0);
}
let outputPath: string | null = null;
const files: string[] = [];
for (let i = 0; i < args.length; i++) {
const arg = args[i] as string;
const next = args[i + 1];
if (arg === "--output" && next) {
outputPath = next;
i++;
} else if (!arg.startsWith("--")) {
files.push(arg);
}
}
interface Imperative {
id: string;
level: "MUST" | "SHOULD" | "MAY";
polarity: "positive" | "negative";
subject: string;
predicate: string;
when: string | null;
source: { file: string; line: number };
tool_scope: "general" | "claude-code" | "codex";
tags: string[];
raw: string;
}
type Level = "MUST" | "SHOULD" | "MAY";
type Polarity = "positive" | "negative";
// Ordered: negative variants before positive (longest-match-first)
const PATTERNS: Array<[RegExp, Level, Polarity]> = [
[/\bMUST\s+NOT\b(.+?)(?:\.|$)/i, "MUST", "negative"],
[/\bSHALL\s+NOT\b(.+?)(?:\.|$)/i, "MUST", "negative"],
[/\bSHOULD\s+NOT\b(.+?)(?:\.|$)/i, "SHOULD", "negative"],
[/\bMAY\s+NOT\b(.+?)(?:\.|$)/i, "MAY", "negative"],
[/\bMUST\b(.+?)(?:\.|$)/i, "MUST", "positive"],
[/\bSHALL\b(.+?)(?:\.|$)/i, "MUST", "positive"],
[/\bREQUIRED\b(.+?)(?:\.|$)/i, "MUST", "positive"],
[/\bSHOULD\b(.+?)(?:\.|$)/i, "SHOULD", "positive"],
[/\bRECOMMENDED\b(.+?)(?:\.|$)/i, "SHOULD", "positive"],
[/\bMAY\b(.+?)(?:\.|$)/i, "MAY", "positive"],
[/\bOPTIONAL\b(.+?)(?:\.|$)/i, "MAY", "positive"],
[/\bNever\b(.+?)(?:\.|$)/, "MUST", "negative"],
[/\bNEVER\b(.+?)(?:\.|$)/, "MUST", "negative"],
[/\bAlways\b(.+?)(?:\.|$)/, "MUST", "positive"],
[/\bALWAYS\b(.+?)(?:\.|$)/, "MUST", "positive"],
[/\bDo\s+NOT\b(.+?)(?:\.|$)/i, "MUST", "negative"],
[/\bDon't\b(.+?)(?:\.|$)/, "MUST", "negative"],
[/\bAvoid\b(.+?)(?:\.|$)/, "SHOULD", "negative"],
[/\bPrefer\b(.+?)(?:\.|$)/, "SHOULD", "positive"],
[/\bDefault\s+to\b(.+?)(?:\.|$)/, "SHOULD", "positive"],
[/\bUse\b(.+?)(?:\.|$)/, "SHOULD", "positive"],
];
function slugify(s: string): string {
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
}
function toolScope(filePath: string, line: string): "general" | "claude-code" | "codex" {
const lower = line.toLowerCase();
if (lower.includes("claude code") || lower.includes("claude-code") || filePath.includes(".claude/")) return "claude-code";
if (lower.includes("codex") || filePath.includes(".codex/")) return "codex";
return "general";
}
function extractSubject(text: string): { subject: string; predicate: string } {
const trimmed = text.trim().replace(/^[,:\s]+/, "");
const m = trimmed.match(/^(agents?|the agent|you|humans?|the human|bots?|reviewers?|teammates?)\s+(.+)/i);
if (m) return { subject: m[1]!.toLowerCase(), predicate: m[2]!.trim() };
return { subject: "agent", predicate: trimmed };
}
function extractWhen(line: string): string | null {
const m = line.match(/\b(?:when|if|during|before|after|while|unless)\s+(.+?)(?:\s*[,.]|\s+(?:MUST|SHOULD|MAY|Never|Always|Do not))/i);
return m ? m[1]!.trim() : null;
}
const results: Imperative[] = [];
const seenIds = new Set<string>();
const seenRaw = new Set<string>();
let inCodeBlock = false;
for (const filePath of files) {
inCodeBlock = false;
let content: string;
try {
content = readFileSync(filePath, "utf-8");
} catch {
process.stderr.write(`[warn] cannot read ${filePath}, skipping\n`);
continue;
}
const lines = content.split("\n");
const fileTags = [basename(filePath, ".md").toLowerCase().replace(/^(rule-|convention-)/, "")].filter(Boolean);
const relPath = relative(process.cwd(), filePath);
for (let i = 0; i < lines.length; i++) {
const line = lines[i] as string;
if (line.startsWith("```")) { inCodeBlock = !inCodeBlock; continue; }
if (inCodeBlock) continue;
if (line.startsWith("<!--") || /^\|[\s-]+\|/.test(line) || line.startsWith("---")) continue;
// Skip headings, table rows, and backtick-heavy lines
if (/^#{1,6}\s/.test(line)) continue;
if ((line.match(/`/g) || []).length > 3) continue;
for (const [pattern, level, polarity] of PATTERNS) {
const match = line.match(pattern);
if (!match) continue;
const raw = line.replace(/^[\s\-*>#]+/, "").trim();
// Deduplicate by raw text (handles inlined rules appearing in multiple sources)
if (seenRaw.has(raw)) break;
seenRaw.add(raw);
const when = extractWhen(line);
let { subject, predicate } = extractSubject(match[1]!);
// Strip the when-clause from predicate only if it appears at the end (after a "when" separator)
if (when) {
const whenIdx = predicate.toLowerCase().lastIndexOf(" when ");
if (whenIdx > 20) {
predicate = predicate.slice(0, whenIdx).trim();
}
}
// Cap predicate length
if (predicate.length > 100) {
predicate = predicate.slice(0, 100).replace(/\s+\S*$/, "").trim();
}
// Skip if predicate is too short to be meaningful
if (predicate.length < 10) break;
const baseId = `${fileTags[0] || slugify(basename(filePath, ".md"))}:${slugify(predicate)}`;
let id = baseId;
let counter = 2;
while (seenIds.has(id)) id = `${baseId}-${counter++}`;
seenIds.add(id);
results.push({
id, level, polarity, subject, predicate, when,
source: { file: relPath, line: i + 1 },
tool_scope: toolScope(filePath, line),
tags: fileTags,
raw,
});
break;
}
}
}
const output = results.map((r) => JSON.stringify(r)).join("\n");
if (outputPath) {
writeFileSync(outputPath, output + "\n", "utf-8");
process.stderr.write(`Wrote ${results.length} imperatives to ${outputPath}\n`);
} else {
if (output) console.log(output);
process.stderr.write(`Total: ${results.length} imperatives from ${files.length} files\n`);
}
Related skills
How it compares
Pick imperatives when agent behavior must be mandatory and ordered, not just documented as soft guidance.
FAQ
What are imperatives in camacho/ai-skills?
imperatives are mandatory agent instructions—ordered steps and hard guardrails—that Claude Code must follow, framed as commands rather than optional suggestions in session prompts.
How do imperatives differ from CLAUDE.md?
imperatives focus on non-negotiable execution order and forbidden actions for agents, while CLAUDE.md often carries broader project context; imperatives tighten behavioral enforcement.