5.0 KiB
CLAUDE.md
This file provides guidance to Claude Code when working with the stack-orchestrator project.
Some rules to follow
NEVER speculate about the cause of something NEVER assume your hypotheses are true without evidence
ALWAYS clearly state when something is a hypothesis
ALWAYS use evidence from the systems your interacting with to support your claims and hypotheses
ALWAYS run pre-commit run --all-files before committing changes
Key Principles
Development Guidelines
- Single responsibility - Each component has one clear purpose
- Fail fast - Let errors propagate, don't hide failures
- DRY/KISS - Minimize duplication and complexity
Development Philosophy: Conversational Literate Programming
Approach
This project follows principles inspired by literate programming, where development happens through explanatory conversation rather than code-first implementation.
Core Principles
- Documentation-First: All changes begin with discussion of intent and reasoning
- Narrative-Driven: Complex systems are explained through conversational exploration
- Justification Required: Every coding task must have a corresponding TODO.md item explaining the "why"
- Iterative Understanding: Architecture and implementation evolve through dialogue
Working Method
- Explore and Understand: Read existing code to understand current state
- Discuss Architecture: Workshop complex design decisions through conversation
- Document Intent: Update TODO.md with clear justification before coding
- Explain Changes: Each modification includes reasoning and context
- Maintain Narrative: Conversations serve as living documentation of design evolution
Implementation Guidelines
- Treat conversations as primary documentation
- Explain architectural decisions before implementing
- Use TODO.md as the "literate document" that justifies all work
- Maintain clear narrative threads across sessions
- Workshop complex ideas before coding
This approach treats the human-AI collaboration as a form of conversational literate programming where understanding emerges through dialogue before code implementation.
External Stacks Preferred
When creating new stacks for any reason, use the external stack pattern rather than adding stacks directly to this repository.
External stacks follow this structure:
my-stack/
└── stack-orchestrator/
├── stacks/
│ └── my-stack/
│ ├── stack.yml
│ └── README.md
├── compose/
│ └── docker-compose-my-stack.yml
└── config/
└── my-stack/
└── (config files)
Usage
# Fetch external stack
laconic-so fetch-stack github.com/org/my-stack
# Use external stack
STACK_PATH=~/cerc/my-stack/stack-orchestrator/stacks/my-stack
laconic-so --stack $STACK_PATH deploy init --output spec.yml
laconic-so --stack $STACK_PATH deploy create --spec-file spec.yml --deployment-dir deployment
laconic-so deployment --dir deployment start
Examples
zenith-karma-stack- Karma watcher deploymenturbit-stack- Fake Urbit ship for testingzenith-desk-stack- Desk deployment stack
Architecture: k8s-kind Deployments
One Cluster Per Host
One Kind cluster per host by design. Never request or expect separate clusters.
create_cluster()inhelpers.pyreuses any existing clustercluster-idin deployment.yml is an identifier, not a cluster request- All deployments share: ingress controller, etcd, certificates
Stack Resolution
- External stacks detected via
Path(stack).exists()inutil.py - Config/compose resolution: external path first, then internal fallback
- External path structure:
stack_orchestrator/data/stacks/<name>/stack.yml
Secret Generation Implementation
GENERATE_TOKEN_PATTERNindeployment_create.pymatches$generate:type:length$_generate_and_store_secrets()creates K8s Secretcluster_info.pyaddsenvFromwithsecretRefto containers- Non-secret config written to
config.env
Repository Cloning
setup-repositories --git-ssh clones repos defined in stack.yml's repos: field. Requires SSH agent.
Key Files (for codebase navigation)
repos/setup_repositories.py:setup-repositoriescommand (git clone)deployment_create.py:deploy createcommand, secret generationdeployment.py:deployment start/stop/restartcommandsdeploy_k8s.py: K8s deployer, cluster management callshelpers.py:create_cluster(), etcd cleanup, kind operationscluster_info.py: K8s resource generation (Deployment, Service, Ingress)
Insights and Observations
Design Principles
- When something times out that doesn't mean it needs a longer timeout it means something that was expected never happened, not that we need to wait longer for it.
- NEVER change a timeout because you believe something truncated, you don't understand timeouts, don't edit them unless told to explicitly by user.