Documentation
¶
Overview ¶
Package tools manages AI agent install targets (e.g., Claude, Cursor). Each Tool implementation links skills from the canonical store into the agent's expected directory structure.
Index ¶
- Constants
- Variables
- func PackagesDir() (string, error)
- func SlugifyRegistry(repo string) string
- func StoreDir() (string, error)
- func WriteCanonicalSkill(canonicalDir string, skillMD []byte) error
- func WriteToPackageStore(name string, files []SkillFile) (string, error)
- func WriteToStore(skillName string, files []SkillFile) (string, error)
- type ClaudeTool
- func (t ClaudeTool) CanonicalTarget(canonicalDir string) (string, bool)
- func (t ClaudeTool) Detect() bool
- func (t ClaudeTool) Install(skillName, canonicalDir, projectRoot string) ([]string, error)
- func (t ClaudeTool) Name() string
- func (t ClaudeTool) SkillPath(skillName, projectRoot string) (string, error)
- func (t ClaudeTool) Uninstall(skillName string) error
- type CodexTool
- func (t CodexTool) CanonicalTarget(canonicalDir string) (string, bool)
- func (t CodexTool) Detect() bool
- func (t CodexTool) Install(skillName, canonicalDir, projectRoot string) ([]string, error)
- func (t CodexTool) Name() string
- func (t CodexTool) SkillPath(skillName, projectRoot string) (string, error)
- func (t CodexTool) Uninstall(skillName string) error
- type CommandTool
- func (t CommandTool) CanonicalTarget(_ string) (string, bool)
- func (t CommandTool) Detect() bool
- func (t CommandTool) Install(skillName, canonicalDir, projectRoot string) ([]string, error)
- func (t CommandTool) Name() string
- func (t CommandTool) SkillPath(skillName, projectRoot string) (string, error)
- func (t CommandTool) Uninstall(skillName string) error
- type CursorTool
- func (t CursorTool) CanonicalTarget(canonicalDir string) (string, bool)
- func (t CursorTool) Detect() bool
- func (t CursorTool) Install(skillName, canonicalDir, projectRoot string) ([]string, error)
- func (t CursorTool) Name() string
- func (t CursorTool) SkillPath(skillName, projectRoot string) (string, error)
- func (t CursorTool) Uninstall(skillName string) error
- type GeminiTool
- func (t GeminiTool) CanonicalTarget(_ string) (string, bool)
- func (t GeminiTool) Detect() bool
- func (t GeminiTool) Install(skillName, canonicalDir, projectRoot string) ([]string, error)
- func (t GeminiTool) Name() string
- func (t GeminiTool) SkillPath(skillName, projectRoot string) (string, error)
- func (t GeminiTool) Uninstall(skillName string) error
- type SkillFile
- type Status
- type Tool
Constants ¶
const ( ToolTypeBuiltin = "builtin" ToolTypeCustom = "custom" )
Variables ¶
var ErrRealDirectoryExists = errors.New("real directory exists at target path")
ErrRealDirectoryExists is returned when replaceSymlink finds a real (non-symlink) directory at the link path. The caller should route the user to `scribe adopt` rather than silently destroying the directory.
Functions ¶
func PackagesDir ¶
PackagesDir returns the ~/.scribe/packages/ directory path.
func SlugifyRegistry ¶
SlugifyRegistry converts "owner/repo" to "owner-repo" for filesystem paths.
func WriteCanonicalSkill ¶
WriteCanonicalSkill rewrites the canonical SKILL.md content and refreshes the stored merge base to match. Used by repair flows that promote a tool-local single-file projection back into the canonical store.
func WriteToPackageStore ¶
WriteToPackageStore writes all package files to ~/.scribe/packages/<name>/. Returns the canonical package directory. Like WriteToStore it does a clean rewrite, but it preserves no merge-base copy and does NOT apply any tool projection — packages are self-installing and Scribe never links them into agent skill dirs.
File-mode handling: scripts named setup / install.sh / install / bootstrap at the package root are made executable so the install runner can invoke them directly. Everything else is written 0644.
func WriteToStore ¶
WriteToStore writes all skill files to ~/.scribe/skills/<skillName>/. Returns the canonical directory path. Called once per skill before any target links are created. After writing, if SKILL.md is among the files, a .scribe-base.md copy is created alongside it to serve as the merge base for 3-way merge on updates.
Types ¶
type ClaudeTool ¶
type ClaudeTool struct{}
ClaudeTool symlinks ~/.claude/skills/<name> → ~/.scribe/skills/<name>/. Claude Code expects a directory containing SKILL.md — a file symlink would appear as a bare file and not be recognised as a skill.
func (ClaudeTool) CanonicalTarget ¶
func (t ClaudeTool) CanonicalTarget(canonicalDir string) (string, bool)
func (ClaudeTool) Detect ¶
func (t ClaudeTool) Detect() bool
func (ClaudeTool) Install ¶
func (t ClaudeTool) Install(skillName, canonicalDir, projectRoot string) ([]string, error)
func (ClaudeTool) Name ¶
func (t ClaudeTool) Name() string
func (ClaudeTool) SkillPath ¶
func (t ClaudeTool) SkillPath(skillName, projectRoot string) (string, error)
func (ClaudeTool) Uninstall ¶
func (t ClaudeTool) Uninstall(skillName string) error
type CodexTool ¶
type CodexTool struct{}
CodexTool exposes Scribe-managed skills to Codex via ~/.agents/skills, which is the directory Codex's native skill discovery reads from. (Codex still keeps config/state under ~/.codex, but skill projections must land in ~/.agents/skills/<name> to be visible to Codex sessions.)
func (CodexTool) CanonicalTarget ¶
type CommandTool ¶
type CommandTool struct {
ToolName string
DetectCommand string
InstallCommand string
UninstallCommand string
PathTemplate string
}
CommandTool is a configurable tool backed by shell command templates.
func (CommandTool) CanonicalTarget ¶
func (t CommandTool) CanonicalTarget(_ string) (string, bool)
CanonicalTarget returns ok=false for CommandTool — the projection shape is defined by user-supplied shell templates and Scribe has no way to know which path inside canonicalDir the install step mirrored.
func (CommandTool) Detect ¶
func (t CommandTool) Detect() bool
func (CommandTool) Install ¶
func (t CommandTool) Install(skillName, canonicalDir, projectRoot string) ([]string, error)
func (CommandTool) Name ¶
func (t CommandTool) Name() string
func (CommandTool) SkillPath ¶
func (t CommandTool) SkillPath(skillName, projectRoot string) (string, error)
SkillPath returns the path this tool would link for skillName, using PathTemplate. Returns an error if no PathTemplate is configured (path is unknown).
func (CommandTool) Uninstall ¶
func (t CommandTool) Uninstall(skillName string) error
type CursorTool ¶
type CursorTool struct {
// WorkDir is the project root. Defaults to os.Getwd() if empty.
WorkDir string
}
CursorTool symlinks .cursor/rules/<name>.mdc → ~/.scribe/skills/<name>/.cursor.mdc. The .cursor.mdc is generated by WriteToStore from SKILL.md frontmatter. Because multiple projects can symlink the same source, updating the store propagates to every project automatically.
func (CursorTool) CanonicalTarget ¶
func (t CursorTool) CanonicalTarget(canonicalDir string) (string, bool)
func (CursorTool) Detect ¶
func (t CursorTool) Detect() bool
func (CursorTool) Install ¶
func (t CursorTool) Install(skillName, canonicalDir, projectRoot string) ([]string, error)
func (CursorTool) Name ¶
func (t CursorTool) Name() string
func (CursorTool) SkillPath ¶
func (t CursorTool) SkillPath(skillName, projectRoot string) (string, error)
func (CursorTool) Uninstall ¶
func (t CursorTool) Uninstall(skillName string) error
type GeminiTool ¶
type GeminiTool struct{}
GeminiTool delegates skill lifecycle management to the native Gemini CLI.
func (GeminiTool) CanonicalTarget ¶
func (t GeminiTool) CanonicalTarget(_ string) (string, bool)
CanonicalTarget returns ok=false because Gemini owns its skill directory through the CLI; reconcile has no filesystem projection to inspect.
func (GeminiTool) Detect ¶
func (t GeminiTool) Detect() bool
func (GeminiTool) Install ¶
func (t GeminiTool) Install(skillName, canonicalDir, projectRoot string) ([]string, error)
func (GeminiTool) Name ¶
func (t GeminiTool) Name() string
func (GeminiTool) SkillPath ¶
func (t GeminiTool) SkillPath(skillName, projectRoot string) (string, error)
SkillPath is not applicable for GeminiTool — Gemini manages skill paths internally via its CLI and does not expose a predictable filesystem location.
func (GeminiTool) Uninstall ¶
func (t GeminiTool) Uninstall(skillName string) error
type SkillFile ¶
type SkillFile struct {
Path string // relative to the skill root (e.g. "scripts/deploy.sh")
Content []byte
}
SkillFile represents a file to be written to the skill store.
type Status ¶
type Tool ¶
type Tool interface {
// Name returns the tool identifier (e.g. "claude", "cursor").
Name() string
// Install creates a link from the agent's expected directory into canonicalDir
// (~/.scribe/skills/<name>). projectRoot scopes tools that support
// project-local projections; an empty projectRoot preserves legacy global
// projection behavior. Returns the paths of the links created.
Install(skillName, canonicalDir, projectRoot string) (paths []string, err error)
// Uninstall removes the links for a skill.
Uninstall(skillName string) error
// Detect reports whether this tool is installed on the machine.
Detect() bool
// SkillPath returns the absolute path where this tool expects the skill
// symlink (or link file) to live. Used by adoption to remove the old
// real directory before Install replaces it with a symlink.
SkillPath(skillName, projectRoot string) (string, error)
// CanonicalTarget returns the path inside canonicalDir that this tool's
// on-disk projection mirrors (e.g. claude → canonicalDir/SKILL.md; codex
// → canonicalDir itself). When ok is false, the tool manages its skills
// opaquely (e.g. via a CLI) and reconcile skips drift inspection.
CanonicalTarget(canonicalDir string) (path string, ok bool)
}
Tool links a skill from the canonical store into a specific AI tool's directory.
func BuiltinByName ¶
func DefaultTools ¶
func DefaultTools() []Tool
DefaultTools returns the standard set of supported AI tools.
func DetectTools ¶
func DetectTools() []Tool
DetectTools returns tools that are actually installed on this machine.