Working with the source alpha

A small guide to
real experiments.

Start with the bundled replay, then bring a reviewed local Git product. These commands describe implemented behavior and expose the current limits.

Quick start

The reproducible entry point is the source build. Use Git, stable Rust/Cargo, Node.js 22+ and pnpm 10. Build the dashboard before installing so release-mode RustEmbed includes the current assets.

Build and install the canonical CLI
git clone https://github.com/OthmaneBlial/GrowthLab.git
cd GrowthLab
pnpm -C ui install --frozen-lockfile
pnpm -C ui build
cargo install --path . --bin growthlab --locked
growthlab demo

On macOS, configured validation requires /usr/bin/sandbox-exec. Its runtime policy has passed local checks on the development host. Linux requires /usr/bin/bwrap and permitted unprivileged namespaces; native Linux runtime behavior is still unverified. Windows validation isolation is not implemented.

This is a source alpha. A passing macOS build does not establish Linux or Windows runtime support, provider authorization, signing, notarization or production readiness. Check any published prerelease notes for its exact platform and limits.

For an uninstalled source checkout, replace growthlab with cargo run --locked --bin growthlab --. The retained orx binary is a compatibility entry point; public workflows use growthlab.

Run without opening a browser automatically
growthlab demo --no-browser

The demo prints a loopback URL and keeps its server running until Ctrl-C. No Docker, agent API key or provider request is required by this declared replay.

Download and verify

GrowthLab ships source first. The current v0.1.0-alpha.20 source prerelease includes a manually validated macOS arm64 CLI archive plus macOS x86_64, Linux x86_64 musl, Linux arm64 musl and Windows x86_64 GNU archives. The public release now also carries cargo-dist-compatible names, checksums, and shell/PowerShell installers; the read-only verifier checks all ten archive/checksum pairs and the local macOS shell-install smoke passed. All are unsigned and not notarized; Linux and Windows runtime and installer proof remain pending.

Build and verify a local archive
scripts/package-cli-archive.sh
scripts/verify-release-archive.sh dist/archives/growthlab-v0.1.0-alpha.20-macos-arm64.tar.gz

The archive verifier is offline. It checks the checksum, rejects traversal and unexpected links, requires the MIT, OpenResearch and dependency notices, and executes the binary only when the target matches the current machine. See the distribution guide ↗ for the target matrix and release limits.

The bundled demo

growthlab demo creates an original fictional PatchKit homepage, a private local Git baseline and three competitor worktrees. Its proposals are declared replay input. The edits, commits, command execution and sealed evidence are real.

Competing approachStructure / links / claimsReview status
Outcome-first positioningExit 0 / 0 / 0Eligible
Proof beside the promiseExit 2 / 0 / 0Ineligible: primary heading removed
Faster first successExit 0 / 0 / 0Eligible

The intended heading failure makes the overall battle status failed. It does not discard the two eligible alternatives. Missing prerequisites or interrupted execution can produce different results; those actual outcomes stay visible.

Open individual check fractions, inspect logs and change records, and review the candidate source and archive digests. No candidate is automatically selected or applied. The demo retains only its newly owned fictional repositories and evidence under the active data root for inspection.

How to read it: replay proposals are SIMULATED, deterministic checks are OBSERVED, and growth outcomes are UNTESTED. These fixture commands are not accessibility certification, performance scores or conversion evidence. The same experiment loop applies to onboarding, pricing and launch work.

Audit one page

Review one local HTML page or one public HTTPS page without preparing a battle. Both paths use the same explainable SEO page-hygiene rubric shown in the dashboard.

Run a page audit
growthlab seo-audit --html ./website/index.html
growthlab seo-audit --html ./website/index.html --format markdown
growthlab seo-audit --url https://example.com/pricing --format markdown

The result exposes eight structural dimensions: title, description, headings, language, useful copy, canonical URL, useful links and image descriptions. Every score is ESTIMATED and tied to direct observations. Partial or missing signals include concrete next steps for the page review. Battle comparisons also show a separate 30-point Page quality hints record for mobile viewport, named controls, form labels, loading sources and claim guardrails. It is source-level guidance, not a Lighthouse score, timing trace, screen-reader audit or accessibility certification.

URL analysis is read-only: it checks same-origin robots.txt, makes one bounded HTTPS request, follows no redirects and sends no credentials. Local files are regular UTF-8 inputs up to 4 MiB. Neither path claims rankings, traffic, conversions, accessibility certification or performance results.

Review a public repository

Inspect one canonical GitHub URL before you bring product context locally. The review reports public description, default branch, license and archive/fork flags as OBSERVED metadata. After reviewing it, you can explicitly clone into a new local folder and register a workspace; an existing growthlab.yaml is preserved, and a missing contract can be supplied locally.

Read public metadata
growthlab repo-audit --url https://github.com/owner/product --format markdown

The request is unauthenticated, bounded, read-only and redirect-free. Credentials, query strings, fragments, non-GitHub hosts and .git URLs are refused. No source files are cloned, executed or registered by the review. For an explicit checkout, use growthlab workspace import-url --url https://github.com/owner/product --path ./product; the destination must be new, no push occurs, and any generated contract is committed only locally. For a starting context without a checkout, use growthlab workspace brief --name … --audience … --goal …; the generated workspace remains local and analysis-only.

Repository metadata is not product, market or growth evidence. GrowthLab does not infer stars, traffic, adoption, rankings, conversion or revenue.

Measure locally

Summarize a user-supplied CSV export without contacting an analytics provider. Each row is one numeric observation; variant and value are required, while metric, distribution and timestamp are optional.

Compare local observations
growthlab measure --csv ./telemetry.csv --format markdown
growthlab measure --csv ./telemetry.csv --baseline control --metric qualified_signup

The report exposes means, sample sizes, totals, arithmetic differences from the supplied baseline, an optional date range and exploratory 95% intervals when samples allow. A distribution or channel column keeps each source baseline separate; without it, rows use the all distribution. Use the same summary in the dashboard's Measure locally panel or from the CLI. It is labelled MEASURED because the values come from your file; it does not establish attribution, causality, statistical significance, rankings, traffic, revenue or conversion lift.

The importer is local and bounded: regular UTF-8 files up to 8 MiB, quoted CSV fields, limited rows and columns, no network request. A missing timestamp or baseline is reported as a limitation rather than filled with invented data.

Choose a growth angle

GrowthLab includes ten reusable role contracts for focused growth work: strategist, researcher, positioning, conversion, ethical SEO, onboarding, pricing, launch, evaluator and skeptic.

RoleFocusOutput
StrategistChoose a tractable growth questionBrief, hypothesis tree and decision rule
ResearcherCollect permitted factsEvidence records and claim map
PositioningMake value easy to understandMessages and claim checklist
ConversionRemove uncertainty before actionPage hierarchy and CTA alternatives
SEOMatch useful pages to search intentIntent brief and local audit steps
OnboardingShorten the path to first valueFirst-value map and quick start
PricingExplore packaging safelyValue hypotheses and guardrails
LaunchPrepare a truthful channel narrativeDrafts, proof links and checklist
EvaluatorApply a stable rubricInspectable scores and rationale
SkepticTry to falsify the claimCounter-hypotheses and evidence gaps

Read the catalog without side effects, or run a role contract inside a registered workspace. growthlab playbook run <project-id> seo --answer "Qualified developer visitors" and POST /api/growth/workspaces/{id}/playbooks/{role} save an inspectable local run with ordered answers, outputs and guardrails. Missing answers stay Unknown; every run is UNTESTED with low confidence. No provider, analytics, product file or publication is touched.

Bring your product

Import supports a local Git repository root with a checked-out branch and committed context, or a local folder with the explicit --init-git option. Public repository review and manual briefs are available from Home. repo-audit reads one unauthenticated GitHub metadata response without cloning or executing source; workspace brief creates a private local analysis snapshot with no remote or provider request.

Create an implementation contract with explicitly allowed paths and real validation commands. init atomically creates a new file and refuses to overwrite one.

Create a product contract
growthlab init --path /path/to/product \
  --name Acme --audience 'Open-source maintainers' \
  --goal 'Increase qualified signups' \
  --mode implementation --allow website/ \
  --deny infra/production/ \
  --validate 'pnpm test' --validate 'pnpm build'
growthlab config check --path /path/to/product

Review growthlab.yaml before importing. Secrets never belong in this file. Existing Git repositories require the on-disk configuration to agree with the committed one. For a non-Git folder, opt into a local snapshot explicitly:

Import and inspect a local workspace
growthlab workspace import --path /path/to/product
# only for a folder without Git
growthlab workspace import --path /path/to/product --init-git
growthlab workspace list
growthlab workspace view <project-id>
growthlab hypotheses <project-id>

The explicit option creates one local main commit after rejecting protected paths such as credentials and .env; it configures no remote and never auto-commits an existing repository. Initial hypothesis templates are UNTESTED and low confidence; they are not proof that a native agent or external researcher ran.

The experiment map groups hypotheses by role and keeps each persisted hypothesisId visible through battle comparisons and exported reports, so a reviewer can follow the same branch from idea to archived evidence.

Permission modes

ModeWhat it permits
analyze_onlyNo product file changes.
draftLab artifacts; no product file changes.
implementationOnly allowed paths, in isolated competitor worktrees. Requires an allowed path and a validation command.
Selected applyA separate explicit delivery action. Configuration never grants automatic product push or deployment.

Allowed and denied paths are relative prefixes, not globs. Denials win. Traversal, absolute paths, symlinks, .git, credential files and protected namespaces are refused.

Run and compare

Battle preparation freezes one imported commit, configuration and validation contract. Three lab-owned branches and worktrees start from that same source. Continuing to work on your product does not move an existing battle’s baseline.

Prepare without executing
growthlab battle 'Improve qualified activation' \
  --project <project-id> --prepare-only
growthlab experiments --project <project-id>
growthlab battle-status <battle-id>

Use the bundled demo first. For your own deterministic replay, the plan is a versioned JSON file containing exactly three ordered implementations with summaries, allowed file edits and stated risks. The full battle guide documents its schema and conservative size limits.

Execute a declared replay and inspect results
growthlab run <battle-id> --replay /path/to/plan.json
growthlab battle-status <battle-id>
growthlab compare <battle-id>

Configured commands execute against content-addressed immutable candidate source archives, with bounded logs and enforced timeouts. They do not run against a mutable agent checkout. The command pass fraction is individually inspectable; eligibility requires every exact command to pass on one successful sealed attempt.

Terminal battles are not silently rerun or overwritten. Make a new battle for a new attempt. Inspect battle status even when orchestration exits zero: a failed configured command is part of the recorded outcome.

Native-agent status: the inherited registry preserves Claude Code, Codex, OpenCode and Cursor adapters. Current strict tools-disabled proposal capability is declared only by Claude Code. Native battle execution is unverified in this environment; adapter detection does not prove provider support.

Static previews

Opt in for a static landing page before preparing a battle. root is relative to the product repository; entry is relative to that root and ends in .html.

Optional growthlab.yaml section
static_preview:
  root: website
  entry: index.html

The CLI also accepts --preview-root website --preview-entry index.html on init. Review and commit the contract before import. The bundled demo already opts in.

After implementation is committed, Rust archives permitted candidate Git objects, a self-contained document and source metadata. The dashboard’s Static preview tab displays that verified document at desktop 1280 × 900 or phone 390 × 844 CSS dimensions, scaled to fit the inspector. When a local Chromium-compatible browser is available, the engine also archives verified desktop and phone PNGs at preview/screenshot-desktop.png and preview/screenshot-phone.png with their dimensions, sizes and SHA-256 values in the metadata. It records optional renderChecks for viewport coverage, visible text length, horizontal overflow and local navigation/paint timings; these are OBSERVED inspection traces of the sanitized document, not Lighthouse, Core Web Vitals, accessibility, visual-regression, real-user or growth evidence. Sealed comparison rows summarize them with the decomposable static-render-hints-v1 rubric when both viewports are available, plus the browser-timing-hints-v1 rubric when timing entries are present. The timing rubric is a local heuristic; when file:// exposes no paint entry, first paint uses a first-rendered-frame proxy.

  • Supported sources: HTML, CSS, PNG, JPEG, GIF, WebP, WOFF and WOFF2.
  • Limits: 128 source files, 4 MiB per file, 8 MiB total source and a 4 MiB packaged document.
  • Scripts, frames, forms, event handlers and navigation are removed. External, unsupported and cyclic resources are omitted.
  • A restrictive archived CSP and an opaque, inert frame with an empty sandbox prevent interaction and script execution.
  • Missing, denied, oversized or unsafe input records an unavailable preview. No render is fabricated.

This is a live browser view of archived static source. A captured PNG is a render artifact, not a visual quality result or measured growth outcome. It shows one viewport; content below the fold can be clipped. Dynamic apps, SVG assets and CSS image-set() string sources are not reproduced. Preview availability does not change candidate eligibility.

Selected delivery

Delivery uses a verified, eligible sealed candidate. A failed candidate cannot be selected, exported or applied. An explicit selection records your decision; it does not change product files.

Review, select and preview
growthlab compare <battle-id>
growthlab select <variant-id>
growthlab apply <variant-id> --check

Apply preview lists changed paths and the patch digest without modifying the product. Actual apply requires the frozen source HEAD, unchanged configuration and a clean ordinary checkout/index. Dirty, staged, untracked, sparse, symlink, changed-policy and changed-baseline states are refused.

Explicitly deliver the selected change
growthlab apply <variant-id>
# Review the resulting product diff before committing it yourself.

GrowthLab does not automatically commit, merge, push or deploy. Apply copies only the selected patch to the product working tree. You review it and use your normal Git workflow.

Export a portable patch instead
growthlab export <variant-id> \
  --output /path/outside/product/selected.patch

Export uses exact committed objects verified against sealed artifacts. Mutable variant branches cannot supply its contents. The parent directory must exist, the destination must be new and outside product/variant checkouts. Existing files and dangling symlinks are refused; Unix output files are owner-private.

Private reports

HTML and Markdown reports are self-contained offline summaries. They include actual command failures, eligibility, selected candidate, diffs, provenance and reproducibility digests. Default reports withhold private names, goals, paths, model identifiers, prompt text, command text and raw logs.

Export a private-context-free summary
growthlab report <battle-id> \
  --output /path/outside/product/battle.html
growthlab report <battle-id> --format markdown \
  --output /path/outside/product/battle.md

A report never changes selection. It works offline without external fonts, JavaScript or network requests. Tampered evidence refuses generation. Create-only owner-private file output follows the same rules as patch export.

Disclose context intentionally

--public-goal discloses only a goal you explicitly provide. --include-context approves disclosure of configured goals, variant titles, implementation summaries and command text; review that exported file before sharing. Full prompts and raw logs are never copied. --without-attribution removes the optional footer.

Share a deliberately chosen public goal
growthlab report <battle-id> --output battle.html \
  --public-goal 'Compare three activation approaches'

Visual privacy: reports do not include candidate source documents or renderings by default. The local candidate inspector exposes verified desktop and phone PNGs when browser capture succeeds; pass --include-visuals to the CLI or includeVisuals=true to the report API when you explicitly want those archived captures embedded. Documentation screenshots are separate from run archives.

Read the evidence

A useful experiment explains how it knows what it knows. These provenance categories remain distinct in domain records and exported results.

MEASURED
Computed from connected real telemetry. The current demo has no such outcome data.
OBSERVED
Produced by a deterministic check or direct inspection, such as an actual exit code or verified page view.
ESTIMATED
A model or rubric estimate with stated assumptions. It is not an objective measurement.
SIMULATED
A declared simulation, such as the demo’s ordered replay proposals.
UNTESTED
No outcome evidence yet. This remains the growth-outcome status of current replay candidates.

Passing all configured commands makes a candidate eligible for review. A command pass fraction does not establish copy clarity, accessibility, performance or conversion lift. Multiple eligible candidates require your judgment; there is no unexplained aggregate score or measured Winner.

Sealed archives bind the frozen contract, proposal context, candidate changes, command logs and policy metadata with SHA-256 digests. Readers verify archived evidence rather than trusting mutable checkout content. Raw CLI JSON and local archives can contain private product context; sanitized report exports are the sharing boundary.

Cancel and recover

Cancellation persists intent for the active battle. Failed and cancelled attempts remain inspectable.

Cancel an owned battle
growthlab battle-status <battle-id> --cancel

Explicit recovery acquires the controller lease and verifies retained checkpoints and seals. It never reruns a provider or validation command, resets a worktree or applies a patch.

Inspect interrupted execution
growthlab battle-status <battle-id>
growthlab recover <battle-id>
growthlab compare <battle-id>

When a registered command is still alive, recovery records waiting. Repeat after that same job ends. An interrupted attempt cannot become eligible just because a recovered command exited zero. Complete terminal checkpoints may recover their exact original seals; previously sealed siblings remain unchanged.

Unknown or incompletely registered launchers keep termination unverified. Stronger registration and interrupted selected-delivery recovery remain gates. Recovery does not guess or kill unrelated processes.

Safety and limits

Default implementation never authorizes production deployment, advertising purchases, email or social messages, live pricing/billing changes, production analytics mutations, repository pushes or customer-data access.

Local data

Default product data is under $XDG_DATA_HOME/growthlab or ~/.local/share/growthlab. Settings use the corresponding GrowthLab configuration namespace. GROWTHLAB_DATA_DIR can explicitly choose another data root. Existing OpenResearch defaults are not silently moved or reused.

Upstream telemetry is disabled in source builds. The upstream updater is refused. The inherited openresearch.sh companion is not a GrowthLab service; local product data is not redirected to it.

Validation isolation

Commands require a supported OS driver, can write their candidate snapshot and private scratch, and receive only approved read-only runtimes. Host network access and unrelated product data are blocked. Exact confinement policy digests accompany observed checks.

PlatformCurrent evidence
macOSLocal runtime checks passed using /usr/bin/sandbox-exec. Future OS compatibility is not promised.
LinuxBubblewrap implementation exists; native runtime verification is pending. User/network namespaces must be permitted.
WindowsValidation isolation is not implemented; validation is refused.

Configured validation dependencies must already be available offline in permitted paths. There is no CPU, memory or disk quota and no unrestricted execution fallback. A missing driver is refused; driver presence alone does not prove kernel permission or successful isolation.

Build with us

Use the repository’s dev-slot helper for isolated local development data, ports and owned processes. Its status prints the actual backend and dashboard URLs.

Start and stop the development dashboard
node scripts/dev-slot.mjs start --db empty
node scripts/dev-slot.mjs status
 node scripts/dev-slot.mjs stop

All six GrowthLab GitHub Actions workflows are manually disabled at the user’s request. Run relevant formatting, Rust, UI and real CLI checks locally. Keep the committed ui/dist current after UI changes.

Core local checks
cargo fmt --all -- --check
cargo test --locked
cargo clippy --all-targets -- -D warnings
pnpm -C ui build
cargo build --locked
python3 scripts/test-growth-demo.py target/debug/growthlab

The overall project estimate is about 95%, subjectively assessed against the full specification. Progress changes when behavior or verification changes; a source scaffold or passing test suite is not a complete-product claim.

Next work includes provider adapters, full visual regression/accessibility evaluation, native-agent verification, dynamic rubric evidence mapping, and broader target-platform release proof.