Skip to main content
Profile templates are install-time packages that write .llmwiki/profile.json. They are not runtime plugins, and they do not contain executable code. If a project has no .llmwiki/profile.json, llmwiki uses the built-in default profile exactly as before.

List templates

The built-in list includes: The public template surface supports built-in templates, local template files, and signed releases from explicitly trusted remote taps.

Inspect a template

Inspection shows the template id, profile id, publisher, version, derived capabilities, connector bindings, digest, and install command.

Install a built-in template

Before writing, llmwiki checks that the active typed corpus is empty. A populated default wiki, even one without .llmwiki/profile.json, is refused so existing wiki/concepts and wiki/queries pages are not orphaned under a new profile. On success this writes:
  • .llmwiki/profile.json
  • attempts to write .llmwiki/template-lock.json
The lock file is advisory provenance for humans and support. Runtime behavior is always determined by .llmwiki/profile.json, which is validated on load.

Install a local template file

Local templates are untrusted declarative input. They go through the same manifest validation, profile validation, connector-binding reconciliation, and overwrite safety checks as built-in templates.

Replacing a profile

llmwiki template init refuses to overwrite an existing profile by default. --force only works when the current typed corpus is empty:
  • no typed entity pages under the active or incoming profile’s entity directories;
  • no relation records;
  • no event records;
  • no artifact files;
  • no workflow runs;
  • no pending or archived review candidates;
  • no unresolved, unsafe, or unreadable typed stores.
If the active profile is present but cannot be loaded, replacement is refused even with --force.

What templates cannot do

Templates cannot include executable code, scripts, postinstall hooks, connector implementations, MCP servers, or out-of-band local or environment trust grants. They may declare workflow gates and permission requests that the normal workflow authority model evaluates at run time. Connector bindings can only name connectors that are both compiled into llmwiki and marked template-installable.

Configure a signed remote tap

A tap is an HTTPS signed index. Adding one requires its Ed25519 public key explicitly; llmwiki does not trust a key merely because a server presents it.
The key file contains base64-encoded Ed25519 SPKI DER public-key bytes. Use --key-base64 instead of --key-file for automation, but never pass both. Adding a tap does not perform network I/O.
Refresh accepts an index only after its tap signature, expiry, sequence, publisher-key continuity, package coordinates, and revocations verify. Fetches remain on the exact configured HTTPS origin, including its port. Redirects cannot move to another origin, and DNS/private-address and response-size checks apply on every hop.

Inspect and verify a remote release

Remote releases use a fully qualified coordinate:
Package bytes are addressed by the digest in the signed index, fetched from the same origin, and verified with the publisher key before they enter the cache. Signed envelopes are cached by coordinate and payload digest so mirrors cannot conflict. Cached packages are rehashed and reverified on every use. The cache is evidence, not authority: deleting it cannot reset accepted sequences, keys, coordinates, or revocations. tap refresh can restore missing or malformed index evidence only from the exact signed snapshot already recorded in state.

Install a remote release

Install by exact coordinate, never by a floating version or search result:
The confirmation summary identifies the coordinate, profile digest, publisher key id, accepted tap sequence, and derived capabilities. Non-interactive use requires explicit confirmation:
Immediately before writing, llmwiki re-verifies the cached signed package under both the project lock and the tap-state lock. It refuses stale evidence, revocation, changed authority, an occupied typed corpus, or a package whose identity no longer matches the requested coordinate. Remote network access finishes before either lock is acquired. The resulting v2 template-lock.json records the coordinate, package digest, tap, accepted index sequence, and publisher key id. This remains advisory provenance. Profile loading and runtime authority come only from the validated .llmwiki/profile.json; editing the lock cannot bless profile drift.

Check provenance and drift

Remote status re-verifies the exact installed release from accepted cached evidence and compares the active profile against the release profile. It can report a clean install, local modification, stale evidence, revocation, unavailable provenance, or a newer verified coordinate. It never trusts the lock’s stored profile digest as proof that the active profile is unchanged.

Update an installed remote template

Preview compatibility before writing:
Apply only an exact newer release:
The planner refuses local profile modifications, incompatible existing pages, relation or artifact violations, unsatisfied lifecycle requirements, pending review candidates, and non-terminal workflow runs. The apply path fetches before locking, then re-resolves old and new releases and reruns the complete compatibility audit under the project and tap-state locks. A state change during review therefore refuses instead of applying a stale decision. An update journals the previous profile and advisory provenance before changing either file. If the process is interrupted, llmwiki template status reports interrupted-write. The next update, compile, or explicit llmwiki recover restores the recorded pre-update state before continuing, so a partial update cannot masquerade as a local profile modification or a clean install.

Signatures and untrusted content

Ed25519 signatures establish who signed exact bytes and whether tap continuity accepts them. They do not establish that publisher-authored display names, workflow labels, or descriptions are safe instructions. llmwiki nonce-fences presentation strings from every non-shipped profile before exposing them to an agent. This decision is derived from active profile bytes, not the mutable lock. Remote packages contain profile configuration only. Remote docs, examples, scripts, executable plugins, and automatic content seeding are not downloaded or run. Publishing a tap is a separate operator workflow. See Publish a signed template tap for the package envelope, index, signing, hosting, rotation, and client-verification procedure.

Disable a tap

Removal disables the tap but intentionally retains its trust history. Re-adding the same name is allowed only with the exact same URL, origin, and root key. This prevents remove-and-readd from becoming an implicit trust reset. Continuity history is append-only and bounded. tap list and tap refresh warn when a tap approaches its persistence limit so operators can plan a new identity or an explicit reset before refresh is refused. If a tap’s root key is lost or its retained history must be discarded, use the explicit destructive operation:
This deletes only that tap’s roots, publisher pins, revocations, and coordinate history. It does not delete project profiles. Re-adding the name afterward is a fresh trust decision and should use a key verified out of band.