| status | ACTIVE |
|---|---|
| version | 4.89 |
| owner_skill | ls-localsetup-framework-changes |
Use this page when you need copy-pasteable LocalSetup commands. For narrative install guidance, start with Quickstart or Multi-platform install.
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.
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.jsonThese 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.
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.
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" recoverThe 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 300The 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.
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.
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.
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 --yesInstall 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.
| 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. |
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 rollbackFrom 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 --ciResolve the registry-owned repo/global state root without writing:
localsetup state path --client codex/codex-cliAdd only that exact repo state child to Git's resolved local exclude:
localsetup state path --client codex/codex-cli --apply-excludeAllocate 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.
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.
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 --restartThe 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.
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.
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.yamlBoth 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 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 --checkOnly the explicit install and mutating update commands invoke Envman's latest bootstrap:
localsetup envman install
localsetup envman updateThe 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/repositoryRepository 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.
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.ascAudit, 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.
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 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.
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 --helpLSCli 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/runtimesReplace 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.
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 --helpHarness 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.
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 \
--yesUseful 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. |
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 --yesSafe 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_IDSee 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/.
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_opslocalsetup 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-catalogUse reprocess-paths for whole-project path-contract reporting. Apply mode is intentionally disabled until allowlisted rewrites are implemented:
localsetup reprocess-pathsUse 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 --watchThe 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 argumentsThe 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.
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 --checkRun 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-pushFor 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 notesplan, 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.