scaffold

package
v0.18.1 Latest Latest
Warning

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

Go to latest
Published: Sep 24, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package scaffold downloads a starting set of files from this repository's main branch and places them in a project. It never overwrites, and it never transforms what it fetches: what is on main is what lands on disk.

Index

Constants

View Source
const BaseURL = "https://raw.githubusercontent.com/ynny-github/agent-sandbox/main/"

BaseURL is where every asset is fetched from. It is pinned to main on purpose, not to the binary's own version: init then works the moment a template lands on main, and the profiles are validated against the operator's own nono before anything is written.

Variables

View Source
var Assets = []Asset{
	{Source: "templates/minimal/agent-sandbox.toml", Dest: "agent-sandbox.toml"},
	{Source: "templates/minimal/command-profile.json", Dest: "command-profile.json", Profile: true},
	{Source: "templates/minimal/claude-profile.json", Dest: "claude-profile.json", Profile: true},
	{
		Source: ".claude/skills/growing-a-nono-profile/SKILL.md",
		Dest:   ".claude/skills/growing-a-nono-profile/SKILL.md",
	},
	{
		Source: ".claude/skills/verifying-nono-sandbox-claims/SKILL.md",
		Dest:   ".claude/skills/verifying-nono-sandbox-claims/SKILL.md",
	},
}

Assets is the fixed set init places. The skills are seeded once and never updated: the project owns them from that point on, which is why there is no --force and no refresh path.

Functions

func Validate

func Validate(ctx context.Context, fetched []Fetched) ([]string, error)

Validate hands every fetched profile to `nono profile validate` before any file is written. What it covers is narrow: the templates are validated on main before merge and init does not transform them, so the case left is the operator's nono differing from the developer's. It is kept because it costs one subprocess call against a dependency agent-sandbox already requires.

It is not a security check. validate inspects syntax, field names, enum values and group references; it does not look at what a profile grants.

Warnings are returned rather than treated as failures. The command template raises [allow_all_network] on ssh by design.

func Write

func Write(dir string, fetched []Fetched) ([]string, []string, error)

Write places every fetched asset under dir. A destination that already exists is skipped, never rewritten: the skills are seeded once and the project owns them afterwards, and a profile a user has grown must not be replaced by an upgrade.

The existence check and the write are one atomic operation (O_WRONLY|O_CREATE|O_EXCL) rather than a stat followed by a separate write. os.Stat follows symlinks, so a dangling symlink at dest would read as fs.ErrNotExist and a subsequent os.WriteFile would then write through it -- potentially outside the project directory entirely. O_EXCL refuses to open through an existing entry, symlink or not, and closes that stat/write race in the process.

Returned paths are Asset.Dest values, in Assets order.

Types

type Asset

type Asset struct {
	// Source is the path under the repository root, appended to BaseURL.
	Source string
	// Dest is the path relative to the project directory.
	Dest string
	// Profile marks a nono profile. Profiles are handed to
	// `nono profile validate` before any file is written.
	Profile bool
}

Asset is one file init places.

type Fetched

type Fetched struct {
	Asset Asset
	URL   string
	Body  []byte
	// ETag is the file's content hash as raw.githubusercontent reports it.
	// It comes free with the response, unlike the branch head sha, which
	// would cost a second request against an unauthenticated rate limit.
	ETag string
}

Fetched is one asset's bytes together with what init reports about their origin. Profiles are a security boundary, so where each byte came from is printed rather than left implicit.

func Fetch

func Fetch(ctx context.Context, client *http.Client, base string) ([]Fetched, error)

Fetch retrieves every asset into memory. It returns no partial result: a failure anywhere means nothing is written, because a half-initialized project combined with "never overwrite" would persist.

Jump to

Keyboard shortcuts

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