First Artifact
Create a complete HTML artifact, verify its durable revision, and choose a public or password-protected share.
This walkthrough creates a private static page, verifies that it is stored in a workspace revision, and then makes an explicit sharing choice. It uses the CLI so every step has a visible success signal.
Before you start
Complete Install. You need the desktop app, the managed grain command and a successful grain login. Use a new folder so the example does not upload unrelated files.
Copyable workflow
Create a page and publish it:
mkdir -p "$HOME/grain-first-artifact"
cd "$HOME/grain-first-artifact"
printf '%s\n' '<!doctype html><html><head><meta charset="utf-8"><title>First Grain artifact</title></head><body><h1>Hello from Grain</h1><p>This page is private until I choose to share it.</p></body></html>' > index.html
grain login
grain init --template html --name "First artifact" --no-open
grain push
grain checkpoint -m "first publish"
grain history --limit 1The commands do the following:
- The first three shell lines create a complete index.html in a disposable local folder.
- grain login authenticates through the desktop app. It does not publish anything.
- grain init creates a static workspace, links the current folder and uploads managed content. --no-open keeps the app from opening automatically. It may write the project agent configuration described in Integrations.
- grain push synchronizes any changes still present in the checkout. Expected human output includes
pushed <n> path(s); if init already uploaded the page, it may report that no additional change was needed. - grain checkpoint records the authored tree as durable history. Expected output is
checkpointed revision #<n>or checkout already matches the latest revision. - grain history --limit 1 verifies that a revision exists. A history revision is the durable-save signal; a local file or open preview alone is not.
Because this walkthrough uses --no-open, init returns the workspace ID, revision metadata and agent-wiring results but does not open or print a private workspace URL. Keep the ID for explicit inspection, then ask the Grain app to open the private preview:
grain --workspace <workspace-id> status
grain --workspace <workspace-id> metadata
grain --workspace <workspace-id> open
grain --workspace <workspace-id> history --limit 5grain open asks the running Grain app to open the selected workspace. The private preview is authenticated in the app; the command itself prints an app-handoff result rather than a public URL. If the app is not running, start it and retry. A history revision remains the durable-save signal, and no public share exists until you run the explicit share step below.
Make a delivery choice
Keep the artifact private while it is unfinished. When it is ready, choose one audience explicitly:
grain --workspace <workspace-id> share --publicExpected output includes a share URL such as https://<slug>.share.rungrain.com and a canonical workspace URL. Anyone with the public link can open it. For a password-protected link, keep the password out of the process argument list and shell history. The CLI accepts GRAIN_SHARE_PASSWORD through --password-env:
read -r -s GRAIN_SHARE_PASSWORD
printf '\n'
export GRAIN_SHARE_PASSWORD
grain --workspace <workspace-id> share --password-env
unset GRAIN_SHARE_PASSWORDA password share requires both the link and the password. The hidden prompt reads the password without echoing it; unset removes it from the current shell afterward. --password '<password>' is also supported for disposable test values, but exposes the value to local process inspection and should not be used for a real secret. The current CLI/MCP creation surface is public or password; named-person/invite access may exist elsewhere in the product UI but is not a documented CLI flag. MCP share calls accept a password as a tool input and pass it to the CLI through this environment flow. See Data and privacy for revocation and copy behavior.
Inspect and manage existing shares without guessing a URL:
grain --json --workspace <workspace-id> share list
grain --json --workspace <workspace-id> share update <share-id> --mode off
grain --json --workspace <workspace-id> share revoke <share-id>Edit and publish again
Edit index.html, then synchronize and checkpoint the same workspace:
grain --workspace <workspace-id> push
grain --workspace <workspace-id> checkpoint -m "update greeting"
grain --workspace <workspace-id> history --limit 2Use the same workspace ID and checkout. Do not create a second workspace just because a push or checkpoint was uncertain.
Recover safely
- Remote drift: If push says “The remote workspace changed since this folder was last synchronized”, run grain pull, inspect the preserved local changes, then push again. Do not use --force unless you have deliberately reviewed what it would replace.
- Missing checkpoint message: add -m "..." ; the message is required for a new checkpoint.
- Failed initialization: rerun with --keep-failed only when you need the partial workspace retained for inspection. If an uncertain request may have created a workspace, use grain list or the returned ID before retrying.
- Wrong audience: run share list, select the returned share ID and use share update --mode off or share revoke. Revocation prevents future access but cannot retract copies already downloaded.
- Runtime command on HTML: this template has no compute sandbox. Use App Runtime and promote to a runtime template if the artifact needs code execution.