# Labcoat — complete documentation Labcoat treats automation as a public interface rather than a shell-screen scraping exercise. ## JSON mode Every command accepts `--json` and emits exactly one envelope on stdout. Logs and progress stay on stderr. ```bash labcoat status --json labcoat deploy build/MyToken.wasm --dry-run --json ``` ```json { "ok": false, "command": "deploy", "schema": "labcoat/v1/error", "error": { "code": "WALLET_MISSING", "message": "project wallet does not exist", "hint": "run `labcoat wallet init` first" } } ``` An envelope being printed produces exit code 0, even when `ok` is false. Read the envelope rather than inferring application success from the process code. ## MCP mode ```bash labcoat mcp serve ``` The stdio MCP server exposes devnet, wallet, compilation, deployment, call, simulation, and trace tools using the same typed operations as the CLI. ## Context endpoints - [`/llms.txt`](/llms.txt) is the concise index. - [`/llms-full.txt`](/llms-full.txt) contains the full public documentation. - Every docs page has a sibling `.md.txt` URL. - [`/reference/cli.json`](/reference/cli.json) is the structured reference. - [`/skill.md`](/skill.md) is the canonical workflow for coding agents. --- ## Test before compiling ```bash labcoat test labcoat test contracts/MyToken.rs ``` Native Rust integration tests run contracts through `labcoat-test`, keeping the fast feedback loop outside the chain. ## Compile ```bash labcoat compile contracts/MyToken.rs ``` Compilation writes: - `build/MyToken.wasm`: raw deployable module. - `build/MyToken.wasm.gz`: compressed distribution artifact. - `build/MyToken.abi.json`: opcode, input, and output metadata. ## Deploy ```bash labcoat deploy build/MyToken.wasm --dry-run labcoat deploy build/MyToken.wasm --name MyToken ``` Deployment uses a Bitcoin commit/reveal envelope, waits for the create trace, and records the resulting `block:tx` ID in `labcoat.lock`. ## Simulate and call ```bash labcoat simulate MyToken 99 labcoat call MyToken 77 500 ``` Arguments may be decimal `u128`, `0x` hexadecimal, or strings up to 16 bytes packed little-endian. Simulation never broadcasts. Calls create a transaction and wait for indexing and decoded execution status. ## Trace ```bash labcoat trace --wait ``` Trace output includes decoded create, invoke, return, and revert events across every protostone in the transaction. --- `labcoat up` checks required service binaries, downloads missing pinned builds, starts the complete stack, and exposes one JSON-RPC gateway. | Service | Purpose | | --- | --- | | bitcoind | Bitcoin regtest chain | | metashrew | Alkanes state index | | ord | Ordinals and inscription index | | esplora | Chain query API | | espo | Explorer and trace services | | gateway | Unified JSON-RPC endpoint on port 18888 | ## Operate the stack ```bash labcoat up labcoat status --json labcoat logs --service metashrew --limit 100 labcoat snapshot clean labcoat restore clean labcoat down ``` Only one Labcoat devnet should run per machine. `status` reports each service, chain height, mempool size, and overall readiness. ## Wallet workflow ```bash labcoat wallet init labcoat wallet addresses --count 3 labcoat fund 1 labcoat mine 1 labcoat wallet utxos ``` The wallet derives BIP-86, BIP-84, BIP-49, and BIP-44 addresses. P2TR is the primary address for Alkanes operations. ## Reset carefully `labcoat reset -y` stops services and permanently removes local chain and index data. Snapshots are the safer choice when you expect to return to a known state. --- Labcoat publishes native binaries for macOS and Linux on arm64 and x86_64. ```bash curl -fsSL https://labcoat.sh/install | sh ``` The installer downloads the latest `cli-v*` release, verifies its SHA-256 checksum, and writes `labcoat` to `${LABCOAT_INSTALL_DIR:-$HOME/.local/bin}`. ## Install a specific version ```bash curl -fsSL https://labcoat.sh/install | sh -s -- 0.7.0 ``` ## Compilation prerequisites Contract compilation requires an LLVM Clang build with a WebAssembly backend. ```bash # macOS brew install llvm # Debian or Ubuntu sudo apt install clang wasi-libc ``` Then verify the complete environment: ```bash labcoat doctor ``` If `$HOME/.local/bin` is not already on `PATH`, the installer prints the exact export command to add. --- ## Create and test a contract ```bash labcoat init hello-alkane cd hello-alkane labcoat test ``` The generated project contains Rust contract sources, native integration tests, public configuration, deployment state, and agent instructions. ## Start the local chain ```bash labcoat up labcoat status labcoat wallet init labcoat wallet addresses ``` Fund the displayed P2TR address and confirm it: ```bash labcoat fund
labcoat mine 1 labcoat wallet utxos ``` ## Compile and deploy ```bash labcoat compile contracts/Example.rs labcoat deploy build/Example.wasm --dry-run labcoat deploy build/Example.wasm ``` Always deploy the raw `.wasm`. The deployment flow performs compression inside the commit/reveal envelope and records the resulting Alkanes ID in `labcoat.lock`. ## Interact and inspect ```bash labcoat simulate Example 1 World labcoat call Example 1 World labcoat trace --wait ``` Finish by stopping the shared local devnet: ```bash labcoat down ``` --- Labcoat is a Rust-first CLI for building Alkanes smart contracts on Bitcoin. It owns project scaffolding, native tests, WebAssembly compilation, the local devnet, wallets, deployments, contract calls, simulation, and decoded traces. ```bash labcoat init hello-alkane cd hello-alkane labcoat test labcoat up ``` ## Pick your path - [Install Labcoat](/docs/getting-started/installation/) on macOS or Linux. - Follow the [quick start](/docs/getting-started/quickstart/) from an empty directory to a deployed contract. - Integrate an AI agent through [MCP or JSON envelopes](/docs/automation/). - Read the generated [CLI reference](/docs/reference/cli/). ## The supported interface The `labcoat` binary is the public interface. Internal Rust crates may evolve, but CLI commands, `labcoat/v1/*` JSON envelopes, and MCP tools are designed for automation. Every JSON error includes a stable code, a human-readable message, and a recovery hint naming the next useful command. --- The retired TypeScript package and its legacy manifest are no longer the supported interface. Back up the project before migrating. ## Recommended sequence 1. Install the current native CLI and run `labcoat doctor`. 2. Commit or copy the existing project and deployment metadata. 3. Run `labcoat lock migrate` once to convert legacy deployment records. 4. Review `labcoat.toml` and remove any secret material. 5. Run `labcoat test` and `labcoat compile` against contract sources. 6. Start a clean local devnet and redeploy; old local-chain IDs are not portable. Use `labcoat lock show` to verify the per-network ledger after migration. The full repository audit remains available in the project’s `docs/migration` directory. --- `labcoat init` creates a Rust-first contract project: ```text contracts/ Rust contract sources tests/ Native integration tests Cargo.toml Host-side test project labcoat.toml Public project configuration labcoat.lock Per-network deployment ledger, created on deploy AGENTS.md Concise instructions for coding agents SKILL.md Complete Labcoat agent workflow ``` ## Settings precedence Settings resolve in this order: ```text CLI flags → LABCOAT_* environment variables → labcoat.toml → defaults ``` `labcoat.toml` supports `network`, `rpc_url`, `wallet_file`, and `fee_rate`. The default network is `regtest` and the default gateway is `http://localhost:18888`. ## Secrets Never put a mnemonic or passphrase in `labcoat.toml` or on the command line. - Set `LABCOAT_WALLET_PASSPHRASE` for the keystore passphrase. - Set `LABCOAT_MNEMONIC` or use `wallet init --mnemonic-stdin` for recovery. - Mainnet and signet refuse wallet operations without an explicit passphrase. ## Deployment state `labcoat.lock` maps contract names to network-specific IDs, hashes, transaction IDs, and deployment status. Commit it when deployments are part of shared project state. After `labcoat reset -y`, redeploy contracts because the local chain no longer contains those IDs. --- > Generated from Labcoat 0.7.0. Run `pnpm sync:reference` after changing CLI or MCP metadata. Rust-native toolkit for building, testing, deploying, and operating Alkanes smart contracts on Bitcoin. ## Install ```bash curl -fsSL https://labcoat.sh/install | sh ``` ## The core loop ```bash labcoat init my-project cd my-project && labcoat test labcoat up labcoat wallet init labcoat fund
&& labcoat mine 1 labcoat compile example labcoat deploy build/example.wasm labcoat abi verify example labcoat call example [args...] labcoat trace --wait labcoat down ``` ## JSON envelopes (agent mode) Every command accepts `--json` and prints exactly one envelope on stdout. Logs go to stderr. When an envelope is printed, inspect its `ok` field instead of the process exit code. ```json {"ok":true,"command":"status","schema":"labcoat/v1/status","result":{}} {"ok":false,"command":"deploy","schema":"labcoat/v1/error","error":{"code":"WALLET_MISSING","message":"...","hint":"run `labcoat wallet init` first"}} ``` Secrets never ride argv: use `LABCOAT_WALLET_PASSPHRASE`, `LABCOAT_MNEMONIC`, or mnemonic stdin. Configuration precedence is CLI flags → environment → `labcoat.toml` → defaults. ## Commands ### `labcoat init` Scaffold a Rust-first Labcoat project ```text init [OPTIONS] [DIRECTORY] ``` Arguments and options: - `directory` (optional): Destination directory (defaults to the current directory) - `force` (optional): Overlay the template onto a non-empty directory Values: `true`, `false`. ### `labcoat test` Compile WASIp1 WebAssembly and run native Rust integration tests ```text test [PACKAGE] ``` Arguments and options: - `package` (optional): Optional Cargo contract package whose host test should run ### `labcoat up` Download binaries if needed and boot the full devnet stack ```text up [OPTIONS] ``` Arguments and options: - `no_download` (optional): Skip the binary download/check step Values: `true`, `false`. - `ci` (optional): CI mode: wait (bounded) for full readiness, then emit the machine-readable endpoint manifest; non-zero exit if the stack never becomes ready Values: `true`, `false`. ### `labcoat down` Stop all devnet services ```text down ``` ### `labcoat status` Show devnet status (services, block height, mempool) ```text status ``` ### `labcoat mine` Mine blocks on the devnet ```text mine [OPTIONS] [COUNT] ``` Arguments and options: - `count` (optional): Number of blocks - `address` (optional): Address to mine to (defaults to the dev address) ### `labcoat fund` Send BTC from the dev wallet to an address ```text fund
[AMOUNT] ``` Arguments and options: - `address` (required) - `amount` (optional): Amount in BTC ### `labcoat logs` Show recent service logs ```text logs [OPTIONS] ``` Arguments and options: - `service` (optional): Filter to one service (bitcoind, metashrew, ord, esplora, espo, jsonrpc) - `limit` (optional): Max entries ### `labcoat reset` Stop services and wipe all chain/index data ```text reset [OPTIONS] ``` Arguments and options: - `yes` (optional): Skip the confirmation prompt Values: `true`, `false`. ### `labcoat snapshot` Snapshot the devnet data directory (stops services first) ```text snapshot [OPTIONS] [NAME] ``` Arguments and options: - `name` (optional) - `list` (optional): List existing snapshots Values: `true`, `false`. ### `labcoat restore` Restore a devnet snapshot (stops services first) ```text restore ``` Arguments and options: - `name` (required) ### `labcoat binaries` Check (and with --download, fetch) service binaries ```text binaries [OPTIONS] ``` Arguments and options: - `download` (optional): Values: `true`, `false`. ### `labcoat wallet` Wallet management (keystore at --wallet-file) ```text wallet ``` #### `labcoat wallet init` Create (or load) the project wallet. Mnemonic is read from LABCOAT_MNEMONIC or — with --mnemonic-stdin — from stdin; never argv ```text init [OPTIONS] ``` Arguments and options: - `mnemonic_stdin` (optional): Read the mnemonic from stdin (one line) Values: `true`, `false`. #### `labcoat wallet addresses` Show receive addresses ```text addresses [OPTIONS] ``` Arguments and options: - `count` (optional) #### `labcoat wallet utxos` Show spendable UTXOs ```text utxos ``` ### `labcoat compile` Compile Cargo contract packages to build/.{wasm,wasm.gz,abi.json} ```text compile [OPTIONS] [PACKAGE] ``` Arguments and options: - `package` (optional): Optional Cargo package name (omitting it builds every contract) - `out_dir` (optional): Output directory ### `labcoat abi` Fetch or verify Wasm-exported contract ABI metadata ```text abi ``` #### `labcoat abi fetch` Fetch ABI metadata from a deployed contract's __meta export ```text fetch [OPTIONS] ``` Arguments and options: - `contract` (required): Contract name from labcoat.lock, or a raw block:tx id - `out` (optional): Write the exact ABI bytes to a file #### `labcoat abi verify` Compare deployed ABI metadata with a locally built contract ```text verify [OPTIONS] ``` Arguments and options: - `contract` (required): Contract name from labcoat.lock, or a raw block:tx id - `package` (optional): Local Cargo contract package (required for raw ids or renamed deployments) ### `labcoat deploy` Deploy a compiled contract (raw .wasm) via commit/reveal envelope ```text deploy [OPTIONS] ``` Arguments and options: - `wasm` (required): Path to the raw .wasm artifact - `name` (optional): Contract name recorded in labcoat.lock (defaults to file stem) - `args` (optional): Constructor cellpack args (u128 / 0x-hex / short strings) - `dry_run` (optional): Validate inputs and show what would happen without broadcasting Values: `true`, `false`. ### `labcoat call` Execute a state-changing call on a deployed contract ```text call [OPTIONS] [ARGS]... ``` Arguments and options: - `contract` (required): Contract: labcoat.lock name or block:tx alkanes id - `opcode` (required): Opcode number - `args` (optional): Cellpack args (u128 / 0x-hex / short strings) - `dry_run` (optional): Validate inputs and show what would happen without broadcasting Values: `true`, `false`. ### `labcoat simulate` Read-only simulation of a contract call ```text simulate [ARGS]... ``` Arguments and options: - `contract` (required): Contract: labcoat.lock name or block:tx alkanes id - `opcode` (required): Opcode number - `args` (optional): Cellpack args (u128 / 0x-hex / short strings) ### `labcoat trace` Decoded protostone traces for a transaction ```text trace [OPTIONS] ``` Arguments and options: - `txid` (required) - `wait` (optional): Poll until the trace is available Values: `true`, `false`. ### `labcoat lock` labcoat.lock utilities ```text lock ``` #### `labcoat lock migrate` Migrate a legacy deployments/manifest.json into labcoat.lock ```text migrate ``` #### `labcoat lock show` Show the lockfile ```text show ``` ### `labcoat mcp` Model Context Protocol server (agent integration) ```text mcp ``` #### `labcoat mcp serve` Serve MCP over stdio (newline-delimited JSON-RPC) ```text serve ``` ### `labcoat docs` Print documentation ```text docs [OPTIONS] ``` Arguments and options: - `llm` (optional): Emit the full command reference + protocol cheatsheet as one LLM-ready markdown document Values: `true`, `false`. ### `labcoat doctor` Diagnose the environment (toolchain, ports, binaries, project state) ```text doctor ``` ## MCP mode `labcoat mcp serve` exposes the same operations over stdio using MCP protocol version `2024-11-05`. | Tool | Description | |---|---| | `devnet_up` | Boot the full Alkanes devnet stack (downloads binaries when missing). Returns service status and the endpoint manifest. | | `devnet_down` | Stop all devnet services. | | `devnet_status` | Devnet service health, block height, and mempool size. | | `devnet_mine` | Mine blocks on the devnet. | | `devnet_fund` | Send BTC from the devnet faucet wallet to an address. | | `devnet_reset` | Stop services and wipe all devnet chain data. | | `devnet_logs` | Recent devnet service logs. | | `wallet_init` | Create or load the project wallet keystore. Optional mnemonic (else generated). | | `wallet_addresses` | Wallet receive addresses per script type. | | `wallet_utxos` | Spendable wallet UTXOs. | | `compile` | Compile Cargo contract packages and extract their Wasm-exported ABIs. | | `test` | Build every contract for WASIp1 and run host integration tests; the first build may take several minutes. | | `abi_fetch` | Fetch ABI metadata from a deployed contract through Metashrew. | | `abi_verify` | Compare a deployed ABI with a locally built contract package. | | `deploy` | Deploy a compiled contract (raw .wasm) via commit/reveal. Records it in labcoat.lock. | | `call` | Execute a state-changing contract call and wait for its trace. | | `simulate` | Read-only simulation of a contract call (no transaction). | | `trace` | Decoded protostone traces for a transaction. | ## Error codes | Code | Meaning | Recovery | |---|---|---| | `CONFIG_INVALID` | configuration is invalid | run `labcoat doctor` | | `WALLET_MISSING` | the project wallet does not exist | run `labcoat wallet init` | | `WALLET_LOCKED` | the keystore could not be unlocked | set `LABCOAT_WALLET_PASSPHRASE` | | `RPC_UNREACHABLE` | the configured gateway cannot be reached | run `labcoat status` | | `INDEXER_LAG` | indexed height did not catch chain height | inspect metashrew logs | | `INSUFFICIENT_FUNDS` | spendable BTC cannot cover the operation | fund the wallet and mine a block | | `EXECUTION_REVERT` | the contract explicitly reverted | inspect the revert reason and trace | | `TRACE_TIMEOUT` | a decoded trace did not arrive in time | retry `labcoat trace --wait` | | `ENVELOPE_INVALID` | an Alkanes transaction envelope is invalid | check the contract and arguments | | `COMPILE_FAILED` | Rust or WebAssembly compilation failed | read stderr and run `labcoat doctor` | | `PACKAGE_NOT_FOUND` | the requested Cargo contract package was not discovered | run `labcoat compile` or pass a package listed in the error | | `ABI_MISMATCH` | local and deployed __meta output differ | compile the deployed source revision and verify the contract ID | | `CONTRACT_NOT_FOUND` | a contract name or ID could not be resolved | run `labcoat lock show` | | `TOOLKIT_ERROR` | the underlying contract toolkit failed | read the error hint | | `BINARY_CRASH` | a managed devnet service exited | inspect `labcoat logs` | ## Protocol cheatsheet - **Cellpack**: [block, tx, opcode, ...args] as u128 values; strings up to 16 bytes are packed little-endian. - **Deploy**: Targets [1, 0]; raw Wasm is compressed inside a taproot commit/reveal envelope. - **Protostone outputs**: Trace output for protostone i is transaction.output.len + 1 + i; Labcoat computes it automatically. - **Synchronization**: State-changing operations wait until the Alkanes index reaches chain height before reading fresh state. - **labcoat.lock**: Per-network deployment ledger mapping names to Alkanes IDs, Wasm hashes, transaction IDs, and status. - **Contract ABI**: Compile and test execute the Wasm __meta export locally; abi fetch and abi verify use Metashrew only for explicit deployed-bytecode inspection. ## alkanes-rs pin All alkanes-rs code paths are pinned to commit `5b7f43567b828d0bb7b8907ce78fa0242943c54d` on the `develop` branch. See TOOLCHAIN.md before changing the pin. --- JSON errors use stable codes and always include a next-step hint. | Code | Meaning | First response | | --- | --- | --- | | `CONFIG_INVALID` | Project or environment configuration is invalid | Run `labcoat doctor` | | `WALLET_MISSING` | No project wallet exists | Run `labcoat wallet init` | | `WALLET_LOCKED` | Passphrase is missing or incorrect | Set `LABCOAT_WALLET_PASSPHRASE` | | `RPC_UNREACHABLE` | The configured gateway cannot be reached | Run `labcoat status` | | `INDEXER_LAG` | Indexed height did not reach chain height | Inspect metashrew logs | | `INSUFFICIENT_FUNDS` | Spendable BTC cannot cover the transaction | Fund and mine the wallet | | `EXECUTION_REVERT` | The contract explicitly reverted | Inspect `revertReason` and trace | | `TRACE_TIMEOUT` | A decoded trace did not arrive in time | Retry `labcoat trace --wait` | | `COMPILE_FAILED` | Rust or Wasm compilation failed | Read stderr and run `labcoat doctor` | | `CONTRACT_NOT_FOUND` | Name or ID could not be resolved | Run `labcoat lock show` | | `BINARY_CRASH` | A managed devnet process exited | Inspect service logs | Do not parse the human message to branch automation. Branch on `error.code` and surface `error.hint` to the operator or agent. --- ## Cellpacks An Alkanes call is encoded as `[block, tx, opcode, ...args]`, where each value is a `u128`. Short string arguments are packed little-endian into one `u128`. ## Deployment envelopes Deployment targets cellpack `[1, 0]`, meaning “create a new alkane.” The raw Wasm module is compressed and placed in a taproot witness envelope across a commit/reveal transaction pair. ## Contract IDs The create trace returns the contract’s `block:tx` ID. Labcoat records it under the chosen contract name in `labcoat.lock`, so later calls can use either form. ## Protostone outputs Trace events attach to virtual outputs. For protostone index `i`, the output is: ```text transaction_output_count + 1 + i ``` `labcoat trace` performs this mapping automatically. ## Index synchronization State-changing operations wait until the Alkanes index height reaches the chain height before reading new state. `INDEXER_LAG` means that bounded wait expired; inspect `labcoat status` and `labcoat logs --service metashrew`.