LearnCard CLI
npx @learncard/cli is two things: a set of commands for setting up and operating an issuer (below), and an interactive REPL for exploring the SDK (further down).
Commands
Every command reads its identity from the .env in the current folder — one folder is one profile on one network. --network staging (or a tRPC URL) targets a non-production network; --json prints a single JSON result on stdout; -y accepts defaults.
send <recipient>
Sends a badge to an email or phone (via the Universal Inbox, with a claim link) or to a profile ID or DID (delivered directly). Signs through your registered signing authority when one exists; --no-template signs locally. --as <profileId> sends as a profile you manage.
org apply <file>
Makes the network match an org spec. Idempotent. --dry-run reads only; --secrets-out <path> is where new service-account tokens go.
doctor
Network preflight: identity, signing service, token scopes, signing authority (test-sign + verify), did:web, credential refresh, and optional webhook POST (--webhook-url). Trusted Registry is a skipped manual check. Does not provision resources. --strict fails on warnings.
whoami
This folder's profile, DID, signing authority, manager DID, and every profile --as can target.
promote --from <net> --to <net> --org <file>
Applies the spec on a second network in .learncard/<network>/. Only the seed and profile ID carry over; tokens land in <target>/secrets.env; runs doctor. --dry-run writes nothing.
status [activityId]
Recent sends, or the claim history of one.
inbox list
Sent inbox credentials. --status PENDING|ISSUED|EXPIRED, --since 7d, --as <profileId>.
refresh history <refreshId>
Versions published for a managed credential.
clr validate <file>
Zod-validates a CLR 2.0 credential and lints it as --profile provisional or official. --dry-run-sign signs and verifies without delivering.
setup-signing, token, webhook, verify, revoke, open, init, export, restore
Single-purpose helpers; --help on each.
LEARNCARD_AS=<profileId> is the environment fallback for --as on every command that accepts it.
A newly generated send --as script reads MANAGED_DID, saved in .env, and stays bound to that managed issuer and network. It rejects a missing or changed DID. Existing scripts are left untouched with a warning that they may use a different issuer.
Org spec
The file org apply and promote read. YAML or JSON. Only issuer is required. Worked examples: packages/learn-card-cli/examples; guide: Bootstrap an Issuer Organization.
issuer.profileId
string
3–40 chars: lowercase letters, digits, hyphens. Must match the folder's PROFILE_ID if one exists.
issuer.displayName
string
Updated in place if it differs.
issuer.branding
object
See branding below.
issuer.signingAuthority.type
learncard-hosted | self-hosted
Hosted: LearnCard creates and registers the key. Self-hosted: also needs endpoint (https) and did. A registered self-hosted signer whose DID differs from did is reported as drift.
issuer.signingAuthority.name
string
≤15 chars, lowercase/digits/hyphens.
profileManager.displayName
string
Creates a profile manager owned by the issuer. Its DID is saved to .env as ORG_PROFILE_MANAGER_DID. Updated in place if it differs.
profileManager.managed[]
{ profileId, displayName, branding? }
Profiles with no seed of their own; act as them with --as. displayName is updated in place if it differs. With a learncard-hosted signer, each also gets its own hosted signing authority registered (so API tokens can sign as it).
serviceAccounts[]
{ name, scopes[], expiresAt? }
One auth grant + API token each. Tokens go to --secrets-out as NAME=… (upper-cased, -→_; normalized keys must be unique). Missing token keys are re-issued. Scope/expiry drift errors with a revoke command before replacement; dry-run reports drifted.
webhooks[].url
https URL
Not registered on the network (webhooks are per issuance). The first is saved as WEBHOOK_URL in .env for doctor and your code.
branding (on issuer and on each managed[] entry) — every field optional; only listed fields are compared, display is merged not replaced:
image, heroImage
https URL
Local paths are rejected with a hint; host the file and use its URL.
shortBio
string ≤280
bio, websiteLink
string / URL
type
organization | service | person
display.*Color
#RRGGBB
backgroundColor, fontColor, accentColor, accentFontColor, idBackgroundColor
display.*Image, display.fade*, display.repeat*
https URL / boolean
backgroundImage, idBackgroundImage and their fade/repeat toggles
Files the CLI keeps
.env
SECURE_SEED, PROFILE_ID, NETWORK_URL, plus per-network facts org apply records (SIGNING_AUTHORITY_*, ORG_PROFILE_MANAGER_DID, WEBHOOK_URL, TEMPLATE_URI). Mode 0600, gitignored.
secrets.env (or --secrets-out)
Service-account tokens for your backend. Mode 0600, gitignored. org apply --secrets-out reads existing keys to determine whether a token needs re-issuing.
.learncard/<network>/
Created by promote: a sibling project folder for the other network.
Interactive REPL
LearnCard CLI is also an easy to use node REPL that instantiates a Learn Card wallet for you and gives you all the tools you need to easily play around with the Learn Card SDK!
Usage
Holder Continuity Export
The CLI also provides REPL helpers from @learncard/holder-continuity for holder-controlled continuity exports. These helpers create a standard ZIP with a readable manifest and encrypted payload files for keys, credentials, presentations, consent records, and status-list snapshots.
getLearnCardBundlePassword() prompts without echoing the password into the REPL, which avoids saving it in REPL history. You can still pass a password string directly for local scripts.
restoreLearnCardFromBundle(...) decrypts the exported seed and returns a wallet with the original DID. It does not upload bundle payloads or recreate index records; use importLearnCardBundle(...) when copying credentials into another wallet.
If you omit the first argument, the CLI exports the default learnCard wallet it created at startup:
Lower-level helpers are also available in the REPL:
For the data model and portability caveats, see Holder Continuity and the @learncard/holder-continuity package BUNDLE_SPEC.md.
Getting Started

From within the CLI, you should be able to start playing around with a basic LearnCard. When the CLI boots up, it creates a default LearnCard called learnCard that you can interact with.
Basic Usage
View your wallet's DID
One of the easiest ways to interact with your LearnCard is to get its DID:
If your LearnCard is initialized to support more DID methods, such as did:web, you could retrieve the corresponding DID through this function.
Basic Verifiable Credential Issuance & Verification Flow
Once the CLI has booted up, you can start issuing credentials. Try a basic Verifiable Credential issuance and verification flow, for example:
Basic Verifiable Presentation Issuance & Verification Flow
Now, take the signedVerifiableCredential you created in the VC issuance flow above, and try wrapping it into a Verifiable Presentation, and verifying it.
Initialize more LearnCards
At any point, you can initialize additional LearnCards in the CLI, which can be helpful for testing cross-wallet flows:
Check out the docs on initializing LearnCards for more ways to create a LearnCard.
And beyond!
There is a ton of functionality exposed through the CLI. Explore the Usage Examples in LearnCard Wallet SDK:
MethodsLast updated
Was this helpful?