feat(cli): remind about unclaimed projects before they expire#1580
feat(cli): remind about unclaimed projects before they expire#1580shapirodaniel wants to merge 2 commits into
Conversation
📦 Bundle Stats —
|
| Metric | Value | vs stack/mint-and-claim/a1/02-mint-core (c561aae) |
|---|---|---|
| Internal (raw) | 2.2 KB | - |
| Internal (gzip) | 838 B | - |
| Bundled (raw) | 11.20 MB | - |
| Bundled (gzip) | 2.11 MB | - |
| Import time | 856ms | -13ms, -1.5% |
bin:sanity
| Metric | Value | vs stack/mint-and-claim/a1/02-mint-core (c561aae) |
|---|---|---|
| Internal (raw) | 782 B | - |
| Internal (gzip) | 423 B | - |
| Bundled (raw) | 9.90 MB | - |
| Bundled (gzip) | 1.78 MB | - |
| Import time | 2.05s | -6ms, -0.3% |
🗺️ View treemap · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
📦 Bundle Stats — @sanity/cli-core
Compared against stack/mint-and-claim/a1/02-mint-core (c561aaee)
| Metric | Value | vs stack/mint-and-claim/a1/02-mint-core (c561aae) |
|---|---|---|
| Internal (raw) | 114.1 KB | - |
| Internal (gzip) | 29.2 KB | - |
| Bundled (raw) | 21.76 MB | - |
| Bundled (gzip) | 3.46 MB | - |
| Import time | 764ms | +2ms, +0.2% |
🗺️ View treemap · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
📦 Bundle Stats — @sanity/cli-build
Compared against stack/mint-and-claim/a1/02-mint-core (c561aaee)
@sanity/cli-build/_internal/build
| Metric | Value | vs stack/mint-and-claim/a1/02-mint-core (c561aae) |
|---|---|---|
| Internal (raw) | 113.8 KB | - |
| Internal (gzip) | 28.7 KB | - |
| Bundled (raw) | 17.76 MB | - |
| Bundled (gzip) | 3.56 MB | - |
| Import time | 1.10s | -0ms, -0.0% |
@sanity/cli-build/_internal/env
| Metric | Value | vs stack/mint-and-claim/a1/02-mint-core (c561aae) |
|---|---|---|
| Internal (raw) | 1.8 KB | - |
| Internal (gzip) | 644 B | - |
| Bundled (raw) | 1.31 MB | - |
| Bundled (gzip) | 333.8 KB | - |
| Import time | 123ms | +2ms, +1.6% |
@sanity/cli-build/_internal/extract
| Metric | Value | vs stack/mint-and-claim/a1/02-mint-core (c561aae) |
|---|---|---|
| Internal (raw) | 8.6 KB | - |
| Internal (gzip) | 2.7 KB | - |
| Bundled (raw) | 155.0 KB | - |
| Bundled (gzip) | 39.5 KB | - |
| Import time | 240ms | +3ms, +1.1% |
🗺️ ./_internal/env · ./_internal/extract · @sanity/cli-build:./_internal/build treemap too large to embed · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
📦 Bundle Stats — create-sanity
Compared against stack/mint-and-claim/a1/02-mint-core (c561aaee)
| Metric | Value | vs stack/mint-and-claim/a1/02-mint-core (c561aae) |
|---|---|---|
| Internal (raw) | 908 B | - |
| Internal (gzip) | 483 B | - |
| Bundled (raw) | 931 B | - |
| Bundled (gzip) | 491 B | - |
| Import time | ❌ ChildProcess denied: node | - |
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
|
bugbot run |
Coverage Delta
Comparing 9 changed files against main @ Overall Coverage
|
d607f3c to
dfb4b5e
Compare
4d6a8f4 to
72e3837
Compare
|
bugbot run |
e2b5c60 to
ed783ab
Compare
03a5f1c to
8f81526
Compare
|
bugbot run |
e43123f to
3a00415
Compare
|
bugbot run |
49bbfe0 to
631a12a
Compare
9182188 to
585e0e5
Compare
|
bugbot run |
e81a97c to
66a782f
Compare
|
bugbot run |
6aa0e48 to
603ef2b
Compare
|
bugbot run |
c098f12 to
84b409e
Compare
1a26343 to
f254af8
Compare
Third layer of the mint-and-claim stack: a machine-global mint ledger in CLI user config, escalating stderr nudges (48/24/8/2h) via a prerun hook, claim-state lookup on the provision API, and the mint command recording each mint into the ledger. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
7020c9b to
05a316a
Compare
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 05a316a. Configure here.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e029e40. Configure here.
| ) | ||
|
|
||
| const urgent = tier >= 3 | ||
| const headline = |
There was a problem hiding this comment.
The body copy changes phrasing across tiers, with three different sentences for "it gets deleted". It could appear as noise rather than escalation, and it's three surfaces to maintain instead of one. I'd keep a constant shape and escalate with colour and the urgency word only. Something like:
You have an unclaimed Sanity project <id> which expires in <N> hours.
Claim it with <url>
Everything keeps working after you claim, including the token in .env.
Future idea: If we know a user is sanity logind could we have a sanity claim command to claim programatically (not sure how often this'll happen though)
| // No expiry from the server: keep the record untouched; the next run re-checks. | ||
| } else { | ||
| announce( | ||
| `⌛ Unclaimed Sanity project ${record.projectId} expired on ${record.expiresAt}. Run \`sanity new\` to mint a new one — where old credentials remain in .env, the guard will walk you through it.`, |
There was a problem hiding this comment.
"where old credentials remain in .env, the guard will walk you through it" - nobody outside this stack will know what "the guard" is. Maybe:
Unclaimed Sanity project expired on and has been deleted.
Run sanity new to create a new project, and remember to claim it within 72 hours
|
all feedback addressed on #1592, canceling this PR to consolidate after offline sync |

Description
this PR adds escalating nudges reminding humans + agents to claim their project before ~72hr expiry is up, via the ledger mechanism leveraged by #1582. high level,
projectIdto claims metadatanotably, we skip
sanity new | sanity projects mintas these commands are geared specifically toward new projects, where the human/agent isn't in a claim motion, ex. when reviving and redeploying content + schemas from an expired projectStack
(each PR reviews against its base; merge bottom-up only):
stack/mint-and-claim/a1/01-terminal-presentationstack/mint-and-claim/a1/02-mint-corestack/mint-and-claim/a1/03-claim-reminders← this diffstack/mint-and-claim/a1/04-init-signpoststack/mint-and-claim/a1/05-remint-guardrailstack/mint-and-claim/a1/06-ambient-reminderstack/mint-and-claim/a1/07-logout-env-tokenWhat to review
util/claimNudges.tstier/dedupe/self-clean logic and the prerun hook ordering inoclif.config.js.Testing
Layer-scoped unit tests included (test:source ≥ 1:1); every layer validated standalone (full typecheck + targeted tests at each checkout).
🤖 Generated with Claude Code
Note
Low Risk
User-local config and stderr-only UX; reminders are best-effort (swallowed errors, fail-open lookups) and do not alter command outcomes or credentials handling.
Overview
Adds escalating claim reminders for minted-but-unclaimed projects: after
projects:mint/sanity new, metadata is stored in user config (unclaimedProjects), and a new prerun hook (claimReminders) prints at most one stderr nudge per CLI run (skipped for mint/new commands so stdout/--jsonstay clean).util/claimNudges.tsdrives a four-tier waterfall (48h → 24h → 8h → 2h left), dedupes vialastNudgeTier, picks the most urgent project, and self-heals malformed registry entries. Before nudging or saying goodbye, it callslookupClaimStateon the provision API (new inmintProject.ts); network failures fail open on local expiry, with claimed/expired cleanup and merge-on-write so concurrent mints are not clobbered. Copy includes an explicit AI agent CTA to surface the claim link.recordMintedProjectis wired into the mint command after a successful mint; config write failures never fail the mint.Reviewed by Cursor Bugbot for commit e029e40. Bugbot is set up for automated code reviews on this repo. Configure here.