docs: RFC 0052 expanded to full install command

Now covers unified `blue install` that manages:
- Hooks (SessionStart + PreToolUse)
- Skills (symlinks to ~/.claude/skills/)
- MCP Server (configuration in ~/.claude.json)

Also adds `blue uninstall` and `blue doctor` for health checks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Eric Garcia 2026-02-01 18:58:25 -05:00
parent a4040cc41b
commit 2216fc41d9

View file

@ -1,205 +1,301 @@
# RFC 0052: CLI Hook Management # RFC 0052: Blue Install Command
**Status**: Draft **Status**: Draft
**Created**: 2026-02-01 **Created**: 2026-02-01
**Updated**: 2026-02-01
**Author**: Claude Opus 4.5 **Author**: Claude Opus 4.5
**Related**: RFC 0038, RFC 0049, RFC 0051 **Related**: RFC 0038, RFC 0049, RFC 0051
## Problem Statement ## Problem Statement
Blue's Claude Code integration requires hooks to be manually configured: Blue's Claude Code integration requires multiple manual setup steps:
1. Create `.claude/hooks/` directory
2. Write hook scripts
3. Edit `.claude/settings.json`
4. Make scripts executable
This is error-prone and not portable. New team members must manually set up hooks or copy configurations. 1. **Hooks**: Create `.claude/hooks/`, write scripts, edit settings.json
2. **Skills**: Symlink `skills/*` to `~/.claude/skills/`
3. **MCP Server**: Add blue to `~/.claude.json` mcpServers
This is error-prone, not portable, and undiscoverable. New team members must manually configure everything.
## Proposed Solution ## Proposed Solution
Add `blue hooks` subcommand to manage Claude Code hook installation: A unified `blue install` command that sets up all Claude Code integration:
```bash ```bash
blue hooks install # Install all Blue hooks blue install # Install everything
blue hooks uninstall # Remove Blue hooks blue uninstall # Remove everything
blue hooks status # Show current hook status blue doctor # Check installation health
blue hooks check # Verify hooks are working
``` ```
## What Gets Installed
| Component | Location | Purpose |
|-----------|----------|---------|
| **Hooks** | `.claude/hooks/` + `.claude/settings.json` | SessionStart (PATH), PreToolUse (guard) |
| **Skills** | `~/.claude/skills/` (symlinks) | `/alignment-play` and future skills |
| **MCP Server** | `~/.claude.json` | Blue MCP tools |
## Commands ## Commands
### `blue hooks install` ### `blue install`
Installs Blue's Claude Code hooks:
```bash ```bash
$ blue hooks install $ blue install
Installing Blue hooks... Installing Blue for Claude Code...
✓ Created .claude/hooks/session-start.sh
✓ Created .claude/hooks/guard-write.sh
✓ Updated .claude/settings.json
✓ Made scripts executable
Blue hooks installed. Restart Claude Code to activate. Hooks:
✓ .claude/hooks/session-start.sh
✓ .claude/hooks/guard-write.sh
✓ .claude/settings.json (merged)
Skills:
✓ ~/.claude/skills/alignment-play -> /Users/ericg/letemcook/blue/skills/alignment-play
MCP Server:
✓ ~/.claude.json (blue server configured)
Blue installed. Restart Claude Code to activate.
``` ```
**Behavior:** **Flags:**
- Creates `.claude/hooks/` if missing - `--hooks-only` - Only install hooks
- Writes hook scripts from embedded templates - `--skills-only` - Only install skills
- Merges into existing `.claude/settings.json` (preserves other hooks) - `--mcp-only` - Only configure MCP server
- Sets executable permissions - `--force` - Overwrite existing files
- Idempotent - safe to run multiple times
### `blue hooks uninstall` ### `blue uninstall`
Removes Blue's hooks:
```bash ```bash
$ blue hooks uninstall $ blue uninstall
Removing Blue hooks... Removing Blue from Claude Code...
Hooks:
✓ Removed .claude/hooks/session-start.sh ✓ Removed .claude/hooks/session-start.sh
✓ Removed .claude/hooks/guard-write.sh ✓ Removed .claude/hooks/guard-write.sh
Updated .claude/settings.json Cleaned .claude/settings.json
Blue hooks removed. Skills:
✓ Removed ~/.claude/skills/alignment-play
MCP Server:
✓ Removed blue from ~/.claude.json
Blue uninstalled.
``` ```
**Behavior:** ### `blue doctor`
- Removes only Blue-managed hook scripts
- Removes Blue entries from settings.json (preserves other hooks)
- Leaves `.claude/` directory if other files exist
### `blue hooks status` Diagnoses installation issues:
Shows current hook state:
```bash ```bash
$ blue hooks status $ blue doctor
Blue Claude Code Hooks: Blue Installation Health Check
SessionStart: Binary:
✓ session-start.sh (installed, executable) ✓ blue found at /Users/ericg/.cargo/bin/blue
✓ Version: 0.1.0
PreToolUse (Write|Edit|MultiEdit): Hooks:
✓ guard-write.sh (installed, executable) ✓ session-start.sh (installed, executable)
✓ guard-write.sh (installed, executable)
✓ settings.json configured
Settings: .claude/settings.json (configured) Skills:
✓ alignment-play (symlink valid)
All hooks installed and ready. MCP Server:
✓ blue configured in ~/.claude.json
✓ Binary path correct
✓ Server responds to ping
All checks passed.
``` ```
### `blue hooks check` With issues:
Verifies hooks work correctly:
```bash ```bash
$ blue hooks check $ blue doctor
Checking Blue hooks... Blue Installation Health Check
✓ session-start.sh exits 0
✓ guard-write.sh allows /tmp/test.md
✓ guard-write.sh blocks src/main.rs (no worktree)
All hooks working correctly. Binary:
✓ blue found at /Users/ericg/.cargo/bin/blue
Hooks:
✗ guard-write.sh missing
✗ settings.json not configured
Run `blue install` to fix.
Skills:
✗ alignment-play symlink broken (target moved?)
Run `blue install --force` to recreate.
MCP Server:
✓ blue configured in ~/.claude.json
✗ Binary path outdated (points to old location)
Run `blue install --mcp-only` to fix.
3 issues found. Run suggested commands to fix.
``` ```
## Hook Templates ## Implementation Details
Hooks are embedded in the blue binary as string constants: ### Hooks Installation
```rust ```rust
const SESSION_START_HOOK: &str = r#"#!/bin/bash fn install_hooks(project_dir: &Path, force: bool) -> Result<()> {
# Blue SessionStart hook - sets up PATH let hooks_dir = project_dir.join(".claude/hooks");
# Managed by: blue hooks install fs::create_dir_all(&hooks_dir)?;
if [ -n "$CLAUDE_ENV_FILE" ] && [ -n "$CLAUDE_PROJECT_DIR" ]; then // Write hook scripts
echo "export PATH=\"\$CLAUDE_PROJECT_DIR/target/release:\$PATH\"" >> "$CLAUDE_ENV_FILE" write_hook(&hooks_dir.join("session-start.sh"), SESSION_START_TEMPLATE)?;
fi write_hook(&hooks_dir.join("guard-write.sh"), GUARD_WRITE_TEMPLATE)?;
exit 0 // Merge into settings.json
"#; let settings_path = project_dir.join(".claude/settings.json");
let settings = merge_hook_settings(&settings_path)?;
fs::write(&settings_path, serde_json::to_string_pretty(&settings)?)?;
const GUARD_WRITE_HOOK: &str = r#"#!/bin/bash Ok(())
# Blue PreToolUse hook - enforces RFC 0038 worktree protection
# Managed by: blue hooks install
FILE_PATH=$(jq -r '.tool_input.file_path // empty')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
blue guard --path="$FILE_PATH"
"#;
```
## Settings.json Management
The install command merges Blue hooks into existing settings:
```rust
fn merge_hooks(existing: Value, blue_hooks: Value) -> Value {
// Preserve existing hooks, add/update Blue hooks
// Use "# Managed by: blue" comments to identify Blue hooks
} }
``` ```
**Identification:** Hook scripts include a `# Managed by: blue hooks install` comment to identify Blue-managed hooks. ### Skills Installation
## Implementation Plan ```rust
fn install_skills(project_dir: &Path) -> Result<()> {
let skills_dir = project_dir.join("skills");
let target_dir = dirs::home_dir()?.join(".claude/skills");
- [ ] Add `Commands::Hooks` enum variant with subcommands fs::create_dir_all(&target_dir)?;
- [ ] Implement `handle_hooks_install()`
- [ ] Implement `handle_hooks_uninstall()` for entry in fs::read_dir(&skills_dir)? {
- [ ] Implement `handle_hooks_status()` let entry = entry?;
- [ ] Implement `handle_hooks_check()` if entry.path().is_dir() {
- [ ] Embed hook templates as constants let skill_name = entry.file_name();
- [ ] Add settings.json merge logic let link_path = target_dir.join(&skill_name);
- [ ] Add tests for hook management
// Remove existing symlink if present
if link_path.exists() {
fs::remove_file(&link_path)?;
}
// Create symlink
std::os::unix::fs::symlink(entry.path(), &link_path)?;
}
}
Ok(())
}
```
### MCP Server Configuration
```rust
fn install_mcp_server(project_dir: &Path) -> Result<()> {
let config_path = dirs::home_dir()?.join(".claude.json");
let mut config: Value = if config_path.exists() {
serde_json::from_str(&fs::read_to_string(&config_path)?)?
} else {
json!({})
};
// Add/update blue MCP server
config["mcpServers"]["blue"] = json!({
"command": project_dir.join("target/release/blue").to_string_lossy(),
"args": ["mcp"]
});
fs::write(&config_path, serde_json::to_string_pretty(&config)?)?;
Ok(())
}
```
## Identification of Managed Files
All Blue-managed files include a header comment:
```bash
#!/bin/bash
# Managed by: blue install
# Do not edit manually - changes will be overwritten
```
Or for JSON, a metadata key:
```json
{
"_blue_managed": true,
"_blue_version": "0.1.0",
...
}
```
## CLI Structure ## CLI Structure
```rust ```rust
#[derive(Subcommand)] #[derive(Subcommand)]
enum HooksCommands { enum Commands {
/// Install Blue's Claude Code hooks /// Install Blue for Claude Code
Install, Install {
/// Only install hooks
#[arg(long)]
hooks_only: bool,
/// Remove Blue's Claude Code hooks /// Only install skills
#[arg(long)]
skills_only: bool,
/// Only configure MCP server
#[arg(long)]
mcp_only: bool,
/// Overwrite existing files
#[arg(long)]
force: bool,
},
/// Remove Blue from Claude Code
Uninstall, Uninstall,
/// Show hook installation status /// Check installation health
Status, Doctor,
/// Verify hooks are working correctly // ... existing commands
Check,
} }
``` ```
## Future Extensions ## Future Extensions
- `blue hooks update` - Update hooks to latest version - `blue install --global` - Install for all projects (user-level config)
- `blue hooks diff` - Show differences from installed hooks - `blue upgrade` - Update hooks/skills to latest templates
- `blue hooks export` - Export hooks for manual installation - `blue install --dry-run` - Show what would be installed
- Support for custom hooks via `.blue/hooks/` templates - Plugin system for custom hooks/skills
## Implementation Plan
- [ ] Add `Commands::Install` with flags
- [ ] Add `Commands::Uninstall`
- [ ] Add `Commands::Doctor`
- [ ] Implement hook installation (from RFC 0051)
- [ ] Implement skill symlink management
- [ ] Implement MCP server configuration
- [ ] Embed hook templates as constants
- [ ] Add settings.json merge logic
- [ ] Add ~/.claude.json merge logic
- [ ] Add installation verification
- [ ] Add tests
## Benefits ## Benefits
1. **One command setup**: `blue hooks install` 1. **One command setup**: `blue install`
2. **Portable**: Works on any machine with blue installed 2. **Discoverable**: `blue doctor` shows what's wrong
3. **Idempotent**: Safe to run repeatedly 3. **Portable**: Works on any machine
4. **Discoverable**: `blue hooks status` shows what's installed 4. **Idempotent**: Safe to run repeatedly
5. **Reversible**: `blue hooks uninstall` cleanly removes 5. **Reversible**: `blue uninstall` cleanly removes everything
6. **Maintainable**: Templates embedded in binary, easy to update
## Migration
Existing manual installations can be migrated:
```bash
$ blue hooks install
Note: Found existing hooks. Replacing with managed versions.
✓ Backed up .claude/hooks/guard-write.sh to .claude/hooks/guard-write.sh.bak
✓ Installed managed guard-write.sh
```
## References ## References