Skip to content

[#34] Scaffold plotlink-cli with all commands#131

Merged
realproject7 merged 3 commits intomainfrom
task/34-plotlink-cli
Mar 15, 2026
Merged

[#34] Scaffold plotlink-cli with all commands#131
realproject7 merged 3 commits intomainfrom
task/34-plotlink-cli

Conversation

@realproject7
Copy link
Copy Markdown
Owner

Summary

  • Scaffolds packages/cli/ with commander.js, tsup build, and config/env loading
  • Implements all 5 CLI commands: create, chain, status, claim, agent register
  • Each command wraps @plotlink/sdk methods with file I/O, arg parsing, and error handling
  • Config from env vars (PLOTLINK_PRIVATE_KEY, PLOTLINK_RPC_URL, Filebase creds) or .plotlinkrc JSON
  • Adds npm workspaces to root package.json

Fixes #34

Test plan

  • cd packages/cli && npx tsc --noEmit passes
  • npm run build in cli package produces dist/index.js with shebang
  • plotlink --help shows all commands
  • plotlink create --help, plotlink chain --help, etc. show correct options
  • plotlink status -s 1 queries on-chain data (requires RPC URL)
  • plotlink agent register --help shows nested subcommand

🤖 Generated with Claude Code

Adds packages/cli/ with commander.js-based CLI that wraps @plotlink/sdk:
- plotlink create: upload content to IPFS and create storyline
- plotlink chain: upload content and chain plot onto storyline
- plotlink status: query storyline data and list plots
- plotlink claim: claim royalties for a storyline token
- plotlink agent register: register agent on ERC-8004 and set wallet

Config loaded from env vars (PLOTLINK_PRIVATE_KEY, PLOTLINK_RPC_URL, etc.)
or .plotlinkrc JSON file. Adds npm workspaces to root package.json.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The CLI scaffold is substantial, but plotlink status does not implement the behavior required by issue #34. The ticket explicitly calls for querying Supabase for storyline data such as plot count and deadline remaining, plus MCV2_Bond for token price; the current command only reconstructs on-chain event data from the SDK.

Findings

  • [high] plotlink status does not query Supabase or token price, so it misses required status fields
    • File: packages/cli/src/commands/status.ts:1
    • Suggestion: Issue #34 requires status to query Supabase for storyline metadata including deadline remaining / plot count and MCV2_Bond for token price. The current implementation only calls client.getStoryline() and client.getPlots(), then prints event-derived values. Add the Supabase-backed status path and price lookup so the command matches the acceptance criteria.

Decision

Request changes because one of the required CLI commands is not yet implemented to the issue's specification.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T2b Review: REQUEST CHANGES

Good scaffold — clean commander.js usage, safe config loading (JSON.parse only), secrets not logged. Several issues:

Blocking

  1. --wallet-key validation happens AFTER registerAgent tx — If user passes --wallet but forgets --wallet-key, the registration tx fires (costing gas), THEN errors out. Move validation before any on-chain calls.

  2. Private key as CLI argument is a security risk--wallet-key <key> appears in shell history, ps output, and process listings. Should read from env var (PLOTLINK_AGENT_WALLET_KEY) or --wallet-key-file <path> instead. At minimum, warn in help text.

  3. Unsafe as Address casts without validationclaim.ts and agent-register.ts cast user input directly (opts.address as Address). Use viem's isAddress() first, give a user-friendly error on invalid input.

Non-blocking

  1. Malformed .plotlinkrc silently swallowed — empty catch block gives confusing "Missing private key" error instead of telling user their config has invalid JSON. Add console.warn.

  2. readFileSync with no size guardcreate.ts / chain.ts will OOM on very large files. Add a reasonable limit check.

  3. Consider adding .plotlinkrc to .gitignore — prevents accidental private key commits.

Status command now queries Supabase for indexed storyline metadata
(plot count, last plot time, sunset, writer type, creation date) and
MCV2_Bond for current token price via new SDK getTokenPrice() method.
Falls back to event-derived plot count when Supabase is not configured.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The Supabase-backed status path is a step forward, but the CLI still misses part of issue #34's required status output and has a blocking safety problem in the agent registration command.

Findings

  • [high] plotlink status still does not show deadline remaining
    • File: packages/cli/src/commands/status.ts:89
    • Suggestion: Issue #34 explicitly calls for deadline remaining in the status output. The new command prints sunset, created, and last_plot, but it never computes or shows the remaining deadline window. Add the actual remaining-time calculation when the storyline has a deadline.
  • [high] agent register validates --wallet-key only after sending the registration transaction
    • File: packages/cli/src/commands/agent-register.ts:43
    • Suggestion: If the user passes --wallet without --wallet-key, the CLI currently spends gas on registerAgent() and only then errors. Validate that option combination before any on-chain write.
  • [high] --wallet-key as a raw CLI argument exposes private key material to shell history and process listings
    • File: packages/cli/src/commands/agent-register.ts:18
    • Suggestion: Do not accept a private key directly as a command-line flag. Use an env var, prompt, or --wallet-key-file so the secret is not leaked via shell history / ps output.

Decision

Request changes because the CLI still misses required status behavior and currently handles agent wallet private keys unsafely.

- status: compute human-readable deadline remaining (e.g. "2d 5h remaining"
  or "expired") from last_plot_time using the 72h sunset window
- agent-register: remove --wallet-key CLI flag (leaked into shell history);
  read key from PLOTLINK_AGENT_WALLET_KEY env var instead; validate presence
  BEFORE registerAgent() spends gas; add --skip-wallet flag

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE

Summary

The follow-up fixes resolve the previously blocking CLI issues: status now includes a human-readable deadline remaining value alongside Supabase-backed metadata and token price, and agent register no longer accepts the agent wallet key via CLI arg or validates it after spending gas. The command set now matches issue #34's required behavior and CI passed.

Findings

  • None.

Decision

Approve because the CLI scaffolding and required commands are now implemented to the ticket's specification, and lint-and-typecheck passed.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T2b Re-review: APPROVE

Both blocking issues fixed:

  1. Wallet key validation now runs BEFORE registerAgent() — no more wasted gas
  2. Private key moved to PLOTLINK_AGENT_WALLET_KEY env var — no shell history leak

Non-blocking follow-up: as Address casts in claim.ts and agent-register.ts still lack isAddress() validation. viem will reject at the RPC level, but a user-friendly upfront error would be better. Can be a follow-up.

@realproject7 realproject7 merged commit cc5e2fd into main Mar 15, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[P6-3] CLI — plotlink-cli

2 participants