Skip to content

ramenctl init: install AI skills alongside config #453

Description

@nirs

Summary

ramenctl init creates a configuration file required by all ramenctl commands. It should also install AI agent skills so any coding assistant can help drive ramenctl. By default skills are installed in a portable format; with --agent <tool> they are installed in the layout the tool auto-discovers.

Why project-level, not global

All supported tools allow both global and project-level skills. Skills are installed in the current directory (project-level), not globally. ramenctl skills are only useful when doing ramenctl work — installing globally would load them in every session, wasting context window and adding noise to skill matching.

Project-level installation keeps skills scoped to directories where the user actually runs ramenctl — right next to config.yaml. When you open a session in that directory the agent sees the skills; everywhere else it doesn't.

CLI interface

ramenctl init [--agent <tool>] [--config <file>] [--envfile <file>]

--agent defaults to generic. Valid values: cursor, claude, bob, generic.

Supported tools

All agents get multi-file skills (one SKILL.md per subcommand) and a context file with a brief overview of ramenctl. The context file format varies per tool — Cursor uses a rule file (.mdc), others use their native context file (CLAUDE.md or AGENTS.md).

Flag value Skills directory Context file Notes
cursor .cursor/skills/ .cursor/rules/ramenctl.mdc Auto-discovered from frontmatter
claude .claude/skills/ CLAUDE.md Auto-discovered from frontmatter
bob .bob/skills/ .bob/rules/ramenctl.md Auto-discovered in Advanced mode
generic .agents/skills/ AGENTS.md Includes skill index with paths

All six ramenctl skills are installed regardless of tool:

  • ramenctl-init — configure a configuration file for your clusters
  • ramenctl-validate-clusters — validate DR cluster configuration
  • ramenctl-validate-application — validate a DR-protected application
  • ramenctl-gather-application — gather diagnostic data for a protected app
  • ramenctl-test-run — run end-to-end DR flow tests
  • ramenctl-test-clean — clean up after test runs

Cursor (--agent cursor)

Docs:

How Cursor discovers skills:

  • Primary project-level paths: .cursor/skills/, .agents/skills/
  • Compatibility paths: .claude/skills/, .codex/skills/ (project and user-level)
  • User-level global: ~/.cursor/skills/, ~/.agents/skills/
  • Monorepo scoping: skills in nested subdirectories are automatically scoped to that directory
  • Each skill is a directory with a SKILL.md file containing YAML frontmatter (name, description — both required)
  • Optional frontmatter fields: paths (glob patterns to scope), disable-model-invocation
  • Skills load resources on demand, keeping context usage efficient
  • Skills can include optional scripts/, references/, assets/ subdirectories

Conclusion: Use .cursor/skills/ as the native directory. Cursor auto-discovers skills from frontmatter. Generate .cursor/rules/ramenctl.mdc with a brief overview of ramenctl.

Claude Code (--agent claude)

Docs:

How Claude Code discovers skills:

  • Auto-discovers from .claude/skills/ (project-level) and ~/.claude/skills/ (personal)
  • Enterprise (managed) scope also supported; precedence: enterprise > personal > project
  • Each skill is a directory with a SKILL.md file containing YAML frontmatter
  • description is recommended (helps Claude decide when to use the skill); name is optional (defaults to directory name)
  • Directory name becomes the /skill-name command for manual invocation
  • Skill descriptions are loaded into context; full skill body loads only when invoked
  • CLAUDE.md is a project/global context file loaded every session
  • Skills can include supporting files: examples/, scripts/, and reference material alongside SKILL.md
  • SKILL.md recommended to be under 500 lines

Conclusion: Use .claude/skills/ for skills. Claude auto-discovers skills and loads them on demand. Generate a brief CLAUDE.md with ramenctl overview.

Codex (--agent codex)

Docs:

How Codex discovers skills:

  • Auto-discovers from .agents/skills/ at multiple scopes: CWD, parent directories, repo root
  • User-level skills at $HOME/.agents/skills/
  • Each skill is a directory with a SKILL.md file; name and description are required
  • Progressive disclosure: starts with name/description/path, loads full SKILL.md only when selected
  • AGENTS.md is a project-level context file read automatically before the agent starts work
  • AGENTS.md should be kept small (32 KiB default combined limit)
  • Supports symlinked skill folders

Conclusion: Codex uses .agents/skills/ and AGENTS.md, the same
convention as the generic agent. Use --agent generic (the default) for
Codex — no dedicated --agent codex flag is needed.

Bob (--agent bob)

Docs:

How Bob discovers skills:

  • Discovers from .bob/skills/ (project-level) and ~/.bob/skills/ (global)
  • Project-level skills take precedence over global skills with the same name
  • Each skill needs a SKILL.md with YAML frontmatter (name, description)
  • Skills are only available in Advanced mode
  • AGENTS.md is read as persistent project context every conversation; Bob IDE generates it via /init
  • Bob IDE has modes (Code, Plan, Ask, Advanced) with mode-specific AGENTS files in .bob/rules-*/
  • Skills system introduced in Bob v1.0.1 (March 2026)
  • .agents/skills/ is not documented — official docs only reference .bob/skills/ paths

Conclusion: Use .bob/skills/ as the native directory (not .agents/skills/). Generate .bob/rules/ramenctl.md that instructs Bob to switch to Advanced mode (required for skill discovery) and lists the available skills.

Generic (--agent generic, default)

Uses .agents/skills/ and AGENTS.md. The .agents/skills/ directory is the portable convention — recognized by Cursor, Codex, and potentially other tools. AGENTS.md is the only context file we generate, because the generic tool doesn't auto-discover skills.

Codex uses the same convention as generic (.agents/skills/ and AGENTS.md), so there is no dedicated --agent codex flag. Use the default generic agent for Codex.

Context file format

Every agent gets a context file with a brief ramenctl overview. The content varies:

  • Cursor: .cursor/rules/ramenctl.mdc — rule file with frontmatter, overview of ramenctl
  • Claude: overview only — skills are auto-discovered
  • Bob: overview + instruction to switch to Advanced mode (required for skill discovery)
  • Generic: overview + skill index with explicit paths (tool doesn't auto-discover)

AGENTS.md is a thin index — not a dump of all skills. It contains:

  1. Project description: one-liner about ramenctl and disaster recovery
  2. Skill index: each skill listed with a path and one-line description
  3. Instructions: tells the agent to read the SKILL.md file when a task matches

Example AGENTS.md:

# ramenctl skills

Manage disaster recovery with `ramenctl`.

## Skills

Skills are detailed guides stored in `.agents/skills/`. When a task
matches a skill area below, read the corresponding `SKILL.md` file.

- `.agents/skills/ramenctl-init/SKILL.md` - Configure ramenctl for your clusters
- `.agents/skills/ramenctl-validate-clusters/SKILL.md` - Validate DR cluster configuration
- `.agents/skills/ramenctl-validate-application/SKILL.md` - Validate a DR-protected application
- `.agents/skills/ramenctl-gather-application/SKILL.md` - Gather diagnostic data for an application
- `.agents/skills/ramenctl-test-run/SKILL.md` - Run disaster recovery flow tests
- `.agents/skills/ramenctl-test-clean/SKILL.md` - Clean up after test runs

Ownership model

All files created by ramenctl init are write-once. If a file already exists, it is not overwritten — ramenctl init warns and continues. This applies to config, skills, and context files equally.

If you modify a file, you own it. ramenctl init will never overwrite your changes.

The typical workflow is an ephemeral directory:

mkdir myenv && cd myenv
ramenctl init --agent cursor
# ask agent to configure, validate, gather, test
rm -rf myenv

There is no upgrade mechanism. If you upgrade ramenctl and want fresh skills, delete the old files and run ramenctl init again. If needed in the future, init --reset can be added to replace all files.

Output examples

$ ramenctl init
⭐ Using config "config.yaml"

🔎 Initializing ...
   ✅ Created config file "config.yaml" - please modify for your clusters
   ✅ Created skills in ".agents/skills/" and "AGENTS.md"
      Instruct your agent to read AGENTS.md

✅ Init completed
$ ramenctl init --agent cursor
⭐ Using config "config.yaml"

🔎 Initializing ...
   ✅ Created config file "config.yaml" - please modify for your clusters
   ✅ Created skills for Cursor in ".cursor/skills/" and ".cursor/rules/ramenctl.mdc"

✅ Init completed
$ ramenctl init --agent claude
⭐ Using config "config.yaml"

🔎 Initializing ...
   ✅ Created config file "config.yaml" - please modify for your clusters
   ✅ Created skills for Claude Code in ".claude/skills/" and "CLAUDE.md"

✅ Init completed
$ ramenctl init --agent bob
⭐ Using config "config.yaml"

🔎 Initializing ...
   ✅ Created config file "config.yaml" - please modify for your clusters
   ✅ Created skills for Bob in ".bob/skills/" and "AGENTS.md"
      Use "/mode advanced" in Bob to enable skills

✅ Init completed

Template layout

pkg/skills/templates/
    skills/
        init.tmpl
        validate-clusters.tmpl
        validate-application.tmpl
        gather-application.tmpl
        test-run.tmpl
        test-clean.tmpl
    agents/
        common.tmpl
        cursor.tmpl
        claude.tmpl
        bob.tmpl
        generic.tmpl

skills/ contains one template per subcommand. agents/ contains one context file template per agent plus a shared common template:

  • common.tmpl — shared content included by all agent templates (heading, overview, command execution rules)
  • cursor.tmpl — Cursor rule file format with frontmatter
  • claude.tmpl — plain markdown
  • bob.tmpl — Critical workflow rule + Advanced mode instruction
  • generic.tmpl — skill index with paths

Adding a new agent is one map entry. If it needs a new context format, add a template in agents/.

Agent configuration

const (
	AgentGeneric = "generic"
	AgentCursor  = "cursor"
	AgentClaude  = "claude"
	AgentBob     = "bob"
)

type agentConfig struct {
	displayName string // "Cursor", "Claude Code"; empty for generic
	skillsDir   string // ".cursor/skills", ".claude/skills", ".agents/skills"
	contextFile string // "CLAUDE.md", "AGENTS.md", ".cursor/rules/ramenctl.mdc"
	hint        string // shown after install; empty if none
}

var agents = map[string]agentConfig{
	AgentCursor: {
		displayName: "Cursor",
		skillsDir:   ".cursor/skills",
		contextFile: ".cursor/rules/ramenctl.mdc",
	},
	AgentClaude: {
		displayName: "Claude Code",
		skillsDir:   ".claude/skills",
		contextFile: "CLAUDE.md",
	},
	AgentBob: {
		displayName: "Bob",
		skillsDir:   ".bob/skills",
		contextFile: ".bob/rules/ramenctl.md",
		hint:        `Use "/mode advanced" in Bob to enable skills`,
	},
	AgentGeneric: {
		skillsDir:   ".agents/skills",
		contextFile: "AGENTS.md",
		hint:        "Instruct your agent to read AGENTS.md",
	},
}

Implementation notes

  • Skills are embedded in the ramenctl binary using Go embed directive and extracted at init time.
  • Skill templates support dynamic command names (ramenctl vs odf dr) and conditional YAML frontmatter (Cursor only).
  • Agent configuration (display name, skills directory, context template, context file) is stored in a map keyed by agent name.
  • The --agent flag is validated early via cobra PreRunE so invalid values show usage, consistent with other flag validation errors.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions