Tiber
Tiber is an event-sourced task board for coding agents. It keeps task and
CI-recovery state in an EventCore/eventcore-fs store on one dedicated orphan
tiber branch and gives agents a deterministic CLI plus stdio MCP tools.
The goal is simple: multiple agents and worktrees can coordinate through one authoritative event history instead of repository ticket files.
Screenshots
These screenshots were captured from this repository after initializing Tiber and creating the top-level tasks for the rename/merge work.
Tiber dashboard showing current repository tasks
Tiber task detail page for the documentation task
Tiber docs browser listing repository markdown docs
Installation
Install the independent plugin with codex plugin add tiber@ai-plugins after
adding this marketplace. The repository's install.sh installs Tiber and
Development System together by default. Tiber needs no .development-system.toml;
its optional project configuration is .tiber.toml.
Resolve bin/tiber from the installed plugin root. The launcher repairs only
Tiber's own versioned binary cache. Linux x86_64 uses the checksum-verified
release; other hosts require Cargo and a verified exact-release source bundle.
On first installed portable MCP startup, Tiber configures one shared user-level
Codex transport that forwards SSH_AUTH_SOCK by name. The installer can also
bootstrap it immediately. A stable dispatcher in PLUGIN_DATA resolves the
currently enabled installed Tiber launcher on each launch, so future Tiber
upgrades require no installer rerun, even when Codex removes the old cache. Existing task history and Git refs require no migration.
SSH authentication and existing installations
Codex 0.166.0 filters SSH_AUTH_SOCK from ordinary MCP environments. Portable
plugin mcp.json does not support env_vars, and ${SSH_AUTH_SOCK} and
$SSH_AUTH_SOCK in env remain literal strings. A saved socket path can become
stale after login or agent restart. This also affects SSH Git fetch/push;
sandbox access alone cannot restore missing agent credentials.
Fresh plugin-only installations bootstrap automatically on their first MCP startup. Fully restart Codex once after that bootstrap to activate forwarding. For existing 1.1.x versioned registrations, migrate once using the current installed helper below or the shared installer. An already deleted old command cannot repair itself. This one-time migration repairs all caller projects:
curl -fsSL https://raw.githubusercontent.com/jwilger/ai-plugins/main/install.sh | sh
Then fully restart Codex from a shell where the current SSH agent is available.
After agent rotation, restart Codex again from the updated environment. Restarting
only MCP inside an already running Codex process cannot refresh its parent
environment. No private keys or session socket paths are stored by this repair.
HTTPS and unsigned repositories can run with SSH_AUTH_SOCK unset; repositories
that require SSH authentication or signing still need usable credentials.
For an already installed current release, run
python3 /absolute/installed/tiber/scripts/configure-codex-mcp.py to check, or
append --apply to repair. Use the actual installed cache root, never a repository
copy. The helper preserves unrelated configuration and refuses an unmanaged
Tiber registration or a symlinked config. Review that registration rather than
replacing it automatically. Do not run competing config writers during repair.
Python 3.11 or later is required for the helper.
A supported direct registration in the user-level Codex config.toml is:
[mcp_servers.tiber]
command = "/absolute/trusted/installed/tiber"
args = ["mcp", "stdio"]
env_vars = ["SSH_AUTH_SOCK"]
env = { TIBER_AGENT_FORWARDING = "current-session" }
Use an absolute trusted installed native executable, or the installed plugin's
bin/tiber launcher with explicit PLUGIN_ROOT and PLUGIN_DATA in env.
The helper instead provisions a stable dispatcher, captures an absolute trusted
Codex CLI path and supplies PLUGIN_DATA; the dispatcher sets the selected
PLUGIN_ROOT at launch. It queries Codex inventory from a neutral directory
without forwarding the agent to that subprocess. Disabled or uninstalled Tiber
fails safely. Runtime PATH replacements are ignored. If the captured Codex
executable disappears after a Codex upgrade, rerun the installed helper with
the current trusted Codex available. Normal Tiber CLI calls never change global
MCP configuration. Bootstrap diagnostics go to stderr. A complete same-name
user declaration replaces the plugin transport; a partial env_vars overlay
is invalid and does not retain plugin environment or working directory. Keep
unrelated existing env_vars when repairing a user-owned direct registration.
Never forward an agent to a PATH-resolved or project-controlled executable.
Never copy keys, source shell startup files, discover arbitrary sockets, or
hardcode a session socket in the MCP configuration.
Legacy plugin-only launchers can still read signing-agent-socket for
compatibility, but that snapshot cannot follow socket changes. Current-session
mode ignores it, including when the parent agent is unset. After the one-time
stable-dispatcher bootstrap, Tiber upgrades need no installer repair. Agent
rotation still requires a full new Codex process from the current agent shell.
tiber.ssh_authentication_failed source_redacted=true reports a known SSH public-key
rejection with safe repair guidance; it does not expose Git stderr or remotes.
For a PATH command, preview tiber install-bin --target-dir ~/.local/bin --dry-run.
The installer never overwrites an existing forwarder. When upgrading a legacy
Development System forwarder, inspect its printed destination, move that old
file to a backup, then explicitly run --apply using the new Tiber launcher.
Do not remove an unrelated executable or silently replace a user's forwarder.
Quick Start
tiber init
tiber create "Document release checklist"
tiber list
tiber list --status done
tiber search "release checklist"
tiber show document-release-checklist
tiber validate --fix
tiber sync
tiber init is explicit. Installing the plugin or starting an agent session does
not mutate the repository.
Tiber task reads and writes also work from a coordination-only primary checkout
when Git cannot report a normal worktree but the repository declares its source
root through core.worktree. Relative values are resolved from the Git
directory. A true bare repository or another context without an explicit
worktree root is refused with actionable repository-context guidance.
For Codex sandboxed sessions, preview the narrow host-access setup before granting broad permissions:
tiber codex-sandbox --dry-run
The preview treats raw Git prefix approvals as case-by-case, including
hash-object, mktree, commit-tree -S, update-ref, fetch, and push.
Persist approval only when the harness can scope it to the exact Tiber-internal
operation rather than a reusable raw git prefix. Prefer the narrowest approval
that lets the same structured Tiber MCP operation be retried. Do not run the
whole Tiber MCP server outside the sandbox unless the narrow Git permissions are
insufficient.
When you start working on an existing task, move it out of the backlog first:
tiber transition <task-ref> in-progress
Backlog tasks are unclaimed work, not informal reservations.
What Tiber Stores
tiberis an orphan Git branch containing the eventcore-fs event store.- Semantic task and CI-recovery events share that store in separate EventCore streams and use expected stream versions for optimistic concurrency.
- A command is successful only after its exact event transaction is published
to
origin/tiberwhen an origin exists. - CLI and MCP commands accept a task id, nickname, or full stem. Users do not need to know stream identifiers or EventCore storage details.
This keeps task state versioned, syncable, and separate from the source branch.
Inspect it through tiber show, tiber list, or the dashboard.
Bare tiber list preserves board-order output for open work. Use
tiber list --status <backlog|in-progress|done|abandoned> to inspect one
lifecycle state. Use tiber search "<query>" to search titles, summaries, and
context across every state; it returns deterministic JSON containing each
matching task's id, status, title, summary, and context. The
tiber.search MCP tool exposes the same results as structured content.
Backlog Capacity
Projects may set a maximum queued backlog in the repository-owned
.tiber.toml:
[backlog]
max_queued = 5
Only tasks in backlog count. The active in-progress task and tasks in
done or abandoned do not. Tiber enforces the limit when creating a task,
reopening completed or abandoned work into backlog, or moving active work
back into backlog. CLI and stdio MCP calls use the same enforcement. The
dashboard exposes no admission route; backlog priority reordering is
count-neutral.
When the queue is full, Tiber refuses before persisting the admission and reports the current count and limit. Choose one explicit outcome: replace a lower-value queued task, combine genuinely overlapping work, or reject the candidate. Do not retry unchanged, raise the limit merely to fit work, or keep an overflow, icebox, shadow, or hidden backlog.
Existing projects require no migration: a missing .tiber.toml or omitted
max_queued setting means unlimited capacity. Adding a limit to an already
over-capacity project does not block moves out of backlog; reduce the queue
before admitting more work. Invalid configuration fails closed for admission
operations. Fix or remove .tiber.toml to recover; removing the setting rolls
back to unlimited capacity.
The replenishment review threshold remains an operating-procedure concern, not Tiber configuration. It triggers judgment about whether to look for candidates and does not define a storage invariant, so Tiber mechanically enforces only the maximum queued count.
Final-Review Completion Policy
Projects can opt into a mechanical completion and delivery gate in the
repository-owned .tiber.toml:
[final_review]
minimum_clean_reviews = 3
When enabled, tiber transition <task-ref> done and
tiber close-from-trailers refuse to close an implementation task until its
authoritative Tiber event history contains the configured number of consecutive
clean reviews. Every review in the final configured sequence must use the
independent-final-review reviewer type, have a distinct review and reviewer
identity, and agree on the declared Git pathspec scope, commit range, source
fingerprint, and verification-evidence scope and fingerprint. Tiber resolves
the supplied commit-range endpoints to full commit OIDs and computes both
fingerprints itself. Reviews use the canonical tiber-final-review-scope-v5
path manifest, which binds each materialized path, Git mode, entry kind, and
exact bytes (or gitlink OID) without binding the staging partition. Completion
and delivery resolve a full commit OID and tree OID once, recompute both scopes
from that immutable tree, and persist those OIDs with the completion event.
The retained requested pathspecs are rematerialized against that selected tree,
so newly committed matching paths invalidate the clean sequence while retained
literal deleted paths remain part of the manifest.
Record every clean review and every review with a substantive finding through
the CLI or the provider-neutral tiber.review.record MCP tool:
tiber review <task-ref> \
--review-id review-3 \
--reviewer reviewer-session-3 \
--reviewer-type independent-final-review \
--scope 'src/**' \
--scope 'tests/**' \
--commit-range base-oid..head-oid \
--outcome clean \
--evidence receipt-or-report-reference \
--timestamp 2026-08-27T12:00:00Z \
--source-fingerprint auto \
--verification-scope .tiber-verification/final-review.txt \
--verification-fingerprint auto
Each record durably includes its identity, reviewer identity and type, the
materialized exact path inventory selected by the requested scope,
commit range, outcome, evidence, timestamp, source fingerprint, verification
scope, and verification fingerprint. Requested scope values are repeated
pathspec arguments, so paths containing spaces remain exact. Tiber resolves
those pathspecs when the review is recorded and retains literal entries for
deleted paths, allowing a content-identical staging and commit step to preserve
the reviewed receipt. Empty scopes and unresolved commit ranges are rejected.
Source fingerprints bind working-tree contents and Git modes. Moving identical
content between unstaged, staged, and committed partitions is metadata-only,
but policy-enabled completion requires every reviewed source and verification
receipt to be represented by the selected commit tree. An uncommitted reviewed
path is rejected with source_not_committed or verification_not_committed;
commit it and record fresh reviews if the committed snapshot differs. A finding clears
the effective clean sequence. A later record with a changed scope, commit range, source fingerprint,
verification scope, or verification fingerprint also starts a new sequence;
this covers scope expansion and changed relevant verification evidence. Source
or verification mutation after the latest clean review is detected when
completion or trailer-driven delivery is attempted. Refusals name the exact
missing count, independence condition, or stale evidence condition.
Immutable-tree evaluation uses a disposable index loaded only from the selected
tree, pins attribute pathspec evaluation to that same tree, uses one bounded
tree listing, and performs one batched blob read into a single retained buffer.
Attribute-magic pathspecs require Git 2.41 or newer. Tiber probes that capability
before immutable evaluation and fails closed with
attribute_source_unsupported plus the upgrade-and-rereview action when the
host Git cannot bind attributes to the selected tree.
Identical source or verification scopes are cached across tasks in one
trailer-delivery command; Git subprocess count is therefore constant per
distinct uncached scope rather than proportional to its file count.
Fingerprinting fails closed with a scope_too_large diagnostic when one Git
enumeration exceeds 16 MiB, the combined scope exceeds 100,000 paths, or the
selected regular-file content exceeds 64 MiB. Narrow the declared scope and
record fresh independent reviews rather than bypassing those limits. A single
trailer-delivery command reuses identical source and verification fingerprints
across its referenced tasks while retaining at most 256 distinct fingerprint
entries and evicting the least recently reused entry when the cache is full.
There is no runtime bypass flag. To opt out deliberately, remove the
[final_review] table (or set minimum_clean_reviews = 0) in a reviewed,
committed project configuration change. Completion and delivery evaluate the
committed policy and reject an uncommitted policy change. That Git-visible change is the audit
record; ordinary CLI, MCP, local completion, and trailer-driven CI delivery
cannot silently bypass an enabled policy. Explicit nonzero minima one and two
are supported; larger configured minima remain enforced. The committed policy,
independence, source/verification fingerprints, and trailer gate remain mandatory.
Existing projects remain opted out after upgrade because a missing table
defaults to zero. Existing Tiber event histories need no migration: review
fields and completion-snapshot fields on older events default to empty during
replay. Historical v4 review fingerprints remain readable but cannot authorize
a new policy-enabled completion; Tiber reports fingerprint_version_legacy
and requires fresh v5 reviews. Source and verification receipts must be
committed before completion (a future explicitly supported immutable external
receipt may provide another durable representation).
Enabling the policy does not grandfather open or completed work: each task must
acquire fresh qualifying records before completion or later trailer-driven
delivery. Disabling and later re-enabling the policy does not erase review
history, but only the current consecutive sequence can satisfy the gate.
New Task Skill
The plugin includes the manually invokable tiber:new-task skill for quick
backlog capture from an agent session:
tiber:new-task Document release checklist
The skill creates the task through structured Tiber MCP tools, records any
obvious summary or acceptance details from the prompt, runs the structured Tiber
MCP validation tool, and leaves the task in backlog unless the user explicitly
asks to start work immediately.
It relies only on structured Tiber MCP tools for creation, validation, and backlog handling. It does not fall back to the Tiber CLI, direct file edits, or shell commands.
CLI Commands
Run tiber --help for the complete command list and
tiber <command> --help for parser-generated command usage. Generated help is
the authoritative CLI grammar.
Common reads:
tiber list
tiber next
tiber show <task-ref>
tiber metadata <task-ref>
Common writes:
tiber create "Task title"
tiber transition <task-ref> <status>
tiber prioritize <task-ref> --before <task-ref>
tiber link <task-ref> blocks <task-ref>
tiber unlink <task-ref> blocks <task-ref>
tiber subtask add <task-ref> "Subtask title"
tiber subtask add <task-ref> "Dependent subtask" --after s1,s2
tiber subtask check <task-ref> s1
tiber subtask uncheck <task-ref> s1
tiber update <task-ref> --summary "New summary" --tags infra,docs
tiber update <task-ref> --pr-mr-url https://github.com/org/repo/pull/42 --pr-mr-status checks-pending
tiber acceptance add <task-ref> "Observable condition"
tiber acceptance check <task-ref> 1
tiber note add <task-ref> "Progress note"
Summary and context values may contain actual line breaks. Tiber preserves those
line breaks and literal backslashes exactly across CLI and MCP updates; callers
do not need to flatten multiline text or replace it with literal \n sequences.
Unsupported control characters and embedded headings reserved by Tiber's task
schema fail with actionable diagnostics before the ticket or board is changed.
Validation and integration:
tiber validate --fix
tiber close-from-trailers
tiber codex-sandbox --dry-run
tiber install-bin --target-dir ~/.local/bin --dry-run
tiber scaffold repo --dry-run
tiber scaffold repo --apply
install-bin is dry-run-first. The dry run reports the target command and
bundled launcher without writing either path. Re-run it with --apply to
install an executable forwarder that invokes the bundled Tiber launcher from
any working directory:
tiber install-bin --target-dir ~/.local/bin --apply
tiber --help
The apply step never replaces an existing tiber file or symlink. Remove or
relocate an existing target deliberately before reinstalling or upgrading.
validate --fix only performs safe mechanical repairs such as misplaced claims
and missing reciprocal links. Dangling references and dependency cycles are
reported for deliberate resolution.
Sync Model
Tiber appends semantic events through EventCore, commits eventcore-fs files to
the tiber branch, and pushes that branch when an origin remote exists.
Signed event commits retain Git's configured author and committer identity so
repository signature-verification rules can attribute them to the owner.
Confirmed concurrent publication is handled as an EventCore version conflict: Tiber refreshes the authoritative branch and retries the pure command with its original invocation identity. Never force-push or choose a side blindly. If publication cannot be confirmed either way, Tiber blocks further mutations until the pending candidate is resolved with:
tiber sync
Repository writes are serialized across concurrent clients. During upgrades,
current clients also hold the legacy tiber.lock sentinel while using their
advisory sidecar lock, so an older installed Tiber and the current version
cannot mutate the board at the same time.
close-from-trailers synchronizes the authoritative board before resolving
Closes: lines from the current HEAD commit. It prints closed <task-id> for
each published transition and exits nonzero when a requested task is missing,
invalid, conflicted, or cannot be pushed. A successful run therefore guarantees
that every task it names is no longer open.
Read commands sync before returning task data. If Tiber can merge remote task state automatically, the read continues with the merged board. If the sync cannot be resolved automatically, the read fails instead of returning stale or locally divergent task data.
CI Recovery Is Tiber-Owned
Tiber is the sole authority for pushed-CI recovery as well as task-board facts. Its typed EventCore facts are stored on the shared Git-backed Tiber authority. Development Discipline reads Tiber's unresolved hold only to gate delivery; it does not keep a second incident, lease, assignment, receipt, or CI state ref.
Stdio MCP
Tiber exposes the same task operations over stdio MCP:
tiber mcp stdio
The plugin manifest invokes its installed bin/tiber entrypoint directly. The
entrypoint selects the shipped native binary for the current supported target
and otherwise invokes the repository's pinned Rust build; MCP configuration
does not use a shell command string or a harness-cache fallback path.
Codex starts that entrypoint from the installed plugin root. Tiber advertises
Codex's sandbox-state metadata capability and resolves each task operation from
the active call's local sandboxCwd, so the authoritative board belongs to the
caller's repository rather than the plugin cache. A later call from another
workspace replaces the process-local repository selection.
Codex discovers Tiber through the plugin-root mcp.json. Because Codex filters
SSH_AUTH_SOCK, installed portable MCP startup automatically configures the
shared user-level transport described under SSH authentication and existing installations.
Its stable dispatcher forwards the current parent agent by variable name to
the selected enabled installed launcher, surviving removed old version caches. After agent rotation, fully restart Codex from the updated agent shell;
restarting MCP alone cannot refresh Codex's environment. Saved
signing-agent-socket files remain legacy compatibility only and are ignored
by the repaired current-session transport. Never pass the agent socket to a
project-controlled executable.
The manifest's ./bin/tiber command is resolved only against the installed
plugin root, never the caller checkout. Reinstall or upgrade the plugin if Codex
reports No such file or directory, tiber.repository_not_found, or one of the
tiber.mcp_* startup sentinel errors while using the tiber MCP server.
Tool names use the tiber.* namespace, for example tiber.create,
tiber.list, tiber.search, tiber.transition, tiber.update, tiber.acceptance.add,
tiber.note.add, tiber.codex_sandbox_setup, tiber.install_bin, and
tiber.validate_fix.
The initialize response also points Codex agents at
tiber.codex_sandbox_setup and tasks://codex-sandbox so sandbox setup can be
discovered through MCP before retrying a failed write.
Dashboard
The dashboard is a browser view with count-neutral backlog priority reordering:
tiber dashboard serve --open
The command selects an available localhost port, prints the complete URL, and opens it in the platform browser. A repeated launch from the same project reports and reuses the healthy existing URL without starting another server or opening another browser window. Different repositories keep independent dashboard instances.
Use tiber dashboard serve when you only want the URL. Request a stable port
with --port <port> or the backwards-compatible TIBER_DASHBOARD_PORT
environment variable; the CLI flag takes precedence. An unavailable requested
port or invalid environment value fails clearly, and requesting a different port while that project's
dashboard is already running reports the conflict instead of starting a second
server. If the browser opener is unavailable or exits unsuccessfully, --open
warns but leaves the dashboard running at the printed URL.
The dashboard lets you inspect the board, reorder backlog priority, view task
files, and browse repository docs. It exposes a read-only /events SSE stream
for live refreshes and a count-neutral priority mutation, but intentionally has
no create, status-transition, general task-write, or /mcp route. Admission
changes go through the CLI or stdio MCP tools.
Scaffold Workflow
Repository integration is dry-run first:
tiber scaffold repo --dry-run
The preview covers:
- a post-commit hook snippet only when the active executable hook verifiably dispatches it; otherwise the preview reports the missing integration
- a GitHub workflow for
tiber close-from-trailerswith pinned checkout and Tiber source revisions plus explicitcontents: writepermission - an optional
just show-tasksrecipe when ajustfileexists - explicit
would write,already configured, andconflictclassifications; equivalent existing hooks and workflows suppress duplicate automation
Apply only after explicit approval of the preview:
tiber scaffold repo --apply
Apply refuses to overwrite a conflicting generated hook or workflow path. After reviewing every reported conflict, explicitly choose replacement with:
tiber scaffold repo --apply --replace-conflicts
Established repositories
Legacy .tasks trees and the former tasks and tiber-coordination branches
are ignored history, not Tiber state. Tiber neither migrates nor mutates them;
recreate any still-useful tickets manually through Tiber commands.
Scaffold resolves Git's active hooks directory. With no configured hook
dispatcher, it reports that local automation was skipped instead of writing an
inert snippet. When core.hooksPath selects a manager-owned directory, a
missing executable dispatcher is a blocking integration conflict; wire that
manager's active post-commit hook to .githooks/post-commit.tiber, then
preview again. Existing active task-closing hooks and push workflows remain
untouched and suppress only their matching generated integration.
The generated GitHub workflow publishes Tiber event transactions with explicit
contents: write permission. It pins actions/checkout and the Tiber source
commit rather than following mutable tags or branches, installs with the
committed Cargo lockfile, and targets the remote default branch when available
(falling back to the current branch in a repository without that remote
metadata). If local repository policy enables commit.gpgsign, scaffold
refuses that generated workflow before writing anything because an unattended
GitHub runner has no repository signing key. Provide repository-owned signed
publication automation and rerun the preview; do not disable signing merely to
admit the generated workflow.
Host-local installation
Tiber owns its versioned binary installation. From the marketplace checkout,
run plugins/tiber/scripts/install-tiber-binaries.sh to install or repair
Tiber. The installer handles only Tiber; Development System repairs its own
executable independently. Tiber's launcher checks its installation marker and
automatically repairs a missing or stale binary before starting. Linux x86_64
uses the verified version-matched release; other hosts use the locked source
build. Pass --from-source to the installer for an intentional source build.
Harness Support
Tiber targets Codex. Its plugin, CLI binary, and MCP server are named tiber.
Its published skills are tiber:tasks and tiber:new-task.