Skip to content

Operator guide

This guide covers workspace setup, repository records, compact queries, MCP operation, optional providers, subscriptions, and environment inventory. See the dashboard guide for browser workflows, the migration guide for older state, and the security model for trust boundaries.

Workspace setup

Create a workspace with conservative private defaults:

sh
maintctl init --name "My projects"
maintctl doctor
maintctl validate

init refuses to replace a document unless --force is supplied. doctor separates required failures from unavailable optional adapters and supports --json. validate reads the document without printing it. Use maintctl workspace rename --name "New name" to review a display-name change, then repeat with --apply to write after confirmation.

The default document uses the XDG data directory. MAINTAINER_HQ_DOCUMENT and --document override it. maintctl version, maintctl --version, and maintctl -V print only the version. Exit status 0 means success, 1 means an operation or health check failed, 2 means usage or precondition failure, and 3 means a required dependency is unavailable.

Repository model

Each repository has a classification, last-known GitHub visibility, lifecycle state, and independently selected capabilities.

  • fleet is displayed as Maintained and means ongoing operator responsibility
  • watchlist means observed without assuming implementation ownership
  • legacy means historical or dormant work retained for context
  • active and archived records refer to repositories that still exist
  • deleted retains last-known identity and visibility but must be Legacy with no capability or secret state

Capability absence means unmanaged. A capability with pending policy, recovery, assessment, or decision means Maintainer HQ owns the concern but still needs evidence. Classification never silently opts a repository into unrelated providers, although a Maintained repository must carry an endpoint-monitoring assessment so a missing decision stays visible.

Never infer deletion from an HTTP 404 alone because inaccessible private repositories can produce the same result. Record lifecycle changes only from explicit operator evidence.

Compact queries

sh
maintctl list
maintctl list --attention yes
maintctl list --classification fleet --monitoring pending --names
maintctl list --visibility private --state archived --json

Classification, visibility, state, monitoring, listing, and attention filters compose. A no-match query succeeds. Table mode prints a readable result, --names emits one canonical identity per line, and --json emits normalized objects.

Resolve an explicit identity or a checkout's exact supported GitHub origin:

sh
maintctl check owner/repository
maintctl check ./path/to/checkout
maintctl check --json
maintctl check --quiet

With no target, check inspects the current checkout. It returns 0 for any recorded identity, including archived or deleted history, and 1 for an untracked resolved identity. It never guesses from the directory name. Use -- before a positional path beginning with a hyphen.

maintctl show --repo owner/repository prints a complete secret-free control record. Without --repo, show prints the full secret-free snapshot. maintctl schedule prints occupied Dependabot update slots as tab-separated rows.

Add and change repositories

Preview a Maintained public repository with pending capabilities:

sh
maintctl repository add --repo owner/repository --classification fleet --visibility public --github-policy pending --endpoint-monitoring pending --ci pending --listing pending

Preview a private Watchlist record without providers:

sh
maintctl repository add --repo owner/repository --classification watchlist --visibility private

Add --apply after reviewing the plan. Interactive confirmation remains the default; --yes skips only the local workspace confirmation and requires --apply.

repository set-scope changes only the selected identity and capability fields. Configured CI requires --ci-workflow; not-applicable CI requires --ci-reason. Listing exclusions, accepted monitoring risk, not-applicable monitoring, and not-applicable CI can carry a dated re-review. When a re-review is scheduled, Maintainer HQ records the exact local repository HEAD as its baseline and revalidates it before planning later changes.

Record monitoring accountability without storing a URL:

sh
maintctl repository set-scope --repo owner/repository --endpoint-monitoring monitored --endpoint-target service-home
maintctl repository set-scope --repo owner/repository --endpoint-monitoring accepted-risk --endpoint-reason "Manual operational check" --endpoint-review 2027-01-15

Endpoint target IDs are canonicalized and deduplicated. missing-targets means a declared ID is absent from an available Endpoint Monitor inventory. unverified means that optional inventory could not be loaded. Target presence is not a health claim.

Rename an identity with repository rename --repo owner/old --new-repo owner/new. Maintainer HQ moves the record, canonicalizes its Hookrelay HMAC name while preserving recovery, and updates repository-scoped secret consumers.

Set GitHub policy from a secret-free JSON override with repository set-policy --repo owner/repository --policy-file policy.json. Configured Dependabot policy supports Docker, GitHub Actions, npm, and pip updater records. Security features are enabled, reason-required unavailable, or, for a narrow repository exception, reason-required disabled. Private Hookrelay intent additionally requires explicit sink admission review before provider access.

Projects and the activity ledger

The workspace document remains the low-churn repository control record. Projects and their rolling feed use the separate private activity sidecar selected by MAINTAINER_HQ_ACTIVITY or -A, --activity; its default is ${XDG_DATA_HOME:-$HOME/.local/share}/maintainer-hq/activity.json. The sidecar is bound to the workspace ID, created lazily on the first applied activity write, and protected as private state.

Create and inspect a project:

sh
maintctl projects add --name "Release train" --repo owner/repository --target-version 0.2.0
maintctl projects add --name "Release train" --repo owner/repository --target-version 0.2.0 --apply
maintctl projects list

Repository attachments must already exist in the workspace document. projects update, projects attach, and projects detach preserve an exact reviewed boundary around metadata and membership changes.

Record operator-owned progress and query it alongside delivery evidence:

sh
maintctl activity add --project <project-id> --type goal --title "Ship 0.2.0" --status active --progress 60
maintctl activity add --project <project-id> --type blocker --title "Release approval" --status open
maintctl activity list --project <project-id> --type blocker
maintctl activity show --entry <entry-id>
maintctl activity pin --entry <entry-id>
maintctl activity ack --entry <entry-id>

Every write first prints an HMAC-bound plan and changes nothing without --apply. Manual goals, milestones, decisions, blockers, next actions, notes, and progress updates have type-specific state. Provider evidence cannot be rewritten as an operator note, while acknowledgement, pin, and archive state remain operator-owned.

Refresh attached repositories explicitly:

sh
maintctl activity refresh --project <project-id> --source local
maintctl activity refresh --project <project-id> --source github
maintctl activity refresh --project <project-id> --source all --apply

Planning performs no provider read. Apply bounds each configured source, stores only allowlisted commit, GitHub Actions run, and release fields, and reports partial coverage without discarding successful evidence. Stable IDs make repeated refreshes idempotent, and local Git plus GitHub observations of one commit merge into one entry. --repository-root controls exact checkout discovery; the GitHub reader uses an authenticated gh installation when selected.

Optional AI activity summaries

AI summaries are off unless the process inherits AI_GATEWAY_API_KEY. MAINTAINER_HQ_AI_MODEL changes the default AI Gateway model, and each request can still name an explicit creator/model. No automatic summarization, background model call, or summary dependency exists in the core feed.

sh
maintctl activity ai-status
maintctl activity summarize --project <project-id> --select-entry <entry-id> --field title --field type
maintctl activity summarize --project <project-id> --select-entry <entry-id> --field title --field type --apply
maintctl activity summaries --project <project-id>
maintctl activity summary --generation <generation-id>

Repeat --select-entry and --field to define the complete outbound disclosure. If no field is supplied, the safe defaults include project name, event type, title, timestamps, and bounded delivery status while excluding entry bodies and repository names. Planning calls only the public model-pricing catalog. It requires an available provider marked for both zero retention and no prompt training, uses the most expensive eligible rates for a conservative estimate, and refuses an estimate above --cost-limit.

Applying refreshes that exact revision-bound plan, persists a pending receipt, then makes one model call routed only through the reviewed eligible providers. The provider request has a fixed output-token ceiling, no SDK retries, a bounded timeout, an idempotency key, and the same no-training and zero-retention requirements. The cost limit is an operator approval boundary, not a provider-side billing cap: a price or metering change can still incur a higher charge, in which case Maintainer HQ records a bounded failed receipt and discards the output.

The private sidecar retains the generated text, selected entry IDs and fields, model, retry lineage, prompt hash, pricing snapshot, eligible providers, estimated input and maximum cost, actual token usage and Gateway cost, timestamps, and terminal status. It never retains the raw prompt or provider error body. activity recover-summary marks a pending receipt left by an interrupted process as aborted without contacting a provider; an active request in the same process cannot be recovered concurrently. Regeneration is always a new explicit plan linked to a terminal generation.

MCP server

Start the stdio server from the project:

sh
npm run mcp -- --read-only

The launcher accepts explicit document, environment, repository, Hookrelay, route, and private-variable paths. Repeat repository and environment roots as needed. Omit --read-only only for a trusted local client. Keep credentials and new secret values in the inherited process environment, not shared client configuration.

OutcomeRead or plan toolsConfirmation-gated tools
Setupdiagnose_installation, plan_workspace_initialization, validate_workspaceapply_workspace_initialization
Inventoryget_workspace_snapshot, list_repositories, get_repository, resolve_checkout_repository, get_repository_headNone
Local stateplan_workspace_change, plan_environment_permission_repairapply_workspace_change, apply_environment_permission_repair
Project activitylist_projects, list_activity, get_activity_entry, get_activity_summary, plan_activity_change, plan_activity_refreshapply_activity_change, apply_activity_refresh
AI activity summaryget_activity_ai_status, list_activity_summaries, get_activity_summary_generation, plan_activity_summary, plan_activity_summary_recoveryapply_activity_summary, apply_activity_summary_recovery
Provider evidenceaudit_workspace, list_dependabot_activity, plan_github_reconciliation, verify_github_reconciliation, plan_hookrelay, verify_hookrelayapply_github_reconciliation, prepare_hookrelay, apply_hookrelay
Recoveryplan_subscription_retirementapply_subscription_retirement
Compatibilityplan_workspace_migration, plan_compatibility_projectionsapply_workspace_migration, write_compatibility_projections

Mutation tools supply the current revision internally. Secret changes identify an inherited environment variable instead of sending a value through MCP. Generated and inherited secret values remain in an expiring memory store. Apply rereads the workspace and local evidence, displays the complete plan through protocol elicitation, validates signed request state, and writes only after explicit approval. Start the MCP process with -A, --activity when it should use a non-default sidecar.

Provider plans are byte-bounded and redacted. Failed, suppressed, truncated, or changed plans cannot be applied. Provider apply tools rerun the exact planner before and after confirmation and retain the provider adapter's confirmation behavior.

Optional provider operations

Core initialization, validation, queries, dashboard use, and MCP reads do not require provider adapters. Configure their commands or paths through MAINTAINER_HQ_* variables and inspect readiness with maintctl doctor.

Audit the selected GitHub and Hookrelay capability sets through private temporary projections:

sh
maintctl audit --local-only
maintctl audit

Reconcile one configured GitHub policy capability:

sh
maintctl reconcile plan --repo owner/repository
maintctl reconcile apply --repo owner/repository
maintctl reconcile verify --repo owner/repository

Operate one declared Hookrelay capability through its phases:

sh
maintctl hookrelay plan --repo owner/repository
maintctl hookrelay prepare --repo owner/repository
maintctl hookrelay plan --repo owner/repository
maintctl hookrelay apply --repo owner/repository
maintctl hookrelay verify --repo owner/repository

Use --include-private on every phase for a reviewed private repository. HMAC rotation is a separate revision-bound local change followed by the same explicit provider phase sequence with --rotate-hmac.

Managed Hookrelay subscriptions

Maintainer HQ can model a non-repository system that sends signed structured CloudEvents. It generates the private route and HMAC internally and stores them only after a confirmed plan:

sh
maintctl subscription add --name status-monitor --source cloudevents --sink discord:status --event-type urn:status-monitor:endpoint:problem:v1

Repeat --sink and --event-type as needed. An optional sender declaration requires the Worker configuration path plus distinct URL and HMAC secret names as one complete group. Reconcile the subscription with repeatable maintctl hookrelay <phase> --subscription status-monitor commands.

Retirement is staged so a provider failure cannot erase recovery:

sh
maintctl subscription unsub status-monitor
maintctl subscription unsub status-monitor --apply
maintctl subscription unsub status-monitor --finalize
maintctl subscription unsub status-monitor --finalize --apply

The first applied stage disables the exact route and retains central recovery. Finalization verifies route, KV, receiver HMAC, declared sender-secret, and sync absence before replacing the record with a credential-free tombstone. Failures retain safe recovery for an exact retry.

Environment inventory

Set MAINTAINER_HQ_ENVIRONMENT_ROOTS or repeat maintctl launch --environment-root <directory> to inventory dotenv-style files. Maintainer HQ recognizes live and template files, rejects linked and oversized candidates, and exposes names and modes without values. Eligible broad live files can be planned and restricted to 0600 from a write dashboard or MCP client.

Migration and compatibility projections

Workspace document versions 1 through 9 normalize to version 10. See the migration guide before persisting an imported workspace. maintctl migrate imports explicit legacy policy and recovery sources. maintctl project writes explicitly requested compatibility projections for an external adapter. Routine reads never leave a secret-bearing projection on disk.

A Strange Lasers project released under AGPL-3.0-only