Skip to content

Latest commit

 

History

History
1031 lines (860 loc) · 56.7 KB

COMMAND_REFERENCE.md

File metadata and controls

1031 lines (860 loc) · 56.7 KB
status ACTIVE
version 4.89
owner_skill ls-localsetup-framework-changes

Command Reference

Use this page when you need copy-pasteable LocalSetup commands. For narrative install guidance, start with Quickstart or Multi-platform install.

Brand assets and media metadata

localsetup branding validate --strict checks the selected source repository's branding policy. localsetup branding render regenerates the reviewed artwork; --check verifies it without writing, and --pack-output <path.zip> produces the versioned asset pack. Rendering uses the optional Pillow/CairoSVG tool environment and bundled, hash-verified fonts.

localsetup media clean-images --input <image.png> --output-directory <existing-dir> --copyright <notice> --creator <owner> --website <url> --rights <terms> writes separate static PNG copies with only the requested metadata. Use shell quoting for values containing spaces. Originals and existing outputs are preserved; pixel and metadata readback are verified automatically. Conflicting copyright requires an explicit reviewed --replace-copyright. Animated images, embedded color profiles, and nontrivial orientation need separate normalization. This command requires Pillow and does not claim support for other media formats.

Common framework preferences

Use localsetup.json in the selected repository for portable preferences, and ~/.local/share/localsetup/config/framework.json for user preferences. Both use schema_version: 1 and the common schema. The repository's own configuration is a complete test policy example. Do not put credentials, private keys or execution grants in it.

localsetup config show --project-root .
localsetup config explain --project-root .
localsetup config validate --project-root .
localsetup config schema
localsetup config presets
localsetup config show --project-root . --file preferences.json

These commands are read-only. show and explain return resolved preference overlays, the source of each leaf, and loaded files. Domain commands retain the final runtime defaults and live readback: use configure, app-profile resolve and test-workers --json for their effective views. schema emits a standalone, offline schema assembled from existing domain owners. Unknown keys, duplicate JSON keys, unsupported versions and invalid combinations fail validation.

Precedence is built-in domain defaults, user preferences, repository preferences, then an explicitly selected invocation file. A file's named preset applies before its explicit fields. Objects merge recursively; arrays replace. Presets workstation, conservative and ci adjust test headroom and worker allowances; they never activate a job. User files and home-relative parent directories must be owned by the current account and not writable by other accounts. Symlinked configuration files are rejected.

Section Existing consumer and boundary
testing Shared resource guard and pytest plugin; legacy [tool.localsetup.testing] remains a fallback.
installation Existing install/configure resolver; explicit legacy --config and CLI flags retain precedence. Repository preferences admit only repo_* selectors, never output paths, personal scope, global selectors or legacy shared selector aliases.
application_profiles User-level array of {application, name, settings} for registered profiles; the existing profile validator and explicit apply lifecycle remain authoritative.
context_index Freshness, chunking, retrieval, worker and logging preferences; storage, identity and enrollment remain with the context-index owner.

Move legacy preferences to the common file one domain at a time. Matching legacy values are accepted; conflicting test, application-profile or context-index values are rejected with the conflicting field names. No command deletes a legacy file or silently changes a running session. New consumers must reuse this resolver and register a bounded schema and scope rather than add another preference path. Bootstrap home and target-directory selection remain explicit CLI or legacy invocation-file inputs; common preferences reject them to avoid recursive or ambiguous configuration discovery.

Signed live configuration remains under the same config command below. It has a separate authority boundary: a preferences file cannot grant access to output filters, secure-container trust, recipient enrollment, snapshot jobs or autonomous execution. Provider credentials and native client settings retain their explicit owners. This is configuration composition, not an automatic migration of every protected store into unsigned JSON.

Signed Configuration

Ordered text filter policies

A configuration authority can register an owner with {"kind":"output-filters"}. Its editable value follows the filter schema: schema_version: 1, rules, and limits. Empty rules preserve text. Every rule has a unique positive order; use gaps such as 10, 20 and 30. Evaluation sorts by that number, independently of array order, for each explicitly selected sink: observation, retained-log or agent-context.

match: word matches a complete, case-sensitive Unicode word. match: regex supports basic groups, alternation, classes and repetition; extensions, backreferences, more than eight nested groups and counted repeats above 128 are rejected. Patterns are bounded to 256 UTF-8 bytes. action: replace requires a literal replacement and continues through later rules. block, quarantine and halt terminate filtering and return no deliverable text. The caller owns quarantine handling and must route halt through its existing cancellation gate.

The shared output_filters.parse_policy() API creates an immutable policy; apply(text, sink=..., check=...) processes one complete text unit and returns text plus bounded transformation metadata. Metadata includes the policy digest, matched orders and match count, never input or pattern values. Text/output bytes, total matches and execution time are bounded; the regex engine gets at most 20ms per matching call before cancellation is rechecked. Invalid rules, unavailable engine, timeouts and limit failures raise fixed errors without passing raw text. This uses the runtime's existing locked regex engine, with no fallback engine.

The signed configuration owner validates and persists policies; configuring it alone does not attach filters to a running consumer. The explicit LSCli output binding selects a signed policy for one run. Consumers must use complete text units, including assembling split streaming text within their own byte and deadline bounds. Apply the same policy to every configured text sink, preserve authenticated fields and original file bytes, and never filter an approval payload into a different command or grant. Opt-in retained event pages use the same policy for their own sink; agent-context integration remains separate.

Manage the shared signed store

Use an explicitly selected private authority binding for the shared signed configuration store. The binding is controller context, separate from editable settings. It selects an already trusted configuration owner; these commands do not generate keys, enroll trust, or make an installed key authoritative.

authority_file="$HOME/.config/localsetup/config-authority.json"
edit_directory="$HOME/.local/state/localsetup/config-edit"
localsetup config --authority-file "$authority_file" status
localsetup config --authority-file "$authority_file" edit --directory "$edit_directory"
# Edit owners/*.json and cadence.json inside the private edit directory.
localsetup config --authority-file "$authority_file" flush --directory "$edit_directory"
localsetup config --authority-file "$authority_file" recover

The edit directory must be new or empty and separate from the signed store. Keep its manifest unchanged. Flush validates every registered owner, checks the base revision and input stability, signs the complete set, then reloads it. The working files remain intact for later edits. An external revision conflicts; export a fresh directory to review that revision without overwriting the earlier working files. An uncertain result may contain a candidate digest; use recover --candidate <digest> when intent persistence also failed. Recovery reuses exact retained bytes and does not sign a replacement.

An owning supervisor can pass the already admitted process cohort to the CLI:

localsetup config --authority-file "$authority_file" flush-all \
  --cohort "$cohort_id" --participant-fd "$first_fd" --participant-fd "$second_fd" \
  --timeout 300

The descriptors must be connected inherited Unix sockets, separate from standard input/output. The 64-hex cohort identity and channel endpoints come from the owning controller, not a process-name or same-user scan. Participants use the shared configuration lifecycle. This freezes their pending sequences, rejects conflicts, publishes one signed revision, and requires all reload acknowledgements. Later edits remain pending. It does not flush unregistered processes or grant a read-only owner write access.

After an uncertain publication, recover --candidate <digest> accepts the same --cohort, repeated --participant-fd and --timeout options to obtain reload acknowledgements over newly admitted channels, without signing another revision. If no write was dispatched, stop/reconcile the original controller operation before using cancel-flush --transaction <reported-transaction> with those channel options. Cancellation releases the captured copy, preserves the pending edits and refuses an unresolved signed-store intent. A lost connection alone is not evidence that the original write stopped.

The authority file is a mode-0600 JSON file in a private directory. Replace these placeholders with verified selections from the owning trust/key lifecycle:

{
  "schema": "localsetup.configuration-authority",
  "version": 1,
  "root": "<absolute-private-store-root>",
  "store_id": "<32-hex-configuration-store-id>",
  "signer": "<explicitly-trusted-owner-fingerprint>",
  "recipients": ["<explicitly-trusted-owner-fingerprint>"],
  "gnupg_home": "<absolute-private-gnupg-home>",
  "write": true,
  "secret": {
    "provider": "envman",
    "name": "LOCALSETUP_CONFIGURATION_SECRET",
    "protected_file_root": null
  },
  "trust": {
    "path": "<absolute-configuration-trust-state-path>",
    "store_id": "<64-hex-trust-store-id>",
    "revision": 1,
    "epoch": 1,
    "scope": ["configuration"]
  },
  "owners": {
    "terminal": {
      "kind": "application-profile",
      "application": "tmux",
      "name": "agent-shell"
    },
    "containers": {
      "kind": "container-runtime",
      "runtime_id": "<32-hex-runtime-id>"
    }
  }
}

The configured scope, store identity, revision, epoch and signer must match the current trusted owner. Set write to false for read-only status/export. Secret providers are env, envman, or protected-file; only the last requires its private protected_file_root. Supply references, never secret values.

The cadence file accepts {"seconds": 60}, with an integer range of 1–3,600. For native terminal tuning, use {"kind":"terminal-runtime"} as the owner descriptor. Its values use the existing strict runtime schema. See binding a live terminal for the separate owner-authorized application command and uncertainty readback. For a container-runtime owner, bind existing resource tuning with localsetup container --runtime-root "$runtime_root" configuration --authority-file "$authority_file" --config-owner containers. This does not enable the runtime or alter its keys, sources or trust policy. See container tuning for scan enrollment and operation-boundary behavior.

Status reports only revision metadata. Flush persists the registered set and does not apply native settings, alter grants, or flush another process's staged memory. See the shared lifecycle for authority, recovery and live-consumer boundaries.

Legacy Container Migration

Inspect exact bytes before selecting an explicit migration:

localsetup container inspect-legacy --source "$legacy_file"
localsetup container migrate-legacy --source "$legacy_file" \
  --expected-sha256 "$observed_digest" --artifact-id "$new_artifact_id" \
  --authority-file "$migration_authority" --output-dir "$new_private_directory"

Use absolute paths and a new output directory under an existing private parent. The artifact ID is a nonzero 32-hex identifier. The separate migration authority selects current publishing/approval policy and an optional legacy verification context; see legacy envelope migration for its exact fields. No indexing runtime is required or enabled.

When preserving content without independently verified origin, the authority must set legacy: null and the command must include --preserve-unverified. The custody record then explicitly retains an unverified origin status. A requested historical verification never falls back to that mode when it fails. Success includes approved ciphertext, exact reconstruction checks and a local completion locator. Existing output directories are refused; failed operations may retain partial ciphertext for inspection. Original bytes and receipts are preserved, and no upload or history cleanup occurs. --timeout defaults to 300 seconds and accepts 1 through 3,600 seconds. The SDK's existing ContainerPreparationLimits controls source, temporary-space and crypto budgets.

Herdr Operations

For Herdr pane, task, remote lifecycle, and provenance work, start with localsetup herdr --help and the ls-herdr-task-routing master skill. The normal ops pack includes its specialists. See Herdr operations for targeting, completion, configuration, and restart semantics. Use localsetup herdr --json provenance check for offline source verification and add --network for a read-only upstream release comparison.

Bootstrap Installer

The public Bash wrapper is the entry point for Linux, macOS, and WSL2. Windows support is WSL2-only.

curl -sSL https://raw.githubusercontent.com/CruxExperts/localsetup/main/install | bash -s --

Run the same wrapper in automation mode:

curl -sSL https://raw.githubusercontent.com/CruxExperts/localsetup/main/install | bash -s -- --non-interactive --yes

Install from a local checkout:

./install --directory .

Attach selected platform adapters to the target repo:

./install --directory . --tools codex,kilo
./install --directory /path/to/localsetup --target-directory /path/to/project --tools cursor

--tools is the compatibility alias for --platforms. If both are omitted on a source-only install, LocalSetup refreshes the managed package library only and does not create repo adapter paths. If a repo target is explicit, selector-free plan, install --apply, and update use auto mode:

localsetup plan --target-directory .
localsetup install --target-directory . --apply
localsetup update --target-directory .

Auto mode infers existing LocalSetup state, applies only unambiguous safe repairs, or installs the normal global baseline for a brand-new repo without adapter paths.

Installer Options

Option Meaning
--directory PATH LocalSetup source checkout containing ls/. Without an explicit checkout, the raw bootstrap creates or refreshes ~/.local/share/localsetup/source.
--target-directory PATH Repo or directory where selected adapter paths and .localsetup/lock.json are written; without selector flags on plan, install --apply, and update, enables auto mode.
--home PATH Home directory for the managed source and package library. Defaults to $HOME.
--yes Accepted legacy flag. For automation, combine with --non-interactive.
--non-interactive Automation mode. Requires --yes and preserves machine-readable output.
--tools LIST Comma-separated platform ids. Alias for --platforms.
--platforms LIST Platform adapter ids. Explicit values override auto mode; errors list registered selector ids.
--codex-agent-conflict POLICY For plan, install, or update, error (default) refuses changed Codex agent files; preserve skips differing readable regular files for this operation and reports them separately.
--preset NAME Selection preset: core, normal, suggested, all, or custom.
--packs LIST Comma-separated skill and workflow packs.
--skills LIST Comma-separated skill ids; use repo:name, personal:name, or framework:name to select an explicit origin. See custom skill integration.
--workflows LIST Comma-separated workflow package ids or workflow aliases.
--skill-classes LIST Comma-separated taxonomy classes.
--skill-tags LIST Comma-separated taxonomy tags.
--exclude-skills LIST Skills to remove unless required by a selected workflow.
--global-* Selection options for the managed package-library baseline, including --global-workflows.
--repo-* Selection options for packages exposed through repo adapter paths, including --repo-workflows.
--mode symlink|portable Adapter write mode. Symlink is the default; portable copies selected packages.
--sync-env Sync the uv-managed source checkout environment from pyproject.toml and uv.lock.
--install-deps Deprecated alias for --sync-env.
--install-uv / --no-install-uv Allow or forbid uv bootstrap when sync is requested.
--offline Run uv sync in offline/cache-only mode.
--no-register-shell Skip ~/.local/bin/localsetup registration.
--color auto|always|never Wizard color mode.
--no-color Alias for --color never.
--glyphs auto|ascii|unicode Wizard glyph mode.
--help / -h / -? / --? Print installer help. Quote question marks in shell commands.

Managed CLI

After registration, the managed shim records the framework source and localsetup targets the nearest Git worktree root from the current directory unless --target-directory is supplied. For an installed wheel, source selection keeps this precedence: explicit --source-root, explicit --repo, source from the enabled managed shim, then a valid source recorded by the selected home's managed shim. The selected home follows existing CLI/config precedence: explicit --home, configured home when not overridden, then the enabled shim's LOCALSETUP_HOME or the user default. The recorded source is read without executing the shim and must contain ls/tools/localsetup.py and a parseable pyproject.toml naming the localsetup project. This checks the expected source layout; it is not a trust boundary against another process running as the same user.

Wheel doctor and doctor repair require an explicit or registered source. If none is usable, they exit with an actionable --source-root message before writing health state or attempting repair. Other wheel commands keep the installed package-resource fallback. Source-checkout invocations keep the checkout as their default source.

The registered shell launcher tries the project environment first, then system Python. If neither can load LocalSetup, its startup message provides a direct diagnostic command. Check source/import errors before rebuilding the environment; a failed import does not establish that the environment is missing or unhealthy. The suggested environment repair applies when the runtime or dependencies are missing. Startup probes suppress raw tracebacks and never run a repair themselves.

localsetup install --tools codex --yes
localsetup verify --tools codex --level filesystem
localsetup adapters check --tools codex
localsetup doctor
localsetup diff --tools codex
localsetup rollback

From this source checkout, run the CLI through uv:

uv run --locked python ls/tools/localsetup.py --source-root . validate-catalog
uv run --locked python ls/tools/localsetup.py --source-root . generate-docs
uv run --locked python ls/tools/localsetup.py --source-root . docs-align check --ci

Client state

Resolve the registry-owned repo/global state root without writing:

localsetup state path --client codex/codex-cli

Add only that exact repo state child to Git's resolved local exclude:

localsetup state path --client codex/codex-cli --apply-exclude

Allocate and then verify a no-overwrite restart artifact:

localsetup state allocate --client codex/codex-cli \
  --agent controller --purpose release-checkpoint --extension md \
  --kind restart-artifact --schema restart-v1 --producer controller \
  --content-file checkpoint.md
localsetup state verify --client codex/codex-cli --artifact <artifact-filename>

Use --scope repo|global only to require a specific supported scope; explicit global scope does not inspect the caller's working directory, while the default auto uses the containing Git worktree or the verified global root. Outputs contain relative state/artifact identifiers rather than absolute machine paths. Verification mismatches exit 1; invalid requests and operational failures exit 2 with a sorted, sanitized JSON error envelope. See Deterministic client state for metadata, collision, stale-binding, and unsupported-state behavior.

CLI Commands

The top-level CLI currently exposes these commands:

plan, install, verify, rollback, update, adapters, configure, doctor, state, shell, app-profile, config, branding, media,
migrate, context, convert, catalog, diff, skill, workflow, why, graph,
candidate-skill, adopt, detach, sbom, scan-migration, audit-global-first,
validate-catalog, generate-docs, provenance, harness, docs-align, context-index, hook-gate,
github-repo,
envman, version-plan, version-sync, release-docs, release-push, self-refresh, install-hooks,
register-shell, wizard, package, verify-release, agent, llm

candidate-skill validate --candidate <path> --json and candidate-skill proposal --candidate <path> --output - inspect repo-scoped candidate skills without promoting them into managed packages or adapter directories.

wizard --repo-profile universal-agent-repo --target-directory <path> --dry-run --report <path> plans the lean universal agent repository shape without entering the interactive installer. Re-run with --apply to create the missing shape files. Existing files with different content are blockers; LocalSetup does not overwrite them.

Most commands emit JSON by default. Commands with explicit human-readable modes, such as context --markdown, document that mode in their own help.

The canonical localsetup and lscli entrypoints and their subcommands accept -h, --help, '-?' and '--?' as help aliases. Quote question marks in shell commands, for example localsetup shell '--?'. Arguments after a literal -- remain workload arguments and are not rewritten as help requests.

Observable shell sessions and application preferences

localsetup shell --help
localsetup app-profile list
localsetup app-profile show tmux agent-shell
localsetup app-profile save tmux agent-shell --settings-json '{"history_limit":20000}'
localsetup shell capabilities
localsetup shell layout --handle H
localsetup shell layout --handle H --mode fixed --ratio build=2 --ratio tests=1
localsetup shell schedule status
localsetup shell observe --handle H --thread THREAD
localsetup shell activity --handle H
localsetup shell observe --handle H --thread THREAD --restart

The shell API returns the execution machine, verified session or operation handle, and a copyable local attachment command. Run that command on the named machine; it does not establish an SSH connection. Preserve the returned operation handle when a wait ends or a connection fails: inspect it rather than running the same workload again. See observable commands for shell lifetime, output limits and cleanup behavior. The native client activity adapter exposes bounded, read-only root and descendant tool metadata for qualified local Codex owners. It reports stale or unavailable coverage separately from shell work.

Profiles are JSON validated by application-specific schemas. Shipped defaults remain framework-owned; saved preferences are private user configuration. Resolution reports each setting's origin and an effective digest. Applying a profile to an existing session requires an explicit verified target and preserves unrelated sessions and native theme settings. The initial shell backend requires Linux /proc process identity. run --stream passes captured output to stdout and returns a known command exit code; a wait timeout returns 124 while preserving the operation. The final JSON receipt goes to stderr when streaming. See the workflow for explicit native-owner binding and the separately authorized, fixed cleanup schedule.

Secure-container indexing and consolidation

localsetup container --runtime-root <absolute-runtime-root> manages indexing and explicitly authorized snapshot jobs for configured runtimes:

Command Purpose
enable-indexing --grant-id <id> Enroll the fixed metadata scan recipe with the durable scheduler
status Show scan configuration, bound schedule and last run result
disable-indexing Revoke future scheduled scans and remove the owned cron entry
configure-consolidation --authority-file <path> --expected-revision <n> Pin separate private snapshot write authority without enabling the runtime
consolidate --reference @artifacts/<artifact>/<version> --event manual Run one authorized exact-version snapshot job; configured events also accept change and scheduled
disable-consolidation --expected-revision <n> Revoke future snapshot writes while preserving retained jobs and history

Agent enrollment accepts --owner-pid, --owner-starttime and --agent-id. The optional --state-root before the command selects the shared private scheduler store. Neither framework installation nor ordinary reads enrolls recurring work. See automatic reconciliation for interval handling, secrets, revocation and recovery. Snapshot commands require separate write authority. An indexing grant does not authorize publication, and --event scheduled does not install recurring work. See configured consolidation modes for the private authority format, client-read integration and worker admission.

Shared policy provenance

The optional policy-owner check consumes the owning stitcher's read-only result:

localsetup doctor \
  --policy-stitch-owner /path/to/scripts/ops/policy_stitch.py \
  --policy-stitch-registry /path/to/policy-stitch.yaml

Both bindings are explicit. The check distinguishes unavailable ownership, rendered-file drift and aligned hashes; it does not bootstrap missing files or claim that an already running client loaded them. Change the authored global policy or native head, then render through its owner instead of editing a managed policy tail.

Envman toolchain

Envman is an optional external toolchain. LocalSetup does not install or update it during ordinary commands. Status is read-only and redacted; the doctor probe is opt-in:

localsetup envman status
localsetup doctor --envman
localsetup envman update --check

Only the explicit install and mutating update commands invoke Envman's latest bootstrap:

localsetup envman install
localsetup envman update

The bootstrap uses uv with CPython 3.12 and supports Linux x86_64 with uv 0.11 or newer. To request Envman's native skill projection, supply exactly one current LocalSetup platform id and one scope:

localsetup envman install --install-skill --skill-scope global --skill-target codex
localsetup envman update --install-skill --skill-scope repository --skill-target codex --target-directory /path/to/repository

Repository scope requires the explicit Git root as --target-directory; global scope does not accept that option. LocalSetup does not invoke envman init. A failed or timed-out mutation has an unknown result and is not automatically retried. See the integration contract for the exact redaction, validation, and rollback boundaries.

GitHub repository enhancement

Use the CLI-first GitHub repository enhancement workflow to inspect a GitHub-hosted repository's settings. Its target syntax is:

localsetup github-repo --repository OWNER/REPO --hostname HOST --checkout PATH --mode MODE

MODE is exactly one of audit, plan, apply, or verify. Both target selectors are explicit: --repository OWNER/REPO and --hostname HOST identify the remote, while the global --repo retains its existing meaning as the LocalSetup source-checkout selector. --checkout PATH selects the local Git checkout used for repository evidence and defaults to .. Use the same checkout for audit/plan and apply/verify; it does not change the global --repo meaning.

localsetup github-repo --repository OWNER/REPO --hostname github.com --checkout . --mode audit
localsetup github-repo --repository OWNER/REPO --hostname github.com --checkout . --mode audit \
  --include-security-alerts
localsetup github-repo --repository OWNER/REPO --hostname github.com --checkout . --mode plan \
  --policy POLICY.json
localsetup github-repo --repository OWNER/REPO --hostname github.com --checkout . --mode apply \
  --plan PLAN.json --authorize-plan DIGEST \
  --operation OP_ID --operation ANOTHER_OP_ID
localsetup github-repo --repository OWNER/REPO --hostname github.com --checkout . --mode verify \
  --plan PLAN.json \
  --trusted-public-key KEYS/maintainer.asc \
  --trusted-public-key KEYS/release.asc

Audit, plan, and verify do not read Dependabot, code-scanning, or secret-scanning alert counts unless that invocation includes --include-security-alerts. By default each count is null with reason security_alert_reads_not_selected; feature settings remain covered and health remains not_assessed. The option requests aggregate counts only, does not expose alert details, and is rejected for apply. It is never inferred from a saved plan or earlier observation.

Plan mode requires the explicit desired-state POLICY.json and produces a plan.json file, a human-readable plan.md, and a JSON summary on stdout with both paths, the SHA-256 digest, and operation IDs. By default, the plan files are written under LocalSetup's per-user private state root at github-repository-operations/<target-key>/plans/<plan-digest>/; the target key binds normalized hostname and immutable repository ID. The default state root must be owned by the current user with mode 0700. Its path components must not be symlinks; ancestors must be root- or user-owned and not group/world writable, except root-owned sticky directories such as /tmp. An unsafe state root fails closed for default plan output, and apply always needs that secure root for its target journal. An optional --output-directory DIR selects another directory, which must be user-owned with mode 0700 and is created with that mode if missing. Its path components cannot be symlinks and its ancestors follow the same ownership and sticky-directory rule. Plan files are created exclusively at mode 0600 without following symlinks; existing files must be user-owned mode-0600, single-link regular files. Use the reported plan.json path for apply and verify; verify mode requires --plan PLAN.json. Saved plans use schema v4; regenerate earlier schema-v2 or schema-v3 saved plans from their reviewed policy before applying or verifying. The repository policy schema remains v2.

Review the exact saved plan JSON, its reported SHA-256 digest, and every operation ID before apply. --authorize-plan DIGEST plus the repeated --operation options authorize only those IDs from that exact plan. Do not use a wildcard or apply the unreviewed remainder. The plan also binds normalized host, immutable GitHub repository ID, and authenticated actor; a changed identity requires a new audit and plan. Destructive or access-changing changes are excluded from the ordinary plan and need a separate reviewed plan and exact authorization. Controls without supported typed operations remain report-only. On github.com, public/private visibility must be the sole setting in its own plan; split or reject a policy that mixes it with other changes before apply. Visibility on other hosts remains report-only while Enterprise Server support is unverified. The documented CLI and REST handling of internal is unresolved.

Each typed operation in plan JSON and Markdown displays a canonical interface descriptor: transport, the fixed command or HTTP method and endpoint template, the plan.target binding, required command flags, and the reason for selecting an API interface. The descriptor is part of the operation identity and plan digest. LocalSetup prefers native gh repo edit only when its available command and flags express the complete operation. Before dispatch it checks bounded gh repo edit --help output for every required flag; a missing command, flag, or unsupported feature fails closed. It does not silently fall back to gh api, switch transports after failure, or replay a failed command. The plan-selected REST path uses gh api only when no native command exactly expresses that operation, and records why. Ruleset mutations use REST through gh api because gh ruleset documents list/check/view operations, not writes.

Collaboration web commit signoff

Policy schema v2 supports the desired Boolean repository.web_commit_signoff_required for the registered collaboration.web_commit_signoff control. For example, set {"schema_version":2,"repository":{"web_commit_signoff_required":true}} to require contributors to sign off on commits made through GitHub's web interface; set the field to false to remove that requirement. The official gh repo edit options do not document an exact native flag for this setting. The typed operation uses PATCH /repos/{owner}/{repo} through gh api, supplies web_commit_signoff_required in the request body, and records this REST selection reason in its interface descriptor. See GitHub's Update a repository API.

All remote write operations are enabled only for github.com while the GitHub Enterprise Server API-version matrix remains unverified. Audits and reads may run on other GitHub hosts, but requested drift there remains incomplete/report-only with a specific compatibility reason.

Audit returns the seven group objects plus one observation for every control in the fixed registry. That registry defines exact coverage for this workflow, not an exhaustive audit of every possible GitHub control. The audit_coverage receipt includes status, expected/observed counts, and lists of missing, duplicate, invalid, or incompletely observed control IDs. A reason-backed unknown, unavailable, inherited, local, UI-only, or not-applicable observation is assessed evidence; it does not mean the requested policy is satisfied. Apply refuses incomplete coverage, and verify returns incomplete when coverage is incomplete. Unsupported controls remain report-only unless a documented typed operation exists.

The plan digest also binds the selected local checkout: a root binding, HEAD, branch or detached state, staged/worktree/untracked counts and a deterministic digest of Git porcelain status bytes, configured upstream, and normalized origin/upstream matches to OWNER/REPO. It hashes only tracked candidate files inspected for structural evidence and any requested social-preview asset. The result omits raw remote URLs, credentials, absolute checkout paths, raw status paths, and file contents. The status digest covers status bytes, not every worktree file. Local checks report structural presence and explicitly do not assess content quality. Apply rechecks the checkout and local evidence before each write and refuses local drift; verify reports incomplete on local drift. Use the same --checkout path for every mode. Paginated REST lists request 100 items per page and stop on a short page; the adapter errors at its 1,000-page bound. Security output redacts alert details and exposes aggregate counts. The per-user LocalSetup state journal and target lock serialize operations for one host and immutable repository ID. If a mutation response is lost or ambiguous, use read-only reconciliation and never replay the write automatically. A repeated apply is a no-op for values already at the desired state.

Plan and verification output distinguishes inventory caveats, authorization findings about ambient token-permission visibility, and requested_policy gaps. Verification reports verified only when operation read-backs pass, requested policy and required handoffs are complete, exact control coverage is complete, and the checkout and its inspected evidence still match the plan. An assessed unknown or unavailable result can have complete evidence coverage while leaving a requested policy unresolved.

Policy-scoped signature and release verification

Policy schema v2 can optionally select signing and release evidence. The verification.signatures object contains exactly commit_oid, tag_name, and expected_primary_fingerprints. The verification.release object contains release_id, tag_name, source_ref, source_commit, signer_workflow, predicate_type, and artifacts. Each artifact supplies asset_id, name, checkout-relative path, and expected_sha256:

{
  "schema_version": 2,
  "verification": {
    "signatures": {
      "commit_oid": "<full-lowercase-git-object-id>",
      "tag_name": "v1.2.3",
      "expected_primary_fingerprints": ["<trusted-primary-fingerprint>"]
    },
    "release": {
      "release_id": 123456,
      "tag_name": "v1.2.3",
      "source_ref": "refs/tags/v1.2.3",
      "source_commit": "<full-lowercase-git-object-id>",
      "signer_workflow": "OWNER/REPO/.github/workflows/release.yml",
      "predicate_type": "https://slsa.dev/provenance/v1",
      "artifacts": [
        {
          "asset_id": 234567,
          "name": "release.tar.gz",
          "path": "dist/release.tar.gz",
          "expected_sha256": "<64-lowercase-hex-digits>"
        }
      ]
    }
  }
}

Replace placeholders with reviewed identities and values. The tag source ref is exactly refs/tags/<tag_name>; the source commit, tag, and release asset must match the selected policy identities. Verification binds the local file's exact bytes to its expected SHA-256 and that digest to the selected release asset ID and name, while provenance checks bind the repository, source, signer workflow, and predicate. A local checksum match alone does not prove that GitHub released those bytes.

Supply OpenPGP public-key files only at verify time, repeating --trusted-public-key FILE once per key. These are verify-only inputs. Key contents and key-file paths are not stored in saved plans or printed in plans or reports; outputs also omit absolute checkout paths and raw GitHub CLI output. When policy requires release checks, a missing or older gh without gh release verify-asset or gh attestation verify leaves the proof unavailable/incomplete. LocalSetup does not install or upgrade gh automatically. If policy declares no verification requirements, release readiness is not_assessed. An apply status of complete describes only the explicitly selected settings operations and their read-backs; it does not establish release readiness.

Tracked repository content is inspected structurally from a fixed bounded allowlist: README and badges, installation/support/contribution/security routes, changelog/version signals, Dependabot configuration, community files, site/Open Graph metadata inputs, accessibility inputs, and footer/attribution inputs. Per-file SHA-256 and size records cover only inspected files; no file contents or absolute paths are returned. This evidence does not review quality.

Schema-v2 policy distinguishes omitting social_preview (no requested action) from an explicit removal. Use this shape to bind a file for a requested upload:

{
  "repository_content": {
    "social_preview": {
      "action": "present",
      "asset_path": "assets/social-preview.png"
    }
  }
}

For removal, use {"repository_content":{"social_preview":{"action":"absent"}}} and omit asset_path. A present asset path must be safe and relative to the selected checkout; validation requires a contained regular non-symlink file under 1 MB whose bytes have PNG, JPEG, or GIF magic. The plan binds its checkout-relative path, SHA-256, size, and detected format, and apply/verify recheck the same file and hash. The remote API confirms only whether a custom social image is set, not that its pixels match the bound file. Complete the Settings UI upload/removal handoff, then verify. A fresh custom-image Boolean that matches the requested presence/absence state can satisfy that selected setting if the local present-image asset remains valid and hash-bound. A false or unavailable Boolean keeps the UI handoff as a requested-policy finding. Even when the setting is complete, the exact remote pixels remain unverified.

The selected registry, named report-only categories, documented permission limits, known API unknowns, and sources accessed 2026-09-26 are in the workflow reference above. For a manual social-preview upload, open the target's Settings page at https://HOST/OWNER/REPO/settings, then use Social preview → Edit → Upload an image. Run verification after the user completes the upload. For a requested absent image, use GitHub's documented Settings removal action and then verify. The API verifies only whether a custom social image is set; it does not check the uploaded pixels or local image hash. Keep a mismatched or unavailable handoff incomplete, and state that a completed Boolean match does not prove exact image identity. Tracked files and release tags remain on the local signed Git and release paths.

localsetup adapters preserves the legacy adapter status list output. Use localsetup adapters check --tools codex for a structured, report-only adapter compatibility payload with ok, adapters, issues, warnings, repair_hints, summary, and suggested existing commands. It exits 0 when the adapter check is OK and 1 when verifier issues are present.

LSCli And Tool-Free Completion

localsetup agent forwards to lscli. Place agent immediately after localsetup; use LSCli subcommand options for workspace, runtime and state selection. The entry point does not translate framework installation selectors into task authority.

lscli --help
lscli doctor --format json
lscli profiles --profiles /private/config/profiles.json --format json
localsetup agent run --help
localsetup llm complete --help

LSCli operations owns full setup/registration, run, control, context, session, branch, recovery and compaction syntax, including stdin/JSONL formats, exit codes and limits. Help and diagnostic/inventory commands do not initialize providers or create missing configuration. Coding uses explicit grants and a qualified protected runtime with actual sandbox/resource preflight; completion has no tools or workspace access grants.

localsetup llm complete --profile example --request request.json --profiles /private/config/profiles.json --runtime-root /private/runtimes

Replace the paths/profile with reviewed inputs. Supplying the request explicitly authorizes its disclosure to that selected provider. The request/result schema and completion command define the one-attempt contract, declared capabilities, local validation and uncertainty/exit handling.

Typed Heartbeat And Controller Accounting

localsetup harness codex-heartbeat plan
localsetup harness codex-heartbeat configure-lscli --help
localsetup harness codex-heartbeat readiness
localsetup harness codex-heartbeat budget
localsetup harness codex-heartbeat accounting --help

Harness automation owns activation and transaction behavior. configure-lscli previews an explicit review or coding connection to an existing provider profile; --apply backs up and replaces configuration without enabling cron. Optional --expected-config-sha256 rejects changes since preview. readiness reports selected-agent static checks without execution; optional --probe makes one bounded provider attempt. Review probing discloses selected granted context; coding probing includes native preflight with model tools disabled. Successful inspection or probing does not prove collection hooks or live cron. The typed LSCli profile uses an owned registration, explicit private profile/grants and protected coding limits. Installation does not activate it. Generated cron commands default to collection only; enable --with-agent explicitly selects scheduled reviews, and enable --collection-only restores collection-only operation. Live crontab installation still requires --install-crontab --yes and preserves unrelated entries. Controller accounting commands cover init/inspect/review, action-plan, later authorization and result reconciliation; reserved run syntax requires all four explicit controller options. Ordinary fresh-profile runs and legacy queue budget reports do not implicitly enforce reserved task accounting. A completed execution still needs controller disposition, and uncertain effects require evidence-backed reconciliation rather than replay.

Install Command Options

The Python CLI install command supports the same selection model as the wrapper:

localsetup install \
  --tools codex \
  --preset suggested \
  --skill-classes development \
  --skill-tags git \
  --skills ls-localsetup-project-context \
  --exclude-skills ls-linux-patch-planning \
  --yes

Useful install options:

Option Meaning
--config PATH Load install config.
--target-directory PATH Override target directory.
--json Make JSON output explicit.
--report PATH Write an install report.
--backup-dir PATH Use an explicit backup location.
--trace-json PATH Append JSONL trace events.
--policy-mode permissive|standard|strict|ci Choose policy strictness.
--dependency-mode managed-venv|prompt-only|user-pip|uv-sync Choose dependency handling.
--apply Apply a planned operation when the command supports plan/apply separation.
--mode symlink|portable Adapter write mode.
--platforms ... / --tools ... Platform adapter ids.

Repair And Health Commands

doctor repair is report-only by default. It infers platforms, adapter mode, repo-visible skills, repo-visible workflows, custom repo skills, and stale framework state, then returns a JSON report with repair_schema_version: 2.

localsetup doctor repair --target-directory .
localsetup doctor repair --target-directory . --repair-mode migration-plan --agent-prompt
localsetup doctor repair --target-directory . --repair-mode migration-plan --emit-agent-prompt /tmp/localsetup-repair.md
localsetup doctor repair --target-directory . --repair-mode safe-repair --yes
localsetup doctor repair --target-directory . --repair-mode apply-with-backups --yes

Safe repair only mutates LocalSetup-owned state. It can back up and remove a legacy ls/ tree only when the target tree is framework-shaped and matches the current source framework contents byte-for-byte. Clean tracked framework trees are backed up, untracked with git rm -r --cached -- ls, and then removed from the working tree. Protected source checkouts, symlinks, dirty trees, framework-shaped trees with extra or modified files, and custom ls/ content are preserved and reported as decisions for migration planning.

Custom repo skills are repo-owned by default. Adapter directories such as .agents/skills, .claude/skills, .cursor/skills, .kilo/skills, and .opencode/skills are shared agent surfaces, not exclusive LocalSetup-owned directories. Historical .codex/skills is inspected only for the proof-gated Codex managed-entry transition. Mixed adapter directories preserve custom content. Same-name collisions and unproven historical links are reported as decisions or blockers. See Adapter ownership.

Health commands surface blocked repairs and handoff prompts:

localsetup health --json
localsetup health repair-queue --json
localsetup health repair-queue --agent-prompts /tmp/localsetup-prompts
localsetup health events --limit 20
localsetup health events --event EVENT_ID
localsetup health request draft --event EVENT_ID
localsetup health --config CONFIG request prepare --event EVENT_ID

See structured failures and reviewed feedback for private event details, observations, and duplicate checks. After explicit approval of the prepared destination and payload, submit with localsetup health --config CONFIG request submit --event EVENT_ID --approve-plan PLAN_DIGEST.

.localsetup/lock.json is intentional managed repo state and remains visible to Git. Runtime summaries and journals are locally excluded through .git/info/exclude: .localsetup/health.json, .localsetup/AGENT_STATUS.md, .localsetup/install-journal/, .localsetup/backups/, .localsetup/state/, and .localsetup/context-index/.

Resolver And Validation Commands

Use resolver commands when scripts, docs, workflows, or agents need directly followable LocalSetup paths:

localsetup path --json
localsetup path source-root
localsetup path framework-root
localsetup path docs-root
localsetup path tools-root
localsetup path package-root
localsetup path package ls-localsetup-project-context SKILL.md
localsetup path doc WORKFLOW_REGISTRY.md
localsetup path tool tmux_ops

localsetup path --json refreshes paths.json under the configured LocalSetup home. Named path commands print one absolute path.

Use package-surface validation after changing skills, workflows, resolver tokens, materialization rules, or deployed path contracts:

localsetup validate-package-surface
localsetup validate-catalog

Use reprocess-paths for whole-project path-contract reporting. Apply mode is intentionally disabled until allowlisted rewrites are implemented:

localsetup reprocess-paths

Use test-workers to inspect the selected project's test policy:

See test resource safety for the shared memory, CPU, process, and timeout limits applied before workers start.

localsetup test-workers
localsetup test-workers --json
localsetup test-workers --workers 4
localsetup test-workers --status --json
localsetup test-workers --watch

The common testing section owns workers ("auto" or a positive integer) and shard_count (1–32), with legacy [tool.localsetup.testing] as a fallback. Auto resolves to max(1, floor(available logical CPU cores / 3)); an explicit value is capped at available logical cores and execution is further constrained by memory. --workers takes precedence over LOCALSETUP_TEST_WORKERS, which takes precedence over the project setting. JSON includes stable hosted CI partitions, the per-runner worker request, and matrix job concurrency. Each isolated CI runner enforces its own CPU and memory limits; local concurrent runs share one guarded host budget. The command reads --target-directory or --repo when supplied, otherwise the current project directory; the installed framework source is not substituted for that project.

In this repository, plain pytest ls/tests -q loads the shared plugin. Local execution has one queue per active worker; pending work is redistributed when workers retire or join. Seeded random ordering mixes related cases before balanced assignment; hosted CI uses the same seed across its isolated matrix jobs and failed-job reruns. Concurrent local runs share one guarded aggregate budget.

Other applications can use the same implementation without copying scripts:

localsetup test-run --project-root . --pytest -- tests -q
localsetup test-run --project-root . --pytest -- tests -q --test-seed 12345
localsetup test-run --project-root . -- your-test-command arguments

The pytest path loads ls.core.test_plugin; the installed environment must include pytest and the qualified pytest-xdist 3.8.0 interface. The generic command gets the resource guard and emergency watchdog, but does not gain between-test queue resizing unless it implements a compatible scheduler. Linux cgroup v2 and a systemd user manager are required. Unsupported controls fail closed. See the adaptive policy and engineering provenance. For machine-readable live worker and memory data, use test-workers --status --json; --watch --json streams changing snapshots. The telemetry contract defines counts, freshness, single-worker behavior and cleanup semantics.

Maintainer Commands

Run these from the repository root when changing docs, catalogs, release metadata, skills, workflows, or platform manifests:

uv run --locked python ls/tools/docs_alignment.py --repo-root . inventory
uv run --locked python ls/tools/docs_alignment.py --repo-root . check --ci
uv run --locked python ls/tools/generate_docs_artifacts.py --repo-root .
uv run --locked python ls/tools/localsetup.py --source-root . generate-docs
uv run --locked python ls/tools/localsetup.py --source-root . validate-catalog
uv run --locked python ls/tools/localsetup.py --source-root . validate-package-surface
uv run --locked ./ls/tests/automated_test.sh
uv run --locked pytest ls/tests -q
git diff --check

Run focused pytest targets and matching LocalSetup validators before broad suites. Reserve the full Python suite for final consolidation on broad/shared runtime changes, release or publish work, dependency changes, or explicit maintainer requests.

Use release-push only when the release wave explicitly includes publishing:

uv run --locked python ls/tools/localsetup.py --source-root . release-push

For release preparation without pushing, run publish-preflight --base origin/main --head HEAD first from a clean worktree. It prepares the direct version-sync candidate unstaged and returns prepared_not_ready when the candidate needs review and a separate generated-document receipt. Add --fix only when the tool should prepare and commit the required version-sync/generated-document slices before the guarded push.

Release documentation has its own source-aware gate:

localsetup release-docs plan --verify-baseline
localsetup release-docs prepare --verify-baseline --candidate .agents/state/<task-slug>/candidate.json
localsetup release-docs apply --candidate .agents/state/<task-slug>/candidate.json
localsetup release-docs render
localsetup release-docs check
localsetup release-docs notes

plan, check, and notes read the candidate; prepare calls the configured protected QC model and writes private proposal evidence; apply writes an accepted hash-bound proposal; render regenerates managed sections and the current guide from an existing versioned record. Preparation and application require a clean checkout. Commit authored preparation before canonical version/generated sync. No command in this family publishes a release. For final draft validation use release-docs check --draft-tag v<version> --expected-commit <sha>; complete artifact verification is still required. See versioning for automatic release, repair, and qualification modes.

Release commands select a valid .localsetup-release.json from the planned committed HEAD. Its verified published anchor owns sequential arithmetic; --base remains comparison metadata. An absent policy retains patch-default. Loose policy changes and explicit version targets cannot override the committed contract. Invalid configuration or historical sync prefixes stop before version mutation; ordinary target drift can be prepared by the existing sync flow. See version policy and exact overrides.