cmd

package
v0.9.4 Latest Latest
Warning

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

Go to latest
Published: Jun 19, 2026 License: MIT Imports: 37 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Execute

func Execute()

Types

type CopyState added in v0.7.21

type CopyState struct {
	Hash     string    `json:"hash"`
	SyncedAt time.Time `json:"synced_at,omitempty"`
}

CopyState records what one on-disk copy of a skill looked like at the last time the mirror reconciled it. A skill lives in N agent directories, each independently editable; a single ContentHash can't say which copy moved. The per-copy baseline can. SyncedAt is a display hint only — it must never be the thing that decides which edit wins (that path silently discards an edit; see cli-per-copy-skill-divergence.md).

type ShadowInfo added in v0.7.3

type ShadowInfo struct {
	SkillID string
	Slug    string
	OrgSlug string // winning org slug; empty for cross-org shadow on the loser side
}

ShadowInfo records a server-reported shadow on one of the caller's skills (migration 047). Returned by fetchShadowMap so pull can skip shadowed slugs and emit a warning instead of writing them to disk.

type SkillConflictError added in v0.7.3

type SkillConflictError struct {
	Slug           string // the slug that conflicted (the one the user tried to create)
	Source         string // "user" or "org" — where the conflicting skill lives
	OwnerOrOrgSlug string // org slug when Source=="org"; empty otherwise
	ServerMessage  string // verbatim server `message` if present
}

SkillConflictError is returned by createSkill when the server's effective-skills check (migration 047) rejects a new slug because it already exists in the caller's user-or-org-inherited skill set. Push surfaces this with a hint pointing at `airskills mv`.

func (*SkillConflictError) Error added in v0.7.3

func (e *SkillConflictError) Error() string

type SkillState added in v0.5.27

type SkillState string

SkillState is the presence/lifecycle state of a single skill on this machine — the FIRST axis of the unified divergence model (platform/doc/changes/unify-skill-divergence-state-model.md). It is determined first and is mutually exclusive, from the (Local, Marker, Remote) presence triple alone.

The SECOND axis — HOW a tracked skill diverges — is carried by the three orthogonal booleans on SkillStateInfo (LocalDirty, RemoteMoved, UpstreamMoved), never by this enum. The old flat vocabulary (synced/modified/modified-pending) collapsed those two axes into one 1-D encoding and could not name the (clean, upstream-moved) cell, which is why `list` and `status` disagreed. `decideState` is the single divergence classifier; every command projects from its output.

User-facing description: doc/internals/sync-state.mdx in the platform repo.

const (
	// StateAvailable — server has a skill the user has not installed on
	// this machine. Rendered as "—" in `airskills list`. (was not-local)
	StateAvailable SkillState = "available"

	// StateUntracked — local dir exists, no marker, and the server has no
	// skill that could account for it. Common when a skill arrived via git
	// rather than `airskills add`.
	StateUntracked SkillState = "untracked"

	// StateAdoptable — local dir exists, no marker, but the server has a
	// skill of the same name whose bytes match exactly. Next sync silently
	// claims it. (was linked)
	StateAdoptable SkillState = "adoptable"

	// StateConflict — local dir exists, no marker, server has a same-named
	// skill whose bytes differ. Folds the old untracked-conflict AND the
	// parked pending-conflict copy into one state, one report. (was
	// untracked-conflict)
	StateConflict SkillState = "conflict"

	// StateTracked — local dir, marker, and remote all present. How it
	// diverges is read off the (LocalDirty, RemoteMoved, UpstreamMoved)
	// booleans, not off this value. (replaces synced / modified /
	// modified-pending)
	StateTracked SkillState = "tracked"

	// StateOrphaned — local dir + marker, but the server no longer has the
	// skill (404 / archived). (was markerStateOrphan / orphan-*)
	StateOrphaned SkillState = "orphaned"

	// StateDisplaced — local dir + marker, but the name now belongs to a
	// different skill on the server (transferred away or org-shadowed).
	// (folds markerStateMoved / moved-keep / shadowed)
	StateDisplaced SkillState = "displaced"
)

type SkillStateInfo added in v0.5.27

type SkillStateInfo struct {
	// Name is the local directory name when the skill exists locally,
	// otherwise the server slug. Stable across server-side renames because
	// tracking matches by skill_id first.
	Name string

	State SkillState

	// Local is true when the skill has a directory on this machine.
	Local bool

	// Remote is the server-side view, if the server knows about this skill.
	// Nil for purely-local untracked directories.
	Remote *apiSkill

	// Marker is the sync.json entry for this skill, if one exists.
	Marker *SyncEntry

	// LocalHash is the Merkle hash of on-disk content. Empty when the skill
	// is not present locally.
	LocalHash string

	// The four divergence coordinates of the unified model. Meaningful only
	// when State == StateTracked; all false otherwise. Sourced is the
	// ownership axis; the other three are the orthogonal divergence flags.
	Sourced       bool // a Source/forked_from upstream pointer exists
	LocalDirty    bool // working ≠ base — I have edits not yet pushed
	RemoteMoved   bool // my_remote_head ≠ base — another of my machines pushed
	UpstreamMoved bool // forks only: the parent moved past upstream_base

	// Overlay marks the one-skill shape for non-owned skills: the marker
	// tracks the UPSTREAM id, local edits are an overlay backed up in a
	// hidden fork (cli-one-skill-overlay-and-lineage-split.md). For overlay
	// rows the matched remote IS the upstream, so RemoteMoved stays false;
	// standing divergence from the upstream is OverlayDiverged ("local
	// changes"), and UpstreamMoved means the upstream moved past the
	// baseline the user last incorporated.
	Overlay         bool
	OverlayDiverged bool // local ≠ upstream head — the user's standing edits
}

SkillStateInfo is one row of classifier output. The classifier emits one row per server-known skill plus one row per local directory that has no marker and no matching server skill.

type SkillsetNotFoundError added in v0.5.24

type SkillsetNotFoundError struct {
	RequestedSlug string
	Available     []string
}

SkillsetNotFoundError is returned when the server reports an unknown skillset slug on /api/v1/skills. Callers render it as a human-readable hint listing the user's available skillsets.

func (*SkillsetNotFoundError) Error added in v0.5.24

func (e *SkillsetNotFoundError) Error() string

type SyncEntry added in v0.3.0

type SyncEntry struct {
	SkillID     string `json:"skill_id"`
	Version     string `json:"version"`
	ContentHash string `json:"content_hash,omitempty"`
	Tool        string `json:"tool"`
	// Copies is the per-copy reconciliation ledger, keyed by absolute
	// skill-dir path. Seeded at marker creation (seedCopyLedgerFromDisk)
	// and maintained by the mirror (mirrorLocalSkills); used to tell which
	// agent copy of a skill diverged. Empty only for legacy markers, in
	// which case a divergence is surfaced for reconciliation rather than
	// guessed (never mtime, never the marker-wide hash). See
	// cli-per-copy-skill-divergence.md.
	Copies    map[string]CopyState `json:"copies,omitempty"`
	OwnerKind string               `json:"owner_kind,omitempty"` // "user" or "org"
	OwnerSlug string               `json:"owner_slug,omitempty"` // e.g. "chrismdp" or "cherrypick"
	// LocalAlias is the on-disk directory name when it differs from
	// the server slug. Set by `airskills add --as <alias>` and by the
	// on-disk migration when it has to disambiguate a rename
	// collision. Empty means "dir name matches server slug." The
	// marker stays the source of truth — see CLAUDE.md "Org
	// namespacing lives in the marker, not on disk."
	LocalAlias string       `json:"local_alias,omitempty"`
	Source     *skillSource `json:"source,omitempty"`
	// Backup references the hidden backup fork holding this skill's local
	// edits when the caller can't write the upstream. Only meaningful on
	// overlay markers (SkillID == the upstream's id). Cleared when the
	// edits land upstream (admin fold-in / accepted suggestion) or the
	// backup is promoted to a visible personal skill (upstream lost).
	Backup *backupRef `json:"backup,omitempty"`
	// ResolvedHash records the upstream content hash the user last
	// reviewed against via `airskills resolve`. Only meaningful for
	// sourced skills (Source != nil). Empty for owned skills, and for
	// sourced skills the user has never resolved against — in that
	// case the classifier treats any divergence as modified-pending.
	ResolvedHash    string `json:"resolved_hash,omitempty"`
	SuggestionID    string `json:"suggestion_id,omitempty"`
	SuggestDeclined bool   `json:"suggest_declined,omitempty"`
	// Deleted is set when the skill was transferred away and local edits
	// prevent removing the old dir. Pushes are blocked for deleted markers.
	Deleted bool   `json:"deleted,omitempty"`
	MovedTo string `json:"moved_to,omitempty"` // new dir name after transfer
}

SyncEntry tracks the sync state of a single skill.

OwnerKind / OwnerSlug record the skill's CURRENT namespace as last seen on the server. They get updated after every push so a server-side transfer is picked up on the next push without a separate sync step. If they change between pushes, the local dir is renamed to match.

type SyncState added in v0.3.0

type SyncState struct {
	Version int                   `json:"version"`
	Skills  map[string]*SyncEntry `json:"skills"`
	// LastSuggestionNotifyAt is the cutoff for printing suggestion
	// accept/decline notifications. Anything reviewed at or before this
	// has already been shown. Stateless alternative to tracking IDs.
	LastSuggestionNotifyAt string `json:"last_suggestion_notify_at,omitempty"`
}

SyncState holds sync metadata for all tracked skills. Stored at ~/.config/airskills/sync.json, keyed by local directory name.

Jump to

Keyboard shortcuts

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