/** * `createHarneryProgram` is the composition point. * * harn (this package's CLI) calls this with `binName: 'harn'`. * Consumer CLIs call this with their own binName, register their * domain-specific subcommands, and then use `parseAsync()`. * * The returned Commander program initially contains lightweight top-level * metadata. `parseAsync()` materializes only the selected implementation. * Consumers that inspect the complete nested tree must first call * `loadAllLazyCommands(program)`. * * Future commands wire in via `registerXxxCommand(program)` calls below. * Each subdirectory under src/commands/ exports its `register…` function * (Commander pattern). */ import { Command } from "commander"; export { type LazyCommandBundle, type LazyCommandDefinition, loadAllLazyCommands, loadLazyCommand, onLazyCommandLoaded, registerLazyCommandBundles, } from "./lazy-commands.js"; export interface HarneryContextOpts { /** * The binary name shown in --help output. Defaults to "harn". Consumer * CLIs pass their own, e.g. `binName: "mycli"`. */ binName?: string; /** * Project-scoped context. Commands that touch state (.harnery/agents/, * .harnery/config.jsonc) consult this to resolve paths + project identity. * Optional: harn standalone runs without it. */ context?: HarneryProgramContext; /** * Adapter that lets consumers route structured emissions into their own * OutputContext (e.g. an AsyncLocalStorage-bound writer). When omitted, * harn standalone falls back to a default JSON-to-stdout emitter (see * `defaultEmit` below). */ emit?: EmitContext; /** * Top-level command names harnery should NOT register. Use when a * consumer wants to replace harnery's implementation with its own * (Commander throws on duplicate registration). Example: the host CLI has * a project-specific `harn web` (docker stack shim) and passes * `skipCommands: ["web"]` so harnery's generic `web` doesn't collide. */ skipCommands?: readonly string[]; } /** One row in a `harn env` section report. */ export interface EnvCheck { label: string; value: string; status?: "ok" | "missing" | "warn" | "info"; } /** * A `harn env` section: an async probe returning its rows. Hosts register extra * sections (e.g. cloud-provider connectivity) via `context.envSections`; harnery * core ships only the generic sections (runtimes, docker, git). */ export type EnvSection = () => Promise; export interface HarneryProgramContext { /** Project name (e.g., "my-monorepo"). Used in user-facing log lines + telemetry tags. */ projectName?: string; /** Override the monorepo-root resolver. Default: walk up looking for `.harnery/`. */ resolveCoordRoot?: () => string | null; /** * Absolute path to the monorepo root. Commands like `env` use this as the * default `cwd` for `git` invocations. When omitted, commands fall back to * `process.cwd()`. */ repoRoot?: string; /** * Submodule directory names relative to `repoRoot`. Consumed by `env` to * report N/M initialized. When omitted, the `env` command skips the * submodule row. */ submodules?: readonly string[]; /** * Extra `harn env` sections keyed by name (e.g. `{ gcp, bq }`). Merged into * the built-in generic sections (runtimes, docker, git), so a host can expose * `harn env ` for its own environment probes without harnery core * carrying provider-specific checks. harn standalone ships none. */ envSections?: Record; /** * Extra directory names for `grep` to exclude by default — host-generated * mirrors, vendored trees, and similar directories that only ever produce * duplicate or noisy matches. Names match at any depth (same semantics as * grep's `--exclude-dir`). Applied alongside the built-in skip list and * disabled together with it by `--no-default-excludes`. harn standalone * ships none. */ grepExcludeDirs?: readonly string[]; /** * Optional callback that returns extra HTTP headers to attach to outbound * `fetch` calls based on the target URL. Useful for consumers that need * to inject auth or bypass headers on certain hostnames (e.g. private * zones behind a WAF). harn standalone skips the callback entirely. */ extraHeaders?: (url: string) => Record; /** * Optional callback that returns extra cookies to persist into the shared * jar before `fetch` / `browse` attach it. Runs only when a jar is in * play (`--no-cookies` skips it). Use this for host-minted session * cookies; `extraHeaders` cannot merge a `Cookie` header once the jar * has already set one. Must stay synchronous, same as `extraHeaders`. * harn standalone skips the callback entirely. */ extraCookies?: import("./lib/cookies/index.js").ExtraCookies; /** * Host-injected vision-model call for `browse --check-critique`. harnery * ships no model client or API key; a consumer wires this to its own * multimodal provider (OpenAI/Anthropic/etc). Given one page tile + the * rubric, it returns that tile's findings. When omitted, `--check-critique` * reports `skipped` rather than a false pass. */ critiqueProvider?: import("./lib/browser/critique.js").CritiqueProvider; /** Load a host vision provider only when browse critique is requested. */ critiqueProviderLoader?: () => Promise; /** * Shell-completion provider-key lookup. Consumers wire this to a function * mapping (commandPath, option/positional) to a provider key, so that * `--workspace` / `--env` etc. tab-complete dynamically against * consumer-specific data sources. harn standalone falls back to no-op * (static completion only). */ completionLookup?: (key: { commandPath: string; option?: string; positional?: number; }) => string | undefined; /** * Shell-completion provider runner. Invoked by the hidden `__complete` * subcommand at tab-time to produce the actual list of completions for * a given provider key. */ completionRunner?: (key: string, partial: string) => Promise; /** * Extra path prefixes that should be excluded from `harn docs lint` * convention checks (auto-generated API reference dumps, vendored * content directories, etc.). Combined with harnery's built-in * exclusions (`.claude/`, `.harnery/`, `.codex/`, `.cursor/`). */ extraDocsExcludedPrefixes?: readonly string[]; /** * Filenames permitted at the host project's `docs/` root (parent repo only). * When set, `harn docs lint` flags any other `.md`/`.json` file sitting * loose at `docs/` root (rule `docs-root-file`) — topic docs belong in * `docs//` subdirs. Names are matched exactly (basename). When * omitted or empty, the rule is a no-op, so standalone `harn` and consumers * that don't opt in are unaffected. Submodule `docs/` roots are never * checked (their entry tiers differ from the parent's). */ docsRootAllowlist?: readonly string[]; /** * Construction-time storage families, logger bindings, and explicit host * exclusions. Harnery validates these against its source-owned catalog; * hosts cannot replace or weaken Harnery descriptors at runtime. */ storage?: import("./core/storage/contract.js").HarneryHostStorageRegistration; /** Maintenance implementations registered at construction time by storage owners. */ storageMaintenanceProviders?: readonly import("./core/storage/maintenance.js").HarneryMaintenanceProvider[]; /** Private inbox implementation. Omission keeps the commands visible but unavailable to invoke. */ coordinationInbox?: import("./core/inbox/service.js").HarneryInboxService; /** Adapter-native conversation providers. Omission keeps explicit history access unavailable. */ conversations?: { catalog: import("./core/conversations/catalog.js").HarneryConversationCatalog; projectScopeId: string; records?: () => readonly import("./core/conversations/contract.js").HarneryConversationRecordV1[]; }; /** * Default Host header for `tunnel up` when `--vhost` is omitted: a literal * host, or a resolver evaluated at start time (e.g. read a dev stack's * configured hostname so the tunnel lands on the right vhost). When unset, or * the resolver returns null, the tunnel falls back to harnery's built-in * default (`localhost`). */ tunnelDefaultVhost?: string | (() => string | null | undefined); } /** * Minimum emission surface harnery commands need to talk to a host CLI's * OutputContext. Intentionally tiny: just the methods commands actually * call. Designed to grow additively: consumers that want richer output * routing implement these methods; everyone else gets `defaultEmit`'s * JSON-to-stdout fallback. */ export interface EmitContext { config(opts: { format?: string; }): void; data(payload: unknown): void; rows(rows: Record[]): void; text(s: string): void; file(path: string, summary: Record): void; error(err: { code: string; message: string; hint?: string; } | Error | unknown): void; log(msg: string, level?: "debug" | "info" | "warn" | "error"): void; setExitCode(n: number): void; } export declare const defaultEmit: EmitContext; /** Mount Harnery's storage and log commands below an arbitrary host namespace. */ export interface HarneryLogStorageCommandOptions extends Pick { commands?: readonly ("storage" | "logs")[]; } export declare function registerHarneryLogStorageCommands(parent: Command, options?: HarneryLogStorageCommandOptions): Promise; export declare function createHarneryProgram(opts?: HarneryContextOpts): Command; //# sourceMappingURL=commander.d.ts.map