Files
kvs-sh/CLAUDE.md
2025-10-05 22:27:26 +03:00

6.3 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

kvs-sh is an interactive CLI shell for the KVS (Key-Value Store) distributed database. Think mongosh, psql, or redis-cli but for KVS. Single Go file implementation (~600 lines) with readline support for command history and auto-completion.

KVS Server Reference

The complete KVS server source code is located at ../kvs/ relative to this repository. Reference it when:

  • Understanding API contracts and response formats
  • Verifying authentication/authorization behavior
  • Checking endpoint paths and HTTP methods
  • Understanding data structures (StoredValue, Member, User, Group types)
  • Implementing new shell commands for backend features

Key server locations:

  • ../kvs/server/handlers.go - All API endpoint implementations
  • ../kvs/server/routes.go - Route definitions and HTTP methods
  • ../kvs/types/types.go - Canonical type definitions (StoredValue, etc.)
  • ../kvs/auth/ - JWT authentication and permission system details
  • ../kvs/README.md - Complete API documentation with curl examples
  • ../kvs/CLAUDE.md - Server architecture and development guidance

When adding new commands to kvs-sh, always verify the actual backend implementation in ../kvs/ rather than making assumptions about API behavior.

Build & Run

# Build
go build -o kvs-shell

# Run
./kvs-shell

# Install to system
go install

Quick Start with Server

# 1. Start KVS server (in ../kvs/)
cd ../kvs && ./kvs config.yaml

# 2. Run shell
./kvs-shell

# 3. In shell:
# connect http://localhost:8080
# auth $KVS_ROOT_TOKEN
# put test/data '{"hello":"world"}'

Important: If auth fails with "token not found", the database has old data. Either:

  • Create a new token via the API, or
  • Wipe database: rm -rf ../kvs/data && mkdir ../kvs/data (restart server to generate root token)

Testing

go test ./...

Architecture

Single-File Design

Everything lives in main.go - intentionally kept simple. The shell is a stateful REPL that maintains:

  • HTTP client connection to KVS backend
  • Current JWT auth token
  • In-memory profile storage (username, token, server URL combinations)
  • Active profile selection

Core Components

KVSClient (main.go:49): Central state container holding:

  • baseURL: KVS server endpoint
  • currentToken: JWT for authentication
  • profiles: In-memory map of saved user profiles (NOT persisted to disk yet)
  • httpClient: Reusable HTTP client with 30s timeout

Command Router (main.go:465): Main loop uses switch statement on first word of input, delegates to handle* methods

Command Parser (main.go:527): Custom parser respecting quotes - critical for JSON arguments like put key '{"foo": "bar"}'

Auto-completion (main.go:503): Prefix tree using readline library for tab completion of commands

HTTP Communication Pattern

All API calls go through doRequest() (main.go:85) which:

  1. Serializes body to JSON if present
  2. Sets Authorization: Bearer <token> header if token exists
  3. Returns (body, statusCode, error) tuple
  4. Delegates HTTP status interpretation to caller

Key Backend API Mappings

  • GET /kv/<key> → Returns StoredValue with UUID, timestamp, data
  • PUT /kv/<key> → Accepts raw JSON, returns UUID + timestamp
  • DELETE /kv/<key> → Returns 204 on success
  • GET /members/ → Returns array of cluster Member objects
  • GET /api/users/<uuid> → Returns User object
  • GET /health → Returns service status map

Type Definitions (main.go:18-46)

Backend response structures are mirrored in the client:

  • StoredValue: The core KV response with UUID, timestamp (int64 unix millis), and json.RawMessage data
  • Member: Cluster member info with ID, address, last_seen timestamp
  • User: User record with nickname hash, groups array, created/updated timestamps
  • Group: Group definition (defined but not yet used in commands)

Profile System

Profiles are in-memory only (see roadmap for persistence plan). When you profile use <name>, it swaps the client's token, userUUID, and baseURL atomically. The * marker in profile listings indicates active profile.

Color Scheme

Uses fatih/color package with semantic coloring:

  • Cyan: labels, headers, structured data keys
  • Green: success messages, confirmations
  • Yellow: warnings, "not found" states
  • Red: errors, invalid usage
  • Magenta: banner/title text

Command Parsing - Critical Implementation Details

parseCommand() (main.go:527-570): Handles both single (') and double (") quotes intelligently.

Key behavior:

  • Quotes are only stripped when they delimit an entire argument (start and end)
  • Supports both ' and " as quote delimiters
  • Tracks which quote type started the argument to handle nesting correctly
  • Preserves quotes that appear mid-argument (for unquoted JSON)

Examples:

put key '{"foo":"bar"}'       # ✅ Strips outer ', preserves inner "
put key {"foo":"bar"}         # ✅ Works (no spaces, compact JSON)
put key {"foo": "bar"}        # ❌ Fails - spaces split into multiple args
put key "{\"foo\":\"bar\"}"   # ✅ Works (escaped quotes in double-quoted arg)

JSON Error Handling (main.go:393-425):

  • printJSONError() provides user-friendly error messages with examples
  • Detects error type (invalid chars, incomplete JSON, etc.) and shows context-specific tips
  • Shows what input was received to help debug quoting issues

Backend Assumptions

The shell expects the KVS backend to:

  1. Accept JWT tokens in Authorization: Bearer <token> header
  2. Return timestamps as Unix milliseconds (int64)
  3. Use standard REST semantics (404 for not found, 204 for delete, 200/201 for success)
  4. Accept raw JSON payloads for PUT operations (not wrapped in metadata)

Known Limitations & Roadmap Items

  1. No persistent profiles - restart loses all profile add data (roadmap #1)
  2. No metadata commands - backend supports owner/group/permissions but shell doesn't expose yet (roadmap #6)
  3. No group management - Group type defined but no CRUD operations (roadmap #5)
  4. No TLS support - HTTP only, no certificate handling (roadmap #8)
  5. No tab completion for keys - only completes command names, not dynamic keys from server (roadmap #10)
  6. user create not implemented - Listed in help but just shows "not implemented" message