treepad

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Aug 23, 2026 License: MIT Imports: 37 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ActionCreated     = "created"      // worktree created this tick
	ActionSkipped     = "skipped"      // branch already existed; nothing to do
	ActionWouldCreate = "would-create" // --dry-run: would have been created
	ActionBlocked     = "blocked"      // gh is available but the parent has no open pull request yet
	ActionGHRequired  = "gh-required"  // gh absent, unauthenticated, or --offline: parent's PR state is unknown
	ActionError       = "error"        // materialise failed; this Chain stops here
	ActionLaunched    = "launched"     // --launch spawned an agent for this member this tick
)

Action values a ReportEntry can carry.

Variables

View Source
var ErrNotTTY = errors.New("tp ui requires an interactive terminal")

ErrNotTTY is returned by UI when stdout is not an interactive terminal.

Functions

func BatchList

func BatchList(ctx context.Context, d deps.Deps, in BatchListInput) error

BatchList prints every Batch, its Chains, and each member's ticket, ref, branch and base. It creates no worktrees and calls gh for nothing.

func BatchSync

func BatchSync(ctx context.Context, d deps.Deps, in BatchSyncInput) (int, error)

BatchSync runs Reconcile and renders the Report for `tp batch sync`. It returns the count of members whose materialisation failed this tick, for the caller to translate into a process exit code.

func ConfigInit

func ConfigInit(ctx context.Context, d deps.Deps, in ConfigInitInput) error

func ConfigShow

func ConfigShow(ctx context.Context, d deps.Deps, _ ConfigShowInput) error

func Diff

func Diff(ctx context.Context, d deps.Deps, in DiffInput) error

Diff diffs the target worktree against base using three-dot merge-base semantics (base...HEAD), matching GitHub PR view. Inherits stdio so the user's pager and color config (delta, diff-so-fancy) apply automatically.

func Doctor

func Doctor(ctx context.Context, d deps.Deps, in DoctorInput) error

func Exec

func Exec(ctx context.Context, d deps.Deps, in ExecInput) (int, error)

Exec runs a command in the named worktree, routing through the detected task runner when the command matches a known script. Returns the child process exit code (non-zero does not produce an error).

func Generate

func Generate(ctx context.Context, d deps.Deps, in GenerateInput) error

func IsDrainDiscardable

func IsDrainDiscardable(msg tea.Msg) bool

IsDrainDiscardable reports whether msg should be skipped by a headless drain loop. Discards uiYankClearMsg (so yankPath survives until View renders the OSC-52 sequence) and spinner.TickMsg (timer-driven, would chain infinitely). Exposed for the e2e/script harness; not intended for production use.

func PlaybookNew

func PlaybookNew(ctx context.Context, d deps.Deps, in PlaybookNewInput) error

PlaybookNew writes stdin verbatim to .claude/playbooks/<name>.md in the main worktree. Treepad composes nothing and interpolates nothing: see ADR 0002.

func ResolveSourceDir

func ResolveSourceDir(
	useCurrentFlag bool,
	sourcePath string,
	cwd string,
	worktrees []worktree.Worktree,
) (string, error)

ResolveSourceDir is a pure function — no I/O. cwd is pre-fetched by the caller and used only when useCurrentFlag is true.

func SkillInstall

func SkillInstall(ctx context.Context, d deps.Deps, in SkillInstallInput) error

func SkillList

func SkillList(_ context.Context, d deps.Deps, _ SkillListInput) error

func Status

func Status(ctx context.Context, d deps.Deps, in StatusInput) error

func UI

func UI(ctx context.Context, d deps.Deps, in StatusInput) error

UI opens a full-screen fleet view. It returns ErrNotTTY when d.Out is not an interactive terminal.

Types

type BatchListInput

type BatchListInput struct {
	JSON      bool
	OutputDir string
}

type BatchSyncInput

type BatchSyncInput struct {
	JSON      bool
	DryRun    bool
	Offline   bool
	Launch    bool
	Batch     string
	OutputDir string
}

BatchSyncInput parameterises the `tp batch sync` command.

type ConfigInitInput

type ConfigInitInput struct {
	Global    bool
	Inherit   bool
	HooksOnly bool
	Force     bool
}

type ConfigShowInput

type ConfigShowInput struct{}

type DiffInput

type DiffInput struct {
	Branch     string
	Base       string // empty defaults to "origin/main"
	OutputFile string // if set, writes uncolored patch here instead of terminal
	ExtraArgs  []string
	Runner     PassthroughRunner // nil uses osPassthroughRunner
}

type DoctorFinding

type DoctorFinding struct {
	Branch string `json:"branch"`
	Path   string `json:"path"`
	Kind   string `json:"kind"`
	Detail string `json:"detail"`
}

type DoctorInput

type DoctorInput struct {
	JSON      bool
	StaleDays int
	Base      string
	Offline   bool
	Strict    bool
	OutputDir string
}

type ExecInput

type ExecInput struct {
	Branch  string
	Command string
	Args    []string
	// Cwd overrides os.Getwd for the same-worktree warning. Empty means use os.Getwd.
	Cwd string
	// Runner overrides the default passthrough.OSRunner for testing.
	Runner PassthroughRunner
}

ExecInput parameterises a tp exec invocation.

type GenerateInput

type GenerateInput struct {
	UseCurrentDir bool
	SourcePath    string
	SyncOnly      bool
	OutputDir     string
	ExtraPatterns []string
	// Branch restricts the sync and artifact generation to a single worktree.
	// Empty means fleet-wide (existing behaviour).
	Branch string
}

type HeadlessUI

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

HeadlessUI drives uiModel synchronously without a TTY or tea.Program. Use NewHeadlessUI to construct; Init / Update / View follow the tea.Model protocol but mutate state in place rather than returning new models.

func NewHeadlessUI

func NewHeadlessUI(ctx context.Context, d deps.Deps, in StatusInput) *HeadlessUI

NewHeadlessUI constructs a HeadlessUI ready for headless key replay. The header clock is fixed at "STATIC" for deterministic output; auto-refresh and toast timers are disabled (nil factories) so no time-based cmds are emitted.

func (*HeadlessUI) EmitCD

func (h *HeadlessUI) EmitCD()

EmitCD writes the cd sentinel and human-readable line to d.Out. No-op when SelectedPath is empty.

func (*HeadlessUI) Init

func (h *HeadlessUI) Init() tea.Cmd

Init follows tea.Model; call once before the first Update.

func (*HeadlessUI) SelectedPath

func (h *HeadlessUI) SelectedPath() string

SelectedPath returns the worktree path chosen via Enter, or "".

func (*HeadlessUI) Update

func (h *HeadlessUI) Update(msg tea.Msg) tea.Cmd

Update feeds msg through the model, stores the updated state, and returns the next command.

func (*HeadlessUI) View

func (h *HeadlessUI) View() string

type PassthroughRunner

type PassthroughRunner = passthrough.Runner

PassthroughRunner is an alias for passthrough.Runner kept for existing callers.

type PlaybookNewInput

type PlaybookNewInput struct {
	// Name is the playbook's basename, without the .md extension.
	Name  string
	Force bool
}

type ReconcileInput

type ReconcileInput struct {
	Batch     string // narrows to one Manifest by name; empty means every Manifest
	DryRun    bool
	Offline   bool // skip the gh call entirely; PR fields report last-known plus staleness
	Launch    bool // spawn an agent for each materialised member with no Activity file yet
	OutputDir string
}

ReconcileInput parameterises Reconcile, called by both `tp batch sync` and (later) `tp ui`'s tick.

type Report

type Report struct {
	Members []ReportEntry `json:"members"`
}

Report is the JSON shape for `--json` and the row source for the TUI: one entry per Member with the action Reconcile took on it this tick.

func Reconcile

func Reconcile(ctx context.Context, d deps.Deps, in ReconcileInput) (Report, error)

Reconcile is the single function driving Batch orchestration. Its five steps run in this fixed order on every tick; materialise and link are implemented so far, the rest land as no-op stubs for later tickets.

type ReportEntry

type ReportEntry struct {
	batch.Member
	WorktreePath string `json:"worktree_path,omitempty"`
	Action       string `json:"action"`
	Error        string `json:"error,omitempty"`
	PRNumber     int    `json:"pr_number,omitempty"`
	PRState      string `json:"pr_state,omitempty"`
	// PRStale is true when --offline was passed, or gh is absent or failed
	// this tick, so PRNumber/PRState are last-known rather than fresh. Its
	// zero value must never be mistaken for "no PR exists" — that case has
	// PRStale false and PRNumber/PRState empty.
	PRStale bool `json:"pr_stale,omitempty"`
	// StackStale is true when restack found this member's worktree diverged
	// from origin/<branch> in a way it cannot safely repair — dirty, or
	// holding a commit git cherry says is not yet upstream — and it is
	// waiting for a human.
	StackStale bool `json:"stack_stale,omitempty"`
	// Removable is true once this member's pull request is MERGED: a
	// reviewer merged on GitHub, so its worktree is safe to remove. Treepad
	// never merges the pull request itself.
	Removable bool `json:"removable,omitempty"`
}

ReportEntry pairs a resolved Member with what Reconcile did about it this tick.

type SkillInstallInput

type SkillInstallInput struct {
	// Names selects which embedded skills to install. Empty means all.
	Names []string
	// Local writes to .agents/skills in the main worktree instead of the
	// user's home directory.
	Local bool
	// Force overwrites a skill directory (or compat symlink) that already exists.
	Force bool
}

type SkillListInput

type SkillListInput struct{}

type StatusInput

type StatusInput struct {
	JSON      bool
	OutputDir string
}

type StatusRow

type StatusRow struct {
	Branch         string              `json:"branch"`
	Path           string              `json:"path"`
	IsMain         bool                `json:"is_main"`
	Dirty          bool                `json:"dirty"`
	Ahead          int                 `json:"ahead"`
	Behind         int                 `json:"behind"`
	HasUpstream    bool                `json:"has_upstream"`
	LastCommit     worktree.CommitInfo `json:"last_commit"`
	ArtifactPath   string              `json:"artifact_path,omitempty"`
	LastTouched    time.Time           `json:"last_touched"`
	Prunable       bool                `json:"prunable,omitempty"`
	PrunableReason string              `json:"prunable_reason,omitempty"`
	// Batch, Chain and Position identify this worktree's place in a Batch
	// Manifest, when its branch is a resolved Chain member; zero-value
	// (Batch empty) means it is not Batch-managed.
	Batch    string `json:"batch,omitempty"`
	Chain    int    `json:"chain,omitempty"`
	Position int    `json:"position,omitempty"`

	// RunState mirrors launcher.RunState (pending/working/idle), derived from
	// the Activity file's mtime. Empty for a non-Batch row: `tp status` never
	// populates it, since deriving it costs nothing but a stat call, the same
	// as tp ui's local ~5s tick.
	RunState string `json:"run_state,omitempty"`
	// PRNumber, PRState and PRStale mirror ReportEntry's fields of the same
	// name, filled in by tp ui's slower gh tick from the last Reconcile
	// Report. Zero-value on a non-Batch row or before the first gh tick
	// completes.
	PRNumber int    `json:"pr_number,omitempty"`
	PRState  string `json:"pr_state,omitempty"`
	PRStale  bool   `json:"pr_stale,omitempty"`
}

Directories

Path Synopsis
Package cdshell owns the __TREEPAD_CD__ shell-bridge protocol.
Package cdshell owns the __TREEPAD_CD__ shell-bridge protocol.
Package lifecycle owns the worktree creation, removal, and pruning verbs.
Package lifecycle owns the worktree creation, removal, and pruning verbs.
Package repo resolves the repository context shared by every treepad verb: the worktree list, the main worktree, the repo slug, and the artifact output directory.
Package repo resolves the repository context shared by every treepad verb: the worktree list, the main worktree, the repo slug, and the artifact output directory.
Package treepadtest provides shared test helpers for packages that depend on treepad sub-package dependencies.
Package treepadtest provides shared test helpers for packages that depend on treepad sub-package dependencies.

Jump to

Keyboard shortcuts

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