export

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package export renders docent guides to exportable text formats.

All skill renderers share one common definition — the Agent Skills open standard (agentskills.io): a <name>/SKILL.md layout whose frontmatter carries a name matching the parent directory and a description within the spec's 1024-character cap. AgentSkill renders exactly that portable shape; harness-specific renderers (ClaudeSkill) layer their harness's extensions on top of it without ever diverging from the layout or the name rules. Both built-in renderers accept an optional NameQualifier that prefixes only the exported name and directory; the source Guide remains unchanged.

Beyond skill rendering, the package owns the byte shape of every guide artifact the Agent Guide Standard serves: Index (the frontmatter-only discovery index), Concat (the form-feed-separated full concatenation), and Write (root-scoped artifact writing). Adapters plumb flags and output around these functions rather than re-implementing the shapes, so a second adapter cannot drift from the first.

Hosts use the export package directly when they need fine-grained control over rendered output, or indirectly through the cobra adapter's "agent export --format <fmt> --dir <dir>" command.

Index

Examples

Constants

View Source
const GuideSeparator = "\f\n"

GuideSeparator divides guides in concatenated output (Concat, served by the cobra adapter as "agent guide --all"). Load validation rejects form feeds in guide content (docent.ErrFormFeed), so splitting on a form-feed line is unambiguous by construction — unlike "---", which every guide's frontmatter opens with.

Variables

View Source
var (
	// ErrInvalidContractVersion is the sentinel Index wraps when a contract
	// version would corrupt the line-oriented index shape: a value
	// containing a newline, carriage return, or colon, or one that is
	// entirely whitespace.
	ErrInvalidContractVersion = errors.New("docent: invalid contract version")

	// ErrInvalidSkillName is the sentinel built-in skill renderers wrap when
	// a qualifier and guide slug do not compose to an Agent Skills name: 1-64
	// lowercase alphanumeric characters and hyphens, with no leading,
	// trailing, or consecutive hyphens. Write validates names before touching
	// the export directory.
	ErrInvalidSkillName = errors.New("docent: invalid exported skill name")

	// ErrPathEscape is the sentinel Write wraps when a Renderer's RelPath
	// lexically escapes the export directory. The check runs before
	// anything touches disk, so an escaping path never leaves partial
	// artifacts behind.
	ErrPathEscape = errors.New("docent: export path escapes the export directory")
)

Sentinel errors for use with errors.Is, so hosts branch on failure classes instead of matching message text.

Functions

func Concat added in v0.2.0

func Concat(guides []docent.Guide) string

Concat returns every guide's raw content concatenated in the given order, each terminated by a newline and separated by GuideSeparator lines so consumers can split the output unambiguously.

func Index added in v0.2.0

func Index(guides []docent.Guide, contractVersion string) (string, error)

Index renders the frontmatter-only guide index — the token-economical discovery view every agent reads first: a header line with the guide count, an optional contract_version line, then one key: value block per guide in the given order (pass GuideSet.Guides() for canonical order).

contractVersion is emitted verbatim on its own line when non-empty; a value that would corrupt the line-oriented shape — one containing a newline, carriage return, or colon, or entirely whitespace — errors with ErrInvalidContractVersion, so a misconfigured host fails loudly instead of serving an unparsable index. Guide fields need no such guard: load validation already rejects multiline values for every field emitted here.

func Write added in v0.2.0

func Write(dir string, r Renderer, guides []docent.Guide) ([]string, error)

Write renders every guide through r and writes one artifact per guide under dir, creating the directory if absent. It returns the written artifact paths relative to dir, in guide order and forward-slash form.

Every relative path is validated — local (else ErrPathEscape) and unique — before anything is written, so a path failing validation never leaves partial artifacts behind. When r also implements ValidatingRenderer, its guide validation runs in that same preflight. The writes themselves go through an os.Root, which refuses any path component that resolves outside dir — a planted symlink, a ".." segment, an absolute path — at open time instead of following it; dir itself is trusted, containment applies beneath it. When a write fails after some artifacts have landed (permissions, disk, an os.Root refusal), the returned slice holds the paths already written, alongside the error.

Types

type AgentSkill

type AgentSkill struct {
	// NameQualifier prefixes the source guide slug in the emitted skill name
	// and directory, separated by a hyphen. Empty preserves the source slug
	// and the historical byte shape. Write validates the final composed name
	// against the Agent Skills constraints before creating any files.
	NameQualifier string
}

AgentSkill renders a docent.Guide to the portable SKILL.md shape defined by the Agent Skills open standard (agentskills.io), the common format consumed by Claude Code, Codex, and other agent runtimes. The frontmatter carries exactly the spec's two required fields: name (the optionally qualified guide slug, which also names the artifact directory, satisfying the spec's name-matches-directory rule) and description (the guide description and when_to_use joined, so a harness can decide whether to load the skill without reading the runbook).

Artifacts conform to the neutral spec and pass its reference validator (skills-ref); this is the format to reach for when the consuming harness is unknown.

Output is deterministic and byte-stable for identical input.

Example

ExampleAgentSkill demonstrates applying a host qualifier without changing the source guide slug.

package main

import (
	"fmt"
	"strings"

	"github.com/matcra587/docent"
	"github.com/matcra587/docent/export"
)

func main() {
	g := docent.Guide{
		Slug:        "core-contract",
		Title:       "Core contract",
		Description: "The host contract.",
		WhenToUse:   "When integrating the CLI.",
	}
	r := export.AgentSkill{NameQualifier: "jira"}

	fmt.Println(r.RelPath(g))
	fmt.Println(strings.Split(r.Render(g), "\n")[1])
	fmt.Println(g.Slug)

}
Output:
jira-core-contract/SKILL.md
name: jira-core-contract
core-contract

func (AgentSkill) RelPath

func (r AgentSkill) RelPath(g docent.Guide) string

RelPath returns the artifact path for g relative to the export root: <name>/SKILL.md, the directory-per-skill layout the spec requires.

func (AgentSkill) Render

func (r AgentSkill) Render(g docent.Guide) string

Render returns the open-standard SKILL.md text for g.

func (AgentSkill) Validate added in v0.4.0

func (r AgentSkill) Validate(g docent.Guide) error

Validate reports whether the qualified name is a conformant Agent Skills name and matches the artifact's parent directory.

type ClaudeSkill

type ClaudeSkill struct {
	// NameQualifier prefixes the source guide slug in the emitted skill name
	// and directory, separated by a hyphen. Empty preserves the source slug
	// and the historical byte shape. Write validates the final composed name
	// against the Agent Skills constraints before creating any files.
	NameQualifier string
}

ClaudeSkill renders a docent.Guide to the Claude Code variant of the SKILL.md shape. Claude Code extends the open standard with a native when_to_use frontmatter field — documented at https://code.claude.com/docs/en/skills.md as "appended to description in the skill listing" — so this renderer keeps description and when_to_use as separate keys instead of joining them. Everything else — layout, name rules, body — is identical to AgentSkill.

Artifacts conform to Claude Code's documented schema, not the neutral spec: the neutral reference validator (skills-ref) rejects when_to_use by design, since the spec's own extension slot is the metadata map. Validate claude-skill output against Claude Code's field set; use AgentSkill when the consuming harness is unknown. Claude Code caps the combined description and when_to_use listing text at 1,536 characters; docent's load-time budget (MaxSkillDescription, 1024, from the neutral spec) is stricter, so a valid guide can never exceed it.

Output is deterministic and byte-stable for identical input.

func (ClaudeSkill) RelPath

func (r ClaudeSkill) RelPath(g docent.Guide) string

RelPath returns the artifact path for g relative to the export root: <name>/SKILL.md, the directory-per-skill layout the spec requires.

func (ClaudeSkill) Render

func (r ClaudeSkill) Render(g docent.Guide) string

Render returns the Claude Code SKILL.md text for g.

func (ClaudeSkill) Validate added in v0.4.0

func (r ClaudeSkill) Validate(g docent.Guide) error

Validate reports whether the qualified name is a conformant Agent Skills name and matches the artifact's parent directory.

type Renderer

type Renderer interface {
	// Render returns the complete artifact text for g.
	Render(g docent.Guide) string

	// RelPath returns the artifact's path relative to the export root,
	// always in forward-slash form.
	RelPath(g docent.Guide) string
}

Renderer is the interface implemented by all export formats. A Renderer converts a single Guide into its text representation and names the artifact path it belongs at; I/O is the caller's responsibility — Write is the package's own root-scoped implementation of that responsibility.

type Runbook

type Runbook struct{}

Runbook renders a docent.Guide to a reading-oriented Markdown runbook: the title as an H1 heading, then each section as an H2 heading and its body, in the guide's validated canonical order. The YAML frontmatter is omitted — slug, commands, and order are machine-routing metadata, redundant with the index the reader already consulted to pick the guide — and there is no generated-do-not-edit header, because the output is served, not written to a file a user could edit.

This is the recommended shape for a single-guide view such as "agent guide <slug>"; frontmatter belongs to the index and skill export. Runbook is presentation, not a file artifact, so it deliberately does not implement Renderer.

Output is deterministic and byte-stable for identical input. A section with an empty body keeps its heading rather than collapsing, the same contract the skill renderers honor.

func (Runbook) Render

func (Runbook) Render(g docent.Guide) string

Render returns the runbook text for g.

type ValidatingRenderer added in v0.4.0

type ValidatingRenderer interface {
	Renderer

	// Validate reports whether g can be rendered without violating the
	// renderer's artifact contract.
	Validate(g docent.Guide) error
}

ValidatingRenderer is a Renderer that validates a guide before Write creates the export directory. The built-in skill renderers implement it so a host-supplied name qualifier cannot produce a non-conformant skill. Host renderers may implement it when their own artifact contract has validation that must complete before any files are written.

Jump to

Keyboard shortcuts

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