Skip to content

Toolchain reference

Every subcommand of gos. Auto-generated output coming with Stream H polish - for now this page is hand-written and may lag the implementation by a rev.

Front-end

Command Purpose
gos parse FILE Print the AST.
gos check [--timings] FILE Parse + resolve + typecheck + exhaustiveness. With --timings, prints per-stage wall-clock times. Parse output is cached by source hash - re-invocations on an unchanged file reuse the parsed AST. Set GOSSAMER_CACHE_TRACE=1 to log cache hits.
gos run FILE Execute via the register-based bytecode VM. Recursive helper workloads may promote through the in-process Cranelift JIT.
gos watch [PATH] [--] [ARGS...] Validate and restart a development service when project inputs change. This is process replacement, not in-process code patching.
gos build [--release] [--target TRIPLE] FILE Produce a native binary (ELF/Mach-O/PE) by lowering through MIR + LLVM (llc -O0; --release runs the full opt -O3 | llc -O3 pipeline) and linking the user's .o against libgossamer_runtime.a. Release builds may use --pgo-collect PATH.profraw to emit an instrumented binary or --pgo-profile PATH.profdata to apply merged LLVM profile data; the modes conflict, profile input must exist, and an input older than the source produces a warning. The Cranelift code path is reserved for the in-process JIT (gos run), not this command. Tier 2 cross deployment is {x86_64,aarch64}-unknown-linux-musl, QEMU-differential-tested in CI. Other registered triples are not supported merely because a local link succeeds; macOS/Windows as cross targets are out of scope.

Formatting + linting + docs

Command Purpose
gos fmt [--check] FILE Rewrite canonically.
gos doc [--html OUT] FILE List items (plain-text) or write an HTML page.
gos lint [--deny-warnings] [--explain ID] [--fix] PATH Run the lint suite (50 lints). --fix writes auto-applicable suggestions back to disk; --explain ID prints long-form rationale.
gos explain CODE Long-form rationale for a diagnostic code.

Testing + benchmarking

Command Purpose
gos test PATH Run #[test] functions and doc-tests extracted from ```-fenced code inside // doc comments. ```text and other language tags are skipped. Accepts a file or a directory.
gos bench [--parallel N] [PATH] Discover and time #[bench] functions; reports ns/op plus JIT tier-up, compile-time, native-code, peak-RSS, and bypassed-VM-work counters. Per-bench iteration counts auto-tune against a 50 ms calibration window (cap 2^20). PATH defaults to the project's src/.

Watch

Command Purpose
gos watch [PATH] [--] [ARGS...] Validate and restart a development service when project inputs change. gos dev is accepted as a compatibility alias.

Housekeeping

Command Purpose
gos clean [--all] [--frontend] [--ir] [--runners] [--packages] [--build-cache] [--vendor] [--dry-run] Remove selected toolchain caches. With no cache-class flag it clears frontend and IR caches; --all includes Rust-binding runners, packages, and legacy build artifacts. --vendor also deletes ./vendor/.
gos cache [--path] [--prune] [--dry-run] Show cache roots and usage, print paths only, or prune files older than 30 days and files exceeding the configured total cap.

Package manager

Command Purpose
gos new ID [--path DIR] [--template bin|lib|workspace] Scaffold a project.
gos init ID Create project.toml in the CWD.
gos add SPEC Add a dependency (name or name@version).
gos remove ID Drop a dependency.
gos update Update locked dependencies within declared ranges.
gos tidy Remove unused project dependencies and canonicalise the manifest.
gos fetch Populate the local cache.
gos vendor Copy fetched deps into ./vendor/.

Registry workflow

Command Purpose
gos publish [--dry-run] Pack, Ed25519-sign, and upload the project to a registry. --dry-run packs + signs and prints metadata without uploading.
gos yank Yank a previously-published version.
gos login / gos logout Save / drop a registry bearer token in ~/.gossamer/credentials.toml.
gos owner Manage the publisher ACL of a published project.

REPL

gos with no arguments - or gos repl - drops into an interactive session. The first-slice supports:

  • Numbered In [N]: / Out[N]: prompts, coloured green / red when stdout is a TTY (ipython-style).
  • Declarations persisting across inputs (fn / struct / enum / use / const / type).
  • let bindings persisting across inputs; every subsequent expression sees previously-bound locals in scope. %bindings lists the active set.
  • Meta-commands %quit, %history, %bindings, %reset, %help, and %ls.
  • %help <symbol> shows stdlib module/item, language-feature, prelude builtin, or built-in macro documentation. Macro names retain their !, for example %help println!; %help /regex/ searches that same surface.
  • %ls lists stdlib modules; %ls <namespace-or-symbol> lists a module's items or matching symbols; %ls /regex/ filters stdlib modules/items.
  • Ctrl-D exits cleanly.

Stream K grows this to IPython parity (syntax highlighting, tab completion, persistent history file, %time / %timeit / %load / %save / %edit / %debug).

Editor integration

Command Purpose
gos lsp Start a language-server-protocol adapter on stdio.

gos lsp is intended for editors, not humans. Shipped capabilities:

  • textDocument/publishDiagnostics on didOpen / didChange - every open document runs through parse + resolve + typecheck and diagnostics are published inline.
  • textDocument/hover - renders a small markdown card with the identifier under the cursor and its interned type when the type checker can resolve it.
  • textDocument/definition - jumps to the declaring item for identifiers that resolve to a top-level fn / struct / enum / trait / type / const / static / mod.
  • textDocument/completion - completion provider for top-level items and keywords in scope.
  • textDocument/references - every whole-word occurrence of the symbol under the cursor, in the same document. Matched syntactically; shadowed locals are reported alongside the real references until the semantic use-to-def map lands.
  • textDocument/prepareRename + textDocument/rename - returns a WorkspaceEdit that renames every occurrence of the symbol in the file. Rejects non-identifier newName inputs.
  • textDocument/inlayHint - emits a : <type> ghost-text hint after every let binding and closure parameter whose type the user did not spell out. Same shape rust-analyzer uses for Rust.

Editors should launch gos lsp over stdio and speak LSP 3.16 with textDocumentSync=Full (incremental edits land in a follow-up).

Pre-built editor integrations

Plug-ins that wire gos lsp into common editors live in a separate repo: danpozmanter/gossamer-editor-support - ships VSCode, Vim, Neovim, Helix, Emacs, Sublime, Zed clients plus a tree-sitter grammar.

Agent integration

Command Purpose
gos mcp Start a model-context-protocol server on stdio.

gos mcp speaks the Model Context Protocol so AI coding agents (Claude Code, OpenCode, Cursor, Zed) can drive the toolchain directly:

  • check - parse + resolve + typecheck; one JSON object per diagnostic (the --message-format json schema).
  • explain - long-form rationale for a diagnostic code.
  • run / build / test - execute programs and test suites; exit code, stdout, and stderr come back, bounded by a per-call timeout_ms.
  • fmt / doc - formatting and item listings.
  • hover / definition / references / workspace_symbols - semantic navigation backed by the same analysis engine as gos lsp.
  • The skill card ships as the gossamer://skill-card resource and the skill-card prompt.

MCP framing is newline-delimited JSON-RPC; LSP framing is Content-Length-headed. gos lsp belongs in an editor's LSP configuration and gos mcp in an agent's MCP configuration - the two are not interchangeable.

Claude Code:

claude mcp add gossamer -- gos mcp

Generic client config:

{ "mcpServers": { "gossamer": { "command": "gos", "args": ["mcp"] } } }

Smoke-test

python3 - <<'PY'
import json, subprocess
p = subprocess.Popen(["gos", "lsp"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
body = json.dumps({"jsonrpc": "2.0", "id": 1, "method": "initialize",
                   "params": {"processId": None, "capabilities": {}}}).encode()
p.stdin.write(f"Content-Length: {len(body)}\r\n\r\n".encode() + body); p.stdin.flush()
print(p.stdout.readline(), p.stdout.readline())
PY