Truestamp CLI

Standalone Go CLI for cryptographic timestamping with Truestamp. Verifies Truestamp proof bundles end to end — user claims, hash chains, Merkle inclusion, Ed25519 signatures, and public-blockchain commitments — with no dependency on the Truestamp service.
Ships as a single static binary. No runtime required.
Install
Install script (macOS, Linux)
curl -fsSL https://get.truestamp.com/install.sh | sh
The script detects your OS/architecture (darwin/linux × amd64/arm64), resolves the latest release, verifies the SHA-256 checksum, installs the binary to /usr/local/bin (or ~/.local/bin if the former isn't writable), and clears the macOS quarantine attribute so the binary runs without a Gatekeeper prompt. Upgrade by re-running the same command.
Pin a specific version:
curl -fsSL https://get.truestamp.com/install.sh | TRUESTAMP_VERSION=v0.1.6 sh
Install to a custom directory:
curl -fsSL https://get.truestamp.com/install.sh | TRUESTAMP_INSTALL_DIR=~/bin sh
Landing page with these same instructions: get.truestamp.com.
Homebrew (macOS and Linux)
brew install truestamp/tap/truestamp-cli
Upgrades:
brew upgrade truestamp/tap/truestamp-cli
macOS Gatekeeper note. The binary is not yet signed with an Apple Developer ID, so the first time you run truestamp after a brew install or brew upgrade macOS will show a dialog titled "truestamp" Not Opened and kill the process. Clear the quarantine attribute once per install to avoid it:
xattr -cr "$(brew --caskroom)/truestamp-cli"
The same instruction is printed by brew as a caveat on install. Signed and notarized builds are on the roadmap; once they ship this step will not be needed.
Go install
go install github.com/truestamp/truestamp-cli/cmd/truestamp@latest
Produces a binary at $GOBIN/truestamp (default ~/go/bin/truestamp). Requires Go 1.22 or newer.
The /cmd/truestamp suffix is required so the go toolchain names the binary truestamp rather than truestamp-cli (Go derives the binary name from the package path's last element).
Direct download
Grab the archive for your platform from the Releases page:
truestamp-cli_<version>_darwin_arm64.tar.gz — Apple Silicon
truestamp-cli_<version>_darwin_amd64.tar.gz — Intel Mac
truestamp-cli_<version>_linux_amd64.tar.gz
truestamp-cli_<version>_linux_arm64.tar.gz
truestamp-cli_<version>_windows_amd64.zip
truestamp-cli_<version>_windows_arm64.zip
Extract and place truestamp somewhere on your PATH. Verify checksums.txt with sha256sum -c before running.
Quick start
truestamp verify proof.json
Exit code 0 on success, 1 on failure or structural error.
Offline verification (no network calls to Truestamp, Stellar, or Bitcoin APIs):
truestamp verify proof.json --skip-external
Silent mode for scripting:
truestamp verify proof.json --output silent && echo valid || echo invalid
Other input sources:
truestamp verify https://example.com/proof.json # URL
truestamp verify --file # Interactive file picker
truestamp verify --url # Interactive URL prompt
cat proof.json | truestamp verify # stdin pipe
Commands
truestamp verify [proof] Verify a Truestamp proof bundle
truestamp config path Print the config file path
truestamp config show Print the resolved configuration (API key masked)
truestamp config init Create a default config file
truestamp version Print detailed build and runtime info
truestamp --version Terse one-line version
truestamp completion <shell> Generate shell completions (bash, zsh, fish)
Run truestamp <command> --help for per-command flags.
Configuration
Settings are resolved in this order (later overrides earlier):
- Compiled defaults
- Config file (
~/.config/truestamp/config.toml by default)
- Environment variables (
TRUESTAMP_*)
- CLI flags
Global flags
| Flag |
Env var |
Default |
--config |
|
~/.config/truestamp/config.toml |
--api-url |
TRUESTAMP_API_URL |
https://www.truestamp.com/api/json |
--api-key |
TRUESTAMP_API_KEY |
|
--keyring-url |
TRUESTAMP_KEYRING_URL |
https://www.truestamp.com/.well-known/keyring.json |
--http-timeout |
TRUESTAMP_HTTP_TIMEOUT |
10s |
--no-color |
NO_COLOR |
false |
Verify-specific flags
| Flag |
Env var |
Default |
--file [path] |
|
|
--url [url] |
|
|
--hash |
|
|
--silent / -s |
TRUESTAMP_VERIFY_SILENT |
false |
--json |
TRUESTAMP_VERIFY_JSON |
false |
--skip-external |
TRUESTAMP_VERIFY_SKIP_EXTERNAL |
false |
--skip-signatures |
TRUESTAMP_VERIFY_SKIP_SIGNATURES |
false |
What gets verified
- Signing key against the published keyring
- Proof structure (required fields, block reference)
- Subject hash — claims hash (
0x11), timestamp validation, item hash (0x13)
- RFC 6962 Merkle inclusion proof against the block root
- Block hash (
0x32) derivation
- Epoch proofs: block hash → each public-blockchain commitment root
- Ed25519 proof signature over the binary payload
- Temporal ordering (item submission before block)
- Stellar commitment via Horizon API (memo + ledger)
- Bitcoin commitment via local crypto (OP_RETURN, txid, partial Merkle tree) plus optional Blockstream API
Skipped selectively with --skip-external and --skip-signatures.
Development
This repo uses mise for tool versions and Task for the developer workflow.
mise install # Installs Go and GoReleaser from .tool-versions
task build # Build for current platform → build/truestamp
task test # Run all tests
task precommit # fmt + vet + test + build-all
task release-snapshot # Local GoReleaser dry-run → dist/
The Go module path is github.com/truestamp/truestamp-cli; releases are tagged vX.Y.Z and drive both the GitHub Release and the Homebrew Cask publication to truestamp/homebrew-tap via GoReleaser.
Cutting a release (maintainer)
Releases are driven entirely by a git tag matching v*. Pushing the tag triggers .github/workflows/release.yml, which runs GoReleaser to build the six platform archives, generate checksums.txt, publish a GitHub Release, and commit an updated cask to truestamp/homebrew-tap.
Prerequisites (one-time)
- Repository secret
HOMEBREW_TAP_GITHUB_TOKEN on truestamp/truestamp-cli with contents:write on truestamp/homebrew-tap. Without it, the release job fails at the cask publication step.
mise install locally so task release-check and task release-snapshot work for pre-flight testing.
Pre-flight checklist
# Working copy is clean and on top of the latest origin/main.
jj git fetch
jj log -r 'main@origin..@' # expect 0 commits not on origin
# All quality gates pass.
task precommit # fmt + vet + test + build-all
# GoReleaser can build the full artifact set with ldflags intact.
task release-check # validates .goreleaser.yaml
task release-snapshot # rm -rf dist/ && goreleaser release --snapshot --clean
# Inspect the generated cask before tagging.
cat dist/homebrew/Casks/truestamp-cli.rb
Update CHANGELOG.md
Move entries from ## [Unreleased] into a new section for the version you're about to cut. Use today's date and the Keep a Changelog grouping (Added / Changed / Fixed / Removed). Add a matching link reference at the bottom.
## [Unreleased]
## [0.2.0] — 2026-04-20
### Added
- ...
Commit and push the CHANGELOG
This repo is a jj colocated workspace. Commit the CHANGELOG edit as a normal change and advance main:
jj describe -m "Prep release v0.2.0"
jj bookmark move main --to @
jj git push --bookmark main
Tag and push
jj doesn't create annotated tags itself — use the git CLI in the same working copy (the jj repo is colocated with .git/):
git tag -a v0.2.0 -m "v0.2.0 - one-line summary of the headline change"
git push origin v0.2.0
The tag must point at the exact commit that main now holds, and must start with v so GoReleaser's trigger (push: tags: ['v*']) fires.
Watch the release
# Stream the run to completion.
run_id=$(gh run list --workflow=release.yml --limit 1 --json databaseId -q '.[].databaseId')
gh run watch "$run_id" --exit-status
# Verify artifacts landed.
gh release view v0.2.0 --json tagName,assets -q '{tag: .tagName, assets: (.assets | length)}'
# Expect: 6 platform archives + checksums.txt = 7 assets.
# Confirm the tap cask updated.
gh api repos/truestamp/homebrew-tap/contents/Casks/truestamp-cli.rb -q '.content' | base64 -d | head
Smoke-test the three install channels
# Homebrew (macOS / Linux).
brew update
brew upgrade truestamp/tap/truestamp-cli
# First run on macOS needs the Gatekeeper xattr workaround — see README.
xattr -cr "$(brew --caskroom)/truestamp-cli"
truestamp version # should show 0.2.0
# Go install.
go install github.com/truestamp/truestamp-cli/cmd/truestamp@v0.2.0
truestamp version # shows v0.2.0 via debug.ReadBuildInfo
# Direct tarball.
curl -sSL "https://github.com/truestamp/truestamp-cli/releases/download/v0.2.0/truestamp-cli_0.2.0_$(uname -s | tr A-Z a-z)_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar -xz
./truestamp version
If the release fails partway
GoReleaser is mostly idempotent, but a partial failure (e.g., tap push rejected) leaves the GitHub Release in place while the tap cask is out of date. To redo cleanly:
# Roll back the failed release.
gh release delete v0.2.0 -y
git push origin :refs/tags/v0.2.0
git tag -d v0.2.0
# Fix the problem in a new commit, push to main, then retag from the fixed commit.
git tag -a v0.2.0 -m "v0.2.0 - ..."
git push origin v0.2.0
Do not re-tag a version that's already propagated to proxy.golang.org — the proxy caches tagged module versions forever. Bump the patch version (v0.2.1) instead.
License
MIT. See LICENSE.
Copyright (c) 2021-2026 Truestamp, Inc. All rights reserved.