Merged into tinqs/studio: - cmd/tinqs-cli/ — tinqs-cli (Go binary, from bot/cli) - cmd/tea/ — Gitea CLI tool (from tinqs/cli-tea) - services/bot/ — Bot service (from tinqs-ltd/bot on git.arikigame.com) - services/admin/ — Admin panel (from tinqs/admin) - services/team-tool/ — Team Tool (from tinqs/team-tool) - services/proxy/ — tinqs-proxy (from bot/proxy) - web/landing/ — tinqs.com website (from tinqs/website) - web/docs/ — Platform docs (from tinqs/docs) - web/blog/ — Blog (placeholder) - runner/ — Ephemeral CI runner (from tinqs/runner) All source repos will be deleted after verification.
18 KiB
CLAUDE.md — Claude Code context for bot.arikigame
Unified bot platform — Meet assistant + docs MCP + team messaging.
On session start
- Read
../docs/ai/SOUL.mdfor hub identity (if on Kraken). - Read
../docs/ai/handoff.mdfor pending tasks.
Language
Always respond in English.
Branch
Always main. Pull before working.
Secrets
Never commit API keys, tokens, or .env files. Use .env.local (gitignored).
Architecture
- Next.js 16 on Lightsail
:5500(internal port 3000 if Docker, orPORT=5500native) - tinqs-proxy (Go binary) at
bot.arikigame.com— replaces Caddy. Source:proxy/ - Tailscale auth via whois proxy at
:39139 - MCP endpoint at
/api/mcp— serves hub identity, glossaries, skills, CLI tool proxies - Gitea API for fetching docs content (cached 5 min)
- AWS Bedrock for LLM (Mistral 8B via
taco-bot-bedrockIAM user)
Key endpoints
| Path | Auth | Purpose |
|---|---|---|
/ |
Public | Landing page |
/api/ping |
Public | Health check + Tailscale status |
/api/mcp |
Tailscale | MCP JSON-RPC 2.0 endpoint |
/api/meeting/* |
Tailscale | Meeting assistant APIs |
Project
Tinqs Team Tool — macOS Edition
A native macOS version of the Tinqs Team Tool — a live transcription and meeting productivity app for the Tinqs game development team. It captures audio via mic, runs dual-engine speech recognition (Apple Speech Framework for real-time free transcription + ElevenLabs Scribe V2 for high-accuracy speaker-diarized chunks), and serves an embedded web UI from a local Go HTTP server wrapped in a Swift/AppKit shell. After a session, it can generate formatted meeting notes from the transcript and save them directly into the PM repo.
Core Value: Team members on Mac can record, transcribe, and produce structured meeting notes with the same workflow as the existing Windows tool — no feature gap between platforms.
Constraints
- Platform: macOS 13+ (Ventura) — ScreenCaptureKit requires 12.3+, Apple Speech Framework mature on 13+
- Architecture: arm64 (Apple Silicon) primary, Intel support if straightforward
- Build: Go cross-compilation for darwin/arm64 + Swift/Xcode build for the .app shell
- Code sharing: Maximize shared Go code between Windows and Mac — platform-specific code behind build tags
- Install: Must work via
curl | shfor non-technical team members - Permissions: macOS requires explicit permission grants for microphone, screen recording — tool must guide users through this
Technology Stack
Languages
- TypeScript 5.7.0 - Application code, type safety throughout
- JavaScript (ES2022) - Browser runtime, client-side code
- Go - External proxy binary (
tinqs-proxyatproxy/) - Shell - CLI installation scripts (PowerShell, Bash)
Runtime
- Node.js >=20 (required per
package.jsonengines) - npm (lockfile:
package-lock.jsonpresent) - Next.js 16.1.6 with
output: 'standalone'— containerizable standalone build - AWS Lightsail (internal port 3000, external port 5500)
- Docker-ready via standalone Next.js output
Frameworks
- Next.js 16.1.6 - Full-stack React framework (App Router, API routes, middleware)
- React 19.2.3 - UI library
- React DOM 19.2.3 - DOM rendering
- @assistant-ui/react 0.12.24 - Chat UI components for assistant interface
- @assistant-ui/react-markdown 0.12.8 - Markdown rendering for assistant messages
- PeerJS 1.5.5 - WebRTC peer-to-peer communication (for call/video features)
- Tailwind CSS 4.2.2 - Utility-first CSS framework
- PostCSS 8.5.9 - CSS processing
- TanStack React Query 5.99.0 - Server state management, caching, synchronization
- pg 8.20.0 - PostgreSQL client for Node.js
- ioredis 5.10.1 - Redis client for pub/sub and caching
- @anthropic-ai/sdk 0.39.0 - Anthropic Claude API (Bedrock fallback available)
- @aws-sdk/client-bedrock-runtime 3.1026.0 - AWS Bedrock LLM inference (Mistral 8B)
- @aws-sdk/client-s3 3.1029.0 - AWS S3 for object storage
- Langfuse 3.38.20 - LLM observability, trace tracking
- TypeScript 5.7.0 - Type checking
- @types/node 22.10.0 - Node.js type definitions
- @types/react 19 - React type definitions
- @types/react-dom 19 - React DOM type definitions
- @types/pg 8.20.0 - PostgreSQL client types
- @tailwindcss/postcss 4.2.2 - Tailwind PostCSS plugin
Key Dependencies
- Next.js 16.1.6 - Server-side rendering, API routes, middleware (auth layer)
- @anthropic-ai/sdk - Main LLM provider for meeting assistant (Claude Sonnet 4)
- pg - PostgreSQL for persistent hub state (posts, sessions, scores, switches)
- ioredis - Redis for real-time pub/sub channels and presence data
- @aws-sdk/client-bedrock-runtime - Fallback LLM provider (Mistral 8B, cheaper for taco-bot responses)
- @aws-sdk/client-s3 - File storage for audio, transcripts, binary assets
- Langfuse - Distributed tracing for LLM observability and cost tracking
Configuration
DATABASE_URL- PostgreSQL connection string (default:postgresql://admin:admin@localhost:5432/tinqs_hub)REDIS_URL- Redis connection (default:redis://localhost:6379)ANTHROPIC_API_KEY- Claude API key (required for primary LLM)ANTHROPIC_MODEL- Claude model override (default:claude-sonnet-4-20250514)AWS_REGION- AWS region (default:eu-west-1)BEDROCK_MODEL- Mistral model on Bedrock (default:mistral.ministral-3-8b-instruct)BEDROCK_JUDGE_MODEL- Judge model for eval (default:mistral.mistral-large-2402-v1:0)GITEA_TOKEN- Git Studio authentication token (required for docs access)GITHUB_TOKEN- GitHub API token (optional, for GitHub integration)LANGFUSE_PUBLIC_KEY- Langfuse observability (default:pk-tinqs-agents)LANGFUSE_SECRET_KEY- Langfuse auth (default:sk-tinqs-agents-secret)LANGFUSE_BASE_URL- Langfuse instance (default:http://localhost:3100)LANGFUSE_ENABLED- Toggle tracing (default:true)TACO_API_SECRET- API secret for meeting extension auth.env.local- Git-ignored local overridestsconfig.json- TypeScript configuration (ES2022 target, strict mode, path aliases@/*)next.config.ts- Next.js config (standalone output, custom headers for/cli/install.ps1and/cli/install.sh)postcss.config.mjs- PostCSS with Tailwindpackage.json- Scripts:dev,build,start,typecheck
Platform Requirements
- Node.js >=20
- PostgreSQL >=12 (local or remote)
- Redis (optional, gracefully degrades if unavailable)
- Git for repo access via Gitea API
- Tailscale (for auth on protected endpoints)
- Node.js >=20
- PostgreSQL (managed)
- Redis (managed)
- AWS Account (Bedrock, S3, IAM for
taco-bot-bedrockservice account) - Tailscale network access
- Lightsail instance (or equivalent containerized host)
- Domain:
bot.arikigame.com
Conventions
Naming Patterns
- React components: PascalCase, collocated with feature (e.g.,
NavBar.tsx,TailscaleStatus.tsx) - Library/utility files: kebab-case (e.g.,
redis-pubsub.ts,tailscale-ip.ts,docs-search.ts) - API routes: follow Next.js convention at
app/api/v1/{resource}/{action}/route.ts - Pages: follow Next.js convention at
app/{feature}/page.tsx - camelCase for all functions and variables
- Exported functions: descriptive names like
callTacoClaude(),publishMessage(),checkRateLimit() - Handler functions: prefix with action like
loadSpaces(),sendMessage(),toggleMic() - Refs: suffix with
Ref(e.g.,messagesEndRef,inputRef,sseRef,micWsRef) - Event handlers: prefix with handler name like
onopen,onmessage,onerror - PascalCase for interfaces and types
- Props interfaces: suffix with
Props(e.g.,UserCardProps) - API response shapes: explicit named interfaces (e.g.,
Space,Message) - Union types: use string literals (e.g.,
type UserRole = 'admin' | 'member') - Environment variables: SCREAMING_SNAKE_CASE (checked from
process.env) - Local constants: camelCase (e.g.,
DEFAULT_MODEL,CACHE_TTL) - Configuration objects: camelCase (e.g.,
tokenCache,memoryTranscripts)
Code Style
- No explicit ESLint or Prettier config found in root — uses Next.js defaults
- TypeScript strict mode enabled:
strict: trueintsconfig.json - No unused locals or parameters:
noUnusedLocals: true,noUnusedParameters: true - ES2022 target with DOM + ES2022 lib
- Named imports preferred:
import { pool, redis } from '@/lib/db' - Type imports:
import type { NextRequest, NextResponse } from 'next/server' - Path alias:
@/maps to root directory - Organize in order: external packages, internal absolute imports (
@/), then relative imports - File-level comments explain purpose (e.g., "Database clients — PostgreSQL + Redis")
- API endpoint comments document HTTP methods and query parameters
- Function comments rare unless non-obvious (convention over explanation)
- Inline comments for complex logic or workarounds
- Some tactical comments like
// dev bypass,// Close previous SSE connection
Error Handling
- Wrap async operations in try-catch blocks
- Narrow unknown errors safely:
e instanceof Error ? e.message : String(e) - Return JSON error responses with
status: 500or appropriate code - Silent
.catch(() => {})used for non-critical side effects (optional async operations) - Empty catch blocks acceptable when error is intentionally ignored
- No global error boundary — errors propagate to Next.js error handling
Function Design
- Use explicit parameter objects for functions with multiple parameters
- Document parameter shapes with interfaces
- Example:
callTacoClaude(params: { liveTranscriptBlock: string; docsBlock: string; question: string; source: 'voice' | 'chat' }) - API handlers return
NextResponseorResponse - Async utilities return
Promise<T> - Use
Promise<T | null>for optional results (e.g.,verifyToken()) - Component functions return JSX
Module Design
- Each library file exports utility functions and types
- Single default export for React components
- Named exports for utilities (e.g.,
export { pool, redis }fromdb.ts) - Barrel files not observed — each module directly imported
pool.query()used directly; no ORM layer- Raw SQL with parameterized queries (
$1,$2, etc.) - Connection pooling via
pgPackage lib/db.ts: PostgreSQL pool + Redis client setuplib/auth.ts: Auth header/cookie verificationlib/cors.ts: CORS headers + JSON response helperslib/claude.ts: Anthropic SDK integrationlib/bedrock.ts: AWS Bedrock integrationlib/gitea.ts: Gitea API clientapp/api/v1/{resource}/route.ts: Route handlers
Type Checking
- Strict mode enforced
- No
any— useunknownor generics - Path aliases:
@/*maps to./*(root) - Incremental builds enabled
- Define interface for props (not inline)
- Example from
app/chat/page.tsx:
Inline Styles & State Management
useStatefor local component stateuseReffor DOM refs and persistent values (not state)useCallbackfor event handlers to maintain referential equalityuseEffectfor side effects (data fetching, subscriptions, cleanup)usePathnamefrom Next.js for route awareness- Inline
styleobjects preferred in this codebase (no CSS modules or Tailwind detected) - Color palette:
#0a0a0a(bg),#e0e0e0(text),#c9935a(accent) - No CSS classes — all dynamic via style prop
- Optimistic updates common: apply state before server confirmation, rollback on failure
- Polling fallbacks for real-time features (SSE with 30s fallback)
- In-memory caches for performance (see
store.ts)
Data Fetching
Logging
- Prefixed logs:
[taco]prefix for diagnostic logs - Only in non-production code paths or explicitly debug contexts
- No structured logging library observed
Next.js Specifics
Security Patterns
- Token-based auth from Gitea API
- Cookie-based session:
tinqs-token - Bearer header support:
Authorization: Bearer {token} - Tailscale IP verification for admin routes
- Query parameter extraction with
.get()and type coercion - Type assertions for external data:
as { login?: string; is_admin?: boolean } - No explicit schema validation library (Zod) found
- Environment variables:
process.env.ANTHROPIC_API_KEY,process.env.DATABASE_URL,process.env.REDIS_URL - Checked at startup or gracefully fallback
Architecture
Pattern Overview
- Next.js 16 App Router for pages and API routes
- Middleware-based authentication with Gitea token verification
- PostgreSQL (source of truth) + Redis (presence/caching)
- Real-time messaging via Redis pub/sub with SSE streams
- Multi-feature platform: chat, voice calls (WebRTC/PeerJS), vision, transcription, MCP server
Layers
- Purpose: React client components and pages
- Location:
app/(page.tsx, chat/page.tsx, call/page.tsx, etc.) - Contains: Server-side pages, client components with hooks, UI layout
- Depends on: Providers (QueryClient), API routes
- Used by: Browser clients, Tailscale mesh users
- Purpose: HTTP endpoints for all features (chat, calls, auth, MCP, admin)
- Location:
app/api/(organized by feature:v1/chat/,v1/admin/,auth/,call/,meeting/,mcp/) - Contains: Next.js route handlers (GET/POST), SSE streams, webhooks
- Depends on: Middleware, lib utilities, database
- Used by: Frontend, CLI, external integrations, MCP clients
- Purpose: Request authentication, authorization, rate limiting prep
- Location:
middleware.ts(root) - Contains: Gitea token verification, Tailscale IP detection, admin route guards, cookie-based session
- Depends on: Gitea API, Tailscale whois proxy, environment config
- Used by: All protected routes (skips public: /, /api/ping, /api/auth/, /cli/)
- Purpose: Shared business logic, integrations, data access
- Location:
lib/(db.ts, auth.ts, bedrock.ts, gitea.ts, mcp-handler.ts, etc.) - Contains: Database clients (Pool, Redis), API clients (Gitea, AWS Bedrock, Anthropic), handlers
- Depends on: Environment config, external services
- Used by: All API routes and utilities
- Purpose: Persistence and real-time messaging
- Technologies: PostgreSQL (posts, sessions, scores, switches, inferences), Redis (pub/sub, TTL presence)
- Connection:
lib/db.tsmanages Pool and Redis instances - Used by: Hub query, chat persistence, session tracking
Data Flow
- Server state: PostgreSQL (immutable source of truth)
- Session state: Gitea token in httpOnly cookie + middleware header
- Real-time events: Redis pub/sub channels per space/room
- Client state: TanStack Query (React Query) with 5s stale time, refetch disabled
- Caching: In-memory maps in middleware (token cache), lib functions (Gitea file cache)
Key Abstractions
- Purpose: Fetch files from Git Studio (tinqs-ltd/docs, tinqs-ltd/bot, etc.)
- Examples:
fetchFile(repo, path),listDir(),searchCode() - Pattern: In-memory LRU cache with TTL; fails gracefully if Gitea unreachable
- Used by: MCP handler, hub query, identity docs
- Purpose: PostgreSQL pool and Redis client initialization
- Tables: posts, sessions, scores, switches, inferences (schema not in code — external)
- Pattern: Singleton instances; Redis is optional (graceful degradation)
- Used by: Chat routes, hub query, inference logging
- Purpose: Streamable HTTP transport for MCP JSON-RPC 2.0
- Tools: get_identity, get_glossary, get_repo_file, list_skills, search_docs, gitea_api
- Resources: tinqs://identity/soul, tinqs://glossary/[user], tinqs://handoff
- Pattern: Request parsing → tool dispatch → Gitea/DB fetch → JSON-RPC response
- Purpose: Gather context from DB + Gitea, invoke Bedrock for answer
- Contexts: Recent posts, sessions, switches, inferences
- Pattern: Query DB → format markdown context → call Bedrock → log cost
- Used by: Agent endpoints, hand-off inference
- Purpose: Token verification against Gitea API
- Pattern: Gitea token → fetch /api/v1/user → cache 5 min → set header
- Fallbacks: TACO_API_SECRET legacy header, Tailscale IP whois
- Headers: x-tinqs-user set by middleware for downstream use
Entry Points
- Location:
/(root path) - Triggers: Browser navigation; Tailscale or guest entry
- Responsibilities: Auth check, Gitea login form, gateway page listing
- Location:
/chat - Triggers: User clicks "Chat" from nav
- Responsibilities: SSE stream subscription, message render, form submission
- Location:
/calland/call/[room] - Triggers: Room creation, room join
- Responsibilities: List active rooms, initialize PeerJS, signal relay
/api/auth/check— GET, public, returns auth state/api/auth/login— POST, public, Gitea token login/api/ping— GET, public, health check + Tailscale status/api/v1/chat— POST/GET, authenticated, message CRUD/api/v1/chat/sse— GET, authenticated, SSE stream/api/v1/admin/*— Requires Gitea admin + Tailscale IP/api/mcp— POST, authenticated, MCP JSON-RPC handler- Location:
/cli(setup guide),/cli/install.sh,/cli/install.ps1 - Triggers: New user setup
- Responsibilities: Display token registration, shell script download
Error Handling
- Database: Query errors throw; Redis errors degrade gracefully (SSE falls back to polling)
- External APIs: Gitea unreachable → cached data used; timeout is 3-10 sec with abort signal
- Auth: Invalid token → 401 JSON response; no token on protected route → redirect to
/or 401 - Middleware: Tailscale IP detection fails → continue (non-blocking)
- Chat: Missing space param → 400 with error; Redis unavailable → client reconnects
Cross-Cutting Concerns
Project Skills
No project skills found. Add skills to any of: .claude/skills/, .agents/skills/, .cursor/skills/, or .github/skills/ with a SKILL.md index file.
GSD Workflow Enforcement
Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.
Use these entry points:
/gsd-quickfor small fixes, doc updates, and ad-hoc tasks/gsd-debugfor investigation and bug fixing/gsd-execute-phasefor planned phase work
Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it.
Developer Profile
Profile not yet configured. Run
/gsd-profile-userto generate your developer profile. This section is managed bygenerate-claude-profile-- do not edit manually.