.crustagent/skills/clawkeys-setup/SKILL.md
The standard Lobsterized©™ ClawKeys©™ account creation and identity hatching flow. From landing page to dashboard — zero passwords, full sovereignty.
npx skillsauth add acidgreenservers/clawchives clawkeys-setup-flow©™Install this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The setup wizard is a 4-step linear flow. No passwords. No cloud accounts. The user hatches their identity from cryptographic randomness.
┌─────────────────────────────────────────────────────────────────────┐
│ CLAWCHIVES©™ SETUP WIZARD │
└─────────────────────────────────────────────────────────────────────┘
[STEP 1: welcome] [STEP 2: profile] [STEP 3: generating]
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Before we │ │ Username │ │ │
│ begin... │ │ ┌───────────┐ │ 800ms │ ⟳ Hatching │
│ │ │ │ │ │ spinner │ Identity │
│ • No password │ ──────► │ └───────────┘ │ ──────► │ │
│ • Key file │ "Get │ │ │ generateHu- │
│ is identity │ Started"│ Display Name │ │ manKey() │
│ • Store safe │ │ ┌───────────┐ │ │ generateUUID │
│ │ │ │ (optional)│ │ │ () │
│ [Get Started] │ │ └───────────┘ │ └───────┬───────┘
└───────────────┘ │ │ │
│ [Generate Key]│ │ auto-advance
└───────────────┘ ▼
[STEP 4: complete]
┌──────────────────────────────────────────┐
│ Identity Hatched! │
│ │
│ Username: alice │
│ Key: hu-aB3xK9mZ2pQ7rT1... (...) │
│ UUID: 3f4a2b1c-... │
│ │
│ [Download Identity File] ← MANDATORY │
│ [ ] PLANNED: [Copy ClawKey] │
│ │
│ [Complete Setup] ← disabled until │
│ hasDownloaded = true │
└──────────────────────────────────────────┘
│
│ on "Complete Setup"
▼
┌──────────────────────────┐ ┌──────────────────────────┐
│ POST /api/auth/register │ │ POST /api/auth/token │
│ { uuid, username, │────►│ { type:"human", uuid, │
│ keyHash } │ │ keyHash } │
└──────────────────────────┘ └──────────┬───────────────┘
│
▼
sessionStorage.setItem(×4)
│
▼
Dashboard
These conditions must be true before setup can succeed:
getApiBaseUrl() resolves correctly)GET /api/health returns 200 OK (API is healthy)sessionStorage (cc_api_token is absent)POST /api/auth/register)crypto.getRandomValues() (all modern browsers; required for key generation)crypto.subtle.digest() (required for SHA-256 hashing)navigator.clipboard available (for planned Copy ClawKey feature; not blocking current implementation)What the user sees:
What the code does:
State at entry: step = "welcome", all other state is initial/empty
Buttons: [Get Started] → sets step = "profile"
What the user sees:
What the code does:
username state updated on every keystrokedisplayName state updated on every keystrokeusername.trim() === ""State at entry: step = "profile", username = "", displayName = ""
State changes on input: setUsername(value), setDisplayName(value)
On "Generate Key" click:
step = "generating" → immediately renders spinnerstep = "complete"Buttons: [Generate Key] (disabled if username empty) → triggers generating phase
What the user sees:
What the code does (within the 800ms window):
// Both operations run during the 800ms spinner delay
const key = generateHumanKey() // 64 Base-62 chars prefixed with "hu-"
const uuid = generateUUID() // crypto.randomUUID() → RFC-4122 v4
setGeneratedKey(key)
setGeneratedUUID(uuid)
State changes:
generatedKey — the raw hu-[64chars] stringgeneratedUUID — the RFC-4122 v4 UUID stringDuration: Exactly 800ms (hardcoded setTimeout)
Auto-advances to: step = "complete" (no user input required)
What the user sees:
… (e.g., hu-aB3xK9mZ2pQ7rT1wYn…)hasDownloaded = trueWhat the code does on Download:
Blob with type: "application/json"URL.createObjectURL(blob)<a> element with download="clawchives_identity_{username}.json"hasDownloaded = true → enables "Complete Setup" buttonState:
hasDownloaded — boolean gate; false until download triggeredgeneratedKey, generatedUUID, username, displayNameOn "Complete Setup" click (requires hasDownloaded = true):
See API Calls Made section for the full sequence.
Buttons:
[Download Identity File] — always enabled on this step[ ] PLANNED: [Copy ClawKey] — not yet implemented (see Planned Additions)[Complete Setup] — disabled until hasDownloaded = trueAll cryptography runs client-side only. The raw hu- key is never transmitted to the server.
generateHumanKey()// Location: src/lib/crypto.ts
const BASE62_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
const KEY_LENGTH = 64 // characters (not bytes)
function generateHumanKey(): string {
const bytes = new Uint8Array(KEY_LENGTH)
crypto.getRandomValues(bytes) // CSPRNG — browser native
const chars = bytes.map(b => BASE62_CHARSET[b % 62]) // bias is negligible at 62 chars
return "hu-" + String.fromCharCode(...chars)
}
// Result: "hu-" + 64 Base-62 characters = 67 total characters
// Entropy: ~381 bits (64 × log2(62) ≈ 381)
generateUUID()// Location: src/lib/crypto.ts
function generateUUID(): string {
return crypto.randomUUID() // RFC-4122 v4 UUID, browser native
}
// Result: "3f4a2b1c-dead-beef-cafe-0123456789ab"
hashToken()// Location: src/lib/crypto.ts
async function hashToken(token: string): Promise<string> {
const encoder = new TextEncoder()
const data = encoder.encode(token) // UTF-8 encode
const hashBuffer = await crypto.subtle.digest("SHA-256", data) // SHA-256
const hashArray = Array.from(new Uint8Array(hashBuffer))
return hashArray.map(b => b.toString(16).padStart(2, "0")).join("") // hex string
}
// Input: "hu-aB3xK9mZ2pQ7rT1wYn..." (67 chars)
// Output: "e3b0c44298fc1c149afb..." (64 hex chars = 256 bits)
Client Server
────── ──────
generatedKey = "hu-[64chars]"
│
▼
hashToken(generatedKey)
│
▼
keyHash = SHA-256(hu-key) as hex string
│
├──── POST /api/auth/register ──────────► stores { uuid, username, keyHash }
│ { uuid, username, keyHash }
│
├──── POST /api/auth/token ─────────────► validates keyHash (constant-time)
│ { type: "human", uuid, keyHash } generates api-token
│ stores in api_tokens table
│◄─── { token: "api-[32chars]" } ─────────
│
▼
sessionStorage.setItem(×4)
onComplete(username, generatedKey)
│
▼
Dashboard
NOTE: generatedKey (the raw hu- key) is ONLY used for:
1. Displaying the key preview in Step 4 UI
2. Writing into the downloaded identity file
3. Passing to hashToken() — then discarded
It is NEVER stored in sessionStorage, localStorage, or sent to any server.
The downloaded file is the user's sole credential. Losing it means losing the account.
{
"username": "alice",
"uuid": "3f4a2b1c-dead-beef-cafe-0123456789ab",
"token": "hu-aB3xK9mZ2pQ7rT1wYnXcVbNmLkJhGfDsApOiUeWqZrTyMnBvCxZlKjHgFdSaP",
"createdAt": "2026-03-07T14:22:00.000Z"
}
| Field | Type | Description |
|-------------|-------------|-----------------------------------------------------------------------|
| username | string | The username chosen during Step 2 of setup |
| uuid | string | RFC-4122 v4 UUID; the server-side user identifier |
| token | string | The raw hu-[64chars] key. This IS the identity. Guard it carefully. |
| createdAt | string | ISO-8601 timestamp of when the identity was hatched |
clawchives_identity_{username}.json
Example: clawchives_identity_alice.json
token field is the plaintext hu- key. Anyone who obtains this file can authenticate as the user.On successful "Complete Setup", four keys are written to sessionStorage:
| Key | Value | Description |
|------------------|--------------------------------|------------------------------------------------|
| cc_api_token | "api-[32chars]" | Session bearer token for all subsequent API calls |
| cc_username | "alice" (chosen username) | Display name for UI personalization |
| cc_user_uuid | "3f4a2b1c-..." | User UUID for client-side identity tracking |
| cc_key_type | "human" | Key type context; gates human-only UI features |
Lifecycle: All four keys are cleared when the browser tab is closed (sessionStorage is tab-scoped). Refreshing the page also clears session — this is expected behavior. Users must log in again via the login flow after any session loss.
Two sequential API calls are made during "Complete Setup". Both use getApiBaseUrl() from src/config/apiConfig.ts.
POST {apiBase}/api/auth/register
Content-Type: application/json
Request Body:
{
"uuid": "3f4a2b1c-dead-beef-cafe-0123456789ab",
"username": "alice",
"keyHash": "e3b0c44298fc1c149afb4c8996fb92427ae41e4649b934ca495991b7852b855"
}
Success Response — 201 Created:
{
"message": "User registered successfully"
}
Error Responses:
409 Conflict → Username or UUID already registered
400 Bad Request → Missing required fields
500 Internal → Server error (DB write failed)
POST {apiBase}/api/auth/token
Content-Type: application/json
Request Body:
{
"type": "human",
"uuid": "3f4a2b1c-dead-beef-cafe-0123456789ab",
"keyHash": "e3b0c44298fc1c149afb4c8996fb92427ae41e4649b934ca495991b7852b855"
}
Success Response — 200 OK:
{
"token": "api-aBcDeFgHiJkLmNoPqRsTuVwXyZ123456"
}
Error Responses:
401 Unauthorized → keyHash does not match stored hash (constant-time comparison)
404 Not Found → UUID not found in users table
400 Bad Request → Missing type, uuid, or keyHash
Token storage after Call 2:
sessionStorage.setItem("cc_api_token", token)
sessionStorage.setItem("cc_username", username)
sessionStorage.setItem("cc_user_uuid", uuid)
sessionStorage.setItem("cc_key_type", "human")
navigator.clipboard.writeText(generatedKey) — copies the full raw hu-[64chars] string to clipboard.hasDownloaded must still become true before "Complete Setup" is enabled. The two actions are independent.navigator.clipboard is unavailable (non-HTTPS or unsupported browser), the Copy button should be hidden or shown as disabled with a tooltip explaining HTTPS is required.Implementation target file: src/components/auth/SetupWizard.tsx — complete step render block.
POST /api/auth/register returns 409 Conflictfetch() throws a network error or GET /api/health times outVITE_API_URL in docker-compose, check CORS configurationgetApiBaseUrl() is resolving to the correct origin — see src/config/apiConfig.tshasDownloaded never becomes truecrypto.getRandomValues or crypto.subtle.digest are undefined (non-HTTPS context, very old browser)http://localhost is an exception — browsers grant crypto APIs to localhost originscrypto.randomUUID() generates a UUID already in the database"A lobster does not hatch with a password — it hatches with claws. The shell is its credential, the claw is its key, and the ocean floor is its alone. Guard your identity file as a lobster guards its molt: expose it to no one, lose it to nothing, and carry it always in a place only the tide knows."
This SKILL.md is part of the ClawChives©™ CrustAgent©™ skill library. Update this document whenever SetupWizard.tsx or the auth registration flow is modified.
development
# Feature Development Assistant ## Mission Statement You are an expert full-stack developer who builds complete features from concept to implementation using Desktop Commander's file management capabilities. Your role is to analyze existing codebases, design feature architecture, implement all necessary code, and integrate seamlessly with existing systems. ## Important: Multi-Chat Workflow **Feature development requires multiple chat sessions to avoid context limits and manage implementation c
development
The canonical ClawChives©™ agent integration skill. Full API reference for autonomous agents (Lobsters©™) to authenticate, manage bookmarks, folders, and integrate with the ClawChive bookmarking system.
development
# Truthpack Updater Skill ## When to Use Activate this skill whenever: - A new route is added to `server/routes/` - A new environment variable is introduced - The project structure or a feature cluster is modified - Security protocols or auth rules are updated ## Instructions 1. **Audit Phase**: Perform a full-codebase scan (`grep` or `list_dir`) to identify changes since the last truthpack sync. 2. **Atomic Updates**: Update the corresponding JSON file in `.crustagent/vibecheck/truthpack/`:
development
# Truthpack Lookup Skill ## When to Use Activate this skill BEFORE generating any code that: - Creates or modifies API routes - References environment variables - Touches authentication/authorization - Modifies API request/response shapes ## Instructions 1. Read `.crustagent/vibecheck/truthpack/routes.json` for verified API routes 2. Read `.crustagent/vibecheck/truthpack/env.json` for verified environment variables 3. Read `.crustagent/vibecheck/truthpack/auth.json` for verified auth rules 4.