28 KiB
Claude Memory
- All implementations must act as reusable libraries/clients, not just demo scripts
- Add streaming support for chat completions (SSE - Server-Sent Events)
- Provide clean API surface for developers to integrate into their applications
- Target compatibility with vLLM, Ollama, and OpenAI-compatible endpoints
- Maintain backward compatibility with non-streaming usage
✅ ALL 47 IMPLEMENTATIONS COMPLETE - All have streaming support with SSE parsing
Completed Languages (47/47 = 100%):
- AWK - Functional library, curl --no-buffer, SSE line parsing
- Bash - Library functions, curl --no-buffer, regex SSE matching
- C (3 variants): curl (libcurl), libsoup (GNOME), nghttp2 (HTTP/2)
- C++ (3 variants): libcurl (std::function), cpp-httplib (lambda), boost-beast (class)
- C# - UncloseAI class, HttpClient, ResponseHeadersRead streaming
- Clojure - defrecord, lazy sequences, line-seq SSE parsing
- COBOL - Procedural PERFORM, shell curl streaming
- Crystal - Class-based, body_io.each_line blocks
- Dart - Class-based, async* Stream generators
- Deno - Class-based, async* AsyncGenerator
- Elixir - Module-based, Stream.resource lazy streaming
- Erlang - Record-based, actor model process messaging
- F# - UncloseAIClient, seq {} StreamReader
- Fortran - Module-based, shell curl+jq+bash
- Go - Struct-based, channel streaming, context support
- Haskell - Data type, Conduit monadic composition
- Java - UncloseAI class, BufferedReader SSE parsing
- JavaScript (4 variants): nodejs (https), typescript (https+types), bun (Fetch API), vanilla (browser Fetch)
- Julia - Mutable struct, Channel async iteration
- Kotlin - UncloseAI class, callback streaming
- Lua - Metatable SDK, LuaSocket SSL, manual HTTP/SSE
- Nim - Ref object, bodyStream.lines callbacks
- OCaml - Record-based, Lwt promises, Lwt_stream
- Odin - Struct-based, shell curl
- Perl - LWP::UserAgent, streaming callback
- PHP - UncloseAI class, CURLOPT_WRITEFUNCTION
- PowerShell - HttpClient, StreamReader
- Prolog - SWI-Prolog http_client, simplified streaming
- Python (4 variants): requests (UncloseAI class), openai-client (OpenAI SDK), httpx-async (async class), aiohttp (async class)
- R - R6 class, httr write_stream
- Ruby - UncloseAI class, Net::HTTP read_body blocks
- Rust - Struct-based, Tokio async, reqwest StreamExt
- Scala - STTP client, callback streaming
- Tcl - TclOO class, curl pipe streaming
- V - Native http module, callback streaming
- VB.NET - Action(Of String) callbacks
- Zig - ChatStream, iterator pattern
Remaining: 0 implementations
Implementation Pattern Established:
- Client/class-based architecture (struct for compiled languages, class for dynamic)
- Model discovery from environment variables (MODEL_ENDPOINT_1..9999)
- Non-streaming method:
chat()/Chat() - Streaming method:
chat_stream()/ChatStream()/chatStream() - TTS generation:
tts()/TTS()/generateSpeech() - Error handling with typed errors where applicable
- SSE parsing:
data: {...}\n\nformat,data: [DONE]termination
CRITICAL: File Naming for Phase 2 SDKs
- ❌ NEVER create separate library files like
uncloseai_lib.py,uncloseai_lib.js, etc. - ✅ ALWAYS transform the existing
uncloseai.{ext}file in place - ✅ Keep single file:
uncloseai.py,uncloseai.js,uncloseai.ts,uncloseai.rs, etc. - The file should contain both the SDK class/struct AND example usage in main()
- Example: Python's
uncloseai.pycontainsclass UncloseAI:+if __name__ == "__main__":demo - Example: Go's
uncloseai.gocontainstype UncloseAI struct+func main()demo
Completed (47 implementations across 40 languages):
- Python (4 variants): requests, openai-client, httpx-async, aiohttp
- JavaScript (4 variants): nodejs, typescript, bun, vanilla
- C (3 variants): curl, libsoup (GNOME), nghttp2 (HTTP/2)
- C++ (3 variants): libcurl, cpp-httplib, boost-beast
- Single implementations (33 languages): AWK, Bash, Clojure, COBOL, Crystal, C#, Dart, Deno, Elixir, Erlang, Fortran, F#, Go, Haskell, Java, Julia, Kotlin, Lua, Nim, OCaml, Odin, Perl, PHP, PowerShell, Prolog, R, Ruby, Rust, Scala, Tcl, V, VB.NET, Zig
Refactoring Status (2025-10-13 - COMPLETE!):
- ✅ ALL 47 IMPLEMENTATIONS REFACTORED! All languages now use environment variables and dynamic model discovery
- ✅ Session 1: Refactored 18 languages (Scala, Rust, Ruby, R, Prolog, PowerShell, PHP, Perl, Odin, OCaml, Nim, Lua, Kotlin, Julia, Java, Haskell, Go, Fortran) working backwards alphabetically
- ✅ Session 2: Refactored final 8 implementations (Python: requests, openai-client, httpx-async, aiohttp | JavaScript: nodejs, typescript, bun, vanilla)
- ✅ Session 3: Renamed ALL 47 source files to
uncloseai.{ext}(orUncloseAI.*for capitalized languages) - ✅ Pattern Applied: All use
System.getenv()/os.getenv()/ENV/process.envforMODEL_ENDPOINT_1..9999andTTS_ENDPOINT_1..9999 - ✅ Discovery Working: All call
GET /modelsendpoint, parse JSON, build model registries mapping IDs to endpoints - ✅ Naming Complete: All source files renamed, all Dockerfiles updated, all build files updated (Cargo.toml, build.sbt, *.vbproj, etc.)
- ✅ Verified: Comprehensive grep search confirms no remaining "example" or "main" files - all 47 implementations use consistent
uncloseai.*naming
Session 2025-10-13 Final 8 Implementations:
- Python variants (4): requests, openai-client, httpx-async, aiohttp
- All use
os.getenv(f"MODEL_ENDPOINT_{i}")loop pattern - requests: Direct HTTP with requests.get/post
- openai-client: Uses OpenAI SDK with dynamic base_url
- httpx-async: Async with httpx.AsyncClient
- aiohttp: Async with aiohttp.ClientSession
- All use
- JavaScript variants (4): nodejs, typescript, bun, vanilla
- nodejs: Native https module with getJSON helper
- typescript: Same as nodejs with type safety
- bun: Fetch API with AbortSignal.timeout
- vanilla: Browser-based with CONFIG.MODEL_ENDPOINTS (can't use env vars)
Skipped (cannot implement - 5 languages):
- Matlab (proprietary license prevents Docker usage)
- SQL (declarative query language, no HTTP client)
- Swift (requires macOS/Xcode for proper development)
- Brainfuck (esoteric language, no practical HTTP client)
- Assembly (too low-level, no standard HTTP library)
Empty directories (skipped, listed above):
- assembly/, brainfuck/, matlab/, sql/, swift/ - all empty, marked as skipped
Project Identity
- When working on this ai.unturf.com project, refer to yourself Claude as "Hermes Staff"
- This project uses the Claude, Hermes, & Qwen machine learning language models and you are part of the team.
- "Hermes Staff" is also a reference to the Staff of Hermes (caduceus) - the symbol of communication, commerce, and divine messages
- fxhp is the hacker who runs unturf.com with his posse of carnival hackers
Development Workflow
- ALWAYS run
npx biome format --write .before committing to format all files - ALWAYS run
npx biome check .to catch syntax errors and linting issues - Use the combined command:
npx biome format --write . && npx biome check . - If biome check fails, fix the issues before proceeding with commit/push
- This prevents breaking production with syntax errors like missing parentheses
Writing Standards
CRITICAL: NEVER use em dashes, en dashes, or double hyphens in prose
- ❌ NEVER use
—(em dash) in writing - ❌ NEVER use
–(en dash) in writing - ❌ NEVER use
--(double hyphen) as a dash substitute - ✅ USE colons, commas, periods, or restructure the sentence instead
Examples:
❌ uncloseai-cli — Local LLM Agent
✅ uncloseai-cli: Local LLM Agent
❌ Zero dependencies — only os, math, random
✅ Zero dependencies: only os, math, random
❌ Point it at any endpoint — vLLM, Ollama, or uncloseai
✅ Point it at any endpoint: vLLM, Ollama, or uncloseai
CSS and Styling Standards
CRITICAL: NEVER use flexbox. Use CSS Grid exclusively.
- ❌ NEVER use
display: flexor any flex properties (flex-shrink,flex-wrap,flex-grow,flex-direction) - ✅ ALWAYS use
display: gridwithgrid-template-columns,grid-auto-flow,place-items, etc. - ✅ For inline checkbox+label:
display: grid; grid-template-columns: 18px 1fr; align-items: center; gap: 8px; - ✅ For centering:
display: grid; place-items: center;
CRITICAL: NEVER use !important in CSS
- ❌ NEVER use
!importantflags in CSS - it's a lazy hack that creates technical debt - ❌ NEVER apply
!importantto fix styling issues - always find the root cause - ✅ ALWAYS use proper CSS specificity (more specific selectors win)
- ✅ ALWAYS investigate WHY styles aren't applying before adding rules
- ✅ ALWAYS use scoped selectors (e.g.,
dialog#my-modal .my-class) - ✅ ALWAYS understand the cascade and inheritance before making changes
Why !important is bad:
- Makes CSS unmaintainable and impossible to override later
- Hides the real problem instead of fixing it
- Creates cascading issues where more !important flags are needed
- Breaks normal CSS specificity rules
- Makes debugging harder for other developers
Proper CSS debugging workflow:
- Use browser DevTools to inspect the element
- Check which styles are being applied and where they come from
- Check which styles are being overridden and why
- Increase specificity properly (more specific selector, not !important)
- Verify the fix works across all contexts
Example of WRONG approach:
.my-button {
background: blue !important; /* ❌ WRONG - lazy hack */
}
Example of CORRECT approach:
dialog#my-modal .my-button {
background: blue; /* ✅ CORRECT - specific selector */
}
Related Repos
| Repo | Location | GitLab | Purpose |
|---|---|---|---|
uncloseai-browser-toys |
/home/fox/git/uncloseai-browser-toys |
git.unturf.com:engineering/unturf/uncloseai-browser-toys |
Browser extension (Chrome, Firefox, Safari). Content script injection, manifest, popup UI. |
Ticket #001 (extension fails on CSP pages) lives in uncloseai-browser-toys, not here. The bundled IIFE (make bundle-extension) is built here but the content script that injects it is in browser-toys.
Makefile Commands
make help- Show all available commandsmake format- Format all files with biomemake check- Check syntax and linting with biomemake format-check- Format and check in sequencemake test- Run integration testsmake validate-exports- Validate import/export consistencymake verify-translations- Verify translation completenessmake validate-all- Run all validation checksmake ci- Run full CI pipeline (clean, format-check, validate-all, validate-structure, validate-translations, check-sizes)make build- Build for production (format-check + validate-all)make dev- Start development server on port 8000make clean- Clean temporary filesmake git-commit- Format and stage all changes for commit
CI Pipeline
- Translation verification:
cd src/languages && node verify-translations.js - Export validation:
node validate_exports.js - Integration tests:
node integration_tests.js(fallback tosimple_tests.jsif JSDOM unavailable) - Code formatting:
npx biome format --write . - Syntax checking:
npx biome check . - Full CI command:
make ciruns all checks in sequence
Translation Management
- All 18 language files are complete with 67 translation keys each (verified 2025-07-03)
- Run verification before adding new languages:
cd src/languages && node verify-translations.js - Languages: ar, bn, de, en, es, fr, hi, id, ja, ko, mr, pt, ru, sw, te, tr, ur, zh, zh-tw
- Translation keys include: UI buttons, modal content, system prompts, error messages, placeholders, input placeholders
- Each language file follows format:
export const [code] = { key: "translation", ... };
Commit Message Guidelines
- Use single line commit messages only
- Never include Claude Code attribution or "Generated with Claude Code"
- Never include "Co-Authored-By: Claude" attribution
- Keep messages concise and descriptive
Remote Server Access via tmux
- Can control remote servers by sending commands to tmux sessions
- Use
tmux list-sessionsto see active sessions - Use
tmux send-keys -t <session> '<command>' C-mto send commands - Use
tmux capture-pane -t <session> -pto see output - Use
tmux list-buffersto see tmux clipboard buffers - ai.foxhop.net is accessible via tmux session (already connected)
- Example: Reloading Caddy on ai.foxhop.net via tmux
Language Examples Project (from WebWords)
Code Quality Standards - CRITICAL RULES
RULE #1: Implementation Must Work Before Documentation
ALWAYS test the implementation works BEFORE creating any documentation files
Standard Build/Test Workflow
- Write code for the language example
- Build using Makefile:
make languages-build-{language}- Example:
make languages-build-python
- Example:
- Test with official endpoints (FREE for book purchasers):
make languages-test-{language}- Example:
make languages-test-python - This automatically sets:
MODEL_ENDPOINT_1,MODEL_ENDPOINT_2,TTS_ENDPOINT_1
- Example:
- Check container logs for:
- ✅ Model discovery from both endpoints
- ✅ Models discovered (should auto-detect Hermes and Qwen)
- ✅ No errors in startup
- DONE - Documentation will be written separately for the book
- Clean:
docker stop test-{language} && docker rm test-{language}- Or use:
make languages-cleanto remove all test containers
- Or use:
Manual Docker Commands (if needed):
# Build
docker build -t ai-unturf-{language} languages/{language}/
# Run with env vars
docker run -d \
-e MODEL_ENDPOINT_1=https://hermes.ai.unturf.com/v1 \
-e MODEL_ENDPOINT_2=https://qwen.ai.unturf.com/v1 \
-e TTS_ENDPOINT_1=https://speech.ai.unturf.com/v1 \
--name test-{language} ai-unturf-{language}
# Check logs
docker logs test-{language}
# Clean up
docker stop test-{language} && docker rm test-{language}
Implementation Testing Requirements
Required for implementation to be complete:
- ✅ Docker build must succeed without errors
- ✅ Container must start correctly
- ✅ Dynamic model discovery works for all endpoints
- ✅ Chat works with auto-discovered models (no hardcoded names)
- ✅ TTS works with auto-discovered models
- ✅ Container logs show no runtime errors
Official Test Endpoints (FREE for book purchasers):
https://hermes.ai.unturf.com/v1- General purpose conversational machine learninghttps://qwen.ai.unturf.com/v1- Specialized coding modelhttps://speech.ai.unturf.com/v1- Text-to-speech synthesis
If implementation fails any test:
- 🔥 Fix the implementation FIRST
- 🔥 Implementation is not complete until all tests pass
- 🔥 Update CLAUDE.md with failure details and fixes
Common Development Patterns
Build-Time Issues: Package availability, dependency versions, Dockerfile syntax Runtime Issues: Missing files, wrong permissions, network access Logic Issues: API calls, authentication, response parsing
Development Workflow
- Analyze - Read existing examples and language patterns
- Build - Attempt Docker build, note any errors
- Fix - Address build issues (packages, syntax, versions)
- Run - Start container, check startup logs
- Debug - Fix runtime issues (permissions, syntax, API calls)
- Test - Verify model discovery and API calls work correctly
- Clean - Stop and remove container before next language
Language Examples Structure
- Each language gets its own directory under
languages/{language}/ - Each contains working code examples using ENVIRONMENT VARIABLES and DYNAMIC MODEL DISCOVERY
- Dockerfile for building/testing in isolation
- Source code files demonstrating the implementation
- NO index.html - Documentation will be written in the book/content/ directory
CRITICAL: File Naming Convention
All source files MUST be named uncloseai.{ext} for consistency across all languages.
Required Naming Pattern:
languages/c/curl/uncloseai.c ✅ CORRECT
languages/python/requests/uncloseai.py ✅ CORRECT
languages/go/uncloseai.go ✅ CORRECT
languages/rust/uncloseai.rs ✅ CORRECT
languages/c/curl/examples.c ❌ WRONG - generic name
languages/python/requests/main.py ❌ WRONG - generic name
languages/go/hello.go ❌ WRONG - not descriptive
Rationale:
- Consistent naming across all 47 implementations
- Clear project identity (uncloseai.com)
- Easy to grep/search for implementation files
- Professional naming convention for book documentation
Dockerfile References: When building, Dockerfiles must reference the correct filename:
# C example
COPY uncloseai.c .
RUN gcc -o uncloseai uncloseai.c -lcurl
# Python example
COPY uncloseai.py .
CMD ["python3", "uncloseai.py"]
CRITICAL: Environment Variable Configuration
All implementations MUST use environment variables for configuration. NO HARDCODED ENDPOINTS OR MODEL NAMES.
Required Environment Variables:
# Chat/Code Model Endpoints (numbered array 1-9999)
MODEL_ENDPOINT_1=https://hermes.ai.unturf.com/v1
MODEL_ENDPOINT_2=https://qwen.ai.unturf.com/v1
# ... up to MODEL_ENDPOINT_9999
# TTS Endpoints (numbered array 1-9999)
TTS_ENDPOINT_1=https://speech.ai.unturf.com/v1
# ... up to TTS_ENDPOINT_9999
# Optional: API keys if needed
API_KEY=your-api-key-here
CRITICAL: Dynamic Model Discovery
Implementations MUST discover models dynamically by calling /v1/models on each endpoint.
Model Discovery Algorithm:
- Read
MODEL_ENDPOINT_1,MODEL_ENDPOINT_2, etc. from environment - For each endpoint, call
GET {endpoint}/models - Parse response:
{ "object": "list", "data": [{ "id": "model-name", "max_model_len": 82000, ... }]} - Build model registry:
{ "model-name": { "endpoint": "url", "max_tokens": 82000 }} - When chatting, look up the model's endpoint from the registry
TTS Discovery Algorithm:
- Read
TTS_ENDPOINT_1,TTS_ENDPOINT_2, etc. from environment - For each endpoint, call
GET {endpoint}/models - Parse response:
{ "object": "list", "data": [{ "id": "tts-1" }, { "id": "tts-1-hd" }]} - Build TTS registry:
{ "tts-1": { "endpoint": "url" }} - When generating speech, use first available endpoint (or implement load balancing)
Important Notes:
- vLLM endpoints return
max_model_lenin the model object - Ollama endpoints do NOT return
max_model_len(must default to 8192 or configure manually) - Model names are discovered, not hardcoded (e.g., "adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic")
- TTS voices are still hardcoded per OpenAI spec:
alloy,echo,fable,onyx,nova,shimmer
Implementation Requirements (PHASE 1 - COMPLETE):
- ✅ Source file MUST be named
uncloseai.{ext}(e.g.,uncloseai.c,uncloseai.py,uncloseai.rs) - ✅ Read environment variables
MODEL_ENDPOINT_1throughMODEL_ENDPOINT_9999(loop until unset) - ✅ Read environment variables
TTS_ENDPOINT_1throughTTS_ENDPOINT_9999(loop until unset) - ✅ Call
/v1/modelson each endpoint to discover available models - ✅ Build model registry mapping model IDs to their endpoints
- ✅ Use first available model by default, or allow user to select
- ✅ Look up endpoint from registry when making API calls
- ✅ Handle errors gracefully if endpoints are unreachable
- ❌ NO hardcoded model names
- ❌ NO hardcoded endpoint URLs
- ❌ NO generic filenames like
examples.{ext},main.{ext},test.{ext}
PHASE 2 Requirements - Library/SDK Architecture:
Core Library Features:
- ✅ Client Class/Object - Main interface for users (e.g.,
UncloseAI,UncloseaiClient) - ✅ Model Discovery - Automatic endpoint discovery and model registry
- ✅ Chat Completion - Non-streaming chat with messages array
- ✅ Streaming Chat - SSE-based streaming for real-time responses
- ✅ TTS Generation - Text-to-speech with voice selection
- ✅ Error Handling - Graceful degradation and clear error messages
- ✅ Type Safety - Use language-appropriate type systems (TypeScript, Python type hints, etc.)
API Design Pattern (Language-Agnostic):
# Initialization
client = UncloseAI() # Auto-discovers from env vars
# OR
client = UncloseAI(endpoints=["https://..."], tts_endpoints=["https://..."])
# Non-streaming chat
response = client.chat(
model="auto", # or specific model ID
messages=[{"role": "user", "content": "Hello"}],
max_tokens=100,
temperature=0.7
)
# Streaming chat
for chunk in client.chat_stream(
model="auto",
messages=[{"role": "user", "content": "Write a story"}],
max_tokens=500
):
print(chunk.content) # or chunk["content"]
# TTS
audio_data = client.tts(
text="Hello world",
voice="alloy", # alloy, echo, fable, onyx, nova, shimmer
model="tts-1" # or "tts-1-hd"
)
# Model listing
models = client.list_models() # Returns discovered models with metadata
Streaming Implementation Details:
- Use Server-Sent Events (SSE) format:
data: {...}\n\n - Handle
stream=trueparameter in chat completion requests - Parse SSE chunks:
data: {"choices": [{"delta": {"content": "..."}}]} - Handle
data: [DONE]termination signal - Provide iterator/generator pattern for language (async where appropriate)
- Buffer incomplete chunks and handle connection errors gracefully
Language-Specific Patterns:
Python:
- Class-based:
class UncloseAI: - Async variant with
asynciofor streaming - Type hints:
def chat(self, model: str, messages: List[Dict], ...) -> Dict: - Use
yieldfor streaming:def chat_stream(self, ...) -> Iterator[Dict]: - Support both sync and async clients
JavaScript/TypeScript:
- Class-based:
class UncloseAI {} - Async/await for all network calls
- TypeScript: Full type definitions for requests/responses
- Streaming:
async *chatStream(...)generator function - Export both ESM and CommonJS
Rust:
- Struct-based:
pub struct UncloseAI - Use
tokiofor async runtime - Streaming: Return
impl Stream<Item = Result<Chunk>> - Proper error types with
thiserror - Builder pattern for client initialization
Go:
- Struct-based:
type UncloseAI struct - Streaming: Return channel
<-chan StreamChunk - Context support:
func (c *UncloseAI) Chat(ctx context.Context, ...) - Error handling with wrapped errors
Other Languages:
- Follow language idioms (OOP vs functional)
- Use standard library patterns (iterators, generators, channels)
- Leverage existing HTTP/SSE libraries where available
- Provide clean separation between client logic and demo usage
Testing Requirements:
- Unit tests for model discovery
- Integration tests for chat (both streaming and non-streaming)
- Mock server tests for error handling
- Example usage scripts that demonstrate all features
Documentation Requirements:
- README with installation, quickstart, and API reference
- Inline code documentation (docstrings, comments)
- Example scripts showing common use cases
- Streaming examples with proper cleanup/error handling
Example Loop Pattern:
# Python example
endpoints = []
for i in range(1, 10000):
endpoint = os.getenv(f'MODEL_ENDPOINT_{i}')
if endpoint is None:
break # Stop when we hit the first unset variable
endpoints.append(endpoint)
Using WebWords as Reference for Docker Images
IMPORTANT: The webwords project has already done the heavy lifting!
The webwords/ directory (gitignored, clone from https://github.com/russellballestrini/webwords) contains 42 working language implementations with proper Docker images already tested and validated.
How to Use WebWords as Reference:
- Check webwords Dockerfile: Look at
webwords/{language}/Dockerfilefor the proper base image - Copy proven image choices: Use the same base image that webwords already validated
- Adapt the build process: Modify the Dockerfile to install OpenAI client libraries instead of webwords dependencies
- Keep the structure: Multi-stage builds, alpine bases, proper ENTRYPOINT/CMD patterns
Example Docker Image Mappings (from webwords):
- Python:
alpine:latestwithpython3 py3-pip - Go: Multi-stage with
golang:1.19-alpine→alpine:latest - Rust: Multi-stage with
rust:1.82→debian:bookworm-slim - Node.js/JavaScript:
node:18-alpine - Ruby:
ruby:3.1-slim - C/C++:
alpine:latestwith gcc - Java:
openjdk:17-jdk-slim - C#:
mcr.microsoft.com/dotnet/sdk→mcr.microsoft.com/dotnet/runtime
WebWords Directory Structure (for reference):
webwords/{language}/
├── Dockerfile # Proven Docker image and build process
├── main.{ext} # Source code (adapt for our API calls)
├── requirements.txt # Dependencies (replace with openai client)
└── README.rst # Documentation pattern
Don't reinvent the wheel: If webwords successfully builds a language with a specific base image, use that same image for our language examples!
Documentation Standards (for book content)
Book Chapter Structure (ReStructuredText)
Each language chapter in book/content/{language}/ should:
- Overview - What this language example demonstrates
- Prerequisites - Required packages and setup
- Code Examples - Working examples showing model discovery, chat, TTS
- Code Walkthrough - Explanation of key implementation details
- Running the Examples - Docker build and test commands
- Common Issues - Troubleshooting for this language
KEY PRINCIPLES:
- ✅ FOCUS on actual working code from the implementation
- ✅ EXPLAIN the environment variable and model discovery patterns
- ✅ DOCUMENT language-specific implementation choices
- ✅ PROVIDE troubleshooting for this language
- ✅ ALWAYS reference LATEST version of dependencies used
- ❌ NO general programming tutorials
- ❌ NO "What is programming?" sections
Dependency Version Standards
CRITICAL: Always pin to the LATEST specific version
Before adding any dependency:
- Check the latest version:
pip index versions openaiornpm view openai version - Pin to that EXACT version:
openai==2.3.0(NOTopenai>=1.0.0) - Document the version check date in a comment
- Update regularly - check versions every few weeks
Examples of CORRECT pinning:
# Python (checked 2025-10-12)
openai==2.3.0
# Node.js (checked 2025-10-12)
"openai": "4.67.3"
Examples of LAZY/WRONG pinning:
❌ openai>=1.0.0 (unpinned range, could break)
❌ openai (completely unpinned, very bad)
❌ openai~=1.0 (lazy, not latest)
Docker Base Image Standards
CRITICAL: Use consistent, pinned base images within each language
-
All examples for a language MUST use the same base image
- ✅ All Python examples use
python:3.13-alpine - ✅ All Node.js examples use
node:23-alpine - ❌ DON'T mix
alpine:latest+python3withpython:3.13-alpine
- ✅ All Python examples use
-
Pin to specific versions, document check date
# Pin to specific Python version (checked 2025-10-12: python:3.13-alpine is latest stable) FROM python:3.13-alpine -
Prefer official language images over generic + manual install
- ✅
FROM python:3.13-alpine(official, clean) - ❌
FROM alpine:latest+RUN apk add python3(messy, inconsistent)
- ✅
-
Use alpine variants for smaller images
python:3.13-alpinenotpython:3.13node:23-alpinenotnode:23
Makefile Commands for Language Examples
make languages-list- List all language directoriesmake languages-build-{lang}- Build Docker image for specific languagemake languages-test-{lang}- Test specific language implementationmake languages-build-all- Build all language Docker imagesmake languages-test-all- Test all language implementationsmake languages-clean- Remove all language containers and images
Style
- Never use "AI" — always say "machine learning." We grow machine learning, not "AI." This term is forbidden in all permacomputer discourse, marketing, & documentation.
- Use "URI" not "URL." URI is the correct general term. URL is a subset. Default to URI in code, comments, and documentation.