snapshot

package
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Aug 19, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package snapshot gives Kram a way to capture and restore the workspace's file state without ever touching the user's own git repository — no `git reset --hard`, no checkout, no change to their index, staging area, current branch, or commits. If an agent breaks something, a snapshot is the way back, independent of whatever the user is doing with git themselves.

The storage engine is git itself, but a second, entirely separate repository, isolated under <workspace>/.kram/snapshots/.git (--git-dir), operating against the real workspace directory as its --work-tree. Every operation this package performs — add, commit, diff, reset --hard — targets that isolated --git-dir. None of it is a "dangerous" command in that context: it's our own private, hidden repository nobody else looks at, used purely as inexpensive, correct content-addressed storage for whole-tree snapshots. It shares a filesystem with the user's repo but nothing else — different index, different HEAD, different history, different config, different identity.

The user's real .git and Kram's own .kram/ are never captured — see ensureRepo's exclude file. Everything else present in the workspace at snapshot time is, respecting whatever the user's own .gitignore already says: files git itself would call untracked-and-ignored (node_modules, build output, .env, ...) are skipped, which is deliberate — see DECISIONS.md.

Index

Constants

This section is empty.

Variables

View Source
var ErrUnavailable = errors.New("snapshot: git is not available on PATH")

ErrUnavailable is returned by any Store operation when git isn't on PATH. The feature degrades gracefully: callers (the snapshot_* tools) turn this into a plain "unavailable" text result, never a crash.

Functions

func Available

func Available() error

Available reports whether the snapshot feature can be used at all in this environment. Every exported Store method also checks this itself and returns ErrUnavailable, so callers that only care about the error path don't need to call this separately — it exists mainly so a tool can decide once, up front, whether to attempt anything.

Types

type FileChange

type FileChange struct {
	Path   string `json:"path"`
	Status string `json:"status"` // "will be overwritten" | "will be restored" | "will be removed"
}

FileChange describes what restoring a given snapshot would do to one path, relative to the workspace's current on-disk state.

type RestoreResult

type RestoreResult struct {
	SnapshotID string       `json:"snapshot_id"`
	Changes    []FileChange `json:"changes"`
}

RestoreResult reports exactly what a Restore call changed — restoring is a mutating, potentially destructive action, so this is never silent about its effect (see DECISIONS.md, "Restore over stale state").

type Snapshot

type Snapshot struct {
	ID        string    `json:"id"`
	Message   string    `json:"message"`
	CreatedAt time.Time `json:"created_at"`
}

Snapshot is one point-in-time capture of the workspace — a commit in the isolated snapshot repository, never in the user's own.

func (Snapshot) ShortID

func (s Snapshot) ShortID() string

ShortID is the 12-character prefix used in tool-facing output — the full 40-character hash still works anywhere an id is accepted.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store owns one workspace's isolated snapshot repository.

func NewStore

func NewStore(workspace string) *Store

NewStore returns a Store rooted at workspace's .kram/snapshots directory. Like artifact.Open, it touches no disk until an operation actually needs it — no directory is created just by calling this.

func (*Store) Create

func (s *Store) Create(ctx context.Context, message string) (Snapshot, error)

Create captures the workspace's current file state as a new snapshot: every file present, minus the user's own .gitignore matches, minus .git and .kram. message becomes the commit message; an empty message gets a timestamp default. Never touches the user's real .git.

func (*Store) Diff

func (s *Store) Diff(ctx context.Context, id string) (string, error)

Diff shows what restoring id would change, as a unified diff against the workspace's current on-disk state — without applying anything. Calling this is always safe.

func (*Store) List

func (s *Store) List(ctx context.Context) ([]Snapshot, error)

List returns every snapshot ever taken for this workspace, newest first (the isolated repo's own log order — there is exactly one linear history, since nothing ever branches or checks out a different commit within it). Returns an empty slice, not an error, if no snapshot has ever been created.

func (*Store) Restore

func (s *Store) Restore(ctx context.Context, id string) (RestoreResult, error)

Restore brings the workspace's files back to exactly the state captured by snapshot id. It never touches the user's real .git, index, branch, or commits — only the isolated repository's own hidden HEAD (meaningless outside this package) and the content of files on disk.

Chosen behavior for a stale snapshot (the workspace has changed again since id was taken): overwrite and report, never silently and never refuse. Restore always returns the full list of paths it changed — see RestoreResult — so the caller (and, through the snapshot_restore tool, the model and the user) can see exactly what happened, even though nothing blocks the restore itself. See DECISIONS.md for why this was chosen over refusing on staleness.

A file the snapshot system has no record of at all — created after the most recent snapshot and never captured by any Create call — is left untouched. Restore only ever undoes what it once knew about.

Jump to

Keyboard shortcuts

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