/**
 * Extra DotAgent repo management.
 *
 * Registers `agents repos add|init|list|remove|enable|disable` (`repo` alias)
 * which manage additional DotAgent repos alongside the primary ~/.agents/.system/
 * repo so private, work, or team skills can ship separately from public ones.
 *
 * Extras are user-level config: managed clones live at ~/.agents-<alias>/ as
 * peer dirs to ~/.agents/, and user-owned repos may live anywhere. All extras
 * are registered in meta.extraRepos. Sync functions merge their resources into
 * agent version homes after the user repo's (user-wins on name collisions).
 */
import type { Command } from 'commander';
/**
 * These are DotAgent *resource* repos, so changes are reported at the resource
 * level ("2 skills, 1 hook") rather than the raw-file level. A resource is the
 * unit a user reasons about: one skill, one command, one plugin — even if it
 * spans several files on disk.
 */
type RepoResourceKind = 'skill' | 'command' | 'plugin' | 'hook' | 'mcp' | 'subagent' | 'rule' | 'workflow' | 'routine' | 'profile' | 'permission' | 'clis' | 'config' | 'other';
export type ChangeAction = 'new' | 'changed' | 'removed';
/**
 * Map a repo-relative path to the resource unit it belongs to. Directory-based
 * resources (skills/foo/SKILL.md) collapse to `skills/foo` so all their files
 * count as one unit; flat config files (agents.yaml, hooks.yaml) count alone.
 */
export declare function resourceUnit(file: string): {
    kind: RepoResourceKind;
    unit: string;
};
/** One resource kind + action, collapsed to a unit count (e.g. 2 new skills). */
export interface CountedResource {
    action: ChangeAction;
    kind: RepoResourceKind;
    count: number;
}
/** Resource-level summary of a changed-file set. */
export interface ResourceDelta {
    /** Counts in display order (grouped new -> changed -> removed, then RESOURCE_ORDER). */
    counts: CountedResource[];
    /** Total distinct resource units changed. */
    total: number;
}
/**
 * Collapse a changed-file set to distinct resource units, then count them by
 * (action, kind). A skill whose three files all changed counts as one changed
 * skill; a unit with mixed add+modify reads as a single change. This is the
 * shared structured core behind every SYNC / CHANGES rendering.
 */
export declare function resourceDelta(entries: {
    action: ChangeAction;
    file: string;
}[]): ResourceDelta;
/**
 * Kind-only brief for the compact (wide-terminal) layout: `(24 skills, 9 commands, +20)`
 * — the top `maxKinds` kinds by display order, with a `+N` remainder. Drops the
 * new/changed verb (the arrow already carries direction) to stay short. Returns
 * '' when there is nothing to summarize.
 */
export declare function deltaBrief(delta: ResourceDelta, maxKinds?: number): string;
/**
 * Render a set of changed files as a resource-level summary, e.g.
 * `2 new skills, 1 changed hook`. Counts distinct resource units (a skill whose
 * three files all changed is "1 changed skill"), grouped by action then kind,
 * and colors each phrase green/yellow/red for new/changed/removed. Caps at
 * `maxParts` phrases, appending `+N more` so a big diff stays scannable.
 */
export declare function formatResourceDelta(entries: {
    action: ChangeAction;
    file: string;
}[], maxParts?: number): string;
/** One side of a divergence: the resource delta plus the raw commit count (fallback). */
interface RepoDivergence {
    delta: ResourceDelta;
    commits: number;
}
/**
 * Structured status for one repo. `raw` is a free-form trailer for special cases
 * (missing repo, no git remote, error) that don't fit the columns; otherwise the
 * fields feed whichever layout (table / cards) the terminal width selects.
 */
export interface RepoRow {
    alias: string;
    raw?: string;
    branch?: string;
    tracking?: boolean;
    pull?: RepoDivergence;
    push?: RepoDivergence;
    clean?: boolean;
    local?: ResourceDelta;
    url?: string;
    commit?: string;
}
/** `owner/repo` from a git URL, for the compact card header. Falls back to the raw URL. */
export declare function repoSlug(url: string): string;
/** Pack colored phrases into `, `-joined lines no wider than `width`. */
export declare function wrapPhrases(parts: string[], width: number): string[];
/** Options shared by `agents repo list` and the `agents repo status` alias. */
export interface RepoStatusOptions {
    verbose?: boolean;
    json?: boolean;
    /** Fan out across every reachable fleet device (`--devices-all`). */
    devicesAll?: boolean;
    /** `all`, or a comma-separated device list (`--devices`). */
    devices?: string;
}
/**
 * Per-device repo status — the unit of the `--devices-all` fleet fan-out. One
 * entry per device: its parsed repo rows when reachable, or `reachable: false`
 * when the peer could not be queried (kept in the model so the table can mark it).
 */
export interface DeviceRepoStatus {
    device: string;
    reachable: boolean;
    rows?: RepoRow[];
}
/**
 * Recursion guard for the fleet fan-out, passed as an env var (not a CLI flag)
 * so an OLDER remote `agents` that predates this feature ignores it harmlessly
 * instead of erroring on an unknown option. A peer new enough to fan out reads
 * it and answers only for itself. Mirrors `NO_FANOUT_ENV` in remote-active.ts.
 */
export declare const NO_REPO_FANOUT_ENV = "AGENTS_REPO_LOCAL";
/**
 * Parse one peer's `repo status --json` stdout (a RepoRow[]) into a single
 * device entry tagged with `machine`. Defensive against version skew: non-JSON
 * or a non-array yields no entry, and non-object rows are dropped rather than
 * throwing. Exported for unit testing without a live tailnet.
 */
export declare function parseRemoteRepoRows(stdout: string, machine: string): DeviceRepoStatus[];
/**
 * Render the fleet repo-status table: one row per (device, repo), with the
 * device name shown once per group. SYNC and CHANGES reuse the same compact
 * cells as the local wide table (`↓N (…)  ↑N` / `clean` / `~N edits`), and an
 * unreachable device collapses to a single `unreachable` marker row. Pure — no
 * I/O — so the aggregation/formatting is unit-testable without live devices.
 */
export declare function renderDeviceStatusRows(results: DeviceRepoStatus[]): string[];
/** Where a `repo status` run should report: this machine only, or the fleet. */
type DeviceIntent = {
    all: true;
} | {
    hosts: string[];
};
/**
 * Read the device-scope flags into an intent, or null for the default local-only
 * run. `--devices-all` (and `--devices all`) sweeps every reachable peer;
 * `--devices box1,box2` targets an explicit list. A peer carrying
 * {@link NO_REPO_FANOUT_ENV} never fans out again (recursion guard).
 */
export declare function resolveDeviceIntent(opts: RepoStatusOptions): DeviceIntent | null;
/** Register the `agents repos` command tree (`repo` is a convenience alias). */
export declare function registerRepoCommands(program: Command): void;
export {};
