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:
- Detect — read marker files (go.mod, package.json, prisma/schema.prisma, …) to infer language, framework, ORM and database, yielding a ProjectInfo.
- Render — turn that ProjectInfo into a commented .codefit.yaml (committed, shared project config) and codefit's own thin SKILL.md.
- 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 ¶
const ConfigName = ".codefit.yaml"
ConfigName is the project config file codefit reads and init writes.
const SkillFileName = "SKILL.md"
SkillFileName is the file every agent looks for inside a skill directory.
const SkillName = "codefit"
SkillName is codefit's skill identifier — the directory name and the frontmatter `name`, per the Anthropic Agent Skills spec.
Variables ¶
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 ¶
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 ¶
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.