profile

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: May 26, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package profile manages the ccx profile registry (~/.ccx/profiles.toml). It implements profile CRUD, validation, atomic file writes, and active- profile detection. All ProfileManager methods take context.Context. The registry file is rewritten atomically on every mutation (write to profiles.toml.tmp, then os.Rename).

Index

Constants

View Source
const (
	EnvActiveProfile = "CCX_ACTIVE_PROFILE"
	EnvConfigDir     = "CLAUDE_CONFIG_DIR"
)

Environment variable names that control active-profile detection. Defined here so tests and callers reference a single source of truth.

Variables

This section is empty.

Functions

func ValidateProfile

func ValidateProfile(p contracts.Profile) error

ValidateProfile checks that p is well-formed enough to be stored in the registry. It does NOT touch the filesystem; existence checks are done by the Manager so that pure validation is cheap and testable.

Rules:

  • Name is non-empty
  • Name matches ^[a-z0-9-]+$
  • ConfigDir is non-empty and absolute (filepath.IsAbs)

Types

type Manager

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

Manager owns the profile registry at <root>/profiles.toml. All mutating methods rewrite the whole file atomically. The zero Manager is not usable; always construct via NewManager.

func NewManager

func NewManager(root string) (*Manager, error)

NewManager returns a Manager rooted at the given directory (typically ~/.ccx). The directory does not need to exist yet; it is created lazily by the first mutating call.

func (*Manager) Active

func (m *Manager) Active(ctx context.Context) (contracts.Profile, bool, error)

Active returns the active profile, if any, plus a boolean indicating whether one was found.

Resolution order, per spec section 6:

  1. If CCX_ACTIVE_PROFILE is set, look it up in the registry. Found -> return (p, true, nil). Not found -> (zero, false, ErrProfileNotFound wrapped).
  2. Else, if CLAUDE_CONFIG_DIR is set, search the registry by ConfigDir. Found -> return (p, true, nil). Not found -> (zero, false, ErrNoActiveProfile wrapped) to indicate an "unmanaged" config dir.
  3. Else, return (zero, false, nil) - no active profile and no error.

func (*Manager) Add

func (m *Manager) Add(ctx context.Context, p contracts.Profile) error

Add registers a new profile. Behavior:

  • Validates the profile shape (name, absolute ConfigDir).
  • Rejects with contracts.ErrProfileAlreadyExists if another profile has the same name.
  • Ensures ConfigDir exists (creating it with mode 0700 if missing).
  • Sets CreatedAt/LastUsedAt to time.Now().UTC() when the caller leaves them zero, so callers can pass a bare Profile{Name, ConfigDir}.
  • Writes the full registry atomically.

func (*Manager) Get

func (m *Manager) Get(ctx context.Context, name string) (contracts.Profile, error)

Get returns the profile with the given name. If no such profile exists, the returned error wraps contracts.ErrProfileNotFound.

func (*Manager) List

func (m *Manager) List(ctx context.Context) ([]contracts.Profile, error)

List returns all profiles, sorted by Name. The returned slice is a fresh copy; mutating it does not affect the on-disk registry.

func (*Manager) MarkUsed

func (m *Manager) MarkUsed(ctx context.Context, name string) error

MarkUsed updates the LastUsedAt field of the named profile to time.Now() in UTC. It is intended to be called by the cli layer after `ccx use` successfully emits an activation script. If no such profile exists, the returned error wraps contracts.ErrProfileNotFound.

func (*Manager) Path

func (m *Manager) Path() string

Path returns the absolute path to the registry file.

func (*Manager) Remove

func (m *Manager) Remove(ctx context.Context, name string) error

Remove deletes the profile with the given name. If no such profile exists, the returned error wraps contracts.ErrProfileNotFound. The file is rewritten atomically only if the registry actually changed.

func (*Manager) Root

func (m *Manager) Root() string

Root returns the registry root directory.

func (*Manager) Update

func (m *Manager) Update(ctx context.Context, name string, fn func(*contracts.Profile) error) error

Update loads the named profile, lets fn mutate it, validates the result, and rewrites the registry atomically. If fn returns an error the registry is left unchanged.

Jump to

Keyboard shortcuts

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