tools

package
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 13, 2026 License: MIT Imports: 12 Imported by: 0

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

View Source
const (
	ToolTypeBuiltin = "builtin"
	ToolTypeCustom  = "custom"
)

Variables

View Source
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

func PackagesDir() (string, error)

PackagesDir returns the ~/.scribe/packages/ directory path.

func SlugifyRegistry

func SlugifyRegistry(repo string) string

SlugifyRegistry converts "owner/repo" to "owner-repo" for filesystem paths.

func StoreDir

func StoreDir() (string, error)

StoreDir returns the ~/.scribe/skills/ directory path.

func WriteCanonicalSkill

func WriteCanonicalSkill(canonicalDir string, skillMD []byte) error

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

func WriteToPackageStore(name string, files []SkillFile) (string, error)

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

func WriteToStore(skillName string, files []SkillFile) (string, error)

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

func (t CodexTool) CanonicalTarget(canonicalDir string) (string, bool)

func (CodexTool) Detect

func (t CodexTool) Detect() bool

func (CodexTool) Install

func (t CodexTool) Install(skillName, canonicalDir, projectRoot string) ([]string, error)

func (CodexTool) Name

func (t CodexTool) Name() string

func (CodexTool) SkillPath

func (t CodexTool) SkillPath(skillName, projectRoot string) (string, error)

func (CodexTool) Uninstall

func (t CodexTool) Uninstall(skillName string) error

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 Status struct {
	Name        string `json:"name"`
	Type        string `json:"type"`
	Enabled     bool   `json:"enabled"`
	Detected    bool   `json:"detected"`
	DetectKnown bool   `json:"detect_known"`
	Source      string `json:"source"`
}

func ResolveStatuses

func ResolveStatuses(cfg *config.Config) ([]Status, error)

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 BuiltinByName(name string) (Tool, bool)

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.

func ResolveActive

func ResolveActive(cfg *config.Config) ([]Tool, error)

func ResolveByName

func ResolveByName(cfg *config.Config, name string) (Tool, error)

ResolveByName returns a Tool for the given name regardless of whether it is currently enabled. Used by uninstall paths so that a tool which originally installed a skill can still clean up after it is disabled.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL