This repository provides developer-facing support for Bitty plugins: the
accepted-contract validator for bitty-plugin.toml with the
bitty-plugin-lint CLI, generated Plugin API v1 LuaLS declarations, and the
Plugin API v1 mock host with its conformance fixtures. The Lua helper SDK
remains pre-implementation under its own task.
CarryCtx is the local-first tool that records this project's tasks, decisions, and checkpoints. Install it globally for local development (recommended):
cargo install carryctx # Rust toolchain, or: npm i -g carryctxCarryCtx engineering state (tasks, sessions, checkpoints) is not cloned. A
fresh clone restores it from the in-repo refs/heads/carryctx-snapshots
branch:
just workflow-import-dry # fetch + validate the snapshot; no DB writes
just workflow-import # initialize CarryCtx state if needed, then importThen carryctx stats reports the restored tasks, sessions, and checkpoints.
Provenance, redaction, and --force behavior are covered under the
repository snapshot documentation below.
This repository will own SDK-specific implementation evidence and contributor guidance after separately reviewed tasks authorize them. It does not own the Bitty host, plugin runtime, capability model, lifecycle, package format, or Terminal Truth.
Canonical product and plugin contracts belong to the bitty-docs repository. The plugin-system specification and the security overview govern future SDK work. An SDK surface must derive from an accepted and verified host contract; it cannot create host behavior by documenting it first.
The SDK validates bitty-plugin.toml against the accepted Plugin API v1
manifest and capability contract in bitty-docs. Validation is fail-closed:
unknown keys are rejected at every schema level, capability identifiers are
checked against the closed v1 set, and every count and length bound is
enforced before a manifest is accepted.
just test # schema, limit, and CLI tests
bun src/cli.ts bitty-plugin.toml # human-readable report
bun src/cli.ts --json bitty-plugin.toml # machine-readable reportThe schema, diagnostic codes, capability table, and known contract gaps are
documented in docs/manifest.md, with validated examples
under docs/examples/.
Generated plugin repositories run the authoritative linter instead of a local
re-implementation. bitty-plugin-lint is plain TypeScript with a
#!/usr/bin/env bun shebang, so the dependency needs no build step and no
registry publication; Bun must be on PATH:
bun add --dev "github:bitty-terminal/bitty-plugin-sdk#<40-char-commit-sha>"
bun run bitty-plugin-lint bitty-plugin.tomlPin the full commit SHA: branch and tag refs move, so the validation contract
is stable only per commit. The github: specifier
resolves only after the pinned commit is pushed to the canonical remote. For
local development against an unpublished checkout, use a local dependency
instead (bun add --dev "file:/path/to/bitty-plugin-sdk" or bun link). The
SDK is not published to a registry (private: true), so registry-based
bunx/npx installs do not resolve.
The same commit-pinned or local dependency also supports the package-root library import:
import { MockHost } from "bitty-plugin-sdk";Runtime and type exports resolve directly to src/index.ts; no build step is
needed. Only the package root is exported, not internal src/* subpaths.
The CLI remains available as bitty-plugin-lint. This support is for
Bun/TypeScript consumers, not Node.js or registry publication. See
docs/mock-host.md for construction and lifecycle
usage.
lua/bitty.d.lua is generated from the accepted Plugin API v1 surface in
surface/bitty-plugin-api-v1.json and checked for drift by just check
(just lua-defs-check). The declarations cover L1 Control and the minimal L2
UI surface only plus the closed v1 event set. Every surface exclusion is
enforced textually against the generated file by tests/lua-defs.test.ts; the
LuaLS negative fixture samples excluded names, the excluded raw scope
literal, and wrong-shape services.get calls. The handler alias returns any
because observation/lifecycle returns are ignored and only the literal false
vetoes, so false, nil, and non-boolean returns all type-check. The one
namespace the host has not wired yet (env; bitty #1303, still deferred after
the #1391 services re-wire) is generated as typed
E_NOT_IMPLEMENTED stubs: still declared, never silent. The bitty.debug
namespace (bitty #1573) is wired except debug.control, which the host still
fails closed with E_NOT_IMPLEMENTED and which is generated as a typed stub
too. The bitty.workspace namespace (list, focus, new, next,
close, rename, move_panel; bitty #1584, ADR 0014) and the
workspace.created/closed/renamed/focused/changed events are wired,
gated on workspace.read (list and events) and workspace.control
(mutations, which only enqueue). Both namespaces are host-implemented
candidates outside the ADR 0009 v1 guarantee; the workspace spellings stay
open under OQ-056. The accepted W-139 history-read family (CTX-0066,
RFC-0004) is wired additively under the NEW history root (never
bitty.terminal.*): bitty.history.transcript.query under
history.transcript.read, bitty.history.commands.query under
history.commands.read, and bitty.history.kv.query under
history.kv.read, plus bitty.selection.copy under the existing
clipboard.write (no new capability per Core W-143); live per-view search
binding, viewport navigation, and selection lifecycles stay Core-owned
deferred pending W-01 + W-138. There is no
bitty.network namespace: it is a v1 surface exclusion, bitty #1604
(DIR-030) removed Core's embedded Lua network binding, and the Lua request
surface of the out-of-process net native component is deferred, not wired.
The accepted W-01 bitty.ui.overlay.* focusable surface plus
overlay.released (CTX-0065) is wired under the coupled grant
ui.overlay.focus. The accepted W-82 composer operations (CTX-0068, plan
W-103 S-2, issue 142) are wired additively: bitty.terminal.submit under
terminal.input.submit and bitty.process.editor.start under
process.editor, with typed outcomes mirroring Core bitty #1661/#1654 and a
first-party/third-party parity-denial proof in conformance. The accepted
W-139 history/search/selection operations (CTX-0066, RFC-0004) are wired
additively with per-source scoped grants, 8-category typed denials,
VM-only delivery, and a history first-party/third-party parity-denial proof
in conformance. The thin W-29 bitty.ui.targets and bitty.ui.labels
bindings (bitty #1641) stay provisional host candidates pending per W-120,
deferred and not wired, recorded as explicit exclusions with no new
capability. The parity pin is bitty main fb44a867 (PR #1641, CTX-0067,
W-43); api_version stays 1.0.0 (additive only). LuaLS conformance runs
locally only: CI has no lua-language-server, so that check skips there.
See docs/lua-defs.md for LuaLS setup, coverage,
exclusions, and validation commands, and
lua/examples/minimal-init.lua for a runnable
example.
The Plugin API v1 mock host models the accepted bitty host bridge for
conformance testing: deny-by-default capability gates with the typed
E_CAPABILITY_DENIED denial, the activation-only registration window,
generation-owned handles, the closed v1 event set, bounded command/store/UI/
snapshot data, wired services, the deferred env (E_NOT_IMPLEMENTED),
tasks/timers on a virtual clock, the bitty.debug inspect/trace backend
(deferred debug.control), and the bitty.workspace domain with its bounded
request queue and workspace.read-gated events. It performs no I/O, spawns
no process, and opens no network.
just conformance # run the declarative fixture suite
bun test tests/mock-host.test.ts # unit-level behavior suite
just check # all quality gatesFixtures live under conformance/; the host contract mapping,
fixture format, and diagnostic codes are documented in
docs/mock-host.md.
CarryCtx runtime state (.git/carryctx/state.sqlite) is never cloned. The
redacted engineering snapshot lives in this repository on the branch
refs/heads/carryctx-snapshots, one commit per publication. The commander's
merge closeout publishes it with just workflow-publish; a fresh clone
restores its local CarryCtx DB from that branch:
just workflow-import-dry # fetch + validate the snapshot; no DB writes
just workflow-import # initialize CarryCtx state if needed, then importThe import fetches refs/heads/carryctx-snapshots, refuses to replace a
non-empty local DB without --force (just workflow-import --force), and
prints provenance (snapshot commit + source). Snapshots are redacted
publication artifacts produced by carryctx export --publication: CarryCtx
refuses them as merge sources, so restore always uses replace mode, and a
secret that leaked before rotation must still be rotated at the source.
This repository does not currently provide:
- a Lua helper SDK or library;
- public Lua functions or host APIs beyond the generated declarations and the test-double mock host;
- a published package or registry release (the linter is consumed as a commit-pinned Git dependency);
- host-version compatibility, deprecation, or support promises; or
- a release, release schedule, or publication channel.
The bitty-plugin-lint CLI and the manifest validator are local developer
tooling. They do not install, execute, or activate plugins.
Repository existence and planned boundaries are not implementation or release evidence.
Future convenience APIs must remain least-privilege and must not grant ambient filesystem, process, network, clipboard, terminal-input, or host-management authority. Canonical security requirements override proposed ergonomics.
The generated declarations and mock-host conformance fixtures were produced under explicitly scoped tasks with accepted source contracts, deterministic validation, and independent review. Any further generated declarations, examples, fixtures, or packages require the same gates. Nothing is installed, published, or released by this README.