@tenderprompt/cli
v0.1.39
Published
Command-line tools for managing Tender App projects from a local checkout.
Readme
Tender CLI
Command-line tools for managing Tender App projects from a local checkout.
The CLI is built for humans and local coding agents. The agent runs locally, edits files locally, and uses normal Git plus explicit Tender API commands for auth, preview, build, and publish. The CLI does not send prompts or chat messages to Tender.
Install
npm install -g @tenderprompt/cliThen run:
tender --version
tender capabilities --jsonWhat You Can Do
Use the CLI to work with Tender Apps from a local checkout or coding-agent session:
- sign in with a bounded device token and optional artifact scope
- print the installed CLI package version with
tender --version,tender -v, ortender version --json - list, create, and rename apps
- bootstrap a local app checkout with Tender project context
- configure the Tender artifact Git remote and credential helper
- discover the current CLI command surface with
tender capabilities --json - preview outbound HTTP binding files without writing them
- validate app source locally before pushing
- build and preview a commit through the Tender API
- publish only after a dry run or explicit
--confirm publish - inspect artifact-scoped analytics without SQL or platform credentials
- inspect artifact-scoped app database tables, schema, and bounded read-only query output
- create private app admin dashboard, resource, view, and widget definitions from structured app database specs
- share app setup between Tender accounts without copying customer data, analytics history, app database rows, secrets, or release history
- run server-validated chart specs and export aggregate rows
- generate starter analytics suggestions
- print a non-mutating default analytics provisioning plan for generated apps
- create, list, update, and delete saved analytics dashboards and charts, with
--dry-runavailable for write previews
The CLI is deterministic by design: every workflow has a non-interactive flag
path, supports --json where automation needs structured output, and avoids
interactive prompts unless the command is explicitly an auth flow.
Typical Flow
tender --version
tender capabilities --json
tender auth login --device --profile edit-preview --artifact artifact_123 --ttl 7d --save-profile agent --json
tender auth status --profile agent --json
tender auth login --device --profile create --shopify-store tender-prompt --save-profile account --json
tender auth status --profile account --json
tender app init artifact_123 --dir ./product-survey-runtime --preview --json
cd ./product-survey-runtime
npm run check
git push tender main
tender app preview artifact_123 --commit "$(git rev-parse HEAD)" --stream --json
tender app publish artifact_123 --commit "$(git rev-parse HEAD)" --confirm publish --stream --jsonLifecycle commands that accept --commit also accept Git refs such as HEAD
and resolve them locally before calling the API.
For agents, keep the pattern simple:
- start with
tender capabilities --json - use
tender app init --previewto clone/bootstrap an existing app checkout - inspect and edit files locally
- run
tender app doctorand local project checks; recommendation quizzes should includeanalytics/quiz-attempt.fixture.jsonso doctor verifies stable attempts, resume/Retake behavior, ordered steps, confirmed actions, and cart-metafield persistence - push source with Git
- call
preview,publish --dry-run, thenpublish --confirm publishonly when the user asked to publish
For replacement work, run tender app analytics authoring --json before adding
or repairing instrumentation. Its agent guidance tells agents to inspect the
existing shopper surface before source edits, keep operator analytics out of
shopper UI, and treat default analytics plus saved starter dashboard charts as
part of generated-app delivery unless the user opts out or there is a concrete
blocker.
Auth
Use the device login flow to mint a local token:
tender auth login --device --profile edit-preview --artifact artifact_123 --ttl 7dFor coding agents, use JSON mode and a saved profile. The login command returns
the approval URL/code immediately and stores a short-lived pending exchange in
the user-level Tender config; after the user approves, complete the profile with
auth status:
tender auth login --device --profile edit-preview --artifact artifact_123 --ttl 7d --save-profile agent --json
tender auth status --profile agent --jsonTTL values are intentionally bounded:
7d14d30d
Use --profile publish only when the token should be allowed to publish.
Publish still requires explicit confirmation with --confirm publish.
Use --profile db-read --artifact <app-id> for read-only app database
inspection.
Credential precedence is explicit-first:
--token--profile <name>TENDER_API_TOKEN- saved default profile
--base-url overrides the base URL for whichever credential source is used.
Git Transport
Tender source movement uses Git:
git push tender mainA push updates app source and can trigger preview work. Publishing remains an explicit lifecycle command so local agents do not accidentally publish production changes.
tender app git setup configures the checkout to avoid thin/external-delta
push packs when possible. The server also handles valid external-delta packs by
indexing the accepted commit after upstream Git accepts the push.
Useful Commands
tender --version
tender capabilities --json
tender app list --json
tender app create --name "Exit Intent Widget" --json
tender app create --name "Data Collection App" --init --dir ./data-collection-app --preview --json
tender app create --name "Product Page Survey Runtime" --init --dir ./product-survey-runtime --scaffold shopify-pdp-survey-runtime --preview --json
tender app share create artifact_123 --expires 7d --claims 1 --json
tender app share inspect tok_share_123 --json
tender app claim tok_share_123 --dir ./widget --confirm source-and-setup --json
tender app update artifact_123 --name "Sale Widget" --json
tender app init artifact_123 --dir ./product-survey-runtime --preview --json
tender app init artifact_123 --dir ./widget --preview --json
tender app bindings outbound --id shopify --host admin.shopify.com --dry-run --json
tender app context status artifact_123 --dir ./widget --json
tender app doctor --dir ./widget --json
tender app validate artifact_123 --json
tender app build artifact_123 --commit "$(git rev-parse HEAD)" --json
tender app preview artifact_123 --commit "$(git rev-parse HEAD)" --stream --json
tender app publish artifact_123 --dry-run --json
tender app publish artifact_123 --commit HEAD --confirm publish --stream --json
tender app db capabilities artifact_123 --json
tender app db tables artifact_123 --env published --json
tender app db schema artifact_123 --env published --table votes --json
tender app db query artifact_123 --env published --sql "select * from votes limit 20" --json
tender app db query artifact_123 --env published --sql "select * from votes order by created_at" --limit 50 --offset 50 --json
tender app db dashboards artifact_123 --create "App admin" --default-env published --dry-run --json
tender app db resources suggest artifact_123 --env published --json
tender app db dashboards render artifact_123 --dashboard app_db_dashboard_123 --env published --json
tender app db resources create artifact_123 --dashboard app_db_dashboard_123 --spec resource.json --dry-run --json
tender app db widgets create artifact_123 --dashboard app_db_dashboard_123 --title "Total signups" --spec widget.json --dry-run --jsonShared app setup
Use this for agency-to-customer or collaborator handoffs where the recipient should get the source and reusable setup, not the source account's data.
Agency side:
tender app share create artifact_123 --expires 7d --claims 1 --jsonRecipient side:
tender app share inspect tok_share_123 --json
tender app claim tok_share_123 --dir ./exit-intent-widget
tender app claim tok_share_123 --dir ./exit-intent-widget --confirm source-and-setup --jsonClaim copies source code, app setup, and analytics dashboard/chart definitions. It does not copy analytics events, aggregates, exports, app database rows, secrets, environment values, release history, or ongoing access to the source artifact.
Analytics
Analytics commands are artifact-scoped and go through Tender's server-side validation. The CLI never exposes raw query credentials, raw SQL, or cross-app data.
Start with capabilities. This is the self-documenting entrypoint for coding agents:
tender app analytics capabilities artifact_123 --include-catalog --range 30d --json
tender app analytics provision artifact_123 --from-app --jsonThat response tells the agent:
- which analytics commands are supported
- the safe chart-spec shape
- retention, range, quota, and security limits
- existing saved dashboards and charts
- bounded observed event names, request paths, property keys, rough types, and counts from artifact-scoped catalog samples
Common read-only commands:
tender app analytics summary artifact_123 --range 30d --json
tender app analytics provision artifact_123 --from-app --json
tender app analytics query artifact_123 --spec chart.json --json
tender app analytics query artifact_123 --spec - --json < chart.json
tender app analytics export catalog artifact_123 --range 30d --json
tender app analytics export query artifact_123 --spec chart.json --format csv
tender app analytics suggestions artifact_123 --range 30d --json
tender app analytics charts templates --json
tender app analytics properties list artifact_123 --jsonSafe write previews:
tender app analytics dashboards artifact_123 --create "Agent dashboard" --dry-run --json
tender app analytics properties activate artifact_123 \
--event signup_started \
--property plan \
--type dimension \
--dry-run \
--json
tender app analytics charts create artifact_123 \
--dashboard analytics_dashboard_123 \
--title "Signup funnel" \
--spec funnel.json \
--dry-run \
--json
tender app analytics charts update artifact_123 \
--chart analytics_chart_123 \
--title "Signup funnel" \
--spec funnel.json \
--dry-run \
--json
tender app analytics charts delete artifact_123 \
--chart analytics_chart_123 \
--dry-run \
--jsonReal saved-dashboard writes use the same commands without --dry-run.
List charts before update/delete so the target chart id and current spec are
explicit:
tender app analytics charts list artifact_123 --dashboard analytics_dashboard_123 --jsonanalytics provision --from-app is a guided plan in this release, not a hidden
write. It returns starter chart specs, write-preview commands, write commands,
blockers, and the chart-list completion proof an external agent should report.
Agents should combine capabilities --include-catalog with local source-code
inspection. For example, inspect where the app calls
__TP_ANALYTICS.invoke(...), propose a chart spec, validate it with
analytics query, and only then create a saved chart.
Use charts templates --json for reusable chart shapes; adapt any placeholders
to observed events, paths, or queryable property keys before querying or saving.
Property group-bys and property metrics need the custom event property to be
available for dashboard queries; charts create and charts update activate
missing properties automatically when the spec includes an event_name = ...
filter. analytics query is read-only, so use
properties activate first when trying an ad hoc property query. When a
query fails for a missing dashboard-query property, the CLI prints the exact
activation commands to run and does not perform that write automatically.
Event payload properties can be tracked by the app, observed in bounded catalog samples, and still not be queryable in fast dashboard charts. Register intended dashboard dimensions and metrics before meaningful traffic starts. Use dimensions for grouping values such as variant, plan, step, source, or outcome, and metrics for numeric values such as score, amount, duration, or quantity. Making a property queryable does not require an app redeploy, but older dashboard-query rows may not fully populate grouped charts until new traffic arrives. Do not make every property queryable; avoid PII, secrets, free text, ids, URLs, or high-cardinality values unless the chart has a clear purpose.
App Database
App database commands are artifact-scoped and go through Tender's server-side
authorization and read-only query checks. The CLI only accepts an app id; it
does not accept tenant ids, runner names, provider account ids, or runtime
storage identifiers. Commands that read data require an explicit --env preview
or --env published; there is no default environment.
Start with capabilities:
tender auth login --device --profile db-read --artifact artifact_123 --ttl 7d --save-profile db --json
tender auth status --profile db --json
tender app db capabilities artifact_123 --profile db --jsonCommon read-only commands:
tender app db tables artifact_123 --env published --profile db --json
tender app db schema artifact_123 --env published --table votes --profile db --json
tender app db query artifact_123 --env published --sql "select * from votes limit 20" --profile db --json
tender app db query artifact_123 \
--env published \
--sql "select * from votes where choice = ?" \
--param coffee \
--profile db \
--json
tender app db query artifact_123 --env published --file ./debug.sql --limit 50 --offset 100 --profile db --json
tender app db query artifact_123 --env published --file - --offset 100 --profile db --json < debug.sqlThe query command sends one read-only statement with positional bindings. Query
responses include requestedLimit, appliedLimit, maxInteractiveLimit,
offset, and nextOffset; agents must request each page explicitly and should
not auto-drain large tables. The interactive row cap is 50 rows per request.
Client and server limits include a 100 KB statement cap and at most 100 bound
parameters. The server enforces the final policy, row limits, response limits,
artifact scope, and audit logging.
Private app admin dashboards are definition-only in the CLI. Use the same
artifact-scoped db-read profile to save dashboards, table-backed resources,
saved views, and widgets; raw app rows stay in the generated app database.
Logged-in users can open saved dashboards at /#/workspace/<artifact-id>/admin.
tender app db resources suggest artifact_123 --profile db --env published --json
tender app db dashboards artifact_123 --profile db --create "Coffee Matcher Admin" --default-env published --json
tender app db resources create artifact_123 --profile db --dashboard app_db_dashboard_123 --spec resource.json --view recent.json --json
tender app db widgets create artifact_123 --profile db --dashboard app_db_dashboard_123 --title "Votes by choice" --spec widget.json --json
tender app db dashboards render artifact_123 --profile db --dashboard app_db_dashboard_123 --env published --jsonSuggested app database resources may include dateRange: { "source":
"dashboard", "column": "created_at" } so saved admin dashboards behave like a
Grafana dashboard: one top-level date range applies to charts and tables by
default, while resource filters stay available for local drill-downs. Use
dateRange: { "source": "off" } or a fixed override only for panels that should
not follow the dashboard date range.
Safety Model
- Local agents run in the user's environment, not in Tender.
- Source moves through artifact Git.
- Preview, build, and publish are explicit API lifecycle operations.
writelets a token edit, preview, push source, and publish.publishremains accepted as an explicit scope for descriptive or older token grants.tender app publishrequires--dry-runor--confirm publish.- Tokens are stored outside the project checkout and are not written into Git remote URLs.
- Analytics commands use tenant/artifact-scoped API routes. They do not expose raw query credentials or raw SQL.
- Dashboard-query property activation is an explicit analytics write and remains tenant/artifact-scoped.
- Raw analytics event export is intentionally not available; exports are bounded catalog metadata or validated aggregate query rows.
- App database commands require
db:read, should use artifact-scoped tokens, and never require provider account ids or runtime storage identifiers.
Related Package
The CLI uses @tenderprompt/tender-app-validator for local Tender App checks.
