scaffold

package
v0.2.3 Latest Latest
Warning

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

Go to latest
Published: Jul 20, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package scaffold powers `codefit init`: it inspects a project on disk and produces the artifacts that make codefit usable from an AI agent.

It does three jobs, all deterministic and LLM-free:

  1. Detect — read marker files (go.mod, package.json, prisma/schema.prisma, …) to infer language, framework, ORM and database, yielding a ProjectInfo.
  2. Render — turn that ProjectInfo into a commented .codefit.yaml (committed, shared project config) and codefit's own thin SKILL.md.
  3. Place — write the skill where each detected agent (Claude Code, OpenCode, Codex) discovers it, declaring every path it touched.

scaffold sits ABOVE the language providers (like the MCP adapter): it is the single place that maps a filesystem to a language. The core stays agnostic.

Index

Constants

View Source
const ConfigName = ".codefit.yaml"

ConfigName is the project config file codefit reads and init writes.

View Source
const SkillFileName = "SKILL.md"

SkillFileName is the file every agent looks for inside a skill directory.

View Source
const SkillName = "codefit"

SkillName is codefit's skill identifier — the directory name and the frontmatter `name`, per the Anthropic Agent Skills spec.

Variables

View Source
var AgentTargets = []AgentTarget{
	{Name: "Claude Code", Markers: []string{".claude", "CLAUDE.md"}, SkillDir: skillDir(".claude")},
	{Name: "OpenCode", Markers: []string{".opencode", "opencode.json", "opencode.jsonc"}, SkillDir: skillDir(".opencode")},
	{Name: "Codex", Markers: []string{".codex"}, SkillDir: skillDir(".agents")},
}

AgentTargets is the SINGLE source of truth for agent → skill-path mapping. To support a new agent or follow a path change, edit this table only.

Markers are files OR dirs: real projects signal an agent with a root config FILE (CLAUDE.md, opencode.json) as often as a dir (.claude, .opencode), so we accept both. AGENTS.md is deliberately NOT a marker: it is a cross-agent convention, so it would falsely match.

NOTE the Codex asymmetry: it is DETECTED by its own marker (.codex, where Codex keeps its project config) but the skill is WRITTEN to .agents/skills (the standardized path Codex actually reads skills from, per OpenAI's Codex docs). Detect-by-X / write-to-Y is deliberate, not a bug — do not "fix" it by making them match, or Codex will stop finding the skill.

Functions

func ConfigExists

func ConfigExists(root string) bool

ConfigExists reports whether root already has a .codefit.yaml — the caller uses it to decide whether to ask before regenerating.

func RenderConfig

func RenderConfig(info ProjectInfo) ([]byte, error)

RenderConfig renders a commented .codefit.yaml for the detected project. Paths are slash-normalized so the committed file is portable across operating systems.

func RenderSkill

func RenderSkill(info ProjectInfo) ([]byte, error)

RenderSkill renders codefit's SKILL.md for the detected project, baking in the language so the example commands are exact.

Types

type AgentTarget

type AgentTarget struct {
	Name     string   // human-facing name, used in the init report
	Markers  []string // project-relative files OR dirs whose presence signals the agent
	SkillDir string   // project-relative dir that holds the skill's SKILL.md
}

AgentTarget maps a coding agent to how codefit detects its presence in a project and where that agent discovers skills.

func DetectAgents

func DetectAgents(root string) []AgentTarget

DetectAgents returns the known agents present in root, in AgentTargets order. An agent is present when any of its markers (a file or a dir) exists.

func PlacementTargets

func PlacementTargets(root string) (targets []AgentTarget, usedFallback bool)

PlacementTargets returns where init should write the skill: the detected agents, or a single standard-location fallback when none are present.

type ConfigAction

type ConfigAction string

ConfigAction reports what Generate did with the project config.

const (
	ConfigCreated     ConfigAction = "created"     // no config existed; written
	ConfigOverwritten ConfigAction = "overwritten" // existed; replaced on permission
	ConfigSkipped     ConfigAction = "skipped"     // existed; left untouched
)

type Options

type Options struct {
	Root            string
	OverwriteConfig bool // when .codefit.yaml exists, replace it (the dev's decision)
}

Options controls a Generate run.

type ProjectInfo

type ProjectInfo struct {
	Name            string // the project directory's base name
	Language        string // typescript | go | python | java
	Framework       string // a value within config.allowedFrameworks, or ""
	ORM             string // prisma | drizzle | typeorm | ""
	DBType          string // postgresql | mysql | sqlite | "" (within config.allowedDBTypes)
	DBParadigm      string // oltp | olap | mixed | "" (oltp when a DB is detected)
	SchemaPaths     []string
	RouteHandlers   int // count of route handlers found (informational, for the report)
	PathCriticality config.PathCriticality
}

ProjectInfo is the deterministic picture of a project that drives config and skill generation. Every field is inferred from files on disk — never an LLM.

func Detect

func Detect(root string) (ProjectInfo, error)

Detect inspects root and infers the project's language and stack from marker files. It returns an error when no supported language can be identified — init must not write a config it cannot stand behind.

type Result

type Result struct {
	Info         ProjectInfo
	ConfigPath   string // project-relative
	ConfigAction ConfigAction
	UsedFallback bool // skill placed in the standard location (no agent detected)
	Skills       []SkillWrite
}

Result is the full account of what Generate did, for the caller to report — nothing is written silently.

func Generate

func Generate(opts Options) (Result, error)

Generate runs the full init: detect the project, write .codefit.yaml (honoring the overwrite decision), and place codefit's skill for every detected agent.

The skill is ALWAYS (re)written — codefit owns it. Only the config is gated on permission, because it is shared, user-owned project config. Generate never prompts: the caller resolves OverwriteConfig and reports the Result.

type SkillWrite

type SkillWrite struct {
	Agent string // the agent whose location it serves
	Path  string // project-relative path written
}

SkillWrite records one skill file placement, for the init report.

Jump to

Keyboard shortcuts

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