Skip to content

ArcadeAI/safeword

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2,096 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SAFEWORD - AI Agent Configuration CLI

CI

Problem: AI agents write code without tests, skip design validation, and lack consistency across projects.

Solution: Portable patterns and guides that enforce test-first development (BDD/TDD), quality standards, and best practices across all your projects.

Repository: https://github.com/TheMostlyGreat/safeword


Quick Start (30 seconds)

1. Install in your project:

cd /path/to/your/project
bunx safeword@latest setup

2. Verify installation:

# Check for SAFEWORD files
test -f .safeword/SAFEWORD.md && echo ".safeword/SAFEWORD.md ✓"
test -f AGENTS.md && echo "AGENTS.md ✓"

Result: Your project now has:

  • .safeword/SAFEWORD.md - Global patterns and workflows
  • .safeword/guides/ - Testing methodology (BDD/TDD), code philosophy
  • .safeword/hooks/ - Auto-linting, quality review hooks
  • .claude/settings.json - Hook configuration for Claude Code
  • .claude/skills/ - Skills and slash-command workflows for Claude Code
  • .codex/config.toml - Hook configuration for Codex
  • .agents/skills/ - Skills for Codex
  • .cursor/hooks.json - Hook configuration for Cursor
  • .cursor/rules/ - Behavior rules for Cursor
  • .cursor/commands/ - Slash commands for Cursor
  • AGENTS.md - Project context with framework reference

Commit these to your repo for team consistency.


How It Fits Your Project

Stack-agnostic — Safeword is a process layer, not a framework opinion. It works alongside any stack — Next, Elysia, Astro, Django, Gin, whatever you use. Your application code and runtime dependencies are never touched.

Your agent config stays yours — Safeword uses AGENTS.md as the primary entry point. If you have an existing CLAUDE.md, it adds one import line at the top — your content is untouched.

Dev-only tools — Safeword installs ESLint, Prettier, and supporting plugins, plus the Gherkin acceptance lane (cucumber-js + tsx), as devDependencies — in every project. A pure Go/Python/Rust repo gets a minimal private: true package.json created to host them (the lane's step definitions are TypeScript and test your app from the outside). These are development tools — they never ship with your application or affect your runtime.

AI guardrails, not human blockers — Hooks and stricter linting rules only fire during AI agent sessions (Claude Code / Cursor / Codex events). They never run during normal human development. Safeword does not install git hooks or modify your commit workflow.

Use in CI if you want — Safeword adds lint, format, and test:bdd scripts to your package.json. You can wire these into your CI pipeline or precommit hooks — but it's your choice, not forced.


How It Works

Every session moves through five phases, in order — and three hard gates stop your agent skipping ahead:

flowchart TD
    start([You ask for something])
    start --> propose

    subgraph clarify ["1 · Clarify — propose and converge"]
      direction TB
      propose["Agent proposes a direction<br/>and surfaces the open questions"]
      converged{"Converged?"}
      propose --> converged
      converged -->|"not yet"| propose
    end

    converged -->|"yes"| classify{"2 · Classify<br/>how big is it?"}

    classify -->|"1 file, no new behavior"| patch["patch — fix it directly"]
    classify -->|"1–2 files, one behavior"| task["task — TDD"]
    classify -->|"3+ files · new state · many flows"| feature["feature — BDD"]

    feature --> phase0["Phase 0 spec:<br/>Jobs To Be Done → Acceptance Criteria → scope"]
    phase0 --> g1{{"Phase gate:<br/>scope / out_of_scope / done_when"}}
    g1 --> scenarios["Define-behavior scenarios"]
    scenarios --> g2{{"Phase gate:<br/>test-definitions.md exists"}}
    g2 --> build

    task --> build["3 · Build<br/>RED → GREEN → REFACTOR"]
    patch --> verify

    build --> verify["4 · Verify<br/>the agent runs the tests"]
    verify --> g3{{"Done gate:<br/>verify.md exists"}}
    g3 --> done([5 · Done])

    loc{{"LOC gate — commit every ~400 lines"}} -.->|throughout build| build
Loading
  • Clarify — the agent proposes a direction and converges with you before building. For features, this writes the product framing first: Jobs To Be Done → Acceptance Criteria → engineering scope.
  • Classify — sizes the work as a patch (fix directly), task (TDD), or feature (BDD).
  • Build — patches go straight to the fix; tasks and features run the RED → GREEN → REFACTOR loop, with features defining behavior scenarios first.
  • Verify — the agent runs the relevant tests itself, never handing you something untested.
  • Done — hard-blocked until /verify writes verify.md to the ticket.

The framework is project-local: it writes to .safeword/, .claude/, .cursor/, .codex/, and .agents/ in your repo — no global install — so teammates get the same discipline the moment they pull. Guides and learnings live in-repo and evolve as you work.


What's Inside

Key directories created in your project:

  • .safeword/guides/ - Core methodology and best practices
  • .safeword/templates/ - Fillable document structures
  • <namespace-root>/tickets/ - Tickets for complex/multi-step work (context anchors)
  • .safeword/hooks/ - Automation scripts (Claude Code + Cursor + Codex)
  • .claude/skills/, .agents/skills/, .cursor/rules/ - Specialized agent capabilities
  • .cursor/commands/ - Slash commands for Cursor

Core Guides

Purpose: Reusable methodology applicable to all projects

Guide Purpose When to Read
planning-guide.md Feature planning workflow, spec creation, BDD/TDD integration Starting any feature
testing-guide.md Test-first workflow (RED/GREEN/REFACTOR), test pyramid, test types Writing tests
learning-extraction.md Extract learnings from debugging, recognition triggers After complex debugging

Documentation Guides

Purpose: Writing effective feature documentation

Guide Purpose When to Read
design-doc-guide.md Design doc structure and best practices Designing complex features
architecture-guide.md Architecture decisions (tech choices, data models) Making architectural decisions
data-architecture-guide.md Data model design (schemas, validation, flows) Database/schema design
context-files-guide.md CLAUDE.md/AGENTS.md structure and best practices Setting up project context

Meta Guides

Purpose: Working with LLMs and documentation structure

Guide Purpose When to Read
llm-writing-guide.md Writing docs that LLMs follow (MECE, examples, context placement) Writing skills, commands, hooks
zombie-process-cleanup.md Port-based cleanup, multi-project isolation Managing dev servers

Templates

Purpose: Fillable structures for feature documentation

Template Purpose Used By
feature-spec-template.md Feature spec (user stories + constraints) planning-guide.md
task-spec-template.md Bug, improvement, refactor, or internal task planning-guide.md
test-definitions-feature.md BDD scenarios (Rule + Scenario + G/W/T + R/G/R) planning-guide.md
design-doc-template.md Design doc structure (architecture, components) design-doc-guide.md
architecture-template.md ADR for decisions with long-term impact planning-guide.md
ticket-template.md Context anchor for complex/multi-step work SAFEWORD.md
work-log-template.md Scratch pad and working memory during execution SAFEWORD.md

Learnings

Purpose: Extracted knowledge that compounds across sessions

Location: <namespace-root>/learnings/[concept].md

What goes here:

  • Debugging discoveries (non-obvious gotchas, integration struggles)
  • Trial-and-error findings (tried 3+ approaches before right one)
  • Architecture insights (discovered during implementation)
  • Testing traps (tests pass but UX broken, or vice versa)

How to extract: Follow learning-extraction.md recognition triggers and templates


Tickets

Purpose: Context anchors for complex/multi-step work to prevent LLM loops

Location: <namespace-root>/tickets/{ID}-{slug}/ for tickets created by safeword ticket new. Older {ID}/ and numeric {id}-{slug}/ folders remain readable by ID.

Structure:

<namespace-root>/
├── tickets/
│   ├── 7K9M3P-login-bug/
│   │   ├── ticket.md           # Ticket definition (frontmatter + work log)
│   │   ├── test-definitions.md # BDD scenarios (Given/When/Then)
│   │   ├── spec.md             # Feature spec for epics (optional)
│   │   └── design.md           # Design doc for complex features (optional)
│   └── completed/              # Archive for done tickets
├── learnings/                  # Extracted knowledge (gotchas, discoveries)
└── tmp/                        # Scratch space (research, logs, etc.)

When to create: Multiple attempts likely, multi-step with dependencies, investigation needed, or risk of losing context


Hooks, Commands & Skills

Hooks (in .safeword/hooks/): TypeScript automation scripts (Bun runtime)

  • session-verify-agents.ts - Verifies AGENTS.md link on session start
  • session-version.ts - Shows safeword version on session start
  • session-lint-check.ts - Checks for lint errors on session start
  • session-cleanup-quality.ts - Garbage-collects old quality state files on session end
  • session-compact-context.ts - Re-injects active ticket context after context compaction
  • prompt-timestamp.ts - Injects timestamp into prompts
  • prompt-questions.ts - Reminds agent to ask clarifying questions
  • post-tool-lint.ts - Auto-lints after file edits
  • post-tool-quality.ts - Tracks LOC, detects phase changes and TDD steps
  • post-tool-bypass-warn.ts - Warns when agent bypasses quality gates
  • pre-tool-quality.ts - Blocks edits when quality gate is active (LOC, phase, or TDD)
  • pre-tool-config-guard.ts - Guards against settings.json modifications
  • stop-quality.ts - Quality review prompt on stop
  • cursor/after-file-edit.ts - Auto-lints after Cursor file edits
  • cursor/stop.ts - Quality review prompt on Cursor stop
  • codex/pre-tool-quality.ts - Adapts Codex PreToolUse events to safeword's quality gate

Skills (in .claude/skills/ and .agents/skills/): Specialized agent capabilities

  • bdd/ - BDD orchestrator for feature-level work (Discovery, Scenarios, TDD, Verify, Splitting, Done)
  • debug/ - Four-phase debugging (investigate before fixing)
  • quality-review/ - Deep code review with web research
  • refactor/ - Small-step refactoring with test verification
  • testing/ - Test writing methodology (iron laws, anti-patterns)
  • ticket-system/ - Ticket system and work logs for context anchoring

Commands: Cursor gets explicit command files in .cursor/commands/; Claude Code exposes slash-command behavior through skills. Codex uses repo-scoped skills in .agents/skills/ rather than command files.

  • /audit - Run architecture and dead code analysis
  • /bdd - Force BDD flow for current task
  • /cleanup-zombies - Kill zombie processes on ports
  • /debug - Four-phase debugging framework
  • /lint - Run linters and formatters
  • /quality-review - Deep code review with web research
  • /refactor - Systematic refactoring with small-step discipline
  • /testing - Test writing guidance and best practices
  • /verify - Verify ticket criteria (tests, build, lint, scenarios, dep drift)

MCP Servers (in .mcp.json / .cursor/mcp.json): Auto-configured integrations

  • context7 - Up-to-date library documentation lookup
  • playwright - Browser automation for testing

CLI Commands

# Set up safeword in current project
bunx safeword@latest setup
bunx safeword@latest setup -y # Non-interactive mode

# Check project health and versions
bunx safeword@latest check
bunx safeword@latest check --offline # Skip remote version check

# Upgrade to latest version
bunx safeword@latest upgrade

# Preview changes before upgrading
bunx safeword@latest diff
bunx safeword@latest diff -v # Show full diff output

# Regenerate architecture config for /audit
bunx safeword@latest sync-config

# Remove safeword from project
bunx safeword reset
bunx safeword reset -y     # Skip confirmation
bunx safeword reset --full # Also remove linting config + packages

Publishing (maintainers)

# From packages/cli/
bun publish

Auto-detection: Detects project type from package.json and enables relevant ESLint plugins only when the framework is installed:

  • TypeScript, React, Next.js, Astro
  • Vitest, Playwright, Storybook, Tailwind, Turbo, TanStack Query
  • Publishable libraries (adds publint)

How Guide Imports Work

AGENTS.md contains a link to .safeword/SAFEWORD.md (also added to CLAUDE.md if present).

SAFEWORD.md then imports guides via the Guides table. Claude Code, Cursor, and Codex load these project-local instructions through their own context surfaces.

Check for Existing Learnings

ls < namespace-root > /learnings/

Extract New Learning

  1. Follow recognition triggers in learning-extraction.md
  2. Create <namespace-root>/learnings/[concept].md
  3. Use template: Problem → Gotcha → Examples → Testing Trap

Syncing Across Machines

Commit .safeword/, .claude/, .cursor/, .codex/, and .agents/ in your project repo for team consistency.


Customizing File Locations

Safeword reads project-level information from the project namespace root: paths.projectRoot when configured, .project/ by default, or legacy .safeword-project/ when that directory already exists. If you already maintain these docs elsewhere, point safeword at your existing files via the optional paths block in .safeword/config.json:

{
  "installedPacks": ["typescript"],
  "paths": {
    "projectRoot": ".project",
    "personas": "docs/personas.md",
    "glossary": "docs/glossary.md",
    "architecture": "ARCHITECTURE.md"
  },
  "docs": {
    "sources": [
      { "type": "local", "path": "README.md" },
      { "type": "local", "path": "docs" },
      { "type": "url", "url": "https://docs.example.com" },
      { "type": "git", "repo": "git@example.com:org/docs.git", "path": "product" }
    ]
  }
}

Rules:

  • All paths.* keys are optional. Unset per-file keys fall back to <namespace-root>/<key>.md.
  • Relative paths resolve against project root (the directory containing .safeword/config.json).
  • Absolute paths are used verbatim — useful for shared monorepo setups where the file lives outside this project's tree.
  • When an override is set, safeword setup does NOT scaffold the default-location stub — one personas.md per project, where you named it.
  • safeword check validates the configured file. If the file is missing, you get a personas-path: error with non-zero exit (loud failure on configured-but-missing). If .safeword-project/personas.md still exists from a prior install, you get a zero-exit advisory naming the orphaned file (cleanup is up to you — safeword never deletes user content).

Tickets and learnings derive from paths.projectRoot. Personas, glossary, and architecture can also be redirected individually with their own paths.* keys.

docs.sources tells audit where customer documentation lives. Local sources are validated by safeword check; URL and git sources are declared inventory for audit runs, which should fetch them when available or report them as skipped coverage. If you want audit to keep using fallback discovery and stop asking for configured sources, set "docs": { "sources": [] }.


Integration with Project Context

How it works:

  1. AGENTS.md links to .safeword/SAFEWORD.md (also adds one import line to CLAUDE.md if present)
  2. SAFEWORD.md imports guides via Guides table
  3. Guides cross-reference each other and templates
  4. Learnings stored in <namespace-root>/learnings/

Result: Modular, maintainable documentation with clear separation of concerns


Principles

  1. Guides - Reusable methodology (test pyramid, BDD/TDD workflow)
  2. Templates - Fillable structures (user stories, test definitions)
  3. Learnings - Extracted knowledge (gotchas, discoveries)
  4. Planning - Feature planning and design (user stories, test definitions, design docs)
  5. Hooks/Skills - Automation and specialized capabilities

Living Documentation: Update as you learn, archive completed work, consolidate when needed


FAQ

Will safeword change my stack or framework? No. Safeword is a process overlay — it adds quality enforcement (BDD/TDD, linting, code review) on top of whatever you already use. It doesn't install application dependencies or modify your source code.

Will it overwrite my CLAUDE.md? No. Safeword uses AGENTS.md as the primary entry point. If you have an existing CLAUDE.md, it prepends a single 4-line block that links to .safeword/SAFEWORD.md. Your existing content stays exactly where it is.

What packages does it install? For JS/TS projects: ESLint, Prettier, and supporting plugins — all as devDependencies (the -D flag). These are code quality tools, not application dependencies. Python, Go, and Rust (beta) use their language-native linters (ruff, golangci-lint, clippy).

I use Biome, dprint, oxfmt, or deno fmt — is that a problem? No. Safeword detects a non-Prettier formatter (biome.json, dprint.json, .oxfmtrc.*, deno.json) and steps aside: it skips Prettier at install and its auto-format hook leaves all formatting to your tool — agent edits are never run through Prettier, for any file type (JS/TS, JSON, CSS, YAML). Files your formatter doesn't cover are left untouched rather than Prettier-formatted. ESLint still runs, because those formatters don't cover security scanning (eslint-plugin-security), cyclomatic complexity (sonarjs), or framework rules (React hooks, Next.js, Astro); safeword's ESLint config disables formatting rules, so it lints without fighting your formatter.

Do teammates need to install safeword separately? No. Commit the .safeword/, .claude/, .cursor/, .codex/, and .agents/ directories to git. When teammates pull, they get the full setup. The linting devDependencies install automatically with npm install / bun install.

Will it interfere with my development workflow? No. Safeword's hooks and stricter linting rules only fire during AI agent sessions. They don't run when you code normally, and safeword does not install git hooks. It adds lint, format, and test:bdd scripts to package.json that you can optionally use in CI or precommit hooks.

What Claude Code permissions does safeword need? Safeword's feature-ticket done-gate verifies that /verify and /audit were actually invoked by reading a session-scoped log written via bash injection at the top of each skill. If Claude Code denies that bash injection, feature tickets hard-block at done-phase.

To pre-approve the injection without prompts (recommended for headless / non-interactive sessions), add these patterns to .claude/settings.json:

{
  "permissions": {
    "allow": ["Bash(bun */.safeword/hooks/record-skill-invocation.ts*)"]
  }
}

This pre-approves the current safeword helper invocation:

  • Claude Code evaluates compound bash commands per subcommand, so the allow rule only needs to cover the Bun helper that writes the log.
  • Bash(bun */.safeword/hooks/record-skill-invocation.ts*) matches Bun running safeword's installed invocation logger from the project .safeword/hooks/ directory.
  • No node -e, mkdir -p, or echo allow rule is needed for the current injection. The helper performs the write itself, and Claude Code treats echo plus read-only git forms as read-only commands.

The injection itself resolves the project namespace root and writes timestamped lines to <namespace-root>/skill-invocations.log — no network calls, no file mutation outside that path. Feature-ticket done gates require this session-scoped proof. Task and patch tickets can still use verify.md when session-scoped invocation proof is unavailable and not required by the gate.


Development

This section is for contributors to safeword itself.

Tech Stack

Component Technology
Runtime Bun (dev), Node 22+ (users)
CLI TypeScript, Commander.js
Build tsup (ESM-only output)
Tests Vitest
Linting ESLint 9 + Prettier

Optional System Binaries

These tools enhance development scripts but are not required:

Binary Purpose Script Install
shfmt Format shell scripts in repo bun format:sh brew install shfmt
dot Generate dependency graph SVG bun deps:graph brew install graphviz

Without these binaries, the scripts print a message and skip.

Development Workflow

Editing Source Templates:

  1. Edit in packages/cli/templates/ (source of truth)
  2. Run bunx safeword upgrade to sync to .safeword/
  3. Test changes

Running Tests:

# Important: Use `bun run test` (Vitest), NOT `bun test` (Bun's runner)
bun run test                      # All tests
bunx vitest run tests/foo.test.ts # Single file
bun run test:integration          # Integration tests
bun run test:watch                # Watch mode

Publishing:

Always run bun publish from packages/cli/ directory, not the monorepo root.

CLI Parity (Claude Code / Cursor / Codex)

The CLI installs matching workflow capabilities for Claude Code, Cursor, and Codex using each agent's native surface.

Source of truth: packages/cli/src/schema.ts

Parity tests: packages/cli/tests/schema.test.ts

Agent Workflow Surface Commands / Hooks
Claude Code .claude/skills/* Skills expose slash-command behavior
Cursor .cursor/rules/{safeword-*,bdd-*}.mdc .cursor/commands/*.md, .cursor/hooks.json
Codex .agents/skills/* .codex/config.toml, .safeword/hooks/codex/*.ts

Editing skills:

  1. Edit templates in packages/cli/templates/skills/ (Claude Code and Codex) and packages/cli/templates/cursor/rules/ (Cursor)
  2. Update packages/cli/src/schema.ts if adding/removing skills
  3. Run parity tests: bun run test -- --testNamePattern="parity"
  4. Run bunx safeword upgrade to sync to local project

Getting Help

About

Personal AI agent guides, templates, and learnings

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages