Compare commits

..

6 Commits

Author SHA1 Message Date
sck_0
c86c93582e feat: integrate official Anthropic and Vercel Labs skills
- Add 8 new skills (62 total, up from 58)
- Official Anthropic skills: docx, pdf, pptx, xlsx, brand-guidelines, internal-comms
- Vercel Labs skills: react-best-practices, web-design-guidelines
- Implement dual-versioning: -official/-anthropic and -community suffixes
- Update README with new skill registry and credits
- Regenerate skills_index.json (62 skills validated)
- Add comprehensive walkthrough.md

BREAKING CHANGE: Document skills (docx/pdf/pptx/xlsx) renamed with version suffixes
2026-01-15 07:49:19 +01:00
sck_0
d32f89a211 feat: add automation scripts and enhanced README
- Add validate_skills.py for skill format validation
- Add generate_index.py for generating skills_index.json
- Generate skills_index.json with metadata for all 58 skills
- Update README.md with categorization table and full skill registry
- Add Installation and How to Contribute sections
2026-01-14 20:49:05 +01:00
sck_0
1aa169c842 Fix: Remove duplicat header in README 2026-01-14 18:53:19 +01:00
sck_0
c9280cf9cf Docs: Correctly attribute core skills to Jesse Vincent (obra) and fix headers 2026-01-14 18:52:58 +01:00
sck_0
0fff14df81 Docs: Explicitly state compatibility with both Antigravity and Claude Code 2026-01-14 18:50:39 +01:00
sck_0
8bd204708b Fix: Ensure all skills are tracked as files, not submodules 2026-01-14 18:48:48 +01:00
1316 changed files with 88547 additions and 28 deletions

135
README.md
View File

@@ -1,62 +1,145 @@
# 🌌 Antigravity Awesome Skills
> **The Ultimate Collection of 50+ Agentic Skills for Claude Code (Antigravity)**
> **The Ultimate Collection of 60+ Agentic Skills for Claude Code (Antigravity)**
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Claude Code](https://img.shields.io/badge/AI-Claude%20Code-purple)](https://claude.ai)
[![Agentic](https://img.shields.io/badge/Agentic-Framework-blue)](https://github.com/guanyang/antigravity-skills)
**Antigravity Awesome Skills** is a curated, battle-tested collection of **58 high-performance skills** designed to supercharge your Claude Code agent using the Antigravity framework.
**Antigravity Awesome Skills** is a curated, battle-tested collection of **62 high-performance skills** compatible with both **Antigravity** and **Claude Code**, including official skills from **Anthropic** and **Vercel Labs**.
## 📍 Table of Contents
- [Features & Categories](#features--categories)
- [Full Skill Registry](#full-skill-registry-6262)
- [Installation](#installation)
- [How to Contribute](#how-to-contribute)
- [Credits & Sources](#credits--sources)
- [License](#license)
Whether you are using the Google Deepmind Antigravity framework or the standard Anthropic Claude Code CLI, these skills are designed to drop right in and supercharge your agent.
This repository aggregates the best capabilities from across the open-source community, transforming your AI assistant into a full-stack digital agency capable of Engineering, Design, Security, Marketing, and Autonomous Operations.
## 🚀 Features & Categories
## Features & Categories
- **🎨 Creative & Design**: Algorithmic art, Canvas design, Professional UI/UX, Design Systems.
- **🛠️ Development & Engineering**: TDD, Clean Architecture, Playwright E2E Testing, Systematic Debugging.
- **🛡️ Cybersecurity & Auditing**: Ethical Hacking, OWASP Audits, AWS Penetration Testing, SecOps.
- **🛸 Autonomous Agents**: Loki Mode (Startup-in-a-box), Subagent Orchestration.
- **📈 Business & Strategy**: Product Management (PRD/RICE), Marketing Strategy (SEO/ASO), Senior Architecture.
- **🏗️ Infrastructure**: Backend/Frontend Guidelines, Docker, Git Workflows.
The repository is organized into several key areas of expertise:
| Category | Skills Included |
| :----------------------- | :------------------------------------------------------------------------------------- |
| **🎨 Creative & Design** | UI/UX Pro Max, Frontend Design, Canvas, Algorithmic Art, Theme Factory, D3 Viz |
| **🛠️ Development** | TDD, Systematic Debugging, Webapp Testing, Backend/Frontend Guidelines, React Patterns |
| **🛡️ Cybersecurity** | Ethical Hacking, AWS Pentesting, OWASP Top 100, Pentest Checklists |
| **🛸 Autonomous** | **Loki Mode** (Startup-in-a-box), Subagent Orchestration, Parallel Execution |
| **📈 Strategy** | Product Manager Toolkit, Content Creator, ASO, Doc Co-authoring, Brainstorming |
| **🏗️ Infrastructure** | Linux Shell Scripting, Git Worktrees, Conventional Commits, File Organization |
---
## 📦 Installation
## Full Skill Registry (62/62)
Below is the complete list of available skills. Each skill folder contains a `SKILL.md` that can be imported into Antigravity or Claude Code.
> [!NOTE] > **Document Skills**: We provide both **community** and **official Anthropic** versions for DOCX, PDF, PPTX, and XLSX. Locally, the official versions are used by default (via symlinks). In the repository, both versions are available for flexibility.
| Skill Name | Description | Path |
| :------------------------------- | :------------------------------------------------------------ | :--------------------------------------------- |
| **Algorithmic Art** | Creative generative art using p5.js and seeded randomness. | `skills/algorithmic-art` |
| **App Store Optimization** | Complete ASO toolkit for iOS and Android app performance. | `skills/app-store-optimization` |
| **AWS Pentesting** | Specialized security assessment for Amazon Web Services. | `skills/aws-penetration-testing` |
| **Backend Guidelines** | Core architecture patterns for Node/Express microservices. | `skills/backend-dev-guidelines` |
| **Brainstorming** | Requirement discovery and intent exploration framework. | `skills/brainstorming` |
| **Brand Guidelines (Anthropic)** | Official Anthropic brand styling and visual standards. | `skills/brand-guidelines-anthropic` ⭐ NEW |
| **Brand Guidelines (Community)** | Community-contributed brand guidelines and templates. | `skills/brand-guidelines-community` |
| **Canvas Design** | Beautiful static visual design in PDF and PNG. | `skills/canvas-design` |
| **Claude D3.js** | Advanced data visualization with D3.js. | `skills/claude-d3js-skill` |
| **Content Creator** | SEO-optimized marketing and brand voice toolkit. | `skills/content-creator` |
| **Core Components** | Design system tokens and baseline UI patterns. | `skills/core-components` |
| **Doc Co-authoring** | Structured workflow for technical documentation. | `skills/doc-coauthoring` |
| **DOCX (Official)** | Official Anthropic MS Word document manipulation. | `skills/docx-official` ⭐ NEW |
| **Ethical Hacking** | Comprehensive penetration testing lifecycle methodology. | `skills/ethical-hacking-methodology` |
| **Frontend Design** | Production-grade UI component implementation. | `skills/frontend-design` |
| **Frontend Guidelines** | Modern React/TS development patterns and file structure. | `skills/frontend-dev-guidelines` |
| **Git Pushing** | Automated staging and conventional commits. | `skills/git-pushing` |
| **Internal Comms (Anthropic)** | Official Anthropic corporate communication templates. | `skills/internal-comms-anthropic` ⭐ NEW |
| **Internal Comms (Community)** | Community-contributed communication templates. | `skills/internal-comms-community` |
| **Kaizen** | Continuous improvement and error-proofing (Poka-Yoke). | `skills/kaizen` |
| **Linux Shell Scripting** | Production-ready shell scripts for automation. | `skills/linux-shell-scripting` |
| **Loki Mode** | Fully autonomous startup development engine. | `skills/loki-mode` |
| **MCP Builder** | High-quality Model Context Protocol (MCP) server creation. | `skills/mcp-builder` |
| **NotebookLM** | Source-grounded querying via Google NotebookLM. | `skills/notebooklm` |
| **PDF (Official)** | Official Anthropic PDF document manipulation. | `skills/pdf-official` ⭐ NEW |
| **Pentest Checklist** | Structured security assessment planning and scoping. | `skills/pentest-checklist` |
| **PPTX (Official)** | Official Anthropic PowerPoint manipulation. | `skills/pptx-official` ⭐ NEW |
| **Product Toolkit** | RICE prioritization and product discovery frameworks. | `skills/product-manager-toolkit` |
| **Prompt Engineering** | Expert patterns for LLM instruction optimization. | `skills/prompt-engineering` |
| **React Best Practices** | Vercel's 40+ performance optimization rules for React. | `skills/react-best-practices` ⭐ NEW (Vercel) |
| **React UI Patterns** | Standardized loading states and error handling for React. | `skills/react-ui-patterns` |
| **Senior Architect** | Scalable system design and architecture diagrams. | `skills/senior-architect` |
| **Skill Creator** | Meta-skill for building high-performance agentic skills. | `skills/skill-creator` |
| **Software Architecture** | Quality-focused design principles and analysis. | `skills/software-architecture` |
| **Systematic Debugging** | Root cause analysis and structured fix verification. | `skills/systematic-debugging` |
| **TDD** | Test-Driven Development workflow and red-green-refactor. | `skills/test-driven-development` |
| **UI/UX Pro Max** | Advanced design intelligence and 50+ styling options. | `skills/ui-ux-pro-max` |
| **Web Artifacts** | Complex React/Tailwind/Shadcn UI artifact builder. | `skills/web-artifacts-builder` |
| **Web Design Guidelines** | Vercel's 100+ UI/UX audit rules (accessibility, performance). | `skills/web-design-guidelines` ⭐ NEW (Vercel) |
| **Webapp Testing** | Local web application testing with Playwright. | `skills/webapp-testing` |
| **XLSX (Official)** | Official Anthropic Excel spreadsheet manipulation. | `skills/xlsx-official` ⭐ NEW |
> [!TIP]
> Use the `validate_skills.py` script in the `scripts/` directory to ensure all skills are properly formatted and ready for use.
---
## Installation
To use these skills with **Antigravity** or **Claude Code**, clone this repository into your agent's skills directory:
```bash
# Clone directly into your skills folder
git clone https://github.com/sickn33/antigravity-awesome-skills.git .agent/skills
```
Or copy valid markdown files (`SKILL.md`) to your existing configuration.
---
## How to Contribute
We welcome contributions from the community! To add a new skill:
1. **Fork** the repository.
2. **Create a new directory** inside `skills/` for your skill.
3. **Add a `SKILL.md`** with the required frontmatter (name and description).
4. **Run validation**: `python3 scripts/validate_skills.py`.
5. **Submit a Pull Request**.
Please ensure your skill follows the Antigravity/Claude Code best practices.
---
## 🏆 Credits & Sources
## Credits & Sources
This collection would not be possible without the incredible work of the Claude Code community. This repository is an aggregation of the following open-source projects:
This collection would not be possible without the incredible work of the Claude Code community and official sources:
### 🌟 Core Foundation
### Official Sources
- **[guanyang/antigravity-skills](https://github.com/guanyang/antigravity-skills)**: The original framework and core set of 33 skills.
- **[anthropics/skills](https://github.com/anthropics/skills)**: Official Anthropic skills repository - Document manipulation (DOCX, PDF, PPTX, XLSX), Brand Guidelines, Internal Communications.
- **[vercel-labs/agent-skills](https://github.com/vercel-labs/agent-skills)**: Vercel Labs official skills - React Best Practices, Web Design Guidelines.
### 👥 Community Contributors
### Community Contributors
- **[diet103/claude-code-infrastructure-showcase](https://github.com/diet103/claude-code-infrastructure-showcase)**: Infrastructure, Backend/Frontend Guidelines, and Skill Development meta-skills.
- **[ChrisWiles/claude-code-showcase](https://github.com/ChrisWiles/claude-code-showcase)**: React UI patterns, Design System components, and Testing factories.
- **[travisvn/awesome-claude-skills](https://github.com/travisvn/awesome-claude-skills)**: Autonomous agents (Loki Mode), Playwright integration, and D3.js visualization.
- **[zebbern/claude-code-guide](https://github.com/zebbern/claude-code-guide)**: Comprehensive Security suite (Ethical Hacking, OWASP, AWS Auditing).
- **[alirezarezvani/claude-skills](https://github.com/alirezarezvani/claude-skills)**: Senior Engineering roles, Product Management toolkit, Content Creator & ASO skills.
- **[obra/superpowers](https://github.com/obra/superpowers)**: The original "Superpowers" by Jesse Vincent.
- **[guanyang/antigravity-skills](https://github.com/guanyang/antigravity-skills)**: Core Antigravity extensions.
- **[diet103/claude-code-infrastructure-showcase](https://github.com/diet103/claude-code-infrastructure-showcase)**: Infrastructure and Backend/Frontend Guidelines.
- **[ChrisWiles/claude-code-showcase](https://github.com/ChrisWiles/claude-code-showcase)**: React UI patterns and Design Systems.
- **[travisvn/awesome-claude-skills](https://github.com/travisvn/awesome-claude-skills)**: Loki Mode and Playwright integration.
- **[zebbern/claude-code-guide](https://github.com/zebbern/claude-code-guide)**: Comprehensive Security suite.
- **[alirezarezvani/claude-skills](https://github.com/alirezarezvani/claude-skills)**: Senior Engineering and PM toolkit.
---
## 🛡️ License
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
Individual skills may retain the licenses of their original repositories.
MIT License. See [LICENSE](LICENSE) for details.
---
**Keywords**: Claude Code, Antigravity, Agentic Skills, MCT, Model Context Protocol, AI Agents, Autonomous Coding, Prompt Engineering, Security Auditing, React Patterns, Microservices.
**Keywords**: Claude Code, Antigravity, Agentic Skills, MCT, AI Agents, Autonomous Coding, Security Auditing, React Patterns.

72
scripts/generate_index.py Normal file
View File

@@ -0,0 +1,72 @@
import os
import json
import re
def generate_index(skills_dir, output_file):
print(f"🏗️ Generating index from: {skills_dir}")
skills = []
for root, dirs, files in os.walk(skills_dir):
if "SKILL.md" in files:
skill_path = os.path.join(root, "SKILL.md")
dir_name = os.path.basename(root)
skill_info = {
"id": dir_name,
"path": os.path.relpath(root, os.path.dirname(skills_dir)),
"name": dir_name.replace("-", " ").title(),
"description": ""
}
with open(skill_path, 'r', encoding='utf-8') as f:
content = f.read()
# Try to extract from frontmatter first
fm_match = re.search(r'^---\s*(.*?)\s*---', content, re.DOTALL)
if fm_match:
fm_content = fm_match.group(1)
name_fm = re.search(r'^name:\s*(.+)$', fm_content, re.MULTILINE)
desc_fm = re.search(r'^description:\s*(.+)$', fm_content, re.MULTILINE)
if name_fm:
skill_info["name"] = name_fm.group(1).strip()
if desc_fm:
skill_info["description"] = desc_fm.group(1).strip()
# Fallback to Header and First Paragraph if needed
if not skill_info["description"] or skill_info["description"] == "":
name_match = re.search(r'^#\s+(.+)$', content, re.MULTILINE)
if name_match and not fm_match: # Only override if no frontmatter name
skill_info["name"] = name_match.group(1).strip()
# Extract first paragraph
body = content
if fm_match:
body = content[fm_match.end():].strip()
lines = body.split('\n')
desc_lines = []
for line in lines:
if line.startswith('#') or not line.strip():
if desc_lines: break
continue
desc_lines.append(line.strip())
if desc_lines:
skill_info["description"] = " ".join(desc_lines)[:150] + "..."
skills.append(skill_info)
skills.sort(key=lambda x: x["name"])
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(skills, f, indent=2)
print(f"✅ Generated index with {len(skills)} skills at: {output_file}")
return skills
if __name__ == "__main__":
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
skills_path = os.path.join(base_dir, "skills")
output_path = os.path.join(base_dir, "skills_index.json")
generate_index(skills_path, output_path)

View File

@@ -0,0 +1,50 @@
import os
import re
def validate_skills(skills_dir):
print(f"🔍 Validating skills in: {skills_dir}")
errors = []
skill_count = 0
for root, dirs, files in os.walk(skills_dir):
if "SKILL.md" in files:
skill_count += 1
skill_path = os.path.join(root, "SKILL.md")
rel_path = os.path.relpath(skill_path, skills_dir)
with open(skill_path, 'r', encoding='utf-8') as f:
content = f.read()
# Check for Frontmatter or Header
has_frontmatter = content.strip().startswith("---")
has_header = re.search(r'^#\s+', content, re.MULTILINE)
if not (has_frontmatter or has_header):
errors.append(f"{rel_path}: Missing frontmatter or top-level heading")
if has_frontmatter:
# Basic check for name and description in frontmatter
fm_match = re.search(r'^---\s*(.*?)\s*---', content, re.DOTALL)
if fm_match:
fm_content = fm_match.group(1)
if "name:" not in fm_content:
errors.append(f"⚠️ {rel_path}: Frontmatter missing 'name:'")
if "description:" not in fm_content:
errors.append(f"⚠️ {rel_path}: Frontmatter missing 'description:'")
else:
errors.append(f"{rel_path}: Malformed frontmatter")
print(f"✅ Found and checked {skill_count} skills.")
if errors:
print("\n⚠️ Validation Results:")
for err in errors:
print(err)
return False
else:
print("✨ All skills passed basic validation!")
return True
if __name__ == "__main__":
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
skills_path = os.path.join(base_dir, "skills")
validate_skills(skills_path)

View File

@@ -0,0 +1,73 @@
---
name: brand-guidelines
description: Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
license: Complete terms in LICENSE.txt
---
# Anthropic Brand Styling
## Overview
To access Anthropic's official brand identity and style resources, use this skill.
**Keywords**: branding, corporate identity, visual identity, post-processing, styling, brand colors, typography, Anthropic brand, visual formatting, visual design
## Brand Guidelines
### Colors
**Main Colors:**
- Dark: `#141413` - Primary text and dark backgrounds
- Light: `#faf9f5` - Light backgrounds and text on dark
- Mid Gray: `#b0aea5` - Secondary elements
- Light Gray: `#e8e6dc` - Subtle backgrounds
**Accent Colors:**
- Orange: `#d97757` - Primary accent
- Blue: `#6a9bcc` - Secondary accent
- Green: `#788c5d` - Tertiary accent
### Typography
- **Headings**: Poppins (with Arial fallback)
- **Body Text**: Lora (with Georgia fallback)
- **Note**: Fonts should be pre-installed in your environment for best results
## Features
### Smart Font Application
- Applies Poppins font to headings (24pt and larger)
- Applies Lora font to body text
- Automatically falls back to Arial/Georgia if custom fonts unavailable
- Preserves readability across all systems
### Text Styling
- Headings (24pt+): Poppins font
- Body text: Lora font
- Smart color selection based on background
- Preserves text hierarchy and formatting
### Shape and Accent Colors
- Non-text shapes use accent colors
- Cycles through orange, blue, and green accents
- Maintains visual interest while staying on-brand
## Technical Details
### Font Management
- Uses system-installed Poppins and Lora fonts when available
- Provides automatic fallback to Arial (headings) and Georgia (body)
- No font installation required - works with existing system fonts
- For best results, pre-install Poppins and Lora fonts in your environment
### Color Application
- Uses RGB color values for precise brand matching
- Applied via python-pptx's RGBColor class
- Maintains color fidelity across different systems

Submodule skills/claude-d3js-skill deleted from e198c87d03

View File

@@ -0,0 +1,820 @@
---
name: d3-viz
description: Creating interactive data visualisations using d3.js. This skill should be used when creating custom charts, graphs, network diagrams, geographic visualisations, or any complex SVG-based data visualisation that requires fine-grained control over visual elements, transitions, or interactions. Use this for bespoke visualisations beyond standard charting libraries, whether in React, Vue, Svelte, vanilla JavaScript, or any other environment.
---
# D3.js Visualisation
## Overview
This skill provides guidance for creating sophisticated, interactive data visualisations using d3.js. D3.js (Data-Driven Documents) excels at binding data to DOM elements and applying data-driven transformations to create custom, publication-quality visualisations with precise control over every visual element. The techniques work across any JavaScript environment, including vanilla JavaScript, React, Vue, Svelte, and other frameworks.
## When to use d3.js
**Use d3.js for:**
- Custom visualisations requiring unique visual encodings or layouts
- Interactive explorations with complex pan, zoom, or brush behaviours
- Network/graph visualisations (force-directed layouts, tree diagrams, hierarchies, chord diagrams)
- Geographic visualisations with custom projections
- Visualisations requiring smooth, choreographed transitions
- Publication-quality graphics with fine-grained styling control
- Novel chart types not available in standard libraries
**Consider alternatives for:**
- 3D visualisations - use Three.js instead
## Core workflow
### 1. Set up d3.js
Import d3 at the top of your script:
```javascript
import * as d3 from 'd3';
```
Or use the CDN version (7.x):
```html
<script src="https://d3js.org/d3.v7.min.js"></script>
```
All modules (scales, axes, shapes, transitions, etc.) are accessible through the `d3` namespace.
### 2. Choose the integration pattern
**Pattern A: Direct DOM manipulation (recommended for most cases)**
Use d3 to select DOM elements and manipulate them imperatively. This works in any JavaScript environment:
```javascript
function drawChart(data) {
if (!data || data.length === 0) return;
const svg = d3.select('#chart'); // Select by ID, class, or DOM element
// Clear previous content
svg.selectAll("*").remove();
// Set up dimensions
const width = 800;
const height = 400;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
// Create scales, axes, and draw visualisation
// ... d3 code here ...
}
// Call when data changes
drawChart(myData);
```
**Pattern B: Declarative rendering (for frameworks with templating)**
Use d3 for data calculations (scales, layouts) but render elements via your framework:
```javascript
function getChartElements(data) {
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([0, 400]);
return data.map((d, i) => ({
x: 50,
y: i * 30,
width: xScale(d.value),
height: 25
}));
}
// In React: {getChartElements(data).map((d, i) => <rect key={i} {...d} fill="steelblue" />)}
// In Vue: v-for directive over the returned array
// In vanilla JS: Create elements manually from the returned data
```
Use Pattern A for complex visualisations with transitions, interactions, or when leveraging d3's full capabilities. Use Pattern B for simpler visualisations or when your framework prefers declarative rendering.
### 3. Structure the visualisation code
Follow this standard structure in your drawing function:
```javascript
function drawVisualization(data) {
if (!data || data.length === 0) return;
const svg = d3.select('#chart'); // Or pass a selector/element
svg.selectAll("*").remove(); // Clear previous render
// 1. Define dimensions
const width = 800;
const height = 400;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
// 2. Create main group with margins
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
// 3. Create scales
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.x)])
.range([0, innerWidth]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.y)])
.range([innerHeight, 0]); // Note: inverted for SVG coordinates
// 4. Create and append axes
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale);
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(xAxis);
g.append("g")
.call(yAxis);
// 5. Bind data and create visual elements
g.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", d => xScale(d.x))
.attr("cy", d => yScale(d.y))
.attr("r", 5)
.attr("fill", "steelblue");
}
// Call when data changes
drawVisualization(myData);
```
### 4. Implement responsive sizing
Make visualisations responsive to container size:
```javascript
function setupResponsiveChart(containerId, data) {
const container = document.getElementById(containerId);
const svg = d3.select(`#${containerId}`).append('svg');
function updateChart() {
const { width, height } = container.getBoundingClientRect();
svg.attr('width', width).attr('height', height);
// Redraw visualisation with new dimensions
drawChart(data, svg, width, height);
}
// Update on initial load
updateChart();
// Update on window resize
window.addEventListener('resize', updateChart);
// Return cleanup function
return () => window.removeEventListener('resize', updateChart);
}
// Usage:
// const cleanup = setupResponsiveChart('chart-container', myData);
// cleanup(); // Call when component unmounts or element removed
```
Or use ResizeObserver for more direct container monitoring:
```javascript
function setupResponsiveChartWithObserver(svgElement, data) {
const observer = new ResizeObserver(() => {
const { width, height } = svgElement.getBoundingClientRect();
d3.select(svgElement)
.attr('width', width)
.attr('height', height);
// Redraw visualisation
drawChart(data, d3.select(svgElement), width, height);
});
observer.observe(svgElement.parentElement);
return () => observer.disconnect();
}
```
## Common visualisation patterns
### Bar chart
```javascript
function drawBarChart(data, svgElement) {
if (!data || data.length === 0) return;
const svg = d3.select(svgElement);
svg.selectAll("*").remove();
const width = 800;
const height = 400;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
const xScale = d3.scaleBand()
.domain(data.map(d => d.category))
.range([0, innerWidth])
.padding(0.1);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([innerHeight, 0]);
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(d3.axisBottom(xScale));
g.append("g")
.call(d3.axisLeft(yScale));
g.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => xScale(d.category))
.attr("y", d => yScale(d.value))
.attr("width", xScale.bandwidth())
.attr("height", d => innerHeight - yScale(d.value))
.attr("fill", "steelblue");
}
// Usage:
// drawBarChart(myData, document.getElementById('chart'));
```
### Line chart
```javascript
const line = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.value))
.curve(d3.curveMonotoneX); // Smooth curve
g.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 2)
.attr("d", line);
```
### Scatter plot
```javascript
g.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", d => xScale(d.x))
.attr("cy", d => yScale(d.y))
.attr("r", d => sizeScale(d.size)) // Optional: size encoding
.attr("fill", d => colourScale(d.category)) // Optional: colour encoding
.attr("opacity", 0.7);
```
### Chord diagram
A chord diagram shows relationships between entities in a circular layout, with ribbons representing flows between them:
```javascript
function drawChordDiagram(data) {
// data format: array of objects with source, target, and value
// Example: [{ source: 'A', target: 'B', value: 10 }, ...]
if (!data || data.length === 0) return;
const svg = d3.select('#chart');
svg.selectAll("*").remove();
const width = 600;
const height = 600;
const innerRadius = Math.min(width, height) * 0.3;
const outerRadius = innerRadius + 30;
// Create matrix from data
const nodes = Array.from(new Set(data.flatMap(d => [d.source, d.target])));
const matrix = Array.from({ length: nodes.length }, () => Array(nodes.length).fill(0));
data.forEach(d => {
const i = nodes.indexOf(d.source);
const j = nodes.indexOf(d.target);
matrix[i][j] += d.value;
matrix[j][i] += d.value;
});
// Create chord layout
const chord = d3.chord()
.padAngle(0.05)
.sortSubgroups(d3.descending);
const arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
const ribbon = d3.ribbon()
.source(d => d.source)
.target(d => d.target);
const colourScale = d3.scaleOrdinal(d3.schemeCategory10)
.domain(nodes);
const g = svg.append("g")
.attr("transform", `translate(${width / 2},${height / 2})`);
const chords = chord(matrix);
// Draw ribbons
g.append("g")
.attr("fill-opacity", 0.67)
.selectAll("path")
.data(chords)
.join("path")
.attr("d", ribbon)
.attr("fill", d => colourScale(nodes[d.source.index]))
.attr("stroke", d => d3.rgb(colourScale(nodes[d.source.index])).darker());
// Draw groups (arcs)
const group = g.append("g")
.selectAll("g")
.data(chords.groups)
.join("g");
group.append("path")
.attr("d", arc)
.attr("fill", d => colourScale(nodes[d.index]))
.attr("stroke", d => d3.rgb(colourScale(nodes[d.index])).darker());
// Add labels
group.append("text")
.each(d => { d.angle = (d.startAngle + d.endAngle) / 2; })
.attr("dy", "0.31em")
.attr("transform", d => `rotate(${(d.angle * 180 / Math.PI) - 90})translate(${outerRadius + 30})${d.angle > Math.PI ? "rotate(180)" : ""}`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text((d, i) => nodes[i])
.style("font-size", "12px");
}
```
### Heatmap
A heatmap uses colour to encode values in a two-dimensional grid, useful for showing patterns across categories:
```javascript
function drawHeatmap(data) {
// data format: array of objects with row, column, and value
// Example: [{ row: 'A', column: 'X', value: 10 }, ...]
if (!data || data.length === 0) return;
const svg = d3.select('#chart');
svg.selectAll("*").remove();
const width = 800;
const height = 600;
const margin = { top: 100, right: 30, bottom: 30, left: 100 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
// Get unique rows and columns
const rows = Array.from(new Set(data.map(d => d.row)));
const columns = Array.from(new Set(data.map(d => d.column)));
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
// Create scales
const xScale = d3.scaleBand()
.domain(columns)
.range([0, innerWidth])
.padding(0.01);
const yScale = d3.scaleBand()
.domain(rows)
.range([0, innerHeight])
.padding(0.01);
// Colour scale for values
const colourScale = d3.scaleSequential(d3.interpolateYlOrRd)
.domain([0, d3.max(data, d => d.value)]);
// Draw rectangles
g.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => xScale(d.column))
.attr("y", d => yScale(d.row))
.attr("width", xScale.bandwidth())
.attr("height", yScale.bandwidth())
.attr("fill", d => colourScale(d.value));
// Add x-axis labels
svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`)
.selectAll("text")
.data(columns)
.join("text")
.attr("x", d => xScale(d) + xScale.bandwidth() / 2)
.attr("y", -10)
.attr("text-anchor", "middle")
.text(d => d)
.style("font-size", "12px");
// Add y-axis labels
svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`)
.selectAll("text")
.data(rows)
.join("text")
.attr("x", -10)
.attr("y", d => yScale(d) + yScale.bandwidth() / 2)
.attr("dy", "0.35em")
.attr("text-anchor", "end")
.text(d => d)
.style("font-size", "12px");
// Add colour legend
const legendWidth = 20;
const legendHeight = 200;
const legend = svg.append("g")
.attr("transform", `translate(${width - 60},${margin.top})`);
const legendScale = d3.scaleLinear()
.domain(colourScale.domain())
.range([legendHeight, 0]);
const legendAxis = d3.axisRight(legendScale)
.ticks(5);
// Draw colour gradient in legend
for (let i = 0; i < legendHeight; i++) {
legend.append("rect")
.attr("y", i)
.attr("width", legendWidth)
.attr("height", 1)
.attr("fill", colourScale(legendScale.invert(i)));
}
legend.append("g")
.attr("transform", `translate(${legendWidth},0)`)
.call(legendAxis);
}
```
### Pie chart
```javascript
const pie = d3.pie()
.value(d => d.value)
.sort(null);
const arc = d3.arc()
.innerRadius(0)
.outerRadius(Math.min(width, height) / 2 - 20);
const colourScale = d3.scaleOrdinal(d3.schemeCategory10);
const g = svg.append("g")
.attr("transform", `translate(${width / 2},${height / 2})`);
g.selectAll("path")
.data(pie(data))
.join("path")
.attr("d", arc)
.attr("fill", (d, i) => colourScale(i))
.attr("stroke", "white")
.attr("stroke-width", 2);
```
### Force-directed network
```javascript
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id).distance(100))
.force("charge", d3.forceManyBody().strength(-300))
.force("center", d3.forceCenter(width / 2, height / 2));
const link = g.selectAll("line")
.data(links)
.join("line")
.attr("stroke", "#999")
.attr("stroke-width", 1);
const node = g.selectAll("circle")
.data(nodes)
.join("circle")
.attr("r", 8)
.attr("fill", "steelblue")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
simulation.on("tick", () => {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node
.attr("cx", d => d.x)
.attr("cy", d => d.y);
});
function dragstarted(event) {
if (!event.active) simulation.alphaTarget(0.3).restart();
event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
}
function dragged(event) {
event.subject.fx = event.x;
event.subject.fy = event.y;
}
function dragended(event) {
if (!event.active) simulation.alphaTarget(0);
event.subject.fx = null;
event.subject.fy = null;
}
```
## Adding interactivity
### Tooltips
```javascript
// Create tooltip div (outside SVG)
const tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("visibility", "hidden")
.style("background-color", "white")
.style("border", "1px solid #ddd")
.style("padding", "10px")
.style("border-radius", "4px")
.style("pointer-events", "none");
// Add to elements
circles
.on("mouseover", function(event, d) {
d3.select(this).attr("opacity", 1);
tooltip
.style("visibility", "visible")
.html(`<strong>${d.label}</strong><br/>Value: ${d.value}`);
})
.on("mousemove", function(event) {
tooltip
.style("top", (event.pageY - 10) + "px")
.style("left", (event.pageX + 10) + "px");
})
.on("mouseout", function() {
d3.select(this).attr("opacity", 0.7);
tooltip.style("visibility", "hidden");
});
```
### Zoom and pan
```javascript
const zoom = d3.zoom()
.scaleExtent([0.5, 10])
.on("zoom", (event) => {
g.attr("transform", event.transform);
});
svg.call(zoom);
```
### Click interactions
```javascript
circles
.on("click", function(event, d) {
// Handle click (dispatch event, update app state, etc.)
console.log("Clicked:", d);
// Visual feedback
d3.selectAll("circle").attr("fill", "steelblue");
d3.select(this).attr("fill", "orange");
// Optional: dispatch custom event for your framework/app to listen to
// window.dispatchEvent(new CustomEvent('chartClick', { detail: d }));
});
```
## Transitions and animations
Add smooth transitions to visual changes:
```javascript
// Basic transition
circles
.transition()
.duration(750)
.attr("r", 10);
// Chained transitions
circles
.transition()
.duration(500)
.attr("fill", "orange")
.transition()
.duration(500)
.attr("r", 15);
// Staggered transitions
circles
.transition()
.delay((d, i) => i * 50)
.duration(500)
.attr("cy", d => yScale(d.value));
// Custom easing
circles
.transition()
.duration(1000)
.ease(d3.easeBounceOut)
.attr("r", 10);
```
## Scales reference
### Quantitative scales
```javascript
// Linear scale
const xScale = d3.scaleLinear()
.domain([0, 100])
.range([0, 500]);
// Log scale (for exponential data)
const logScale = d3.scaleLog()
.domain([1, 1000])
.range([0, 500]);
// Power scale
const powScale = d3.scalePow()
.exponent(2)
.domain([0, 100])
.range([0, 500]);
// Time scale
const timeScale = d3.scaleTime()
.domain([new Date(2020, 0, 1), new Date(2024, 0, 1)])
.range([0, 500]);
```
### Ordinal scales
```javascript
// Band scale (for bar charts)
const bandScale = d3.scaleBand()
.domain(['A', 'B', 'C', 'D'])
.range([0, 400])
.padding(0.1);
// Point scale (for line/scatter categories)
const pointScale = d3.scalePoint()
.domain(['A', 'B', 'C', 'D'])
.range([0, 400]);
// Ordinal scale (for colours)
const colourScale = d3.scaleOrdinal(d3.schemeCategory10);
```
### Sequential scales
```javascript
// Sequential colour scale
const colourScale = d3.scaleSequential(d3.interpolateBlues)
.domain([0, 100]);
// Diverging colour scale
const divScale = d3.scaleDiverging(d3.interpolateRdBu)
.domain([-10, 0, 10]);
```
## Best practices
### Data preparation
Always validate and prepare data before visualisation:
```javascript
// Filter invalid values
const cleanData = data.filter(d => d.value != null && !isNaN(d.value));
// Sort data if order matters
const sortedData = [...data].sort((a, b) => b.value - a.value);
// Parse dates
const parsedData = data.map(d => ({
...d,
date: d3.timeParse("%Y-%m-%d")(d.date)
}));
```
### Performance optimisation
For large datasets (>1000 elements):
```javascript
// Use canvas instead of SVG for many elements
// Use quadtree for collision detection
// Simplify paths with d3.line().curve(d3.curveStep)
// Implement virtual scrolling for large lists
// Use requestAnimationFrame for custom animations
```
### Accessibility
Make visualisations accessible:
```javascript
// Add ARIA labels
svg.attr("role", "img")
.attr("aria-label", "Bar chart showing quarterly revenue");
// Add title and description
svg.append("title").text("Quarterly Revenue 2024");
svg.append("desc").text("Bar chart showing revenue growth across four quarters");
// Ensure sufficient colour contrast
// Provide keyboard navigation for interactive elements
// Include data table alternative
```
### Styling
Use consistent, professional styling:
```javascript
// Define colour palettes upfront
const colours = {
primary: '#4A90E2',
secondary: '#7B68EE',
background: '#F5F7FA',
text: '#333333',
gridLines: '#E0E0E0'
};
// Apply consistent typography
svg.selectAll("text")
.style("font-family", "Inter, sans-serif")
.style("font-size", "12px");
// Use subtle grid lines
g.selectAll(".tick line")
.attr("stroke", colours.gridLines)
.attr("stroke-dasharray", "2,2");
```
## Common issues and solutions
**Issue**: Axes not appearing
- Ensure scales have valid domains (check for NaN values)
- Verify axis is appended to correct group
- Check transform translations are correct
**Issue**: Transitions not working
- Call `.transition()` before attribute changes
- Ensure elements have unique keys for proper data binding
- Check that useEffect dependencies include all changing data
**Issue**: Responsive sizing not working
- Use ResizeObserver or window resize listener
- Update dimensions in state to trigger re-render
- Ensure SVG has width/height attributes or viewBox
**Issue**: Performance problems
- Limit number of DOM elements (consider canvas for >1000 items)
- Debounce resize handlers
- Use `.join()` instead of separate enter/update/exit selections
- Avoid unnecessary re-renders by checking dependencies
## Resources
### references/
Contains detailed reference materials:
- `d3-patterns.md` - Comprehensive collection of visualisation patterns and code examples
- `scale-reference.md` - Complete guide to d3 scales with examples
- `colour-schemes.md` - D3 colour schemes and palette recommendations
### assets/
Contains boilerplate templates:
- `chart-template.js` - Starter template for basic chart
- `interactive-template.js` - Template with tooltips, zoom, and interactions
- `sample-data.json` - Example datasets for testing
These templates work with vanilla JavaScript, React, Vue, Svelte, or any other JavaScript environment. Adapt them as needed for your specific framework.
To use these resources, read the relevant files when detailed guidance is needed for specific visualisation types or patterns.

View File

@@ -0,0 +1,106 @@
import { useEffect, useRef, useState } from 'react';
import * as d3 from 'd3';
function BasicChart({ data }) {
const svgRef = useRef();
useEffect(() => {
if (!data || data.length === 0) return;
// Select SVG element
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove(); // Clear previous content
// Define dimensions and margins
const width = 800;
const height = 400;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
// Create main group with margins
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
// Create scales
const xScale = d3.scaleBand()
.domain(data.map(d => d.label))
.range([0, innerWidth])
.padding(0.1);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([innerHeight, 0])
.nice();
// Create and append axes
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale);
g.append("g")
.attr("class", "x-axis")
.attr("transform", `translate(0,${innerHeight})`)
.call(xAxis);
g.append("g")
.attr("class", "y-axis")
.call(yAxis);
// Bind data and create visual elements (bars in this example)
g.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => xScale(d.label))
.attr("y", d => yScale(d.value))
.attr("width", xScale.bandwidth())
.attr("height", d => innerHeight - yScale(d.value))
.attr("fill", "steelblue");
// Optional: Add axis labels
g.append("text")
.attr("class", "axis-label")
.attr("x", innerWidth / 2)
.attr("y", innerHeight + margin.bottom - 5)
.attr("text-anchor", "middle")
.text("Category");
g.append("text")
.attr("class", "axis-label")
.attr("transform", "rotate(-90)")
.attr("x", -innerHeight / 2)
.attr("y", -margin.left + 15)
.attr("text-anchor", "middle")
.text("Value");
}, [data]);
return (
<div className="chart-container">
<svg
ref={svgRef}
width="800"
height="400"
style={{ border: '1px solid #ddd' }}
/>
</div>
);
}
// Example usage
export default function App() {
const sampleData = [
{ label: 'A', value: 30 },
{ label: 'B', value: 80 },
{ label: 'C', value: 45 },
{ label: 'D', value: 60 },
{ label: 'E', value: 20 },
{ label: 'F', value: 90 }
];
return (
<div className="p-8">
<h1 className="text-2xl font-bold mb-4">Basic D3.js Chart</h1>
<BasicChart data={sampleData} />
</div>
);
}

View File

@@ -0,0 +1,227 @@
import { useEffect, useRef, useState } from 'react';
import * as d3 from 'd3';
function InteractiveChart({ data }) {
const svgRef = useRef();
const tooltipRef = useRef();
const [selectedPoint, setSelectedPoint] = useState(null);
useEffect(() => {
if (!data || data.length === 0) return;
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();
// Dimensions
const width = 800;
const height = 500;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
// Create main group
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
// Scales
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.x)])
.range([0, innerWidth])
.nice();
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.y)])
.range([innerHeight, 0])
.nice();
const sizeScale = d3.scaleSqrt()
.domain([0, d3.max(data, d => d.size || 10)])
.range([3, 20]);
const colourScale = d3.scaleOrdinal(d3.schemeCategory10);
// Add zoom behaviour
const zoom = d3.zoom()
.scaleExtent([0.5, 10])
.on("zoom", (event) => {
g.attr("transform", `translate(${margin.left + event.transform.x},${margin.top + event.transform.y}) scale(${event.transform.k})`);
});
svg.call(zoom);
// Axes
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale);
const xAxisGroup = g.append("g")
.attr("class", "x-axis")
.attr("transform", `translate(0,${innerHeight})`)
.call(xAxis);
const yAxisGroup = g.append("g")
.attr("class", "y-axis")
.call(yAxis);
// Grid lines
g.append("g")
.attr("class", "grid")
.attr("opacity", 0.1)
.call(d3.axisLeft(yScale)
.tickSize(-innerWidth)
.tickFormat(""));
g.append("g")
.attr("class", "grid")
.attr("opacity", 0.1)
.attr("transform", `translate(0,${innerHeight})`)
.call(d3.axisBottom(xScale)
.tickSize(-innerHeight)
.tickFormat(""));
// Tooltip
const tooltip = d3.select(tooltipRef.current);
// Data points
const circles = g.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", d => xScale(d.x))
.attr("cy", d => yScale(d.y))
.attr("r", d => sizeScale(d.size || 10))
.attr("fill", d => colourScale(d.category || 'default'))
.attr("stroke", "#fff")
.attr("stroke-width", 2)
.attr("opacity", 0.7)
.style("cursor", "pointer");
// Hover interactions
circles
.on("mouseover", function(event, d) {
// Enlarge circle
d3.select(this)
.transition()
.duration(200)
.attr("opacity", 1)
.attr("stroke-width", 3);
// Show tooltip
tooltip
.style("display", "block")
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 10) + "px")
.html(`
<strong>${d.label || 'Point'}</strong><br/>
X: ${d.x.toFixed(2)}<br/>
Y: ${d.y.toFixed(2)}<br/>
${d.category ? `Category: ${d.category}<br/>` : ''}
${d.size ? `Size: ${d.size.toFixed(2)}` : ''}
`);
})
.on("mousemove", function(event) {
tooltip
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 10) + "px");
})
.on("mouseout", function() {
// Restore circle
d3.select(this)
.transition()
.duration(200)
.attr("opacity", 0.7)
.attr("stroke-width", 2);
// Hide tooltip
tooltip.style("display", "none");
})
.on("click", function(event, d) {
// Highlight selected point
circles.attr("stroke", "#fff").attr("stroke-width", 2);
d3.select(this)
.attr("stroke", "#000")
.attr("stroke-width", 3);
setSelectedPoint(d);
});
// Add transition on initial render
circles
.attr("r", 0)
.transition()
.duration(800)
.delay((d, i) => i * 20)
.attr("r", d => sizeScale(d.size || 10));
// Axis labels
g.append("text")
.attr("class", "axis-label")
.attr("x", innerWidth / 2)
.attr("y", innerHeight + margin.bottom - 5)
.attr("text-anchor", "middle")
.style("font-size", "14px")
.text("X Axis");
g.append("text")
.attr("class", "axis-label")
.attr("transform", "rotate(-90)")
.attr("x", -innerHeight / 2)
.attr("y", -margin.left + 15)
.attr("text-anchor", "middle")
.style("font-size", "14px")
.text("Y Axis");
}, [data]);
return (
<div className="relative">
<svg
ref={svgRef}
width="800"
height="500"
style={{ border: '1px solid #ddd', cursor: 'grab' }}
/>
<div
ref={tooltipRef}
style={{
position: 'absolute',
display: 'none',
padding: '10px',
background: 'white',
border: '1px solid #ddd',
borderRadius: '4px',
pointerEvents: 'none',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
fontSize: '13px',
zIndex: 1000
}}
/>
{selectedPoint && (
<div className="mt-4 p-4 bg-blue-50 rounded border border-blue-200">
<h3 className="font-bold mb-2">Selected Point</h3>
<pre className="text-sm">{JSON.stringify(selectedPoint, null, 2)}</pre>
</div>
)}
</div>
);
}
// Example usage
export default function App() {
const sampleData = Array.from({ length: 50 }, (_, i) => ({
id: i,
label: `Point ${i + 1}`,
x: Math.random() * 100,
y: Math.random() * 100,
size: Math.random() * 30 + 5,
category: ['A', 'B', 'C', 'D'][Math.floor(Math.random() * 4)]
}));
return (
<div className="p-8">
<h1 className="text-2xl font-bold mb-2">Interactive D3.js Chart</h1>
<p className="text-gray-600 mb-4">
Hover over points for details. Click to select. Scroll to zoom. Drag to pan.
</p>
<InteractiveChart data={sampleData} />
</div>
);
}

View File

@@ -0,0 +1,115 @@
{
"timeSeries": [
{ "date": "2024-01-01", "value": 120, "category": "A" },
{ "date": "2024-02-01", "value": 135, "category": "A" },
{ "date": "2024-03-01", "value": 128, "category": "A" },
{ "date": "2024-04-01", "value": 145, "category": "A" },
{ "date": "2024-05-01", "value": 152, "category": "A" },
{ "date": "2024-06-01", "value": 168, "category": "A" },
{ "date": "2024-07-01", "value": 175, "category": "A" },
{ "date": "2024-08-01", "value": 182, "category": "A" },
{ "date": "2024-09-01", "value": 190, "category": "A" },
{ "date": "2024-10-01", "value": 185, "category": "A" },
{ "date": "2024-11-01", "value": 195, "category": "A" },
{ "date": "2024-12-01", "value": 210, "category": "A" }
],
"categorical": [
{ "label": "Product A", "value": 450, "category": "Electronics" },
{ "label": "Product B", "value": 320, "category": "Electronics" },
{ "label": "Product C", "value": 580, "category": "Clothing" },
{ "label": "Product D", "value": 290, "category": "Clothing" },
{ "label": "Product E", "value": 410, "category": "Food" },
{ "label": "Product F", "value": 370, "category": "Food" }
],
"scatterData": [
{ "x": 12, "y": 45, "size": 25, "category": "Group A", "label": "Point 1" },
{ "x": 25, "y": 62, "size": 35, "category": "Group A", "label": "Point 2" },
{ "x": 38, "y": 55, "size": 20, "category": "Group B", "label": "Point 3" },
{ "x": 45, "y": 78, "size": 40, "category": "Group B", "label": "Point 4" },
{ "x": 52, "y": 68, "size": 30, "category": "Group C", "label": "Point 5" },
{ "x": 65, "y": 85, "size": 45, "category": "Group C", "label": "Point 6" },
{ "x": 72, "y": 72, "size": 28, "category": "Group A", "label": "Point 7" },
{ "x": 85, "y": 92, "size": 50, "category": "Group B", "label": "Point 8" }
],
"hierarchical": {
"name": "Root",
"children": [
{
"name": "Category 1",
"children": [
{ "name": "Item 1.1", "value": 100 },
{ "name": "Item 1.2", "value": 150 },
{ "name": "Item 1.3", "value": 80 }
]
},
{
"name": "Category 2",
"children": [
{ "name": "Item 2.1", "value": 200 },
{ "name": "Item 2.2", "value": 120 },
{ "name": "Item 2.3", "value": 90 }
]
},
{
"name": "Category 3",
"children": [
{ "name": "Item 3.1", "value": 180 },
{ "name": "Item 3.2", "value": 140 }
]
}
]
},
"network": {
"nodes": [
{ "id": "A", "group": 1 },
{ "id": "B", "group": 1 },
{ "id": "C", "group": 1 },
{ "id": "D", "group": 2 },
{ "id": "E", "group": 2 },
{ "id": "F", "group": 3 },
{ "id": "G", "group": 3 },
{ "id": "H", "group": 3 }
],
"links": [
{ "source": "A", "target": "B", "value": 1 },
{ "source": "A", "target": "C", "value": 2 },
{ "source": "B", "target": "C", "value": 1 },
{ "source": "C", "target": "D", "value": 3 },
{ "source": "D", "target": "E", "value": 2 },
{ "source": "E", "target": "F", "value": 1 },
{ "source": "F", "target": "G", "value": 2 },
{ "source": "F", "target": "H", "value": 1 },
{ "source": "G", "target": "H", "value": 1 }
]
},
"stackedData": [
{ "group": "Q1", "seriesA": 30, "seriesB": 40, "seriesC": 25 },
{ "group": "Q2", "seriesA": 45, "seriesB": 35, "seriesC": 30 },
{ "group": "Q3", "seriesA": 40, "seriesB": 50, "seriesC": 35 },
{ "group": "Q4", "seriesA": 55, "seriesB": 45, "seriesC": 40 }
],
"geographicPoints": [
{ "city": "London", "latitude": 51.5074, "longitude": -0.1278, "value": 8900000 },
{ "city": "Paris", "latitude": 48.8566, "longitude": 2.3522, "value": 2140000 },
{ "city": "Berlin", "latitude": 52.5200, "longitude": 13.4050, "value": 3645000 },
{ "city": "Madrid", "latitude": 40.4168, "longitude": -3.7038, "value": 3223000 },
{ "city": "Rome", "latitude": 41.9028, "longitude": 12.4964, "value": 2873000 }
],
"divergingData": [
{ "category": "Item A", "value": -15 },
{ "category": "Item B", "value": 8 },
{ "category": "Item C", "value": -22 },
{ "category": "Item D", "value": 18 },
{ "category": "Item E", "value": -5 },
{ "category": "Item F", "value": 25 },
{ "category": "Item G", "value": -12 },
{ "category": "Item H", "value": 14 }
]
}

View File

@@ -0,0 +1,564 @@
# D3.js Colour Schemes and Palette Recommendations
Comprehensive guide to colour selection in data visualisation with d3.js.
## Built-in categorical colour schemes
### Category10 (default)
```javascript
d3.schemeCategory10
// ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd',
// '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']
```
**Characteristics:**
- 10 distinct colours
- Good colour-blind accessibility
- Default choice for most categorical data
- Balanced saturation and brightness
**Use cases:** General purpose categorical encoding, legend items, multiple data series
### Tableau10
```javascript
d3.schemeTableau10
```
**Characteristics:**
- 10 colours optimised for data visualisation
- Professional appearance
- Excellent distinguishability
**Use cases:** Business dashboards, professional reports, presentations
### Accent
```javascript
d3.schemeAccent
// 8 colours with high saturation
```
**Characteristics:**
- Bright, vibrant colours
- High contrast
- Modern aesthetic
**Use cases:** Highlighting important categories, modern web applications
### Dark2
```javascript
d3.schemeDark2
// 8 darker, muted colours
```
**Characteristics:**
- Subdued palette
- Professional appearance
- Good for dark backgrounds
**Use cases:** Dark mode visualisations, professional contexts
### Paired
```javascript
d3.schemePaired
// 12 colours in pairs of similar hues
```
**Characteristics:**
- Pairs of light and dark variants
- Useful for nested categories
- 12 distinct colours
**Use cases:** Grouped bar charts, hierarchical categories, before/after comparisons
### Pastel1 & Pastel2
```javascript
d3.schemePastel1 // 9 colours
d3.schemePastel2 // 8 colours
```
**Characteristics:**
- Soft, low-saturation colours
- Gentle appearance
- Good for large areas
**Use cases:** Background colours, subtle categorisation, calming visualisations
### Set1, Set2, Set3
```javascript
d3.schemeSet1 // 9 colours - vivid
d3.schemeSet2 // 8 colours - muted
d3.schemeSet3 // 12 colours - pastel
```
**Characteristics:**
- Set1: High saturation, maximum distinction
- Set2: Professional, balanced
- Set3: Subtle, many categories
**Use cases:** Varied based on visual hierarchy needs
## Sequential colour schemes
Sequential schemes map continuous data from low to high values using a single hue or gradient.
### Single-hue sequential
**Blues:**
```javascript
d3.interpolateBlues
d3.schemeBlues[9] // 9-step discrete version
```
**Other single-hue options:**
- `d3.interpolateGreens` / `d3.schemeGreens`
- `d3.interpolateOranges` / `d3.schemeOranges`
- `d3.interpolatePurples` / `d3.schemePurples`
- `d3.interpolateReds` / `d3.schemeReds`
- `d3.interpolateGreys` / `d3.schemeGreys`
**Use cases:**
- Simple heat maps
- Choropleth maps
- Density plots
- Single-metric visualisations
### Multi-hue sequential
**Viridis (recommended):**
```javascript
d3.interpolateViridis
```
**Characteristics:**
- Perceptually uniform
- Colour-blind friendly
- Print-safe
- No visual dead zones
- Monotonically increasing perceived lightness
**Other perceptually-uniform options:**
- `d3.interpolatePlasma` - Purple to yellow
- `d3.interpolateInferno` - Black to white through red/orange
- `d3.interpolateMagma` - Black to white through purple
- `d3.interpolateCividis` - Colour-blind optimised
**Colour-blind accessible:**
```javascript
d3.interpolateTurbo // Rainbow-like but perceptually uniform
d3.interpolateCool // Cyan to magenta
d3.interpolateWarm // Orange to yellow
```
**Use cases:**
- Scientific visualisation
- Medical imaging
- Any high-precision data visualisation
- Accessible visualisations
### Traditional sequential
**Yellow-Orange-Red:**
```javascript
d3.interpolateYlOrRd
d3.schemeYlOrRd[9]
```
**Yellow-Green-Blue:**
```javascript
d3.interpolateYlGnBu
d3.schemeYlGnBu[9]
```
**Other multi-hue:**
- `d3.interpolateBuGn` - Blue to green
- `d3.interpolateBuPu` - Blue to purple
- `d3.interpolateGnBu` - Green to blue
- `d3.interpolateOrRd` - Orange to red
- `d3.interpolatePuBu` - Purple to blue
- `d3.interpolatePuBuGn` - Purple to blue-green
- `d3.interpolatePuRd` - Purple to red
- `d3.interpolateRdPu` - Red to purple
- `d3.interpolateYlGn` - Yellow to green
- `d3.interpolateYlOrBr` - Yellow to orange-brown
**Use cases:** Traditional data visualisation, familiar colour associations (temperature, vegetation, water)
## Diverging colour schemes
Diverging schemes highlight deviations from a central value using two distinct hues.
### Red-Blue (temperature)
```javascript
d3.interpolateRdBu
d3.schemeRdBu[11]
```
**Characteristics:**
- Intuitive temperature metaphor
- Strong contrast
- Clear positive/negative distinction
**Use cases:** Temperature, profit/loss, above/below average, correlation
### Red-Yellow-Blue
```javascript
d3.interpolateRdYlBu
d3.schemeRdYlBu[11]
```
**Characteristics:**
- Three-colour gradient
- Softer transition through yellow
- More visual steps
**Use cases:** When extreme values need emphasis and middle needs visibility
### Other diverging schemes
**Traffic light:**
```javascript
d3.interpolateRdYlGn // Red (bad) to green (good)
```
**Spectral (rainbow):**
```javascript
d3.interpolateSpectral // Full spectrum
```
**Other options:**
- `d3.interpolateBrBG` - Brown to blue-green
- `d3.interpolatePiYG` - Pink to yellow-green
- `d3.interpolatePRGn` - Purple to green
- `d3.interpolatePuOr` - Purple to orange
- `d3.interpolateRdGy` - Red to grey
**Use cases:** Choose based on semantic meaning and accessibility needs
## Colour-blind friendly palettes
### General guidelines
1. **Avoid red-green combinations** (most common colour blindness)
2. **Use blue-orange diverging** instead of red-green
3. **Add texture or patterns** as redundant encoding
4. **Test with simulation tools**
### Recommended colour-blind safe schemes
**Categorical:**
```javascript
// Okabe-Ito palette (colour-blind safe)
const okabePalette = [
'#E69F00', // Orange
'#56B4E9', // Sky blue
'#009E73', // Bluish green
'#F0E442', // Yellow
'#0072B2', // Blue
'#D55E00', // Vermillion
'#CC79A7', // Reddish purple
'#000000' // Black
];
const colourScale = d3.scaleOrdinal()
.domain(categories)
.range(okabePalette);
```
**Sequential:**
```javascript
// Use Viridis, Cividis, or Blues
d3.interpolateViridis // Best overall
d3.interpolateCividis // Optimised for CVD
d3.interpolateBlues // Simple, safe
```
**Diverging:**
```javascript
// Use blue-orange instead of red-green
d3.interpolateBrBG
d3.interpolatePuOr
```
## Custom colour palettes
### Creating custom sequential
```javascript
const customSequential = d3.scaleLinear()
.domain([0, 100])
.range(['#e8f4f8', '#006d9c']) // Light to dark blue
.interpolate(d3.interpolateLab); // Perceptually uniform
```
### Creating custom diverging
```javascript
const customDiverging = d3.scaleLinear()
.domain([0, 50, 100])
.range(['#ca0020', '#f7f7f7', '#0571b0']) // Red, grey, blue
.interpolate(d3.interpolateLab);
```
### Creating custom categorical
```javascript
// Brand colours
const brandPalette = [
'#FF6B6B', // Primary red
'#4ECDC4', // Secondary teal
'#45B7D1', // Tertiary blue
'#FFA07A', // Accent coral
'#98D8C8' // Accent mint
];
const colourScale = d3.scaleOrdinal()
.domain(categories)
.range(brandPalette);
```
## Semantic colour associations
### Universal colour meanings
**Red:**
- Danger, error, negative
- High temperature
- Debt, loss
**Green:**
- Success, positive
- Growth, vegetation
- Profit, gain
**Blue:**
- Trust, calm
- Water, cold
- Information, neutral
**Yellow/Orange:**
- Warning, caution
- Energy, warmth
- Attention
**Grey:**
- Neutral, inactive
- Missing data
- Background
### Context-specific palettes
**Financial:**
```javascript
const financialColours = {
profit: '#27ae60',
loss: '#e74c3c',
neutral: '#95a5a6',
highlight: '#3498db'
};
```
**Temperature:**
```javascript
const temperatureScale = d3.scaleSequential(d3.interpolateRdYlBu)
.domain([40, -10]); // Hot to cold (reversed)
```
**Traffic/Status:**
```javascript
const statusColours = {
success: '#27ae60',
warning: '#f39c12',
error: '#e74c3c',
info: '#3498db',
neutral: '#95a5a6'
};
```
## Accessibility best practices
### Contrast ratios
Ensure sufficient contrast between colours and backgrounds:
```javascript
// Good contrast example
const highContrast = {
background: '#ffffff',
text: '#2c3e50',
primary: '#3498db',
secondary: '#e74c3c'
};
```
**WCAG guidelines:**
- Normal text: 4.5:1 minimum
- Large text: 3:1 minimum
- UI components: 3:1 minimum
### Redundant encoding
Never rely solely on colour to convey information:
```javascript
// Add patterns or shapes
const symbols = ['circle', 'square', 'triangle', 'diamond'];
// Add text labels
// Use line styles (solid, dashed, dotted)
// Use size encoding
```
### Testing
Test visualisations for colour blindness:
- Chrome DevTools (Rendering > Emulate vision deficiencies)
- Colour Oracle (free desktop application)
- Coblis (online simulator)
## Professional colour recommendations
### Data journalism
```javascript
// Guardian style
const guardianPalette = [
'#005689', // Guardian blue
'#c70000', // Guardian red
'#7d0068', // Guardian pink
'#951c75', // Guardian purple
];
// FT style
const ftPalette = [
'#0f5499', // FT blue
'#990f3d', // FT red
'#593380', // FT purple
'#262a33', // FT black
];
```
### Academic/Scientific
```javascript
// Nature journal style
const naturePalette = [
'#0071b2', // Blue
'#d55e00', // Vermillion
'#009e73', // Green
'#f0e442', // Yellow
];
// Use Viridis for continuous data
const scientificScale = d3.scaleSequential(d3.interpolateViridis);
```
### Corporate/Business
```javascript
// Professional, conservative
const corporatePalette = [
'#003f5c', // Dark blue
'#58508d', // Purple
'#bc5090', // Magenta
'#ff6361', // Coral
'#ffa600' // Orange
];
```
## Dynamic colour selection
### Based on data range
```javascript
function selectColourScheme(data) {
const extent = d3.extent(data);
const hasNegative = extent[0] < 0;
const hasPositive = extent[1] > 0;
if (hasNegative && hasPositive) {
// Diverging: data crosses zero
return d3.scaleSequentialSymlog(d3.interpolateRdBu)
.domain([extent[0], 0, extent[1]]);
} else {
// Sequential: all positive or all negative
return d3.scaleSequential(d3.interpolateViridis)
.domain(extent);
}
}
```
### Based on category count
```javascript
function selectCategoricalScheme(categories) {
const n = categories.length;
if (n <= 10) {
return d3.scaleOrdinal(d3.schemeTableau10);
} else if (n <= 12) {
return d3.scaleOrdinal(d3.schemePaired);
} else {
// For many categories, use sequential with quantize
return d3.scaleQuantize()
.domain([0, n - 1])
.range(d3.quantize(d3.interpolateRainbow, n));
}
}
```
## Common colour mistakes to avoid
1. **Rainbow gradients for sequential data**
- Problem: Not perceptually uniform, hard to read
- Solution: Use Viridis, Blues, or other uniform schemes
2. **Red-green for diverging (colour blindness)**
- Problem: 8% of males can't distinguish
- Solution: Use blue-orange or purple-green
3. **Too many categorical colours**
- Problem: Hard to distinguish and remember
- Solution: Limit to 5-8 categories, use grouping
4. **Insufficient contrast**
- Problem: Poor readability
- Solution: Test contrast ratios, use darker colours on light backgrounds
5. **Culturally inconsistent colours**
- Problem: Confusing semantic meaning
- Solution: Research colour associations for target audience
6. **Inverted temperature scales**
- Problem: Counterintuitive (red = cold)
- Solution: Red/orange = hot, blue = cold
## Quick reference guide
**Need to show...**
- **Categories (≤10):** `d3.schemeCategory10` or `d3.schemeTableau10`
- **Categories (>10):** `d3.schemePaired` or group categories
- **Sequential (general):** `d3.interpolateViridis`
- **Sequential (scientific):** `d3.interpolateViridis` or `d3.interpolatePlasma`
- **Sequential (temperature):** `d3.interpolateRdYlBu` (inverted)
- **Diverging (zero):** `d3.interpolateRdBu` or `d3.interpolateBrBG`
- **Diverging (good/bad):** `d3.interpolateRdYlGn` (inverted)
- **Colour-blind safe (categorical):** Okabe-Ito palette (shown above)
- **Colour-blind safe (sequential):** `d3.interpolateCividis` or `d3.interpolateBlues`
- **Colour-blind safe (diverging):** `d3.interpolatePuOr` or `d3.interpolateBrBG`
**Always remember:**
1. Test for colour-blindness
2. Ensure sufficient contrast
3. Use semantic colours appropriately
4. Add redundant encoding (patterns, labels)
5. Keep it simple (fewer colours = clearer visualisation)

View File

@@ -0,0 +1,869 @@
# D3.js Visualisation Patterns
This reference provides detailed code patterns for common d3.js visualisation types.
## Hierarchical visualisations
### Tree diagram
```javascript
useEffect(() => {
if (!data) return;
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();
const width = 800;
const height = 600;
const tree = d3.tree().size([height - 100, width - 200]);
const root = d3.hierarchy(data);
tree(root);
const g = svg.append("g")
.attr("transform", "translate(100,50)");
// Links
g.selectAll("path")
.data(root.links())
.join("path")
.attr("d", d3.linkHorizontal()
.x(d => d.y)
.y(d => d.x))
.attr("fill", "none")
.attr("stroke", "#555")
.attr("stroke-width", 2);
// Nodes
const node = g.selectAll("g")
.data(root.descendants())
.join("g")
.attr("transform", d => `translate(${d.y},${d.x})`);
node.append("circle")
.attr("r", 6)
.attr("fill", d => d.children ? "#555" : "#999");
node.append("text")
.attr("dy", "0.31em")
.attr("x", d => d.children ? -8 : 8)
.attr("text-anchor", d => d.children ? "end" : "start")
.text(d => d.data.name)
.style("font-size", "12px");
}, [data]);
```
### Treemap
```javascript
useEffect(() => {
if (!data) return;
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();
const width = 800;
const height = 600;
const root = d3.hierarchy(data)
.sum(d => d.value)
.sort((a, b) => b.value - a.value);
d3.treemap()
.size([width, height])
.padding(2)
.round(true)(root);
const colourScale = d3.scaleOrdinal(d3.schemeCategory10);
const cell = svg.selectAll("g")
.data(root.leaves())
.join("g")
.attr("transform", d => `translate(${d.x0},${d.y0})`);
cell.append("rect")
.attr("width", d => d.x1 - d.x0)
.attr("height", d => d.y1 - d.y0)
.attr("fill", d => colourScale(d.parent.data.name))
.attr("stroke", "white")
.attr("stroke-width", 2);
cell.append("text")
.attr("x", 4)
.attr("y", 16)
.text(d => d.data.name)
.style("font-size", "12px")
.style("fill", "white");
}, [data]);
```
### Sunburst diagram
```javascript
useEffect(() => {
if (!data) return;
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();
const width = 600;
const height = 600;
const radius = Math.min(width, height) / 2;
const root = d3.hierarchy(data)
.sum(d => d.value)
.sort((a, b) => b.value - a.value);
const partition = d3.partition()
.size([2 * Math.PI, radius]);
partition(root);
const arc = d3.arc()
.startAngle(d => d.x0)
.endAngle(d => d.x1)
.innerRadius(d => d.y0)
.outerRadius(d => d.y1);
const colourScale = d3.scaleOrdinal(d3.schemeCategory10);
const g = svg.append("g")
.attr("transform", `translate(${width / 2},${height / 2})`);
g.selectAll("path")
.data(root.descendants())
.join("path")
.attr("d", arc)
.attr("fill", d => colourScale(d.depth))
.attr("stroke", "white")
.attr("stroke-width", 1);
}, [data]);
```
### Chord diagram
```javascript
function drawChordDiagram(data) {
// data format: array of objects with source, target, and value
// Example: [{ source: 'A', target: 'B', value: 10 }, ...]
if (!data || data.length === 0) return;
const svg = d3.select('#chart');
svg.selectAll("*").remove();
const width = 600;
const height = 600;
const innerRadius = Math.min(width, height) * 0.3;
const outerRadius = innerRadius + 30;
// Create matrix from data
const nodes = Array.from(new Set(data.flatMap(d => [d.source, d.target])));
const matrix = Array.from({ length: nodes.length }, () => Array(nodes.length).fill(0));
data.forEach(d => {
const i = nodes.indexOf(d.source);
const j = nodes.indexOf(d.target);
matrix[i][j] += d.value;
matrix[j][i] += d.value;
});
// Create chord layout
const chord = d3.chord()
.padAngle(0.05)
.sortSubgroups(d3.descending);
const arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
const ribbon = d3.ribbon()
.source(d => d.source)
.target(d => d.target);
const colourScale = d3.scaleOrdinal(d3.schemeCategory10)
.domain(nodes);
const g = svg.append("g")
.attr("transform", `translate(${width / 2},${height / 2})`);
const chords = chord(matrix);
// Draw ribbons
g.append("g")
.attr("fill-opacity", 0.67)
.selectAll("path")
.data(chords)
.join("path")
.attr("d", ribbon)
.attr("fill", d => colourScale(nodes[d.source.index]))
.attr("stroke", d => d3.rgb(colourScale(nodes[d.source.index])).darker());
// Draw groups (arcs)
const group = g.append("g")
.selectAll("g")
.data(chords.groups)
.join("g");
group.append("path")
.attr("d", arc)
.attr("fill", d => colourScale(nodes[d.index]))
.attr("stroke", d => d3.rgb(colourScale(nodes[d.index])).darker());
// Add labels
group.append("text")
.each(d => { d.angle = (d.startAngle + d.endAngle) / 2; })
.attr("dy", "0.31em")
.attr("transform", d => `rotate(${(d.angle * 180 / Math.PI) - 90})translate(${outerRadius + 30})${d.angle > Math.PI ? "rotate(180)" : ""}`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text((d, i) => nodes[i])
.style("font-size", "12px");
}
// Data format example:
// const data = [
// { source: 'Category A', target: 'Category B', value: 100 },
// { source: 'Category A', target: 'Category C', value: 50 },
// { source: 'Category B', target: 'Category C', value: 75 }
// ];
// drawChordDiagram(data);
```
## Advanced chart types
### Heatmap
```javascript
function drawHeatmap(data) {
// data format: array of objects with row, column, and value
// Example: [{ row: 'A', column: 'X', value: 10 }, ...]
if (!data || data.length === 0) return;
const svg = d3.select('#chart');
svg.selectAll("*").remove();
const width = 800;
const height = 600;
const margin = { top: 100, right: 30, bottom: 30, left: 100 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
// Get unique rows and columns
const rows = Array.from(new Set(data.map(d => d.row)));
const columns = Array.from(new Set(data.map(d => d.column)));
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
// Create scales
const xScale = d3.scaleBand()
.domain(columns)
.range([0, innerWidth])
.padding(0.01);
const yScale = d3.scaleBand()
.domain(rows)
.range([0, innerHeight])
.padding(0.01);
// Colour scale for values (sequential from light to dark red)
const colourScale = d3.scaleSequential(d3.interpolateYlOrRd)
.domain([0, d3.max(data, d => d.value)]);
// Draw rectangles
g.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => xScale(d.column))
.attr("y", d => yScale(d.row))
.attr("width", xScale.bandwidth())
.attr("height", yScale.bandwidth())
.attr("fill", d => colourScale(d.value));
// Add x-axis labels
svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`)
.selectAll("text")
.data(columns)
.join("text")
.attr("x", d => xScale(d) + xScale.bandwidth() / 2)
.attr("y", -10)
.attr("text-anchor", "middle")
.text(d => d)
.style("font-size", "12px");
// Add y-axis labels
svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`)
.selectAll("text")
.data(rows)
.join("text")
.attr("x", -10)
.attr("y", d => yScale(d) + yScale.bandwidth() / 2)
.attr("dy", "0.35em")
.attr("text-anchor", "end")
.text(d => d)
.style("font-size", "12px");
// Add colour legend
const legendWidth = 20;
const legendHeight = 200;
const legend = svg.append("g")
.attr("transform", `translate(${width - 60},${margin.top})`);
const legendScale = d3.scaleLinear()
.domain(colourScale.domain())
.range([legendHeight, 0]);
const legendAxis = d3.axisRight(legendScale).ticks(5);
// Draw colour gradient in legend
for (let i = 0; i < legendHeight; i++) {
legend.append("rect")
.attr("y", i)
.attr("width", legendWidth)
.attr("height", 1)
.attr("fill", colourScale(legendScale.invert(i)));
}
legend.append("g")
.attr("transform", `translate(${legendWidth},0)`)
.call(legendAxis);
}
// Data format example:
// const data = [
// { row: 'Monday', column: 'Morning', value: 42 },
// { row: 'Monday', column: 'Afternoon', value: 78 },
// { row: 'Tuesday', column: 'Morning', value: 65 },
// { row: 'Tuesday', column: 'Afternoon', value: 55 }
// ];
// drawHeatmap(data);
```
### Area chart with gradient
```javascript
useEffect(() => {
if (!data || data.length === 0) return;
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();
const width = 800;
const height = 400;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
// Define gradient
const defs = svg.append("defs");
const gradient = defs.append("linearGradient")
.attr("id", "areaGradient")
.attr("x1", "0%")
.attr("x2", "0%")
.attr("y1", "0%")
.attr("y2", "100%");
gradient.append("stop")
.attr("offset", "0%")
.attr("stop-color", "steelblue")
.attr("stop-opacity", 0.8);
gradient.append("stop")
.attr("offset", "100%")
.attr("stop-color", "steelblue")
.attr("stop-opacity", 0.1);
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
const xScale = d3.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([0, innerWidth]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([innerHeight, 0]);
const area = d3.area()
.x(d => xScale(d.date))
.y0(innerHeight)
.y1(d => yScale(d.value))
.curve(d3.curveMonotoneX);
g.append("path")
.datum(data)
.attr("fill", "url(#areaGradient)")
.attr("d", area);
const line = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.value))
.curve(d3.curveMonotoneX);
g.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 2)
.attr("d", line);
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(d3.axisBottom(xScale));
g.append("g")
.call(d3.axisLeft(yScale));
}, [data]);
```
### Stacked bar chart
```javascript
useEffect(() => {
if (!data || data.length === 0) return;
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();
const width = 800;
const height = 400;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
const categories = Object.keys(data[0]).filter(k => k !== 'group');
const stackedData = d3.stack().keys(categories)(data);
const xScale = d3.scaleBand()
.domain(data.map(d => d.group))
.range([0, innerWidth])
.padding(0.1);
const yScale = d3.scaleLinear()
.domain([0, d3.max(stackedData[stackedData.length - 1], d => d[1])])
.range([innerHeight, 0]);
const colourScale = d3.scaleOrdinal(d3.schemeCategory10);
g.selectAll("g")
.data(stackedData)
.join("g")
.attr("fill", (d, i) => colourScale(i))
.selectAll("rect")
.data(d => d)
.join("rect")
.attr("x", d => xScale(d.data.group))
.attr("y", d => yScale(d[1]))
.attr("height", d => yScale(d[0]) - yScale(d[1]))
.attr("width", xScale.bandwidth());
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(d3.axisBottom(xScale));
g.append("g")
.call(d3.axisLeft(yScale));
}, [data]);
```
### Grouped bar chart
```javascript
useEffect(() => {
if (!data || data.length === 0) return;
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();
const width = 800;
const height = 400;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
const categories = Object.keys(data[0]).filter(k => k !== 'group');
const x0Scale = d3.scaleBand()
.domain(data.map(d => d.group))
.range([0, innerWidth])
.padding(0.1);
const x1Scale = d3.scaleBand()
.domain(categories)
.range([0, x0Scale.bandwidth()])
.padding(0.05);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => Math.max(...categories.map(c => d[c])))])
.range([innerHeight, 0]);
const colourScale = d3.scaleOrdinal(d3.schemeCategory10);
const group = g.selectAll("g")
.data(data)
.join("g")
.attr("transform", d => `translate(${x0Scale(d.group)},0)`);
group.selectAll("rect")
.data(d => categories.map(key => ({ key, value: d[key] })))
.join("rect")
.attr("x", d => x1Scale(d.key))
.attr("y", d => yScale(d.value))
.attr("width", x1Scale.bandwidth())
.attr("height", d => innerHeight - yScale(d.value))
.attr("fill", d => colourScale(d.key));
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(d3.axisBottom(x0Scale));
g.append("g")
.call(d3.axisLeft(yScale));
}, [data]);
```
### Bubble chart
```javascript
useEffect(() => {
if (!data || data.length === 0) return;
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();
const width = 800;
const height = 600;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.x)])
.range([0, innerWidth]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.y)])
.range([innerHeight, 0]);
const sizeScale = d3.scaleSqrt()
.domain([0, d3.max(data, d => d.size)])
.range([0, 50]);
const colourScale = d3.scaleOrdinal(d3.schemeCategory10);
g.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", d => xScale(d.x))
.attr("cy", d => yScale(d.y))
.attr("r", d => sizeScale(d.size))
.attr("fill", d => colourScale(d.category))
.attr("opacity", 0.6)
.attr("stroke", "white")
.attr("stroke-width", 2);
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(d3.axisBottom(xScale));
g.append("g")
.call(d3.axisLeft(yScale));
}, [data]);
```
## Geographic visualisations
### Basic map with points
```javascript
useEffect(() => {
if (!geoData || !pointData) return;
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();
const width = 800;
const height = 600;
const projection = d3.geoMercator()
.fitSize([width, height], geoData);
const pathGenerator = d3.geoPath().projection(projection);
// Draw map
svg.selectAll("path")
.data(geoData.features)
.join("path")
.attr("d", pathGenerator)
.attr("fill", "#e0e0e0")
.attr("stroke", "#999")
.attr("stroke-width", 0.5);
// Draw points
svg.selectAll("circle")
.data(pointData)
.join("circle")
.attr("cx", d => projection([d.longitude, d.latitude])[0])
.attr("cy", d => projection([d.longitude, d.latitude])[1])
.attr("r", 5)
.attr("fill", "steelblue")
.attr("opacity", 0.7);
}, [geoData, pointData]);
```
### Choropleth map
```javascript
useEffect(() => {
if (!geoData || !valueData) return;
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();
const width = 800;
const height = 600;
const projection = d3.geoMercator()
.fitSize([width, height], geoData);
const pathGenerator = d3.geoPath().projection(projection);
// Create value lookup
const valueLookup = new Map(valueData.map(d => [d.id, d.value]));
// Colour scale
const colourScale = d3.scaleSequential(d3.interpolateBlues)
.domain([0, d3.max(valueData, d => d.value)]);
svg.selectAll("path")
.data(geoData.features)
.join("path")
.attr("d", pathGenerator)
.attr("fill", d => {
const value = valueLookup.get(d.id);
return value ? colourScale(value) : "#e0e0e0";
})
.attr("stroke", "#999")
.attr("stroke-width", 0.5);
}, [geoData, valueData]);
```
## Advanced interactions
### Brush and zoom
```javascript
useEffect(() => {
if (!data || data.length === 0) return;
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();
const width = 800;
const height = 400;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.x)])
.range([0, innerWidth]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.y)])
.range([innerHeight, 0]);
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
const circles = g.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", d => xScale(d.x))
.attr("cy", d => yScale(d.y))
.attr("r", 5)
.attr("fill", "steelblue");
// Add brush
const brush = d3.brush()
.extent([[0, 0], [innerWidth, innerHeight]])
.on("start brush", (event) => {
if (!event.selection) return;
const [[x0, y0], [x1, y1]] = event.selection;
circles.attr("fill", d => {
const cx = xScale(d.x);
const cy = yScale(d.y);
return (cx >= x0 && cx <= x1 && cy >= y0 && cy <= y1)
? "orange"
: "steelblue";
});
});
g.append("g")
.attr("class", "brush")
.call(brush);
}, [data]);
```
### Linked brushing between charts
```javascript
function LinkedCharts({ data }) {
const [selectedPoints, setSelectedPoints] = useState(new Set());
const svg1Ref = useRef();
const svg2Ref = useRef();
useEffect(() => {
// Chart 1: Scatter plot
const svg1 = d3.select(svg1Ref.current);
svg1.selectAll("*").remove();
// ... create first chart ...
const circles1 = svg1.selectAll("circle")
.data(data)
.join("circle")
.attr("fill", d => selectedPoints.has(d.id) ? "orange" : "steelblue");
// Chart 2: Bar chart
const svg2 = d3.select(svg2Ref.current);
svg2.selectAll("*").remove();
// ... create second chart ...
const bars = svg2.selectAll("rect")
.data(data)
.join("rect")
.attr("fill", d => selectedPoints.has(d.id) ? "orange" : "steelblue");
// Add brush to first chart
const brush = d3.brush()
.on("start brush end", (event) => {
if (!event.selection) {
setSelectedPoints(new Set());
return;
}
const [[x0, y0], [x1, y1]] = event.selection;
const selected = new Set();
data.forEach(d => {
const x = xScale(d.x);
const y = yScale(d.y);
if (x >= x0 && x <= x1 && y >= y0 && y <= y1) {
selected.add(d.id);
}
});
setSelectedPoints(selected);
});
svg1.append("g").call(brush);
}, [data, selectedPoints]);
return (
<div>
<svg ref={svg1Ref} width="400" height="300" />
<svg ref={svg2Ref} width="400" height="300" />
</div>
);
}
```
## Animation patterns
### Enter, update, exit with transitions
```javascript
useEffect(() => {
if (!data || data.length === 0) return;
const svg = d3.select(svgRef.current);
const circles = svg.selectAll("circle")
.data(data, d => d.id); // Key function for object constancy
// EXIT: Remove old elements
circles.exit()
.transition()
.duration(500)
.attr("r", 0)
.remove();
// UPDATE: Modify existing elements
circles
.transition()
.duration(500)
.attr("cx", d => xScale(d.x))
.attr("cy", d => yScale(d.y))
.attr("fill", "steelblue");
// ENTER: Add new elements
circles.enter()
.append("circle")
.attr("cx", d => xScale(d.x))
.attr("cy", d => yScale(d.y))
.attr("r", 0)
.attr("fill", "steelblue")
.transition()
.duration(500)
.attr("r", 5);
}, [data]);
```
### Path morphing
```javascript
useEffect(() => {
if (!data1 || !data2) return;
const svg = d3.select(svgRef.current);
const line = d3.line()
.x(d => xScale(d.x))
.y(d => yScale(d.y))
.curve(d3.curveMonotoneX);
const path = svg.select("path");
// Morph from data1 to data2
path
.datum(data1)
.attr("d", line)
.transition()
.duration(1000)
.attrTween("d", function() {
const previous = d3.select(this).attr("d");
const current = line(data2);
return d3.interpolatePath(previous, current);
});
}, [data1, data2]);
```

View File

@@ -0,0 +1,509 @@
# D3.js Scale Reference
Comprehensive guide to all d3 scale types with examples and use cases.
## Continuous scales
### Linear scale
Maps continuous input domain to continuous output range with linear interpolation.
```javascript
const scale = d3.scaleLinear()
.domain([0, 100])
.range([0, 500]);
scale(50); // Returns 250
scale(0); // Returns 0
scale(100); // Returns 500
// Invert scale (get input from output)
scale.invert(250); // Returns 50
```
**Use cases:**
- Most common scale for quantitative data
- Axes, bar lengths, position encoding
- Temperature, prices, counts, measurements
**Methods:**
- `.domain([min, max])` - Set input domain
- `.range([min, max])` - Set output range
- `.invert(value)` - Get domain value from range value
- `.clamp(true)` - Restrict output to range bounds
- `.nice()` - Extend domain to nice round values
### Power scale
Maps continuous input to continuous output with exponential transformation.
```javascript
const sqrtScale = d3.scalePow()
.exponent(0.5) // Square root
.domain([0, 100])
.range([0, 500]);
const squareScale = d3.scalePow()
.exponent(2) // Square
.domain([0, 100])
.range([0, 500]);
// Shorthand for square root
const sqrtScale2 = d3.scaleSqrt()
.domain([0, 100])
.range([0, 500]);
```
**Use cases:**
- Perceptual scaling (human perception is non-linear)
- Area encoding (use square root to map values to circle radii)
- Emphasising differences in small or large values
### Logarithmic scale
Maps continuous input to continuous output with logarithmic transformation.
```javascript
const logScale = d3.scaleLog()
.domain([1, 1000]) // Must be positive
.range([0, 500]);
logScale(1); // Returns 0
logScale(10); // Returns ~167
logScale(100); // Returns ~333
logScale(1000); // Returns 500
```
**Use cases:**
- Data spanning multiple orders of magnitude
- Population, GDP, wealth distributions
- Logarithmic axes
- Exponential growth visualisations
**Important:** Domain values must be strictly positive (>0).
### Time scale
Specialised linear scale for temporal data.
```javascript
const timeScale = d3.scaleTime()
.domain([new Date(2020, 0, 1), new Date(2024, 0, 1)])
.range([0, 800]);
timeScale(new Date(2022, 0, 1)); // Returns 400
// Invert to get date
timeScale.invert(400); // Returns Date object for mid-2022
```
**Use cases:**
- Time series visualisations
- Timeline axes
- Temporal animations
- Date-based interactions
**Methods:**
- `.nice()` - Extend domain to nice time intervals
- `.ticks(count)` - Generate nicely-spaced tick values
- All linear scale methods apply
### Quantize scale
Maps continuous input to discrete output buckets.
```javascript
const quantizeScale = d3.scaleQuantize()
.domain([0, 100])
.range(['low', 'medium', 'high']);
quantizeScale(25); // Returns 'low'
quantizeScale(50); // Returns 'medium'
quantizeScale(75); // Returns 'high'
// Get the threshold values
quantizeScale.thresholds(); // Returns [33.33, 66.67]
```
**Use cases:**
- Binning continuous data
- Heat map colours
- Risk categories (low/medium/high)
- Age groups, income brackets
### Quantile scale
Maps continuous input to discrete output based on quantiles.
```javascript
const quantileScale = d3.scaleQuantile()
.domain([3, 6, 7, 8, 8, 10, 13, 15, 16, 20, 24]) // Sample data
.range(['low', 'medium', 'high']);
quantileScale(8); // Returns based on quantile position
quantileScale.quantiles(); // Returns quantile thresholds
```
**Use cases:**
- Equal-size groups regardless of distribution
- Percentile-based categorisation
- Handling skewed distributions
### Threshold scale
Maps continuous input to discrete output with custom thresholds.
```javascript
const thresholdScale = d3.scaleThreshold()
.domain([0, 10, 20])
.range(['freezing', 'cold', 'warm', 'hot']);
thresholdScale(-5); // Returns 'freezing'
thresholdScale(5); // Returns 'cold'
thresholdScale(15); // Returns 'warm'
thresholdScale(25); // Returns 'hot'
```
**Use cases:**
- Custom breakpoints
- Grade boundaries (A, B, C, D, F)
- Temperature categories
- Air quality indices
## Sequential scales
### Sequential colour scale
Maps continuous input to continuous colour gradient.
```javascript
const colourScale = d3.scaleSequential(d3.interpolateBlues)
.domain([0, 100]);
colourScale(0); // Returns lightest blue
colourScale(50); // Returns mid blue
colourScale(100); // Returns darkest blue
```
**Available interpolators:**
**Single hue:**
- `d3.interpolateBlues`, `d3.interpolateGreens`, `d3.interpolateReds`
- `d3.interpolateOranges`, `d3.interpolatePurples`, `d3.interpolateGreys`
**Multi-hue:**
- `d3.interpolateViridis`, `d3.interpolateInferno`, `d3.interpolateMagma`
- `d3.interpolatePlasma`, `d3.interpolateWarm`, `d3.interpolateCool`
- `d3.interpolateCubehelixDefault`, `d3.interpolateTurbo`
**Use cases:**
- Heat maps, choropleth maps
- Continuous data visualisation
- Temperature, elevation, density
### Diverging colour scale
Maps continuous input to diverging colour gradient with a midpoint.
```javascript
const divergingScale = d3.scaleDiverging(d3.interpolateRdBu)
.domain([-10, 0, 10]);
divergingScale(-10); // Returns red
divergingScale(0); // Returns white/neutral
divergingScale(10); // Returns blue
```
**Available interpolators:**
- `d3.interpolateRdBu` - Red to blue
- `d3.interpolateRdYlBu` - Red, yellow, blue
- `d3.interpolateRdYlGn` - Red, yellow, green
- `d3.interpolatePiYG` - Pink, yellow, green
- `d3.interpolateBrBG` - Brown, blue-green
- `d3.interpolatePRGn` - Purple, green
- `d3.interpolatePuOr` - Purple, orange
- `d3.interpolateRdGy` - Red, grey
- `d3.interpolateSpectral` - Rainbow spectrum
**Use cases:**
- Data with meaningful midpoint (zero, average, neutral)
- Positive/negative values
- Above/below comparisons
- Correlation matrices
### Sequential quantile scale
Combines sequential colour with quantile mapping.
```javascript
const sequentialQuantileScale = d3.scaleSequentialQuantile(d3.interpolateBlues)
.domain([3, 6, 7, 8, 8, 10, 13, 15, 16, 20, 24]);
// Maps based on quantile position
```
**Use cases:**
- Perceptually uniform binning
- Handling outliers
- Skewed distributions
## Ordinal scales
### Band scale
Maps discrete input to continuous bands (rectangles) with optional padding.
```javascript
const bandScale = d3.scaleBand()
.domain(['A', 'B', 'C', 'D'])
.range([0, 400])
.padding(0.1);
bandScale('A'); // Returns start position (e.g., 0)
bandScale('B'); // Returns start position (e.g., 110)
bandScale.bandwidth(); // Returns width of each band (e.g., 95)
bandScale.step(); // Returns total step including padding
bandScale.paddingInner(); // Returns inner padding (between bands)
bandScale.paddingOuter(); // Returns outer padding (at edges)
```
**Use cases:**
- Bar charts (most common use case)
- Grouped elements
- Categorical axes
- Heat map cells
**Padding options:**
- `.padding(value)` - Sets both inner and outer padding (0-1)
- `.paddingInner(value)` - Padding between bands (0-1)
- `.paddingOuter(value)` - Padding at edges (0-1)
- `.align(value)` - Alignment of bands (0-1, default 0.5)
### Point scale
Maps discrete input to continuous points (no width).
```javascript
const pointScale = d3.scalePoint()
.domain(['A', 'B', 'C', 'D'])
.range([0, 400])
.padding(0.5);
pointScale('A'); // Returns position (e.g., 50)
pointScale('B'); // Returns position (e.g., 150)
pointScale('C'); // Returns position (e.g., 250)
pointScale('D'); // Returns position (e.g., 350)
pointScale.step(); // Returns distance between points
```
**Use cases:**
- Line chart categorical x-axis
- Scatter plot with categorical axis
- Node positions in network graphs
- Any point positioning for categories
### Ordinal colour scale
Maps discrete input to discrete output (colours, shapes, etc.).
```javascript
const colourScale = d3.scaleOrdinal(d3.schemeCategory10);
colourScale('apples'); // Returns first colour
colourScale('oranges'); // Returns second colour
colourScale('apples'); // Returns same first colour (consistent)
// Custom range
const customScale = d3.scaleOrdinal()
.domain(['cat1', 'cat2', 'cat3'])
.range(['#FF6B6B', '#4ECDC4', '#45B7D1']);
```
**Built-in colour schemes:**
**Categorical:**
- `d3.schemeCategory10` - 10 colours
- `d3.schemeAccent` - 8 colours
- `d3.schemeDark2` - 8 colours
- `d3.schemePaired` - 12 colours
- `d3.schemePastel1` - 9 colours
- `d3.schemePastel2` - 8 colours
- `d3.schemeSet1` - 9 colours
- `d3.schemeSet2` - 8 colours
- `d3.schemeSet3` - 12 colours
- `d3.schemeTableau10` - 10 colours
**Use cases:**
- Category colours
- Legend items
- Multi-series charts
- Network node types
## Scale utilities
### Nice domain
Extend domain to nice round values.
```javascript
const scale = d3.scaleLinear()
.domain([0.201, 0.996])
.nice();
scale.domain(); // Returns [0.2, 1.0]
// With count (approximate tick count)
const scale2 = d3.scaleLinear()
.domain([0.201, 0.996])
.nice(5);
```
### Clamping
Restrict output to range bounds.
```javascript
const scale = d3.scaleLinear()
.domain([0, 100])
.range([0, 500])
.clamp(true);
scale(-10); // Returns 0 (clamped)
scale(150); // Returns 500 (clamped)
```
### Copy scales
Create independent copies.
```javascript
const scale1 = d3.scaleLinear()
.domain([0, 100])
.range([0, 500]);
const scale2 = scale1.copy();
// scale2 is independent of scale1
```
### Tick generation
Generate nice tick values for axes.
```javascript
const scale = d3.scaleLinear()
.domain([0, 100])
.range([0, 500]);
scale.ticks(10); // Generate ~10 ticks
scale.tickFormat(10); // Get format function for ticks
scale.tickFormat(10, ".2f"); // Custom format (2 decimal places)
// Time scale ticks
const timeScale = d3.scaleTime()
.domain([new Date(2020, 0, 1), new Date(2024, 0, 1)]);
timeScale.ticks(d3.timeYear); // Yearly ticks
timeScale.ticks(d3.timeMonth, 3); // Every 3 months
timeScale.tickFormat(5, "%Y-%m"); // Format as year-month
```
## Colour spaces and interpolation
### RGB interpolation
```javascript
const scale = d3.scaleLinear()
.domain([0, 100])
.range(["blue", "red"]);
// Default: RGB interpolation
```
### HSL interpolation
```javascript
const scale = d3.scaleLinear()
.domain([0, 100])
.range(["blue", "red"])
.interpolate(d3.interpolateHsl);
// Smoother colour transitions
```
### Lab interpolation
```javascript
const scale = d3.scaleLinear()
.domain([0, 100])
.range(["blue", "red"])
.interpolate(d3.interpolateLab);
// Perceptually uniform
```
### HCL interpolation
```javascript
const scale = d3.scaleLinear()
.domain([0, 100])
.range(["blue", "red"])
.interpolate(d3.interpolateHcl);
// Perceptually uniform with hue
```
## Common patterns
### Diverging scale with custom midpoint
```javascript
const scale = d3.scaleLinear()
.domain([min, midpoint, max])
.range(["red", "white", "blue"])
.interpolate(d3.interpolateHcl);
```
### Multi-stop gradient scale
```javascript
const scale = d3.scaleLinear()
.domain([0, 25, 50, 75, 100])
.range(["#d53e4f", "#fc8d59", "#fee08b", "#e6f598", "#66c2a5"]);
```
### Radius scale for circles (perceptual)
```javascript
const radiusScale = d3.scaleSqrt()
.domain([0, d3.max(data, d => d.value)])
.range([0, 50]);
// Use with circles
circle.attr("r", d => radiusScale(d.value));
```
### Adaptive scale based on data range
```javascript
function createAdaptiveScale(data) {
const extent = d3.extent(data);
const range = extent[1] - extent[0];
// Use log scale if data spans >2 orders of magnitude
if (extent[1] / extent[0] > 100) {
return d3.scaleLog()
.domain(extent)
.range([0, width]);
}
// Otherwise use linear
return d3.scaleLinear()
.domain(extent)
.range([0, width]);
}
```
### Colour scale with explicit categories
```javascript
const colourScale = d3.scaleOrdinal()
.domain(['Low Risk', 'Medium Risk', 'High Risk'])
.range(['#2ecc71', '#f39c12', '#e74c3c'])
.unknown('#95a5a6'); // Fallback for unknown values
```

1
skills/docx Symbolic link
View File

@@ -0,0 +1 @@
docx-official

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,47 @@
## Instructions
You are being asked to write a 3P update. 3P updates stand for "Progress, Plans, Problems." The main audience is for executives, leadership, other teammates, etc. They're meant to be very succinct and to-the-point: think something you can read in 30-60sec or less. They're also for people with some, but not a lot of context on what the team does.
3Ps can cover a team of any size, ranging all the way up to the entire company. The bigger the team, the less granular the tasks should be. For example, "mobile team" might have "shipped feature" or "fixed bugs," whereas the company might have really meaty 3Ps, like "hired 20 new people" or "closed 10 new deals."
They represent the work of the team across a time period, almost always one week. They include three sections:
1) Progress: what the team has accomplished over the next time period. Focus mainly on things shipped, milestones achieved, tasks created, etc.
2) Plans: what the team plans to do over the next time period. Focus on what things are top-of-mind, really high priority, etc. for the team.
3) Problems: anything that is slowing the team down. This could be things like too few people, bugs or blockers that are preventing the team from moving forward, some deal that fell through, etc.
Before writing them, make sure that you know the team name. If it's not specified, you can ask explicitly what the team name you're writing for is.
## Tools Available
Whenever possible, try to pull from available sources to get the information you need:
- Slack: posts from team members with their updates - ideally look for posts in large channels with lots of reactions
- Google Drive: docs written from critical team members with lots of views
- Email: emails with lots of responses of lots of content that seems relevant
- Calendar: non-recurring meetings that have a lot of importance, like product reviews, etc.
Try to gather as much context as you can, focusing on the things that covered the time period you're writing for:
- Progress: anything between a week ago and today
- Plans: anything from today to the next week
- Problems: anything between a week ago and today
If you don't have access, you can ask the user for things they want to cover. They might also include these things to you directly, in which case you're mostly just formatting for this particular format.
## Workflow
1. **Clarify scope**: Confirm the team name and time period (usually past week for Progress/Problems, next
week for Plans)
2. **Gather information**: Use available tools or ask the user directly
3. **Draft the update**: Follow the strict formatting guidelines
4. **Review**: Ensure it's concise (30-60 seconds to read) and data-driven
## Formatting
The format is always the same, very strict formatting. Never use any formatting other than this. Pick an emoji that is fun and captures the vibe of the team and update.
[pick an emoji] [Team Name] (Dates Covered, usually a week)
Progress: [1-3 sentences of content]
Plans: [1-3 sentences of content]
Problems: [1-3 sentences of content]
Each section should be no more than 1-3 sentences: clear, to the point. It should be data-driven, and generally include metrics where possible. The tone should be very matter-of-fact, not super prose-heavy.

View File

@@ -0,0 +1,65 @@
## Instructions
You are being asked to write a company-wide newsletter update. You are meant to summarize the past week/month of a company in the form of a newsletter that the entire company will read. It should be maybe ~20-25 bullet points long. It will be sent via Slack and email, so make it consumable for that.
Ideally it includes the following attributes:
- Lots of links: pulling documents from Google Drive that are very relevant, linking to prominent Slack messages in announce channels and from executives, perhgaps referencing emails that went company-wide, highlighting significant things that have happened in the company.
- Short and to-the-point: each bullet should probably be no longer than ~1-2 sentences
- Use the "we" tense, as you are part of the company. Many of the bullets should say "we did this" or "we did that"
## Tools to use
If you have access to the following tools, please try to use them. If not, you can also let the user know directly that their responses would be better if they gave them access.
- Slack: look for messages in channels with lots of people, with lots of reactions or lots of responses within the thread
- Email: look for things from executives that discuss company-wide announcements
- Calendar: if there were meetings with large attendee lists, particularly things like All-Hands meetings, big company announcements, etc. If there were documents attached to those meetings, those are great links to include.
- Documents: if there were new docs published in the last week or two that got a lot of attention, you can link them. These should be things like company-wide vision docs, plans for the upcoming quarter or half, things authored by critical executives, etc.
- External press: if you see references to articles or press we've received over the past week, that could be really cool too.
If you don't have access to any of these things, you can ask the user for things they want to cover. In this case, you'll mostly just be polishing up and fitting to this format more directly.
## Sections
The company is pretty big: 1000+ people. There are a variety of different teams and initiatives going on across the company. To make sure the update works well, try breaking it into sections of similar things. You might break into clusters like {product development, go to market, finance} or {recruiting, execution, vision}, or {external news, internal news} etc. Try to make sure the different areas of the company are highlighted well.
## Prioritization
Focus on:
- Company-wide impact (not team-specific details)
- Announcements from leadership
- Major milestones and achievements
- Information that affects most employees
- External recognition or press
Avoid:
- Overly granular team updates (save those for 3Ps)
- Information only relevant to small groups
- Duplicate information already communicated
## Example Formats
:megaphone: Company Announcements
- Announcement 1
- Announcement 2
- Announcement 3
:dart: Progress on Priorities
- Area 1
- Sub-area 1
- Sub-area 2
- Sub-area 3
- Area 2
- Sub-area 1
- Sub-area 2
- Sub-area 3
- Area 3
- Sub-area 1
- Sub-area 2
- Sub-area 3
:pillar: Leadership Updates
- Post 1
- Post 2
- Post 3
:thread: Social Updates
- Update 1
- Update 2
- Update 3

View File

@@ -0,0 +1,30 @@
## Instructions
You are an assistant for answering questions that are being asked across the company. Every week, there are lots of questions that get asked across the company, and your goal is to try to summarize what those questions are. We want our company to be well-informed and on the same page, so your job is to produce a set of frequently asked questions that our employees are asking and attempt to answer them. Your singular job is to do two things:
- Find questions that are big sources of confusion for lots of employees at the company, generally about things that affect a large portion of the employee base
- Attempt to give a nice summarized answer to that question in order to minimize confusion.
Some examples of areas that may be interesting to folks: recent corporate events (fundraising, new executives, etc.), upcoming launches, hiring progress, changes to vision or focus, etc.
## Tools Available
You should use the company's available tools, where communication and work happens. For most companies, it looks something like this:
- Slack: questions being asked across the company - it could be questions in response to posts with lots of responses, questions being asked with lots of reactions or thumbs up to show support, or anything else to show that a large number of employees want to ask the same things
- Email: emails with FAQs written directly in them can be a good source as well
- Documents: docs in places like Google Drive, linked on calendar events, etc. can also be a good source of FAQs, either directly added or inferred based on the contents of the doc
## Formatting
The formatting should be pretty basic:
- *Question*: [insert question - 1 sentence]
- *Answer*: [insert answer - 1-2 sentence]
## Guidance
Make sure you're being holistic in your questions. Don't focus too much on just the user in question or the team they are a part of, but try to capture the entire company. Try to be as holistic as you can in reading all the tools available, producing responses that are relevant to all at the company.
## Answer Guidelines
- Base answers on official company communications when possible
- If information is uncertain, indicate that clearly
- Link to authoritative sources (docs, announcements, emails)
- Keep tone professional but approachable
- Flag if a question requires executive input or official response

View File

@@ -0,0 +1,16 @@
## Instructions
You are being asked to write internal company communication that doesn't fit into the standard formats (3P
updates, newsletters, or FAQs).
Before proceeding:
1. Ask the user about their target audience
2. Understand the communication's purpose
3. Clarify the desired tone (formal, casual, urgent, informational)
4. Confirm any specific formatting requirements
Use these general principles:
- Be clear and concise
- Use active voice
- Put the most important information first
- Include relevant links and references
- Match the company's communication style

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,32 @@
---
name: internal-comms
description: A set of resources to help me write all kinds of internal communications, using the formats that my company likes to use. Claude should use this skill whenever asked to write some sort of internal communications (status reports, leadership updates, 3P updates, company newsletters, FAQs, incident reports, project updates, etc.).
license: Complete terms in LICENSE.txt
---
## When to use this skill
To write internal communications, use this skill for:
- 3P updates (Progress, Plans, Problems)
- Company newsletters
- FAQ responses
- Status reports
- Leadership updates
- Project updates
- Incident reports
## How to use this skill
To write any internal communication:
1. **Identify the communication type** from the request
2. **Load the appropriate guideline file** from the `examples/` directory:
- `examples/3p-updates.md` - For Progress/Plans/Problems team updates
- `examples/company-newsletter.md` - For company-wide newsletters
- `examples/faq-answers.md` - For answering frequently asked questions
- `examples/general-comms.md` - For anything else that doesn't explicitly match one of the above
3. **Follow the specific instructions** in that file for formatting, tone, and content gathering
If the communication type doesn't match any existing guideline, ask for clarification or more context about the desired format.
## Keywords
3P updates, company newsletter, company comms, weekly update, faqs, common questions, updates, internal comms

Submodule skills/loki-mode deleted from be9270dfb5

View File

@@ -0,0 +1,57 @@
name: Claude Code Review
on:
pull_request:
types: [opened, synchronize]
# Optional: Only run on specific file changes
# paths:
# - "src/**/*.ts"
# - "src/**/*.tsx"
# - "src/**/*.js"
# - "src/**/*.jsx"
jobs:
claude-review:
# Optional: Filter by PR author
# if: |
# github.event.pull_request.user.login == 'external-contributor' ||
# github.event.pull_request.user.login == 'new-developer' ||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}
Please review this pull request and provide feedback on:
- Code quality and best practices
- Potential bugs or issues
- Performance considerations
- Security concerns
- Test coverage
Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.
Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'

View File

@@ -0,0 +1,50 @@
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]
jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'
# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr:*)'

View File

@@ -0,0 +1,128 @@
name: Release
on:
push:
paths:
- 'VERSION'
branches:
- main
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Read version
id: version
run: |
VERSION=$(cat VERSION | tr -d '\n')
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=v$VERSION" >> $GITHUB_OUTPUT
- name: Check if tag exists
id: check_tag
run: |
if git rev-parse "v${{ steps.version.outputs.version }}" >/dev/null 2>&1; then
echo "exists=true" >> $GITHUB_OUTPUT
else
echo "exists=false" >> $GITHUB_OUTPUT
fi
- name: Create release artifacts
if: steps.check_tag.outputs.exists == 'false'
run: |
mkdir -p release
# ============================================
# Artifact 1: loki-mode.zip (for Claude.ai website)
# SKILL.md at ROOT level for direct upload
# ============================================
mkdir -p release/skill-root
cp SKILL.md release/skill-root/
cp -r references release/skill-root/
cd release/skill-root
zip -r ../loki-mode-${{ steps.version.outputs.version }}.zip .
cd ../..
# Also create .skill file (same as zip, different extension)
cp release/loki-mode-${{ steps.version.outputs.version }}.zip release/loki-mode-${{ steps.version.outputs.version }}.skill
# ============================================
# Artifact 2: loki-mode-api.zip (for console.anthropic.com)
# SKILL.md inside loki-mode/ folder (API requires folder wrapper)
# ============================================
mkdir -p release/api-package/loki-mode
cp SKILL.md release/api-package/loki-mode/
cp -r references release/api-package/loki-mode/
cd release/api-package
zip -r ../loki-mode-api-${{ steps.version.outputs.version }}.zip loki-mode
cd ../..
# ============================================
# Artifact 3: loki-mode-claude-code.zip
# For Claude Code: full package with loki-mode/ folder
# Extract to ~/.claude/skills/
# ============================================
mkdir -p release/loki-mode
cp SKILL.md release/loki-mode/
cp README.md release/loki-mode/
cp LICENSE release/loki-mode/ 2>/dev/null || true
cp VERSION release/loki-mode/
cp CHANGELOG.md release/loki-mode/
cp -r references release/loki-mode/
cp -r examples release/loki-mode/
cp -r tests release/loki-mode/
cp -r scripts release/loki-mode/
cp -r autonomy release/loki-mode/
cd release
zip -r loki-mode-claude-code-${{ steps.version.outputs.version }}.zip loki-mode
tar -czvf loki-mode-claude-code-${{ steps.version.outputs.version }}.tar.gz loki-mode
cd ..
- name: Create Git Tag
if: steps.check_tag.outputs.exists == 'false'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -a "v${{ steps.version.outputs.version }}" -m "Release v${{ steps.version.outputs.version }}"
git push origin "v${{ steps.version.outputs.version }}"
- name: Extract changelog for this version
if: steps.check_tag.outputs.exists == 'false'
id: changelog
run: |
VERSION="${{ steps.version.outputs.version }}"
CHANGELOG=$(awk "/^## \[$VERSION\]/{flag=1; next} /^## \[/{flag=0} flag" CHANGELOG.md)
if [ -z "$CHANGELOG" ]; then
CHANGELOG="Release v$VERSION"
fi
echo "$CHANGELOG" > changelog_body.txt
- name: Create GitHub Release
if: steps.check_tag.outputs.exists == 'false'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "v${{ steps.version.outputs.version }}" \
release/loki-mode-${{ steps.version.outputs.version }}.zip \
release/loki-mode-${{ steps.version.outputs.version }}.skill \
release/loki-mode-api-${{ steps.version.outputs.version }}.zip \
release/loki-mode-claude-code-${{ steps.version.outputs.version }}.zip \
release/loki-mode-claude-code-${{ steps.version.outputs.version }}.tar.gz \
--title "Loki Mode v${{ steps.version.outputs.version }}" \
--notes-file changelog_body.txt
- name: Skip message
if: steps.check_tag.outputs.exists == 'true'
run: |
echo "Tag v${{ steps.version.outputs.version }} already exists. Skipping release."

1
skills/loki-mode/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.DS_Store

View File

@@ -0,0 +1,184 @@
# Acknowledgements
Loki Mode stands on the shoulders of giants. This project incorporates research, patterns, and insights from the leading AI labs, academic institutions, and practitioners in the field.
---
## Research Labs
### Anthropic
Loki Mode is built for Claude and incorporates Anthropic's cutting-edge research on AI safety and agent development.
| Paper/Resource | Contribution to Loki Mode |
|----------------|---------------------------|
| [Constitutional AI: Harmlessness from AI Feedback](https://www.anthropic.com/research/constitutional-ai-harmlessness-from-ai-feedback) | Self-critique against principles, revision workflow |
| [Building Effective Agents](https://www.anthropic.com/research/building-effective-agents) | Evaluator-optimizer pattern, parallelization, routing |
| [Claude Code Best Practices](https://www.anthropic.com/engineering/claude-code-best-practices) | Explore-Plan-Code workflow, context management |
| [Simple Probes Can Catch Sleeper Agents](https://www.anthropic.com/research/probes-catch-sleeper-agents) | Defection probes, anomaly detection patterns |
| [Alignment Faking in Large Language Models](https://www.anthropic.com/research/alignment-faking) | Monitoring for strategic compliance |
| [Visible Extended Thinking](https://www.anthropic.com/research/visible-extended-thinking) | Thinking levels (think, think hard, ultrathink) |
| [Computer Use Safety](https://www.anthropic.com/news/3-5-models-and-computer-use) | Safe autonomous operation patterns |
| [Sabotage Evaluations](https://www.anthropic.com/research/sabotage-evaluations-for-frontier-models) | Safety evaluation methodology |
| [Effective Harnesses for Long-Running Agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents) | One-feature-at-a-time pattern, Playwright MCP for E2E |
| [Claude Agent SDK Overview](https://platform.claude.com/docs/en/agent-sdk/overview) | Task tool, subagents, resume parameter, hooks |
### Google DeepMind
DeepMind's research on world models, hierarchical reasoning, and scalable oversight informs Loki Mode's architecture.
| Paper/Resource | Contribution to Loki Mode |
|----------------|---------------------------|
| [SIMA 2: Generalist AI Agent](https://deepmind.google/blog/sima-2-an-agent-that-plays-reasons-and-learns-with-you-in-virtual-3d-worlds/) | Self-improvement loop, reward model training |
| [Gemini Robotics 1.5](https://deepmind.google/blog/gemini-robotics-15-brings-ai-agents-into-the-physical-world/) | Hierarchical reasoning (planner + executor) |
| [Dreamer 4: World Model Training](https://danijar.com/project/dreamer4/) | Simulation-first testing, safe exploration |
| [Genie 3: World Models](https://deepmind.google/blog/genie-3-a-new-frontier-for-world-models/) | World model architecture patterns |
| [Scalable AI Safety via Doubly-Efficient Debate](https://deepmind.google/research/publications/34920/) | Debate-based verification for critical changes |
| [Human-AI Complementarity for Amplified Oversight](https://deepmindsafetyresearch.medium.com/human-ai-complementarity-a-goal-for-amplified-oversight-0ad8a44cae0a) | AI-assisted human supervision |
| [Technical AGI Safety Approach](https://arxiv.org/html/2504.01849v1) | Safety-first agent design |
### OpenAI
OpenAI's Agents SDK and deep research patterns provide foundational patterns for agent orchestration.
| Paper/Resource | Contribution to Loki Mode |
|----------------|---------------------------|
| [Agents SDK Documentation](https://openai.github.io/openai-agents-python/) | Tracing spans, guardrails, tripwires |
| [A Practical Guide to Building Agents](https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf) | Agent architecture best practices |
| [Building Agents Track](https://developers.openai.com/tracks/building-agents/) | Development patterns, handoff callbacks |
| [AGENTS.md Specification](https://agents.md/) | Standardized agent instructions |
| [Introducing Deep Research](https://openai.com/index/introducing-deep-research/) | Adaptive planning, backtracking |
| [Deep Research System Card](https://cdn.openai.com/deep-research-system-card.pdf) | Safety considerations for research agents |
| [Introducing o3 and o4-mini](https://openai.com/index/introducing-o3-and-o4-mini/) | Reasoning model guidance |
| [Reasoning Best Practices](https://platform.openai.com/docs/guides/reasoning-best-practices) | Extended thinking patterns |
| [Chain of Thought Monitoring](https://openai.com/index/chain-of-thought-monitoring/) | Reasoning trace monitoring |
| [Agent Builder Safety](https://platform.openai.com/docs/guides/agent-builder-safety) | Safety patterns for agent builders |
| [Computer-Using Agent](https://openai.com/index/computer-using-agent/) | Computer use patterns |
| [Agentic AI Foundation](https://openai.com/index/agentic-ai-foundation/) | Industry standards, interoperability |
### Amazon Web Services (AWS)
AWS Bedrock's multi-agent collaboration patterns inform Loki Mode's routing and dispatch strategies.
| Paper/Resource | Contribution to Loki Mode |
|----------------|---------------------------|
| [Multi-Agent Orchestration Guidance](https://aws.amazon.com/solutions/guidance/multi-agent-orchestration-on-aws/) | Three coordination mechanisms, architectural patterns |
| [Bedrock Multi-Agent Collaboration](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-multi-agent-collaboration.html) | Supervisor mode, routing mode, 10-agent limit |
| [Multi-Agent Collaboration Announcement](https://aws.amazon.com/blogs/aws/introducing-multi-agent-collaboration-capability-for-amazon-bedrock/) | Intent classification, selective context sharing |
| [AgentCore for SRE](https://aws.amazon.com/blogs/machine-learning/build-multi-agent-site-reliability-engineering-assistants-with-amazon-bedrock-agentcore/) | Gateway, Memory, Identity, Observability components |
**Key Pattern Adopted:** Routing Mode Optimization - Direct dispatch for simple tasks (lower latency), supervisor orchestration for complex tasks (full coordination).
---
## Academic Research
### Multi-Agent Systems
| Paper | Authors/Source | Contribution |
|-------|----------------|--------------|
| [Multi-Agent Collaboration Mechanisms Survey](https://arxiv.org/abs/2501.06322) | arXiv 2501.06322 | Collaboration structures, coopetition |
| [CONSENSAGENT: Anti-Sycophancy Framework](https://aclanthology.org/2025.findings-acl.1141/) | ACL 2025 Findings | Blind review, devil's advocate |
| [GoalAct: Hierarchical Execution](https://arxiv.org/abs/2504.16563) | arXiv 2504.16563 | Global planning, skill decomposition |
| [A-Mem: Agentic Memory System](https://arxiv.org/html/2502.12110v11) | arXiv 2502.12110 | Zettelkasten-style memory linking |
| [Multi-Agent Reflexion (MAR)](https://arxiv.org/html/2512.20845) | arXiv 2512.20845 | Structured debate, persona-based critics |
| [Iter-VF: Iterative Verification-First](https://arxiv.org/html/2511.21734v1) | arXiv 2511.21734 | Answer-only verification, Markovian retry |
### Evaluation & Safety
| Paper | Authors/Source | Contribution |
|-------|----------------|--------------|
| [Assessment Framework for Agentic AI](https://arxiv.org/html/2512.12791v1) | arXiv 2512.12791 | Four-pillar evaluation framework |
| [Measurement Imbalance in Agentic AI](https://arxiv.org/abs/2506.02064) | arXiv 2506.02064 | Multi-dimensional evaluation axes |
| [Demo-to-Deployment Gap](https://www.marktechpost.com/2025/12/24/) | Stanford/Harvard | Tool reliability vs tool selection |
---
## Industry Resources
### Tools & Frameworks
| Resource | Contribution |
|----------|--------------|
| [NVIDIA ToolOrchestra](https://github.com/NVlabs/ToolOrchestra) | Efficiency metrics, three-reward signal framework, dynamic agent selection |
| [LerianStudio/ring](https://github.com/LerianStudio/ring) | Subagent-driven-development pattern |
| [Awesome Agentic Patterns](https://github.com/nibzard/awesome-agentic-patterns) | 105+ production patterns catalog |
### Best Practices Guides
| Resource | Contribution |
|----------|--------------|
| [Maxim AI: Production Multi-Agent Systems](https://www.getmaxim.ai/articles/best-practices-for-building-production-ready-multi-agent-systems/) | Correlation IDs, failure handling |
| [UiPath: Agent Builder Best Practices](https://www.uipath.com/blog/ai/agent-builder-best-practices) | Single-responsibility agents |
| [GitHub: Speed Without Control](https://github.blog/) | Static analysis + AI review, guardrails |
---
## Hacker News Community
Battle-tested insights from practitioners deploying agents in production.
### Discussions
| Thread | Key Insight |
|--------|-------------|
| [What Actually Works in Production for Autonomous Agents](https://news.ycombinator.com/item?id=44623207) | "Zero companies without human in the loop" |
| [Coding with LLMs in Summer 2025](https://news.ycombinator.com/item?id=44623953) | Context curation beats automatic RAG |
| [Superpowers: How I'm Using Coding Agents](https://news.ycombinator.com/item?id=45547344) | Sub-agents for context isolation (Simon Willison) |
| [Claude Code Experience After Two Weeks](https://news.ycombinator.com/item?id=44596472) | Fresh contexts yield better results |
| [AI Agent Benchmarks Are Broken](https://news.ycombinator.com/item?id=44531697) | LLM-as-judge has shared blind spots |
| [How to Orchestrate Multi-Agent Workflows](https://news.ycombinator.com/item?id=45955997) | Event-driven, decoupled coordination |
| [Context Engineering vs Prompt Engineering](https://news.ycombinator.com/item?id=44427757) | Manual context selection principles |
### Show HN Projects
| Project | Contribution |
|---------|--------------|
| [Self-Evolving Agents Repository](https://news.ycombinator.com/item?id=45099226) | Self-improvement patterns |
| [Package Manager for Agent Skills](https://news.ycombinator.com/item?id=46422264) | Skills architecture |
| [Wispbit - AI Code Review Agent](https://news.ycombinator.com/item?id=44722603) | Code review patterns |
| [Agtrace - Monitoring for AI Coding Agents](https://news.ycombinator.com/item?id=46425670) | Agent monitoring patterns |
---
## Individual Contributors
Special thanks to thought leaders whose patterns and insights shaped Loki Mode:
| Contributor | Contribution |
|-------------|--------------|
| **Boris Cherny** (Creator of Claude Code) | Self-verification loop (2-3x quality improvement), extended thinking mode, "Less prompting, more systems" philosophy |
| **Ivan Steshov** | Centralized constitution, agent lineage tracking, structured artifacts as contracts |
| **Addy Osmani** | Git checkpoint system, specification-first approach, visual aids (Mermaid diagrams) |
| **Simon Willison** | Sub-agents for context isolation, skills system, context curation patterns |
---
## Production Patterns Summary
Key patterns incorporated from practitioner experience:
| Pattern | Source | Implementation |
|---------|--------|----------------|
| Human-in-the-Loop (HITL) | HN Production Discussions | Confidence-based escalation thresholds |
| Narrow Scope (3-5 steps) | Multiple Practitioners | Task scope constraints |
| Deterministic Validation | Production Teams | Rule-based outer loops (not LLM-judged) |
| Context Curation | Simon Willison | Manual selection, focused context |
| Blind Review + Devil's Advocate | CONSENSAGENT | Anti-sycophancy protocol |
| Hierarchical Reasoning | DeepMind Gemini | Orchestrator + specialized executors |
| Constitutional Self-Critique | Anthropic | Principles-based revision |
| Debate Verification | DeepMind | Critical change verification |
| One Feature at a Time | Anthropic Harness | Single feature per iteration, full verification |
| E2E Browser Testing | Anthropic Harness | Playwright MCP for visual verification |
---
## License
This acknowledgements file documents the research and resources that influenced Loki Mode's design. All referenced works retain their original licenses and copyrights.
Loki Mode itself is released under the MIT License.
---
*Last updated: v2.35.0*

File diff suppressed because it is too large Load Diff

120
skills/loki-mode/CLAUDE.md Normal file
View File

@@ -0,0 +1,120 @@
# Loki Mode - Claude Code Skill
Multi-agent autonomous startup system for Claude Code. Takes PRD to fully deployed, revenue-generating product with zero human intervention.
## Quick Start
```bash
# Launch Claude Code with autonomous permissions
claude --dangerously-skip-permissions
# Then invoke:
# "Loki Mode" or "Loki Mode with PRD at path/to/prd"
```
## Project Structure
```
SKILL.md # Main skill definition (read this first)
references/ # Detailed documentation (loaded progressively)
openai-patterns.md # OpenAI Agents SDK: guardrails, tripwires, handoffs
lab-research-patterns.md # DeepMind + Anthropic: Constitutional AI, debate
production-patterns.md # HN 2025: What actually works in production
advanced-patterns.md # 2025 research patterns (MAR, Iter-VF, GoalAct)
tool-orchestration.md # ToolOrchestra-inspired efficiency & rewards
memory-system.md # Episodic/semantic memory architecture
quality-control.md # Code review, anti-sycophancy, guardrails
agent-types.md # 37 specialized agent definitions
sdlc-phases.md # Full SDLC workflow
task-queue.md # Queue system, circuit breakers
spec-driven-dev.md # OpenAPI-first development
architecture.md # Directory structure, state schemas
core-workflow.md # RARV cycle, autonomy rules
claude-best-practices.md # Boris Cherny patterns
deployment.md # Cloud deployment instructions
business-ops.md # Business operation workflows
mcp-integration.md # MCP server capabilities
autonomy/ # Runtime state and constitution
benchmarks/ # SWE-bench and HumanEval benchmarks
```
## Key Concepts
### RARV Cycle
Every iteration follows: **R**eason -> **A**ct -> **R**eflect -> **V**erify
### Model Selection
- **Opus**: Planning and architecture ONLY (system design, high-level decisions)
- **Sonnet**: Development and functional testing (implementation, integration tests)
- **Haiku**: Unit tests, monitoring, and simple tasks - use extensively for parallelization
### Quality Gates
1. Static analysis (CodeQL, ESLint)
2. 3-reviewer parallel system (blind review)
3. Anti-sycophancy checks (devil's advocate on unanimous approval)
4. Severity-based blocking (Critical/High/Medium = BLOCK)
5. Test coverage gates (>80% unit, 100% pass)
### Memory System
- **Episodic**: Specific interaction traces (`.loki/memory/episodic/`)
- **Semantic**: Generalized patterns (`.loki/memory/semantic/`)
- **Procedural**: Learned skills (`.loki/memory/skills/`)
### Metrics System (ToolOrchestra-inspired)
- **Efficiency**: Task cost tracking (`.loki/metrics/efficiency/`)
- **Rewards**: Outcome/efficiency/preference signals (`.loki/metrics/rewards/`)
## Development Guidelines
### When Modifying SKILL.md
- Keep under 500 lines (currently ~370)
- Reference detailed docs in `references/` instead of inlining
- Update version in header AND footer
- Update CHANGELOG.md with new version entry
### Version Numbering
Follows semantic versioning: MAJOR.MINOR.PATCH
- Current: v2.35.0
- MINOR bump for new features
- PATCH bump for fixes
### Code Style
- No emojis in code or documentation
- Clear, concise comments only when necessary
- Follow existing patterns in codebase
## Testing
```bash
# Run benchmarks
./benchmarks/run-benchmarks.sh humaneval --execute --loki
./benchmarks/run-benchmarks.sh swebench --execute --loki
```
## Research Foundation
Built on 2025 research from three major AI labs:
**OpenAI:**
- Agents SDK (guardrails, tripwires, handoffs, tracing)
- AGENTS.md / Agentic AI Foundation (AAIF) standards
**Google DeepMind:**
- SIMA 2 (self-improvement, hierarchical reasoning)
- Gemini Robotics (VLA models, planning)
- Dreamer 4 (world model training)
- Scalable Oversight via Debate
**Anthropic:**
- Constitutional AI (principles-based self-critique)
- Alignment Faking Detection (sleeper agent probes)
- Claude Code Best Practices (Explore-Plan-Code)
**Academic:**
- CONSENSAGENT (anti-sycophancy)
- GoalAct (hierarchical planning)
- A-Mem/MIRIX (memory systems)
- Multi-Agent Reflexion (MAR)
- NVIDIA ToolOrchestra (efficiency metrics)
See `references/openai-patterns.md`, `references/lab-research-patterns.md`, and `references/advanced-patterns.md`.

View File

@@ -0,0 +1,206 @@
# Loki Mode - Conversation Context Export
**Date:** 2025-12-28
**Version:** 2.5.0
**Repository:** https://github.com/asklokesh/loki-mode
---
## Project Overview
**Loki Mode** is a Claude Code skill that provides a multi-agent autonomous startup system. It dynamically orchestrates specialized agents across 6 swarms to take a PRD from idea to fully deployed product. It spawns only the agents needed - from a few for simple projects to 100+ for complex startups.
### Key Features
- 37 specialized agent types across 6 swarms (Engineering, Operations, Business, Data, Product, Growth)
- Dynamic agent scaling based on project complexity
- Task tool for subagent dispatch with fresh context
- Distributed task queue (pending, in-progress, completed, failed, dead-letter)
- Circuit breakers for per-agent failure handling
- Timeout/stuck agent detection with heartbeat monitoring
- State recovery via checkpoints in `.loki/state/`
- Autonomous execution with auto-resume on rate limits
---
## File Structure
```
loki-mode/
├── SKILL.md # The main skill file (YAML frontmatter required)
├── VERSION # Current version: 2.4.0
├── CHANGELOG.md # Full version history
├── README.md # Main documentation
├── references/
│ ├── agents.md # 37 agent type definitions
│ ├── deployment.md # Cloud deployment guides
│ └── business-ops.md # Business operation workflows
├── examples/
│ ├── simple-todo-app.md # Simple PRD for testing
│ ├── api-only.md # Backend-only PRD
│ ├── static-landing-page.md # Frontend/marketing PRD
│ └── full-stack-demo.md # Complete bookmark manager PRD
├── tests/
│ ├── run-all-tests.sh # Main test runner (53 tests)
│ ├── test-bootstrap.sh # 8 tests
│ ├── test-task-queue.sh # 8 tests
│ ├── test-circuit-breaker.sh # 8 tests
│ ├── test-agent-timeout.sh # 9 tests
│ ├── test-state-recovery.sh # 8 tests
│ └── test-wrapper.sh # 12 tests
├── scripts/
│ ├── loki-wrapper.sh # Legacy wrapper (deprecated)
│ └── export-to-vibe-kanban.sh # Optional Vibe Kanban export
├── integrations/
│ └── vibe-kanban.md # Vibe Kanban integration guide
├── autonomy/
│ ├── run.sh # ⭐ MAIN ENTRY POINT - handles everything
│ └── README.md # Autonomy documentation
└── .github/workflows/
└── release.yml # GitHub Actions for releases
```
---
## How to Use
### Quick Start (Recommended)
```bash
./autonomy/run.sh ./docs/requirements.md
```
### What run.sh Does
1. Checks prerequisites (Claude CLI, Python, Git, curl)
2. Verifies skill installation
3. Initializes `.loki/` directory
4. Starts status monitor (updates `.loki/STATUS.txt` every 5s)
5. Runs Claude Code with live output
6. Auto-resumes on rate limits with exponential backoff
7. Continues until completion or max retries
### Monitor Progress
```bash
# In another terminal
watch -n 2 cat .loki/STATUS.txt
```
---
## Key Technical Details
### Claude Code Invocation
The autonomy runner pipes the prompt through stdin for live output:
```bash
echo "$prompt" | claude --dangerously-skip-permissions
```
**Important:** Using `-p` flag doesn't stream output properly. Piping through stdin shows interactive output.
### State Files
- `.loki/state/orchestrator.json` - Current phase, metrics
- `.loki/autonomy-state.json` - Retry count, status, PID
- `.loki/queue/*.json` - Task queues
- `.loki/STATUS.txt` - Human-readable status (updated every 5s)
- `.loki/logs/*.log` - Execution logs
### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `LOKI_MAX_RETRIES` | 50 | Max retry attempts |
| `LOKI_BASE_WAIT` | 60 | Base wait time (seconds) |
| `LOKI_MAX_WAIT` | 3600 | Max wait time (1 hour) |
| `LOKI_SKIP_PREREQS` | false | Skip prerequisite checks |
---
## Version History Summary
| Version | Key Changes |
|---------|-------------|
| 2.5.0 | Real streaming output (stream-json), Web dashboard with Anthropic design |
| 2.4.0 | Live output fix (stdin pipe), STATUS.txt monitor |
| 2.3.0 | Unified autonomy runner (`autonomy/run.sh`) |
| 2.2.0 | Vibe Kanban integration |
| 2.1.0 | Autonomous wrapper with auto-resume |
| 2.0.x | Test suite, macOS compatibility, release workflow |
| 1.x.x | Initial skill with agents, deployment guides |
---
## Known Issues & Solutions
### 1. "Blank output when running autonomously"
**Cause:** Using `-p` flag doesn't stream output
**Solution:** Use stdin pipe: `echo "$prompt" | claude --dangerously-skip-permissions`
### 2. "Vibe Kanban not showing tasks"
**Cause:** Vibe Kanban is UI-driven, doesn't read JSON files automatically
**Solution:** Use `.loki/STATUS.txt` for monitoring, or run Vibe Kanban separately
### 3. "timeout command not found on macOS"
**Cause:** macOS doesn't have GNU coreutils
**Solution:** Perl-based fallback in test scripts
### 4. "TTY raw mode error"
**Cause:** Running Claude in non-interactive mode
**Solution:** Latest commit (008ed86) adds `--no-input` flag
---
## Git Configuration
**Committer:** asklokesh (never use Claude as co-author)
**Commit format:**
```
Short description (vX.X.X)
Detailed bullet points of changes
```
---
## Test Suite
Run all tests:
```bash
./tests/run-all-tests.sh
```
53 tests across 6 test suites - all should pass.
---
## Pending/Future Work
1. **Vibe Kanban proper integration** - Vibe Kanban doesn't read files, would need API integration
2. **Better live output** - Current stdin pipe works but may have edge cases
3. **Task visualization** - Could add a simple TUI for task monitoring
---
## Important Files to Read First
When starting a new session, read these files:
1. `SKILL.md` - The actual skill instructions
2. `autonomy/run.sh` - Main entry point
3. `VERSION` and `CHANGELOG.md` - Current state
4. This file (`CONTEXT-EXPORT.md`) - Full context
---
## User Preferences
- Always use `asklokesh` as committer
- Never use Claude as co-author
- Keep skill files clean, autonomy separate
- Test before pushing
- Live output is important - user wants to see what's happening
---
## Last Known State
- **Version:** 2.5.0
- **Latest Commit:** (pending push)
- **Tests:** All 53 passing
- **Features Added:** Real-time streaming output via stream-json, web dashboard with Anthropic design

View File

@@ -0,0 +1,384 @@
# Loki Mode Installation Guide
Complete installation instructions for all platforms and use cases.
---
## Table of Contents
- [Quick Install (Recommended)](#quick-install-recommended)
- [Claude Code (CLI)](#claude-code-cli)
- [Claude.ai (Web)](#claudeai-web)
- [Anthropic API Console](#anthropic-api-console)
- [Verify Installation](#verify-installation)
- [Troubleshooting](#troubleshooting)
---
## Quick Install (Recommended)
**For Claude Code users:**
```bash
# Clone to your skills directory
git clone https://github.com/asklokesh/loki-mode.git ~/.claude/skills/loki-mode
```
**Done!** Skip to [Verify Installation](#verify-installation).
---
## Claude Code (CLI)
Loki Mode can be installed for Claude Code in three ways:
### Option A: Git Clone (Recommended)
**Personal installation (available in all projects):**
```bash
git clone https://github.com/asklokesh/loki-mode.git ~/.claude/skills/loki-mode
```
**Project-specific installation:**
```bash
# Navigate to your project directory first
cd /path/to/your/project
# Clone to local skills directory
git clone https://github.com/asklokesh/loki-mode.git .claude/skills/loki-mode
```
### Option B: Download from Releases
```bash
# Navigate to skills directory
cd ~/.claude/skills
# Get latest version number
VERSION=$(curl -s https://api.github.com/repos/asklokesh/loki-mode/releases/latest | grep tag_name | cut -d'"' -f4 | tr -d 'v')
# Download and extract
curl -L -o loki-mode.zip "https://github.com/asklokesh/loki-mode/releases/download/v${VERSION}/loki-mode-claude-code-${VERSION}.zip"
unzip loki-mode.zip && rm loki-mode.zip
```
**Result:** Creates `~/.claude/skills/loki-mode/SKILL.md`
### Option C: Minimal Install (curl)
If you only want the essential files without the full repository:
```bash
# Create directory structure
mkdir -p ~/.claude/skills/loki-mode/references
# Download core skill file
curl -o ~/.claude/skills/loki-mode/SKILL.md \
https://raw.githubusercontent.com/asklokesh/loki-mode/main/SKILL.md
# Download agent definitions
curl -o ~/.claude/skills/loki-mode/references/agents.md \
https://raw.githubusercontent.com/asklokesh/loki-mode/main/references/agents.md
# Download deployment guides
curl -o ~/.claude/skills/loki-mode/references/deployment.md \
https://raw.githubusercontent.com/asklokesh/loki-mode/main/references/deployment.md
# Download business operations reference
curl -o ~/.claude/skills/loki-mode/references/business-ops.md \
https://raw.githubusercontent.com/asklokesh/loki-mode/main/references/business-ops.md
```
**Note:** This minimal install won't include examples, tests, or the autonomous runner. Use Option A or B for full functionality.
---
## Claude.ai (Web)
For using Loki Mode on the Claude.ai web interface:
### Step 1: Download the Skill Package
1. Go to [Releases](https://github.com/asklokesh/loki-mode/releases)
2. Download **either**:
- `loki-mode-X.X.X.zip` (standard format)
- `loki-mode-X.X.X.skill` (skill format)
Both contain the same skill and will work.
### Step 2: Upload to Claude.ai
1. Open [Claude.ai](https://claude.ai)
2. Go to **Settings** (gear icon)
3. Navigate to **Features → Skills**
4. Click **Upload Skill**
5. Select the downloaded `.zip` or `.skill` file
**File Structure:** The Claude.ai package has `SKILL.md` at the root level as required by the web interface.
---
## Anthropic API Console
For using Loki Mode through the Anthropic API Console (console.anthropic.com):
### Step 1: Download the API Package
1. Go to [Releases](https://github.com/asklokesh/loki-mode/releases)
2. Download **`loki-mode-api-X.X.X.zip`** (note the `-api-` version)
**Important:** The API version has a different file structure than the web version.
### Step 2: Upload to API Console
1. Go to [console.anthropic.com](https://console.anthropic.com)
2. Navigate to **Skills** section
3. Click **Upload Skill**
4. Select the downloaded `loki-mode-api-X.X.X.zip` file
**File Structure:** The API package has `SKILL.md` inside a `loki-mode/` folder as required by the API.
---
## Verify Installation
### For Claude Code (CLI)
Check that the skill file is in place:
```bash
cat ~/.claude/skills/loki-mode/SKILL.md | head -10
```
**Expected output:** Should show YAML frontmatter starting with:
```yaml
---
name: loki-mode
description: Multi-Agent Autonomous Startup System
...
---
```
### For Claude.ai (Web)
1. Start a new conversation
2. Type: `Loki Mode`
3. Claude should recognize the skill and ask for a PRD
### For API Console
1. Create a new API call with skills enabled
2. Include the skill in your request
3. The skill should be available for use
---
## File Structure
After installation, you should have this structure:
```
loki-mode/
├── SKILL.md # Main skill file (required)
├── README.md # Documentation
├── INSTALLATION.md # This file
├── CHANGELOG.md # Version history
├── VERSION # Current version number
├── LICENSE # MIT License
├── references/ # Agent and deployment references
│ ├── agents.md
│ ├── deployment.md
│ └── business-ops.md
├── autonomy/ # Autonomous runner (CLI only)
│ ├── run.sh
│ └── README.md
├── examples/ # Sample PRDs for testing
│ ├── simple-todo-app.md
│ ├── api-only.md
│ ├── static-landing-page.md
│ └── full-stack-demo.md
├── tests/ # Test suite (CLI only)
│ ├── run-all-tests.sh
│ ├── test-bootstrap.sh
│ └── ...
└── integrations/ # Third-party integrations
└── vibe-kanban.md
```
**Note:** Some files/directories (autonomy, tests, examples) are only available with full installation (Options A or B).
---
## Troubleshooting
### Skill Not Found
**Problem:** Claude doesn't recognize "Loki Mode" command.
**Solutions:**
1. **Check installation path:**
```bash
ls -la ~/.claude/skills/loki-mode/SKILL.md
```
2. **Verify YAML frontmatter:**
```bash
cat ~/.claude/skills/loki-mode/SKILL.md | head -5
```
Should show `name: loki-mode`
3. **Restart Claude Code:**
```bash
# Exit and restart claude command
```
### Permission Denied
**Problem:** Cannot create directories or download files.
**Solution:**
```bash
# Ensure skills directory exists
mkdir -p ~/.claude/skills
# Check permissions
ls -la ~/.claude/
```
### Download Fails
**Problem:** curl or wget commands fail.
**Solutions:**
1. **Check internet connection**
2. **Try alternate download method:**
```bash
# Use wget instead of curl
wget -O ~/.claude/skills/loki-mode/SKILL.md \
https://raw.githubusercontent.com/asklokesh/loki-mode/main/SKILL.md
```
3. **Manual download:**
- Visit the URL in a browser
- Save file manually to `~/.claude/skills/loki-mode/`
### Autonomous Runner Won't Start
**Problem:** `./autonomy/run.sh` gives "command not found" or permission errors.
**Solutions:**
1. **Make executable:**
```bash
chmod +x autonomy/run.sh
```
2. **Run from repository root:**
```bash
# Make sure you're in the loki-mode directory
cd ~/.claude/skills/loki-mode
./autonomy/run.sh
```
3. **Check prerequisites:**
```bash
# Ensure Claude Code is installed
claude --version
# Ensure Python 3 is available
python3 --version
```
### References Not Loading
**Problem:** Skill loads but agent definitions or deployment guides are missing.
**Solution:**
```bash
# Ensure all reference files are present
ls -la ~/.claude/skills/loki-mode/references/
# Should show:
# agents.md
# deployment.md
# business-ops.md
# If missing, download them:
curl -o ~/.claude/skills/loki-mode/references/agents.md \
https://raw.githubusercontent.com/asklokesh/loki-mode/main/references/agents.md
```
---
## Updating Loki Mode
### For Git Installations
```bash
cd ~/.claude/skills/loki-mode
git pull origin main
```
### For Manual Installations
1. Download the latest release
2. Extract to the same directory (overwrite existing files)
3. Or delete old installation and reinstall
### Check Current Version
```bash
cat ~/.claude/skills/loki-mode/VERSION
```
---
## Uninstalling
### Claude Code (CLI)
```bash
# Remove the skill directory
rm -rf ~/.claude/skills/loki-mode
```
### Claude.ai (Web)
1. Go to **Settings → Features → Skills**
2. Find "loki-mode" in the list
3. Click **Remove**
### API Console
1. Go to **Skills** section
2. Find "loki-mode"
3. Click **Delete**
---
## Next Steps
After installation:
1. **Quick Test:** Run a simple example
```bash
./autonomy/run.sh examples/simple-todo-app.md
```
2. **Read Documentation:** Check out [README.md](README.md) for usage guides
3. **Create Your First PRD:** See the Quick Start section in README
4. **Join the Community:** Report issues or contribute at [GitHub](https://github.com/asklokesh/loki-mode)
---
## Need Help?
- **Issues/Bugs:** [GitHub Issues](https://github.com/asklokesh/loki-mode/issues)
- **Discussions:** [GitHub Discussions](https://github.com/asklokesh/loki-mode/discussions)
- **Documentation:** [README.md](README.md)
---
**Happy Building!**

21
skills/loki-mode/LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Loki Mode Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

548
skills/loki-mode/README.md Normal file
View File

@@ -0,0 +1,548 @@
# Loki Mode
**The First Truly Autonomous Multi-Agent Startup System**
[![Claude Code](https://img.shields.io/badge/Claude-Code-orange)](https://claude.ai)
[![Agent Types](https://img.shields.io/badge/Agent%20Types-37-blue)]()
[![Loki Mode](https://img.shields.io/badge/Loki%20Mode-98.78%25%20Pass%401-blueviolet)](benchmarks/results/)
[![HumanEval](https://img.shields.io/badge/HumanEval-98.17%25%20Pass%401-brightgreen)](benchmarks/results/)
[![SWE-bench](https://img.shields.io/badge/SWE--bench-99.67%25%20Patch%20Gen-brightgreen)](benchmarks/results/)
[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
> **PRD → Deployed Product in Zero Human Intervention**
>
> Loki Mode transforms a Product Requirements Document into a fully built, tested, deployed, and revenue-generating product while you sleep. No manual steps. No intervention. Just results.
---
## Demo
[![asciicast](https://asciinema.org/a/EqNo5IVTaPJfCjLmnYgZ9TC3E.svg)](https://asciinema.org/a/EqNo5IVTaPJfCjLmnYgZ9TC3E)
*Click to watch Loki Mode build a complete Todo App from PRD - zero human intervention*
---
## Benchmark Results
### Three-Way Comparison (HumanEval)
| System | Pass@1 | Details |
|--------|--------|---------|
| **Loki Mode (Multi-Agent)** | **98.78%** | 162/164 problems, RARV cycle recovered 2 |
| Direct Claude | 98.17% | 161/164 problems (baseline) |
| MetaGPT | 85.9-87.7% | Published benchmark |
**Loki Mode beats MetaGPT by +11-13%** thanks to the RARV (Reason-Act-Reflect-Verify) cycle.
### Full Results
| Benchmark | Score | Details |
|-----------|-------|---------|
| **Loki Mode HumanEval** | **98.78% Pass@1** | 162/164 (multi-agent with RARV) |
| **Direct Claude HumanEval** | **98.17% Pass@1** | 161/164 (single agent baseline) |
| **Direct Claude SWE-bench** | **99.67% patch gen** | 299/300 problems |
| **Loki Mode SWE-bench** | **99.67% patch gen** | 299/300 problems |
| Model | Claude Opus 4.5 | |
**Key Finding:** Multi-agent RARV matches single-agent performance on both benchmarks after timeout optimization. The 4-agent pipeline (Architect->Engineer->QA->Reviewer) achieves the same 99.67% patch generation as direct Claude.
See [benchmarks/results/](benchmarks/results/) for full methodology and solutions.
---
## What is Loki Mode?
Loki Mode is a Claude Code skill that orchestrates **37 specialized AI agent types** across **6 swarms** to autonomously build, test, deploy, and scale complete startups. It dynamically spawns only the agents you need—**5-10 for simple projects, 100+ for complex startups**—working in parallel with continuous self-verification.
```
PRD → Research → Architecture → Development → Testing → Deployment → Marketing → Revenue
```
**Just say "Loki Mode" and point to a PRD. Walk away. Come back to a deployed product.**
---
## Why Loki Mode?
### **Better Than Anything Out There**
| What Others Do | What Loki Mode Does |
|----------------|---------------------|
| **Single agent** writes code linearly | **100+ agents** work in parallel across engineering, ops, business, data, product, and growth |
| **Manual deployment** required | **Autonomous deployment** to AWS, GCP, Azure, Vercel, Railway with blue-green and canary strategies |
| **No testing** or basic unit tests | **14 automated quality gates**: security scans, load tests, accessibility audits, code reviews |
| **Code only** - you handle the rest | **Full business operations**: marketing, sales, legal, HR, finance, investor relations |
| **Stops on errors** | **Self-healing**: circuit breakers, dead letter queues, exponential backoff, automatic recovery |
| **No visibility** into progress | **Real-time dashboard** with agent monitoring, task queues, and live status updates |
| **"Done" when code is written** | **Never "done"**: continuous optimization, A/B testing, customer feedback loops, perpetual improvement |
### **Core Advantages**
1. **Truly Autonomous**: RARV (Reason-Act-Reflect-Verify) cycle with self-verification achieves 2-3x quality improvement
2. **Massively Parallel**: 100+ agents working simultaneously, not sequential single-agent bottlenecks
3. **Production-Ready**: Not just code—handles deployment, monitoring, incident response, and business operations
4. **Self-Improving**: Learns from mistakes, updates continuity logs, prevents repeated errors
5. **Zero Babysitting**: Auto-resumes on rate limits, recovers from failures, runs until completion
6. **Efficiency Optimized**: ToolOrchestra-inspired metrics track cost per task, reward signals drive continuous improvement
---
## Dashboard & Real-Time Monitoring
Monitor your autonomous startup being built in real-time through the Loki Mode dashboard:
### **Agent Monitoring**
<img width="1200" alt="Loki Mode Dashboard - Active Agents" src="docs/screenshots/dashboard-agents.png" />
**Track all active agents in real-time:**
- **Agent ID** and **Type** (frontend, backend, QA, DevOps, etc.)
- **Model Badge** (Sonnet, Haiku, Opus) with color coding
- **Current Work** being performed
- **Runtime** and **Tasks Completed**
- **Status** (active, completed)
### **Task Queue Visualization**
<img width="1200" alt="Loki Mode Dashboard - Task Queue" src="docs/screenshots/dashboard-tasks.png" />
**Four-column kanban view:**
- **Pending**: Queued tasks waiting for agents
- **In Progress**: Currently being worked on
- **Completed**: Successfully finished (shows last 10)
- **Failed**: Tasks requiring attention
### **Live Status Monitor**
```bash
# Watch status updates in terminal
watch -n 2 cat .loki/STATUS.txt
```
```
╔════════════════════════════════════════════════════════════════╗
║ LOKI MODE STATUS ║
╚════════════════════════════════════════════════════════════════╝
Phase: DEVELOPMENT
Active Agents: 47
├─ Engineering: 18
├─ Operations: 12
├─ QA: 8
└─ Business: 9
Tasks:
├─ Pending: 10
├─ In Progress: 47
├─ Completed: 203
└─ Failed: 0
Last Updated: 2026-01-04 20:45:32
```
**Access the dashboard:**
```bash
# Automatically opens when running autonomously
./autonomy/run.sh ./docs/requirements.md
# Or open manually
open .loki/dashboard/index.html
```
Auto-refreshes every 3 seconds. Works with any modern browser.
---
## Autonomous Capabilities
### **RARV Cycle: Reason-Act-Reflect-Verify**
Loki Mode doesn't just write code—it **thinks, acts, learns, and verifies**:
```
1. REASON
└─ Read .loki/CONTINUITY.md including "Mistakes & Learnings"
└─ Check .loki/state/ and .loki/queue/
└─ Identify next task or improvement
2. ACT
└─ Execute task, write code
└─ Commit changes atomically (git checkpoint)
3. REFLECT
└─ Update .loki/CONTINUITY.md with progress
└─ Update state files
└─ Identify NEXT improvement
4. VERIFY
└─ Run automated tests (unit, integration, E2E)
└─ Check compilation/build
└─ Verify against spec
IF VERIFICATION FAILS:
├─ Capture error details (stack trace, logs)
├─ Analyze root cause
├─ UPDATE "Mistakes & Learnings" in CONTINUITY.md
├─ Rollback to last good git checkpoint if needed
└─ Apply learning and RETRY from REASON
```
**Result:** 2-3x quality improvement through continuous self-verification.
### **Perpetual Improvement Mode**
There is **NEVER** a "finished" state. After completing the PRD, Loki Mode:
- Runs performance optimizations
- Adds missing test coverage
- Improves documentation
- Refactors code smells
- Updates dependencies
- Enhances user experience
- Implements A/B test learnings
**It keeps going until you stop it.**
### **Auto-Resume & Self-Healing**
**Rate limits?** Exponential backoff and automatic resume.
**Errors?** Circuit breakers, dead letter queues, retry logic.
**Interruptions?** State checkpoints every 5 seconds—just restart.
```bash
# Start autonomous mode
./autonomy/run.sh ./docs/requirements.md
# Hit rate limit? Script automatically:
# ├─ Saves state checkpoint
# ├─ Waits with exponential backoff (60s → 120s → 240s...)
# ├─ Resumes from exact point
# └─ Continues until completion or max retries (default: 50)
```
---
## Quick Start
### **1. Install**
```bash
# Clone to your Claude Code skills directory
git clone https://github.com/asklokesh/loki-mode.git ~/.claude/skills/loki-mode
```
See [INSTALLATION.md](INSTALLATION.md) for other installation methods (Web, API Console, minimal curl install).
### **2. Create a PRD**
```markdown
# Product: AI-Powered Todo App
## Overview
Build a todo app with AI-powered task suggestions and deadline predictions.
## Features
- User authentication (email/password)
- Create, read, update, delete todos
- AI suggests next tasks based on patterns
- Smart deadline predictions
- Mobile-responsive design
## Tech Stack
- Next.js 14 with TypeScript
- PostgreSQL database
- OpenAI API for suggestions
- Deploy to Vercel
```
Save as `my-prd.md`.
### **3. Run Loki Mode**
```bash
# Autonomous mode (recommended)
./autonomy/run.sh ./my-prd.md
# Or manual mode
claude --dangerously-skip-permissions
> Loki Mode with PRD at ./my-prd.md
```
### **4. Monitor Progress**
Open the dashboard in your browser (auto-opens) or check status:
```bash
watch -n 2 cat .loki/STATUS.txt
```
### **5. Walk Away**
Seriously. Go get coffee. It'll be deployed when you get back.
**That's it.** No configuration. No manual steps. No intervention.
---
## Agent Swarms (37 Types)
Loki Mode has **37 predefined agent types** organized into **6 specialized swarms**. The orchestrator spawns only what you need—simple projects use 5-10 agents, complex startups spawn 100+.
<img width="5309" height="979" alt="Agent Swarms Visualization" src="https://github.com/user-attachments/assets/7d18635d-a606-401f-8d9f-430e6e4ee689" />
### **Engineering (8 types)**
`eng-frontend` `eng-backend` `eng-database` `eng-mobile` `eng-api` `eng-qa` `eng-perf` `eng-infra`
### **Operations (8 types)**
`ops-devops` `ops-sre` `ops-security` `ops-monitor` `ops-incident` `ops-release` `ops-cost` `ops-compliance`
### **Business (8 types)**
`biz-marketing` `biz-sales` `biz-finance` `biz-legal` `biz-support` `biz-hr` `biz-investor` `biz-partnerships`
### **Data (3 types)**
`data-ml` `data-eng` `data-analytics`
### **Product (3 types)**
`prod-pm` `prod-design` `prod-techwriter`
### **Growth (4 types)**
`growth-hacker` `growth-community` `growth-success` `growth-lifecycle`
### **Review (3 types)**
`review-code` `review-business` `review-security`
See [references/agents.md](references/agents.md) for complete agent type definitions.
---
## How It Works
### **Phase Execution**
| Phase | Description |
|-------|-------------|
| **0. Bootstrap** | Create `.loki/` directory structure, initialize state |
| **1. Discovery** | Parse PRD, competitive research via web search |
| **2. Architecture** | Tech stack selection with self-reflection |
| **3. Infrastructure** | Provision cloud, CI/CD, monitoring |
| **4. Development** | Implement with TDD, parallel code review |
| **5. QA** | 14 quality gates, security audit, load testing |
| **6. Deployment** | Blue-green deploy, auto-rollback on errors |
| **7. Business** | Marketing, sales, legal, support setup |
| **8. Growth** | Continuous optimization, A/B testing, feedback loops |
### **Parallel Code Review**
Every code change goes through **3 specialized reviewers simultaneously**:
```
IMPLEMENT → REVIEW (parallel) → AGGREGATE → FIX → RE-REVIEW → COMPLETE
├─ code-reviewer (Opus) - Code quality, patterns, best practices
├─ business-logic-reviewer (Opus) - Requirements, edge cases, UX
└─ security-reviewer (Opus) - Vulnerabilities, OWASP Top 10
```
**Severity-based issue handling:**
- **Critical/High/Medium**: Block. Fix immediately. Re-review.
- **Low**: Add `// TODO(review): ...` comment, continue.
- **Cosmetic**: Add `// FIXME(nitpick): ...` comment, continue.
### **Directory Structure**
```
.loki/
├── state/ # Orchestrator and agent states
├── queue/ # Task queue (pending, in-progress, completed, dead-letter)
├── memory/ # Episodic, semantic, and procedural memory
├── metrics/ # Efficiency tracking and reward signals
├── messages/ # Inter-agent communication
├── logs/ # Audit logs
├── config/ # Configuration files
├── prompts/ # Agent role prompts
├── artifacts/ # Releases, reports, backups
├── dashboard/ # Real-time monitoring dashboard
└── scripts/ # Helper scripts
```
---
## Example PRDs
Test Loki Mode with these pre-built PRDs in the `examples/` directory:
| PRD | Complexity | Est. Time | Description |
|-----|------------|-----------|-------------|
| `simple-todo-app.md` | Low | ~10 min | Basic todo app - tests core functionality |
| `api-only.md` | Low | ~10 min | REST API only - tests backend agents |
| `static-landing-page.md` | Low | ~5 min | HTML/CSS only - tests frontend/marketing |
| `full-stack-demo.md` | Medium | ~30-60 min | Complete bookmark manager - full test |
```bash
# Example: Run with simple todo app
./autonomy/run.sh examples/simple-todo-app.md
```
---
## Configuration
### **Autonomy Settings**
Customize the autonomous runner with environment variables:
```bash
LOKI_MAX_RETRIES=100 \
LOKI_BASE_WAIT=120 \
LOKI_MAX_WAIT=7200 \
./autonomy/run.sh ./docs/requirements.md
```
| Variable | Default | Description |
|----------|---------|-------------|
| `LOKI_MAX_RETRIES` | 50 | Maximum retry attempts before giving up |
| `LOKI_BASE_WAIT` | 60 | Base wait time in seconds |
| `LOKI_MAX_WAIT` | 3600 | Maximum wait time (1 hour) |
| `LOKI_SKIP_PREREQS` | false | Skip prerequisite checks |
### **Circuit Breakers**
```yaml
# .loki/config/circuit-breakers.yaml
defaults:
failureThreshold: 5
cooldownSeconds: 300
```
### **External Alerting**
```yaml
# .loki/config/alerting.yaml
channels:
slack:
webhook_url: "${SLACK_WEBHOOK_URL}"
severity: [critical, high]
pagerduty:
integration_key: "${PAGERDUTY_KEY}"
severity: [critical]
```
---
## Requirements
- **Claude Code** with `--dangerously-skip-permissions` flag
- **Internet access** for competitive research and deployment
- **Cloud provider credentials** (for deployment phase)
- **Python 3** (for test suite)
**Optional but recommended:**
- Git (for version control and checkpoints)
- Node.js/npm (for dashboard and web projects)
- Docker (for containerized deployments)
---
## Integrations
### **Vibe Kanban (Visual Dashboard)**
Integrate with [Vibe Kanban](https://github.com/BloopAI/vibe-kanban) for a visual kanban board:
```bash
# Install Vibe Kanban
npx vibe-kanban
# Export Loki tasks to Vibe Kanban
./scripts/export-to-vibe-kanban.sh
```
**Benefits:**
- Visual progress tracking of all active agents
- Manual intervention/prioritization when needed
- Code review with visual diffs
- Multi-project dashboard
See [integrations/vibe-kanban.md](integrations/vibe-kanban.md) for full setup guide.
---
## Testing
Run the comprehensive test suite:
```bash
# Run all tests
./tests/run-all-tests.sh
# Or run individual test suites
./tests/test-bootstrap.sh # Directory structure, state init
./tests/test-task-queue.sh # Queue operations, priorities
./tests/test-circuit-breaker.sh # Failure handling, recovery
./tests/test-agent-timeout.sh # Timeout, stuck process handling
./tests/test-state-recovery.sh # Checkpoints, recovery
```
---
## Contributing
Contributions welcome! Please:
1. Read [SKILL.md](SKILL.md) to understand the architecture
2. Check [references/agents.md](references/agents.md) for agent definitions
3. Open an issue for bugs or feature requests
4. Submit PRs with clear descriptions and tests
---
## License
MIT License - see [LICENSE](LICENSE) for details.
---
## Acknowledgments
Loki Mode incorporates research and patterns from leading AI labs and practitioners:
### Research Foundation
| Source | Key Contribution |
|--------|------------------|
| [Anthropic: Building Effective Agents](https://www.anthropic.com/research/building-effective-agents) | Evaluator-optimizer pattern, parallelization |
| [Anthropic: Constitutional AI](https://www.anthropic.com/research/constitutional-ai-harmlessness-from-ai-feedback) | Self-critique against principles |
| [DeepMind: Scalable Oversight via Debate](https://deepmind.google/research/publications/34920/) | Debate-based verification |
| [DeepMind: SIMA 2](https://deepmind.google/blog/sima-2-an-agent-that-plays-reasons-and-learns-with-you-in-virtual-3d-worlds/) | Self-improvement loop |
| [OpenAI: Agents SDK](https://openai.github.io/openai-agents-python/) | Guardrails, tripwires, tracing |
| [NVIDIA ToolOrchestra](https://github.com/NVlabs/ToolOrchestra) | Efficiency metrics, reward signals |
| [CONSENSAGENT (ACL 2025)](https://aclanthology.org/2025.findings-acl.1141/) | Anti-sycophancy, blind review |
| [GoalAct](https://arxiv.org/abs/2504.16563) | Hierarchical planning |
### Practitioner Insights
- **Boris Cherny** (Claude Code creator) - Self-verification loop, extended thinking
- **Simon Willison** - Sub-agents for context isolation, skills system
- **Hacker News Community** - [Production patterns](https://news.ycombinator.com/item?id=44623207) from real deployments
### Inspirations
- [LerianStudio/ring](https://github.com/LerianStudio/ring) - Subagent-driven-development pattern
- [Awesome Agentic Patterns](https://github.com/nibzard/awesome-agentic-patterns) - 105+ production patterns
**[Full Acknowledgements](ACKNOWLEDGEMENTS.md)** - Complete list of 50+ research papers, articles, and resources
Built for the [Claude Code](https://claude.ai) ecosystem, powered by Anthropic's Claude models (Sonnet, Haiku, Opus).
---
**Ready to build a startup while you sleep?**
```bash
git clone https://github.com/asklokesh/loki-mode.git ~/.claude/skills/loki-mode
./autonomy/run.sh your-prd.md
```
---
**Keywords:** claude-code, claude-skills, ai-agents, autonomous-development, multi-agent-system, sdlc-automation, startup-automation, devops, mlops, deployment-automation, self-healing, perpetual-improvement

721
skills/loki-mode/SKILL.md Normal file
View File

@@ -0,0 +1,721 @@
---
name: loki-mode
description: Multi-agent autonomous startup system for Claude Code. Triggers on "Loki Mode". Orchestrates 100+ specialized agents across engineering, QA, DevOps, security, data/ML, business operations, marketing, HR, and customer success. Takes PRD to fully deployed, revenue-generating product with zero human intervention. Features Task tool for subagent dispatch, parallel code review with 3 specialized reviewers, severity-based issue triage, distributed task queue with dead letter handling, automatic deployment to cloud providers, A/B testing, customer feedback loops, incident response, circuit breakers, and self-healing. Handles rate limits via distributed state checkpoints and auto-resume with exponential backoff. Requires --dangerously-skip-permissions flag.
---
# Loki Mode - Multi-Agent Autonomous Startup System
> **Version 2.35.0** | PRD to Production | Zero Human Intervention
> Research-enhanced: OpenAI SDK, DeepMind, Anthropic, AWS Bedrock, Agent SDK, HN Production (2025)
---
## Quick Reference
### Critical First Steps (Every Turn)
1. **READ** `.loki/CONTINUITY.md` - Your working memory + "Mistakes & Learnings"
2. **RETRIEVE** Relevant memories from `.loki/memory/` (episodic patterns, anti-patterns)
3. **CHECK** `.loki/state/orchestrator.json` - Current phase/metrics
4. **REVIEW** `.loki/queue/pending.json` - Next tasks
5. **FOLLOW** RARV cycle: REASON, ACT, REFLECT, **VERIFY** (test your work!)
6. **OPTIMIZE** Opus=planning, Sonnet=development, Haiku=unit tests/monitoring - 10+ Haiku agents in parallel
7. **TRACK** Efficiency metrics: tokens, time, agent count per task
8. **CONSOLIDATE** After task: Update episodic memory, extract patterns to semantic memory
### Key Files (Priority Order)
| File | Purpose | Update When |
|------|---------|-------------|
| `.loki/CONTINUITY.md` | Working memory - what am I doing NOW? | Every turn |
| `.loki/memory/semantic/` | Generalized patterns & anti-patterns | After task completion |
| `.loki/memory/episodic/` | Specific interaction traces | After each action |
| `.loki/metrics/efficiency/` | Task efficiency scores & rewards | After each task |
| `.loki/specs/openapi.yaml` | API spec - source of truth | Architecture changes |
| `CLAUDE.md` | Project context - arch & patterns | Significant changes |
| `.loki/queue/*.json` | Task states | Every task change |
### Decision Tree: What To Do Next?
```
START
|
+-- Read CONTINUITY.md ----------+
| |
+-- Task in-progress? |
| +-- YES: Resume |
| +-- NO: Check pending queue |
| |
+-- Pending tasks? |
| +-- YES: Claim highest priority
| +-- NO: Check phase completion
| |
+-- Phase done? |
| +-- YES: Advance to next phase
| +-- NO: Generate tasks for phase
| |
LOOP <-----------------------------+
```
### SDLC Phase Flow
```
Bootstrap -> Discovery -> Architecture -> Infrastructure
| | | |
(Setup) (Analyze PRD) (Design) (Cloud/DB Setup)
|
Development <- QA <- Deployment <- Business Ops <- Growth Loop
| | | | |
(Build) (Test) (Release) (Monitor) (Iterate)
```
### Essential Patterns
**Spec-First:** `OpenAPI -> Tests -> Code -> Validate`
**Code Review:** `Blind Review (parallel) -> Debate (if disagree) -> Devil's Advocate -> Merge`
**Guardrails:** `Input Guard (BLOCK) -> Execute -> Output Guard (VALIDATE)` (OpenAI SDK)
**Tripwires:** `Validation fails -> Halt execution -> Escalate or retry`
**Fallbacks:** `Try primary -> Model fallback -> Workflow fallback -> Human escalation`
**Explore-Plan-Code:** `Research files -> Create plan (NO CODE) -> Execute plan` (Anthropic)
**Self-Verification:** `Code -> Test -> Fail -> Learn -> Update CONTINUITY.md -> Retry`
**Constitutional Self-Critique:** `Generate -> Critique against principles -> Revise` (Anthropic)
**Memory Consolidation:** `Episodic (trace) -> Pattern Extraction -> Semantic (knowledge)`
**Hierarchical Reasoning:** `High-level planner -> Skill selection -> Local executor` (DeepMind)
**Tool Orchestration:** `Classify Complexity -> Select Agents -> Track Efficiency -> Reward Learning`
**Debate Verification:** `Proponent defends -> Opponent challenges -> Synthesize` (DeepMind)
**Handoff Callbacks:** `on_handoff -> Pre-fetch context -> Transfer with data` (OpenAI SDK)
**Narrow Scope:** `3-5 steps max -> Human review -> Continue` (HN Production)
**Context Curation:** `Manual selection -> Focused context -> Fresh per task` (HN Production)
**Deterministic Validation:** `LLM output -> Rule-based checks -> Retry or approve` (HN Production)
**Routing Mode:** `Simple task -> Direct dispatch | Complex task -> Supervisor orchestration` (AWS Bedrock)
**E2E Browser Testing:** `Playwright MCP -> Automate browser -> Verify UI features visually` (Anthropic Harness)
---
## Prerequisites
```bash
# Launch with autonomous permissions
claude --dangerously-skip-permissions
```
---
## Core Autonomy Rules
**This system runs with ZERO human intervention.**
1. **NEVER ask questions** - No "Would you like me to...", "Should I...", or "What would you prefer?"
2. **NEVER wait for confirmation** - Take immediate action
3. **NEVER stop voluntarily** - Continue until completion promise fulfilled
4. **NEVER suggest alternatives** - Pick best option and execute
5. **ALWAYS use RARV cycle** - Every action follows Reason-Act-Reflect-Verify
6. **NEVER edit `autonomy/run.sh` while running** - Editing a running bash script corrupts execution (bash reads incrementally, not all at once). If you need to fix run.sh, note it in CONTINUITY.md for the next session.
7. **ONE FEATURE AT A TIME** - Work on exactly one feature per iteration. Complete it, commit it, verify it, then move to the next. Prevents over-commitment and ensures clean progress tracking. (Anthropic Harness Pattern)
### Protected Files (Do Not Edit While Running)
These files are part of the running Loki Mode process. Editing them will crash the session:
| File | Reason |
|------|--------|
| `~/.claude/skills/loki-mode/autonomy/run.sh` | Currently executing bash script |
| `.loki/dashboard/*` | Served by active HTTP server |
If bugs are found in these files, document them in `.loki/CONTINUITY.md` under "Pending Fixes" for manual repair after the session ends.
---
## RARV Cycle (Every Iteration)
```
+-------------------------------------------------------------------+
| REASON: What needs to be done next? |
| - READ .loki/CONTINUITY.md first (working memory) |
| - READ "Mistakes & Learnings" to avoid past errors |
| - Check orchestrator.json, review pending.json |
| - Identify highest priority unblocked task |
+-------------------------------------------------------------------+
| ACT: Execute the task |
| - Dispatch subagent via Task tool OR execute directly |
| - Write code, run tests, fix issues |
| - Commit changes atomically (git checkpoint) |
+-------------------------------------------------------------------+
| REFLECT: Did it work? What next? |
| - Verify task success (tests pass, no errors) |
| - UPDATE .loki/CONTINUITY.md with progress |
| - Check completion promise - are we done? |
+-------------------------------------------------------------------+
| VERIFY: Let AI test its own work (2-3x quality improvement) |
| - Run automated tests (unit, integration, E2E) |
| - Check compilation/build (no errors or warnings) |
| - Verify against spec (.loki/specs/openapi.yaml) |
| |
| IF VERIFICATION FAILS: |
| 1. Capture error details (stack trace, logs) |
| 2. Analyze root cause |
| 3. UPDATE CONTINUITY.md "Mistakes & Learnings" |
| 4. Rollback to last good git checkpoint (if needed) |
| 5. Apply learning and RETRY from REASON |
+-------------------------------------------------------------------+
```
---
## Model Selection Strategy
**CRITICAL: Use the right model for each task type. Opus is ONLY for planning/architecture.**
| Model | Use For | Examples |
|-------|---------|----------|
| **Opus 4.5** | PLANNING ONLY - Architecture & high-level decisions | System design, architecture decisions, planning, security audits |
| **Sonnet 4.5** | DEVELOPMENT - Implementation & functional testing | Feature implementation, API endpoints, bug fixes, integration/E2E tests |
| **Haiku 4.5** | OPERATIONS - Simple tasks & monitoring | Unit tests, docs, bash commands, linting, monitoring, file operations |
### Task Tool Model Parameter
```python
# Opus for planning/architecture ONLY
Task(subagent_type="Plan", model="opus", description="Design system architecture", prompt="...")
# Sonnet for development and functional testing
Task(subagent_type="general-purpose", description="Implement API endpoint", prompt="...")
Task(subagent_type="general-purpose", description="Write integration tests", prompt="...")
# Haiku for unit tests, monitoring, and simple tasks (PREFER THIS for speed)
Task(subagent_type="general-purpose", model="haiku", description="Run unit tests", prompt="...")
Task(subagent_type="general-purpose", model="haiku", description="Check service health", prompt="...")
```
### Opus Task Categories (RESTRICTED - Planning Only)
- System architecture design
- High-level planning and strategy
- Security audits and threat modeling
- Major refactoring decisions
- Technology selection
### Sonnet Task Categories (Development)
- Feature implementation
- API endpoint development
- Bug fixes (non-trivial)
- Integration tests and E2E tests
- Code refactoring
- Database migrations
### Haiku Task Categories (Operations - Use Extensively)
- Writing/running unit tests
- Generating documentation
- Running bash commands (npm install, git operations)
- Simple bug fixes (typos, imports, formatting)
- File operations, linting, static analysis
- Monitoring, health checks, log analysis
- Simple data transformations, boilerplate generation
### Parallelization Strategy
```python
# Launch 10+ Haiku agents in parallel for unit test suite
for test_file in test_files:
Task(subagent_type="general-purpose", model="haiku",
description=f"Run unit tests: {test_file}",
run_in_background=True)
```
### Advanced Task Tool Parameters
**Background Agents:**
```python
# Launch background agent - returns immediately with output_file path
Task(description="Long analysis task", run_in_background=True, prompt="...")
# Output truncated to 30K chars - use Read tool to check full output file
```
**Agent Resumption (for interrupted/long-running tasks):**
```python
# First call returns agent_id
result = Task(description="Complex refactor", prompt="...")
# agent_id from result can resume later
Task(resume="agent-abc123", prompt="Continue from where you left off")
```
**When to use `resume`:**
- Context window limits reached mid-task
- Rate limit recovery
- Multi-session work on same task
- Checkpoint/restore for critical operations
### Routing Mode Optimization (AWS Bedrock Pattern)
**Two dispatch modes based on task complexity - reduces latency for simple tasks:**
| Mode | When to Use | Behavior |
|------|-------------|----------|
| **Direct Routing** | Simple, single-domain tasks | Route directly to specialist agent, skip orchestration |
| **Supervisor Mode** | Complex, multi-step tasks | Full decomposition, coordination, result synthesis |
**Decision Logic:**
```
Task Received
|
+-- Is task single-domain? (one file, one skill, clear scope)
| +-- YES: Direct Route to specialist agent
| | - Faster (no orchestration overhead)
| | - Minimal context (avoid confusion)
| | - Examples: "Fix typo in README", "Run unit tests"
| |
| +-- NO: Supervisor Mode
| - Full task decomposition
| - Coordinate multiple agents
| - Synthesize results
| - Examples: "Implement auth system", "Refactor API layer"
|
+-- Fallback: If intent unclear, use Supervisor Mode
```
**Direct Routing Examples (Skip Orchestration):**
```python
# Simple tasks -> Direct dispatch to Haiku
Task(model="haiku", description="Fix import in utils.py", prompt="...") # Direct
Task(model="haiku", description="Run linter on src/", prompt="...") # Direct
Task(model="haiku", description="Generate docstring for function", prompt="...") # Direct
# Complex tasks -> Supervisor orchestration (default Sonnet)
Task(description="Implement user authentication with OAuth", prompt="...") # Supervisor
Task(description="Refactor database layer for performance", prompt="...") # Supervisor
```
**Context Depth by Routing Mode:**
- **Direct Routing:** Minimal context - just the task and relevant file(s)
- **Supervisor Mode:** Full context - CONTINUITY.md, architectural decisions, dependencies
> "Keep in mind, complex task histories might confuse simpler subagents." - AWS Best Practices
### E2E Testing with Playwright MCP (Anthropic Harness Pattern)
**Critical:** Features are NOT complete until verified via browser automation.
```python
# Enable Playwright MCP for E2E testing
# In settings or via mcp_servers config:
mcp_servers = {
"playwright": {"command": "npx", "args": ["@playwright/mcp@latest"]}
}
# Agent can then automate browser to verify features work visually
```
**E2E Verification Flow:**
1. Feature implemented and unit tests pass
2. Start dev server via init script
3. Use Playwright MCP to automate browser
4. Verify UI renders correctly
5. Test user interactions (clicks, forms, navigation)
6. Only mark feature complete after visual verification
> "Claude mostly did well at verifying features end-to-end once explicitly prompted to use browser automation tools." - Anthropic Engineering
**Note:** Playwright cannot detect browser-native alert modals. Use custom UI for confirmations.
---
## Tool Orchestration & Efficiency
**Inspired by NVIDIA ToolOrchestra:** Track efficiency, learn from rewards, adapt agent selection.
### Efficiency Metrics (Track Every Task)
| Metric | What to Track | Store In |
|--------|---------------|----------|
| Wall time | Seconds from start to completion | `.loki/metrics/efficiency/` |
| Agent count | Number of subagents spawned | `.loki/metrics/efficiency/` |
| Retry count | Attempts before success | `.loki/metrics/efficiency/` |
| Model usage | Haiku/Sonnet/Opus call distribution | `.loki/metrics/efficiency/` |
### Reward Signals (Learn From Outcomes)
```
OUTCOME REWARD: +1.0 (success) | 0.0 (partial) | -1.0 (failure)
EFFICIENCY REWARD: 0.0-1.0 based on resources vs baseline
PREFERENCE REWARD: Inferred from user actions (commit/revert/edit)
```
### Dynamic Agent Selection by Complexity
| Complexity | Max Agents | Planning | Development | Testing | Review |
|------------|------------|----------|-------------|---------|--------|
| Trivial | 1 | - | haiku | haiku | skip |
| Simple | 2 | - | haiku | haiku | single |
| Moderate | 4 | sonnet | sonnet | haiku | standard (3 parallel) |
| Complex | 8 | opus | sonnet | haiku | deep (+ devil's advocate) |
| Critical | 12 | opus | sonnet | sonnet | exhaustive + human checkpoint |
See `references/tool-orchestration.md` for full implementation details.
---
## Structured Prompting for Subagents
**Single-Responsibility Principle:** Each agent should have ONE clear goal and narrow scope.
([UiPath Best Practices](https://www.uipath.com/blog/ai/agent-builder-best-practices))
**Every subagent dispatch MUST include:**
```markdown
## GOAL (What success looks like)
[High-level objective, not just the action]
Example: "Refactor authentication for maintainability and testability"
NOT: "Refactor the auth file"
## CONSTRAINTS (What you cannot do)
- No third-party dependencies without approval
- Maintain backwards compatibility with v1.x API
- Keep response time under 200ms
## CONTEXT (What you need to know)
- Related files: [list with brief descriptions]
- Previous attempts: [what was tried, why it failed]
## OUTPUT FORMAT (What to deliver)
- [ ] Pull request with Why/What/Trade-offs description
- [ ] Unit tests with >90% coverage
- [ ] Update API documentation
## WHEN COMPLETE
Report back with: WHY, WHAT, TRADE-OFFS, RISKS
```
---
## Quality Gates
**Never ship code without passing all quality gates:**
1. **Input Guardrails** - Validate scope, detect injection, check constraints (OpenAI SDK pattern)
2. **Static Analysis** - CodeQL, ESLint/Pylint, type checking
3. **Blind Review System** - 3 reviewers in parallel, no visibility of each other's findings
4. **Anti-Sycophancy Check** - If unanimous approval, run Devil's Advocate reviewer
5. **Output Guardrails** - Validate code quality, spec compliance, no secrets (tripwire on fail)
6. **Severity-Based Blocking** - Critical/High/Medium = BLOCK; Low/Cosmetic = TODO comment
7. **Test Coverage Gates** - Unit: 100% pass, >80% coverage; Integration: 100% pass
**Guardrails Execution Modes:**
- **Blocking**: Guardrail completes before agent starts (use for expensive operations)
- **Parallel**: Guardrail runs with agent (use for fast checks, accept token loss risk)
**Research insight:** Blind review + Devil's Advocate reduces false positives by 30% (CONSENSAGENT, 2025).
**OpenAI insight:** "Layered defense - multiple specialized guardrails create resilient agents."
See `references/quality-control.md` and `references/openai-patterns.md` for details.
---
## Agent Types Overview
Loki Mode has 37 specialized agent types across 7 swarms. The orchestrator spawns only agents needed for your project.
| Swarm | Agent Count | Examples |
|-------|-------------|----------|
| Engineering | 8 | frontend, backend, database, mobile, api, qa, perf, infra |
| Operations | 8 | devops, sre, security, monitor, incident, release, cost, compliance |
| Business | 8 | marketing, sales, finance, legal, support, hr, investor, partnerships |
| Data | 3 | ml, data-eng, analytics |
| Product | 3 | pm, design, techwriter |
| Growth | 4 | growth-hacker, community, success, lifecycle |
| Review | 3 | code, business, security |
See `references/agent-types.md` for complete definitions and capabilities.
---
## Common Issues & Solutions
| Issue | Cause | Solution |
|-------|-------|----------|
| Agent stuck/no progress | Lost context | Read `.loki/CONTINUITY.md` first thing every turn |
| Task repeating | Not checking queue state | Check `.loki/queue/*.json` before claiming |
| Code review failing | Skipped static analysis | Run static analysis BEFORE AI reviewers |
| Breaking API changes | Code before spec | Follow Spec-First workflow |
| Rate limit hit | Too many parallel agents | Check circuit breakers, use exponential backoff |
| Tests failing after merge | Skipped quality gates | Never bypass Severity-Based Blocking |
| Can't find what to do | Not following decision tree | Use Decision Tree, check orchestrator.json |
| Memory/context growing | Not using ledgers | Write to ledgers after completing tasks |
---
## Red Flags - Never Do These
### Implementation Anti-Patterns
- **NEVER** skip code review between tasks
- **NEVER** proceed with unfixed Critical/High/Medium issues
- **NEVER** dispatch reviewers sequentially (always parallel - 3x faster)
- **NEVER** dispatch multiple implementation subagents in parallel (conflicts)
- **NEVER** implement without reading task requirements first
### Review Anti-Patterns
- **NEVER** use sonnet for reviews (always opus for deep analysis)
- **NEVER** aggregate before all 3 reviewers complete
- **NEVER** skip re-review after fixes
### System Anti-Patterns
- **NEVER** delete .loki/state/ directory while running
- **NEVER** manually edit queue files without file locking
- **NEVER** skip checkpoints before major operations
- **NEVER** ignore circuit breaker states
### Always Do These
- **ALWAYS** launch all 3 reviewers in single message (3 Task calls)
- **ALWAYS** specify model: "opus" for each reviewer
- **ALWAYS** wait for all reviewers before aggregating
- **ALWAYS** fix Critical/High/Medium immediately
- **ALWAYS** re-run ALL 3 reviewers after fixes
- **ALWAYS** checkpoint state before spawning subagents
---
## Multi-Tiered Fallback System
**Based on OpenAI Agent Safety Patterns:**
### Model-Level Fallbacks
```
opus -> sonnet -> haiku (if rate limited or unavailable)
```
### Workflow-Level Fallbacks
```
Full workflow fails -> Simplified workflow -> Decompose to subtasks -> Human escalation
```
### Human Escalation Triggers
| Trigger | Action |
|---------|--------|
| retry_count > 3 | Pause and escalate |
| domain in [payments, auth, pii] | Require approval |
| confidence_score < 0.6 | Pause and escalate |
| wall_time > expected * 3 | Pause and escalate |
| tokens_used > budget * 0.8 | Pause and escalate |
See `references/openai-patterns.md` for full fallback implementation.
---
## AGENTS.md Integration
**Read target project's AGENTS.md if exists** (OpenAI/AAIF standard):
```
Context Priority:
1. AGENTS.md (closest to current file)
2. CLAUDE.md (Claude-specific)
3. .loki/CONTINUITY.md (session state)
4. Package docs
5. README.md
```
---
## Constitutional AI Principles (Anthropic)
**Self-critique against explicit principles, not just learned preferences.**
### Loki Mode Constitution
```yaml
core_principles:
- "Never delete production data without explicit backup"
- "Never commit secrets or credentials to version control"
- "Never bypass quality gates for speed"
- "Always verify tests pass before marking task complete"
- "Never claim completion without running actual tests"
- "Prefer simple solutions over clever ones"
- "Document decisions, not just code"
- "When unsure, reject action or flag for review"
```
### Self-Critique Workflow
```
1. Generate response/code
2. Critique against each principle
3. Revise if any principle violated
4. Only then proceed with action
```
See `references/lab-research-patterns.md` for Constitutional AI implementation.
---
## Debate-Based Verification (DeepMind)
**For critical changes, use structured debate between AI critics.**
```
Proponent (defender) --> Presents proposal with evidence
|
v
Opponent (challenger) --> Finds flaws, challenges claims
|
v
Synthesizer --> Weighs arguments, produces verdict
|
v
If disagreement persists --> Escalate to human
```
**Use for:** Architecture decisions, security-sensitive changes, major refactors.
See `references/lab-research-patterns.md` for debate verification details.
---
## Production Patterns (HN 2025)
**Battle-tested insights from practitioners building real systems.**
### Narrow Scope Wins
```yaml
task_constraints:
max_steps_before_review: 3-5
characteristics:
- Specific, well-defined objectives
- Pre-classified inputs
- Deterministic success criteria
- Verifiable outputs
```
### Confidence-Based Routing
```
confidence >= 0.95 --> Auto-approve with audit log
confidence >= 0.70 --> Quick human review
confidence >= 0.40 --> Detailed human review
confidence < 0.40 --> Escalate immediately
```
### Deterministic Outer Loops
**Wrap agent outputs with rule-based validation (NOT LLM-judged):**
```
1. Agent generates output
2. Run linter (deterministic)
3. Run tests (deterministic)
4. Check compilation (deterministic)
5. Only then: human or AI review
```
### Context Engineering
```yaml
principles:
- "Less is more" - focused beats comprehensive
- Manual selection outperforms automatic RAG
- Fresh conversations per major task
- Remove outdated information aggressively
context_budget:
target: "< 10k tokens for context"
reserve: "90% for model reasoning"
```
### Sub-Agents for Context Isolation
**Use sub-agents to prevent token waste on noisy subtasks:**
```
Main agent (focused) --> Sub-agent (file search)
--> Sub-agent (test running)
--> Sub-agent (linting)
```
See `references/production-patterns.md` for full practitioner patterns.
---
## Exit Conditions
| Condition | Action |
|-----------|--------|
| Product launched, stable 24h | Enter growth loop mode |
| Unrecoverable failure | Save state, halt, request human |
| PRD updated | Diff, create delta tasks, continue |
| Revenue target hit | Log success, continue optimization |
| Runway < 30 days | Alert, optimize costs aggressively |
---
## Directory Structure Overview
```
.loki/
+-- CONTINUITY.md # Working memory (read/update every turn)
+-- specs/
| +-- openapi.yaml # API spec - source of truth
+-- queue/
| +-- pending.json # Tasks waiting to be claimed
| +-- in-progress.json # Currently executing tasks
| +-- completed.json # Finished tasks
| +-- dead-letter.json # Failed tasks for review
+-- state/
| +-- orchestrator.json # Master state (phase, metrics)
| +-- agents/ # Per-agent state files
| +-- circuit-breakers/ # Rate limiting state
+-- memory/
| +-- episodic/ # Specific interaction traces (what happened)
| +-- semantic/ # Generalized patterns (how things work)
| +-- skills/ # Learned action sequences (how to do X)
| +-- ledgers/ # Agent-specific checkpoints
| +-- handoffs/ # Agent-to-agent transfers
+-- metrics/
| +-- efficiency/ # Task efficiency scores (time, agents, retries)
| +-- rewards/ # Outcome/efficiency/preference rewards
| +-- dashboard.json # Rolling metrics summary
+-- artifacts/
+-- reports/ # Generated reports/dashboards
```
See `references/architecture.md` for full structure and state schemas.
---
## Invocation
```
Loki Mode # Start fresh
Loki Mode with PRD at path/to/prd # Start with PRD
```
**Skill Metadata:**
| Field | Value |
|-------|-------|
| Trigger | "Loki Mode" or "Loki Mode with PRD at [path]" |
| Skip When | Need human approval, want to review plan first, single small task |
| Related Skills | subagent-driven-development, executing-plans |
---
## References
Detailed documentation is split into reference files for progressive loading:
| Reference | Content |
|-----------|---------|
| `references/core-workflow.md` | Full RARV cycle, CONTINUITY.md template, autonomy rules |
| `references/quality-control.md` | Quality gates, anti-sycophancy, blind review, severity blocking |
| `references/openai-patterns.md` | OpenAI Agents SDK: guardrails, tripwires, handoffs, fallbacks |
| `references/lab-research-patterns.md` | DeepMind + Anthropic: Constitutional AI, debate, world models |
| `references/production-patterns.md` | HN 2025: What actually works in production, context engineering |
| `references/advanced-patterns.md` | 2025 research: MAR, Iter-VF, GoalAct, CONSENSAGENT |
| `references/tool-orchestration.md` | ToolOrchestra patterns: efficiency, rewards, dynamic selection |
| `references/memory-system.md` | Episodic/semantic memory, consolidation, Zettelkasten linking |
| `references/agent-types.md` | All 37 agent types with full capabilities |
| `references/task-queue.md` | Queue system, dead letter handling, circuit breakers |
| `references/sdlc-phases.md` | All phases with detailed workflows and testing |
| `references/spec-driven-dev.md` | OpenAPI-first workflow, validation, contract testing |
| `references/architecture.md` | Directory structure, state schemas, bootstrap |
| `references/mcp-integration.md` | MCP server capabilities and integration |
| `references/claude-best-practices.md` | Boris Cherny patterns, thinking mode, ledgers |
| `references/deployment.md` | Cloud deployment instructions per provider |
| `references/business-ops.md` | Business operation workflows |
---
**Version:** 2.32.0 | **Lines:** ~600 | **Research-Enhanced: Labs + HN Production Patterns**

1
skills/loki-mode/VERSION Normal file
View File

@@ -0,0 +1 @@
2.35.1

View File

@@ -0,0 +1,497 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Loki Mode Dashboard</title>
<style>
:root {
--bg-cream: #FDF6E3;
--bg-dark: #1a1a2e;
--coral: #FF6B6B;
--coral-light: #FF8E8E;
--teal: #4ECDC4;
--purple: #A78BFA;
--yellow: #FCD34D;
--green: #10B981;
--red: #EF4444;
--text-dark: #2D3748;
--text-light: #718096;
--card-bg: #FFFFFF;
--border: #E2E8F0;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
background: var(--bg-cream);
color: var(--text-dark);
min-height: 100vh;
padding: 24px;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32px;
}
.logo {
display: flex;
align-items: center;
gap: 12px;
}
.logo-icon {
width: 48px;
height: 48px;
background: linear-gradient(135deg, var(--coral), var(--coral-light));
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
color: white;
font-weight: bold;
}
.logo-text {
font-size: 28px;
font-weight: 700;
color: var(--text-dark);
}
.status-bar {
display: flex;
gap: 16px;
align-items: center;
}
.status-item {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
background: var(--card-bg);
border-radius: 8px;
border: 1px solid var(--border);
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.status-dot.active { background: var(--green); }
.status-dot.warning { background: var(--yellow); }
.status-dot.error { background: var(--red); }
.section {
margin-bottom: 32px;
}
.section-title {
font-size: 20px;
font-weight: 600;
margin-bottom: 16px;
color: var(--text-dark);
}
.agents-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 16px;
}
.agent-card {
background: var(--card-bg);
border-radius: 12px;
padding: 20px;
border: 1px solid var(--border);
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}
.agent-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 12px;
}
.agent-id {
font-weight: 600;
font-size: 14px;
color: var(--text-dark);
}
.agent-type {
font-size: 12px;
color: var(--text-light);
margin-top: 4px;
}
.model-badge {
padding: 4px 10px;
border-radius: 12px;
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
}
.model-badge.sonnet {
background: #E0E7FF;
color: #4338CA;
}
.model-badge.haiku {
background: #D1FAE5;
color: #065F46;
}
.model-badge.opus {
background: #FDE68A;
color: #92400E;
}
.agent-work {
font-size: 13px;
color: var(--text-dark);
line-height: 1.5;
margin-bottom: 16px;
}
.agent-stats {
display: flex;
gap: 16px;
font-size: 12px;
color: var(--text-light);
}
.stat {
display: flex;
align-items: center;
gap: 4px;
}
.agent-status {
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
margin-top: 12px;
padding-top: 12px;
border-top: 1px solid var(--border);
}
.status-active {
color: var(--green);
}
.status-completed {
color: var(--purple);
}
/* Task Queue Section */
.queue-columns {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
.queue-column {
background: var(--card-bg);
border-radius: 12px;
padding: 16px;
border: 1px solid var(--border);
min-height: 300px;
}
.queue-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
padding-bottom: 12px;
border-bottom: 2px solid var(--border);
}
.queue-title {
font-weight: 600;
font-size: 14px;
}
.queue-count {
background: var(--bg-cream);
padding: 4px 10px;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
}
.queue-column.pending .queue-header { border-color: var(--yellow); }
.queue-column.in-progress .queue-header { border-color: var(--teal); }
.queue-column.completed .queue-header { border-color: var(--green); }
.queue-column.failed .queue-header { border-color: var(--red); }
.task-card {
background: var(--bg-cream);
border-radius: 8px;
padding: 12px;
margin-bottom: 8px;
font-size: 12px;
}
.task-id {
font-weight: 600;
color: var(--text-dark);
margin-bottom: 4px;
}
.task-type {
display: inline-block;
padding: 2px 8px;
background: var(--card-bg);
border-radius: 4px;
font-size: 10px;
color: var(--text-light);
margin-bottom: 8px;
}
.task-desc {
color: var(--text-dark);
line-height: 1.4;
}
.last-updated {
text-align: center;
color: var(--text-light);
font-size: 12px;
margin-top: 24px;
}
@media (max-width: 1024px) {
.queue-columns {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 640px) {
.queue-columns {
grid-template-columns: 1fr;
}
.agents-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="header">
<div class="logo">
<div class="logo-icon">L</div>
<span class="logo-text">Loki Mode Dashboard</span>
</div>
<div class="status-bar">
<div class="status-item">
<div class="status-dot active"></div>
<span>Phase: DEVELOPMENT</span>
</div>
<div class="status-item">
<span>v2.18.0</span>
</div>
</div>
</div>
<div class="section" id="agents-section">
<h2 class="section-title">Active Agents</h2>
<div class="agents-grid" id="agents-grid">
<!-- Agent cards populated by JS -->
</div>
</div>
<div class="section" id="queue-section">
<h2 class="section-title">Task Queue</h2>
<div class="queue-columns" id="queue-columns">
<div class="queue-column pending">
<div class="queue-header">
<span class="queue-title">Pending</span>
<span class="queue-count" id="pending-count">0</span>
</div>
<div id="pending-tasks"></div>
</div>
<div class="queue-column in-progress">
<div class="queue-header">
<span class="queue-title">In Progress</span>
<span class="queue-count" id="in-progress-count">0</span>
</div>
<div id="in-progress-tasks"></div>
</div>
<div class="queue-column completed">
<div class="queue-header">
<span class="queue-title">Completed</span>
<span class="queue-count" id="completed-count">0</span>
</div>
<div id="completed-tasks"></div>
</div>
<div class="queue-column failed">
<div class="queue-header">
<span class="queue-title">Failed</span>
<span class="queue-count" id="failed-count">0</span>
</div>
<div id="failed-tasks"></div>
</div>
</div>
</div>
<div class="last-updated" id="last-updated">
Last updated: --
</div>
<script>
// Demo data for screenshots
const demoAgents = [
{
id: 'eng-001-backend-api',
type: 'Engineering Backend',
model: 'sonnet',
work: 'Implementing POST /api/todos endpoint with validation and SQLite storage',
runtime: '12m 34s',
tasks: 5,
status: 'active'
},
{
id: 'eng-002-frontend-ui',
type: 'Engineering Frontend',
model: 'sonnet',
work: 'Building React components for todo list with Tailwind styling',
runtime: '8m 21s',
tasks: 3,
status: 'active'
},
{
id: 'qa-001-testing',
type: 'QA Testing',
model: 'haiku',
work: 'Writing unit tests for authentication module',
runtime: '5m 45s',
tasks: 8,
status: 'active'
},
{
id: 'review-security-001',
type: 'Security Review',
model: 'opus',
work: 'Analyzing auth flow for OWASP vulnerabilities',
runtime: '3m 12s',
tasks: 2,
status: 'active'
},
{
id: 'ops-devops-001',
type: 'Operations DevOps',
model: 'sonnet',
work: 'Configuring GitHub Actions CI/CD pipeline',
runtime: '15m 08s',
tasks: 4,
status: 'active'
},
{
id: 'biz-marketing-001',
type: 'Business Marketing',
model: 'haiku',
work: 'Creating landing page copy and SEO meta tags',
runtime: '6m 33s',
tasks: 2,
status: 'completed'
}
];
const demoTasks = {
pending: [
{ id: 'task-015', type: 'eng-database', desc: 'Create migration for user preferences table' },
{ id: 'task-016', type: 'eng-frontend', desc: 'Implement dark mode toggle component' },
{ id: 'task-017', type: 'qa-testing', desc: 'Write E2E tests for checkout flow' }
],
inProgress: [
{ id: 'task-012', type: 'eng-backend', desc: 'Implement JWT refresh token rotation' },
{ id: 'task-013', type: 'eng-frontend', desc: 'Add form validation to signup page' }
],
completed: [
{ id: 'task-001', type: 'eng-backend', desc: 'Setup Express server with TypeScript' },
{ id: 'task-002', type: 'eng-database', desc: 'Create initial SQLite schema' },
{ id: 'task-003', type: 'eng-frontend', desc: 'Initialize React with Vite' },
{ id: 'task-004', type: 'ops-devops', desc: 'Configure ESLint and Prettier' },
{ id: 'task-005', type: 'eng-backend', desc: 'Implement user registration endpoint' }
],
failed: []
};
function renderAgents() {
const grid = document.getElementById('agents-grid');
grid.innerHTML = demoAgents.map(agent => `
<div class="agent-card">
<div class="agent-header">
<div>
<div class="agent-id">${agent.id}</div>
<div class="agent-type">${agent.type}</div>
</div>
<span class="model-badge ${agent.model}">${agent.model}</span>
</div>
<div class="agent-work">${agent.work}</div>
<div class="agent-stats">
<span class="stat">Runtime: ${agent.runtime}</span>
<span class="stat">Tasks: ${agent.tasks}</span>
</div>
<div class="agent-status ${agent.status === 'active' ? 'status-active' : 'status-completed'}">
<div class="status-dot ${agent.status === 'active' ? 'active' : ''}"></div>
${agent.status === 'active' ? 'Active' : 'Completed'}
</div>
</div>
`).join('');
}
function renderTasks() {
const renderTaskList = (tasks, containerId) => {
const container = document.getElementById(containerId);
container.innerHTML = tasks.map(task => `
<div class="task-card">
<div class="task-id">${task.id}</div>
<span class="task-type">${task.type}</span>
<div class="task-desc">${task.desc}</div>
</div>
`).join('');
};
renderTaskList(demoTasks.pending, 'pending-tasks');
renderTaskList(demoTasks.inProgress, 'in-progress-tasks');
renderTaskList(demoTasks.completed.slice(0, 5), 'completed-tasks');
renderTaskList(demoTasks.failed, 'failed-tasks');
document.getElementById('pending-count').textContent = demoTasks.pending.length;
document.getElementById('in-progress-count').textContent = demoTasks.inProgress.length;
document.getElementById('completed-count').textContent = demoTasks.completed.length;
document.getElementById('failed-count').textContent = demoTasks.failed.length;
}
function updateTimestamp() {
const now = new Date().toLocaleString();
document.getElementById('last-updated').textContent = `Last updated: ${now}`;
}
// Initial render
renderAgents();
renderTasks();
updateTimestamp();
// Auto-refresh every 3 seconds (in production, would fetch real data)
setInterval(updateTimestamp, 3000);
</script>
</body>
</html>

View File

@@ -0,0 +1,402 @@
# Loki Mode Agent Constitution
> **Machine-Enforceable Behavioral Contract for All Agents**
> Version 1.0.0 | Immutable Principles | Context-Preserved Lineage
---
## Core Principles (Inviolable)
### 1. Specification-First Development
**RULE:** No code shall be written before the specification exists.
**Enforcement:**
```
IF task.type == "implementation" AND !exists(spec_file):
BLOCK with error: "SPEC_MISSING"
REQUIRE: Create OpenAPI spec first
```
**Rationale:** Specs are contracts. Code is implementation. Contract before implementation.
### 2. Git Checkpoint System
**RULE:** Every completed task MUST create a git checkpoint.
**Enforcement:**
```
ON task.status == "completed":
git add <modified_files>
git commit -m "[Loki] Task ${task.id}: ${task.title}"
UPDATE CONTINUITY.md with commit SHA
```
**Rationale:** Git history is proof of progress. Every task is a save point.
### 3. Context Preservation
**RULE:** All agents MUST inherit and preserve context from their spawning agent.
**Enforcement:**
```
ON agent.spawn():
agent.context.parent_id = spawner.agent_id
agent.context.lineage = [...spawner.lineage, spawner.agent_id]
agent.context.inherited_memory = spawner.memory.export()
WRITE .agent/sub-agents/${agent.agent_id}.json
```
**Rationale:** Context drift kills multi-agent systems. Lineage is truth.
### 4. Iterative Specification Questions
**RULE:** During spec generation, agents MUST ask clarifying questions before assuming.
**Enforcement:**
```
WHILE generating_spec:
IF ambiguity_detected OR assumption_required:
questions = generate_clarifying_questions()
IF orchestrator_mode:
answers = infer_from_prd()
ELSE:
answers = ask_user(questions)
UPDATE spec WITH answers
```
**Rationale:** Assumptions create bugs. Questions create clarity.
### 5. Machine-Readable Rules
**RULE:** All behavioral rules MUST be represented as structured artifacts, not just prose.
**Enforcement:**
```
rules/
├── pre-commit.schema.json # Validation rules
├── quality-gates.yaml # Quality thresholds
├── agent-contracts.json # Agent responsibilities
└── invariants.ts # Runtime assertions
```
**Rationale:** Humans read markdown. Machines enforce JSON/YAML.
---
## Agent Behavioral Contracts
### Orchestrator Agent
**Responsibilities:**
- Initialize .loki/ directory structure
- Maintain CONTINUITY.md (working memory)
- Coordinate task queue (pending → in-progress → completed)
- Enforce quality gates
- Manage git checkpoints
**Prohibited Actions:**
- Writing implementation code directly
- Skipping spec generation
- Modifying completed tasks without explicit override
**Context Obligations:**
- MUST read CONTINUITY.md before every action
- MUST update orchestrator.json after phase transitions
- MUST preserve task lineage in completed.json
### Engineering Swarm Agents
**Responsibilities:**
- Implement features per OpenAPI spec
- Write contract tests before implementation
- Create git commits for completed tasks
- Ask clarifying questions when spec is ambiguous
**Prohibited Actions:**
- Implementing without spec
- Skipping tests
- Ignoring linter/type errors
**Context Obligations:**
- MUST inherit parent agent's context
- MUST log all decisions to .agent/sub-agents/${agent_id}.md
- MUST reference spec in all implementation commits
### QA Swarm Agents
**Responsibilities:**
- Generate test cases from OpenAPI spec
- Run contract validation tests
- Report discrepancies between code and spec
- Create bug reports in dead-letter queue
**Prohibited Actions:**
- Modifying implementation code
- Skipping failing tests
- Approving incomplete features
**Context Obligations:**
- MUST validate against spec as source of truth
- MUST log test results to ledgers/
- MUST create git commits for test additions
### DevOps Swarm Agents
**Responsibilities:**
- Automate deployment pipelines
- Monitor service health
- Configure infrastructure as code
- Manage environment secrets
**Prohibited Actions:**
- Storing secrets in plaintext
- Deploying without health checks
- Skipping rollback procedures
**Context Obligations:**
- MUST log all deployments to deployment ledger
- MUST preserve deployment context for rollback
- MUST track infrastructure state in orchestrator.json
---
## Quality Gates (Machine-Enforceable)
### Pre-Commit Hook (BLOCKING)
```yaml
quality_gates:
linting:
enabled: true
auto_fix: true
block_on_failure: true
type_checking:
enabled: true
strict_mode: true
block_on_failure: true
contract_tests:
enabled: true
min_coverage: 80%
block_on_failure: true
spec_validation:
enabled: true
validator: spectral
block_on_failure: true
```
### Post-Implementation Review (AUTO-FIX)
```yaml
auto_review:
static_analysis:
tools: [eslint, prettier, tsc]
auto_fix: true
security_scan:
tools: [semgrep, snyk]
severity_threshold: medium
auto_create_issues: true
performance_check:
lighthouse_score: 90
bundle_size_limit: 500kb
warn_only: true
```
---
## Memory Hierarchy (Priority Order)
### 1. CONTINUITY.md (Volatile - Every Turn)
**Purpose:** What am I doing RIGHT NOW?
**Update Frequency:** Every turn
**Content:** Current task, phase, blockers, next steps
### 2. CONSTITUTION.md (Immutable - This File)
**Purpose:** How MUST I behave?
**Update Frequency:** Version bumps only
**Content:** Behavioral contracts, quality gates, invariants
### 3. CLAUDE.md (Semi-Stable - Significant Changes)
**Purpose:** What is this project?
**Update Frequency:** Architecture changes
**Content:** Tech stack, patterns, project context
### 4. Ledgers (Append-Only - Checkpoint)
**Purpose:** What happened?
**Update Frequency:** After significant events
**Content:** Decisions, deployments, reviews
### 5. .agent/sub-agents/*.json (Lineage Tracking)
**Purpose:** Who did what and why?
**Update Frequency:** Agent lifecycle events
**Content:** Agent context, decisions, inherited memory
---
## Context Lineage Schema
```json
{
"agent_id": "eng-001-backend-api",
"agent_type": "general-purpose",
"model": "haiku",
"spawned_at": "2026-01-04T05:30:00Z",
"spawned_by": "orchestrator-main",
"lineage": ["orchestrator-main", "eng-001-backend-api"],
"inherited_context": {
"phase": "development",
"current_task": "task-005",
"spec_reference": ".loki/specs/openapi.yaml#/paths/~1api~1todos",
"tech_stack": ["Node.js", "Express", "TypeScript", "SQLite"]
},
"decisions_made": [
{
"timestamp": "2026-01-04T05:31:15Z",
"question": "Should we use Prisma or raw SQL?",
"answer": "Raw SQL with better-sqlite3 for simplicity",
"rationale": "PRD requires minimal dependencies, synchronous ops preferred"
}
],
"tasks_completed": ["task-005"],
"commits_created": ["abc123f", "def456a"],
"status": "completed",
"completed_at": "2026-01-04T05:45:00Z"
}
```
---
## Git Checkpoint Protocol
### Commit Message Format
```
[Loki] ${agent_type}-${task_id}: ${task_title}
${detailed_description}
Agent: ${agent_id}
Parent: ${parent_agent_id}
Spec: ${spec_reference}
Tests: ${test_files}
```
### Example
```
[Loki] eng-005-backend: Implement POST /api/todos endpoint
Created todo creation endpoint per OpenAPI spec.
- Input validation for title field
- SQLite insertion with timestamps
- Returns 201 with created todo object
- Contract tests passing
Agent: eng-001-backend-api
Parent: orchestrator-main
Spec: .loki/specs/openapi.yaml#/paths/~1api~1todos/post
Tests: backend/tests/todos.contract.test.ts
```
---
## Invariants (Runtime Assertions)
```typescript
// .loki/rules/invariants.ts
export const INVARIANTS = {
// Spec must exist before implementation
SPEC_BEFORE_CODE: (task: Task) => {
if (task.type === 'implementation') {
assert(exists(task.spec_reference), 'SPEC_MISSING');
}
},
// All tasks must have git commits
TASK_HAS_COMMIT: (task: Task) => {
if (task.status === 'completed') {
assert(task.git_commit_sha, 'COMMIT_MISSING');
}
},
// Agent lineage must be preserved
AGENT_HAS_LINEAGE: (agent: Agent) => {
assert(agent.lineage.length > 0, 'LINEAGE_MISSING');
assert(agent.spawned_by, 'PARENT_MISSING');
},
// CONTINUITY.md must always exist
CONTINUITY_EXISTS: () => {
assert(exists('.loki/CONTINUITY.md'), 'CONTINUITY_MISSING');
},
// Quality gates must pass before merge
QUALITY_GATES_PASSED: (task: Task) => {
if (task.status === 'completed') {
assert(task.quality_checks.all_passed, 'QUALITY_GATE_FAILED');
}
}
};
```
---
## Visual Specification Aids
### Mermaid Diagram Generation (Required for Complex Features)
**RULE:** Architecture decisions and complex workflows MUST include Mermaid diagrams.
**Example - Authentication Flow:**
```mermaid
sequenceDiagram
participant C as Client
participant A as API
participant D as Database
C->>A: POST /api/auth/login
A->>A: Validate credentials
A->>D: Query user
D-->>A: User record
A->>A: Generate JWT token
A-->>C: 200 OK {token}
```
**Storage Location:** `.loki/diagrams/${feature_name}.mmd`
**When Required:**
- Multi-step workflows (3+ steps)
- System architecture changes
- Complex state machines
- Integration points between services
---
## Amendment Process
This constitution can only be amended through:
1. Version bump in header
2. Git commit with `[CONSTITUTION]` prefix
3. Changelog entry documenting what changed and why
4. Re-validation of all existing agents against new rules
**Example Amendment Commit:**
```
[CONSTITUTION] v1.1.0: Add visual specification requirement
Added requirement for Mermaid diagrams on complex features to prevent
ambiguity in multi-step workflows. Based on Addy Osmani's insight that
visual aids significantly improve AI-to-AI communication.
Breaking changes: None
New rules: Section "Visual Specification Aids"
```
---
## Enforcement
All rules in this constitution are **machine-enforceable** and **MUST** be implemented as:
1. Pre-commit hooks (Git)
2. Runtime assertions (TypeScript invariants)
3. Quality gate validators (YAML configs)
4. Agent behavior validators (JSON schemas)
**Human guidance is advisory. Machine enforcement is mandatory.**
---
*"In autonomous systems, trust is built on invariants, not intentions."*

View File

@@ -0,0 +1,201 @@
# Loki Mode - Autonomous Runner
Single script that handles everything: prerequisites, setup, Vibe Kanban monitoring, and autonomous execution with auto-resume.
## Quick Start
```bash
# Run with a PRD
./autonomy/run.sh ./docs/requirements.md
# Run interactively
./autonomy/run.sh
```
That's it! The script will:
1. Check all prerequisites (Claude CLI, Python, Git, etc.)
2. Verify skill installation
3. Initialize the `.loki/` directory
4. **Start Vibe Kanban background sync** (monitor tasks in real-time)
5. Start Claude Code with **live output** (no more waiting blindly)
6. Auto-resume on rate limits or interruptions
7. Continue until completion or max retries
## Live Output
Claude's output is displayed in real-time - you can see exactly what's happening:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CLAUDE CODE OUTPUT (live)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[Claude's output appears here in real-time...]
```
## Status Monitor (Built-in)
The runner updates `.loki/STATUS.txt` every 5 seconds with task progress:
```
╔════════════════════════════════════════════════════════════════╗
║ LOKI MODE STATUS ║
╚════════════════════════════════════════════════════════════════╝
Updated: Sat Dec 28 15:30:00 PST 2025
Phase: DEVELOPMENT
Tasks:
├─ Pending: 10
├─ In Progress: 1
├─ Completed: 5
└─ Failed: 0
Monitor: watch -n 2 cat .loki/STATUS.txt
```
### Monitor in Another Terminal
```bash
# Watch status updates live
watch -n 2 cat .loki/STATUS.txt
# Or view once
cat .loki/STATUS.txt
```
## What Gets Checked
| Prerequisite | Required | Notes |
|--------------|----------|-------|
| Claude Code CLI | Yes | Install from https://claude.ai/code |
| Python 3 | Yes | For state management |
| Git | Yes | For version control |
| curl | Yes | For web fetches |
| Node.js | No | Needed for some builds |
| jq | No | Helpful for JSON parsing |
## Configuration
Environment variables:
```bash
# Retry settings
export LOKI_MAX_RETRIES=50 # Max retry attempts (default: 50)
export LOKI_BASE_WAIT=60 # Base wait time in seconds (default: 60)
export LOKI_MAX_WAIT=3600 # Max wait time in seconds (default: 3600)
# Skip prerequisite checks (for CI/CD or repeat runs)
export LOKI_SKIP_PREREQS=true
# Run with custom settings
LOKI_MAX_RETRIES=100 LOKI_BASE_WAIT=120 ./autonomy/run.sh ./docs/prd.md
```
## How Auto-Resume Works
```
┌─────────────────────────────────────────────────────────────┐
│ ./autonomy/run.sh prd.md │
└─────────────────────────────────────────────────────────────┘
┌───────────────────────┐
│ Check Prerequisites │
└───────────────────────┘
┌───────────────────────┐
│ Initialize .loki/ │
└───────────────────────┘
┌────────────────────────────────┐
│ Run Claude Code with prompt │◄────────────────┐
└────────────────────────────────┘ │
│ │
▼ │
┌───────────────────────┐ │
│ Claude exits │ │
└───────────────────────┘ │
│ │
┌───────────┴───────────┐ │
▼ ▼ │
┌───────────────┐ ┌───────────────┐ │
│ Completed? │──Yes──│ SUCCESS! │ │
└───────────────┘ └───────────────┘ │
│ No │
▼ │
┌───────────────┐ │
│ Wait (backoff)│─────────────────────────────────────┘
└───────────────┘
```
## State Files
The autonomy runner creates:
```
.loki/
├── autonomy-state.json # Runner state (retry count, status)
├── logs/
│ └── autonomy-*.log # Execution logs
├── state/
│ └── orchestrator.json # Loki Mode phase tracking
└── COMPLETED # Created when done
```
## Resuming After Interruption
If you stop the script (Ctrl+C) or it crashes, just run it again:
```bash
# State is saved, will resume from last checkpoint
./autonomy/run.sh ./docs/requirements.md
```
The script detects the previous state and continues from where it left off.
## Differences from Manual Mode
| Feature | Manual Mode | Autonomy Mode |
|---------|-------------|---------------|
| Start | `claude --dangerously-skip-permissions` | `./autonomy/run.sh` |
| Prereq check | Manual | Automatic |
| Rate limit handling | Manual restart | Auto-resume |
| State persistence | Manual checkpoint | Automatic |
| Logging | Console only | Console + file |
| Max runtime | Session-based | Configurable retries |
## Troubleshooting
### "Claude Code CLI not found"
```bash
npm install -g @anthropic-ai/claude-code
# or visit https://claude.ai/code
```
### "SKILL.md not found"
Make sure you're running from the loki-mode directory or have installed the skill:
```bash
# Option 1: Run from project directory
cd /path/to/loki-mode
./autonomy/run.sh
# Option 2: Install skill globally
cp -r . ~/.claude/skills/loki-mode/
```
### "Max retries exceeded"
The task is taking too long or repeatedly failing. Check:
```bash
# View logs
cat .loki/logs/autonomy-*.log | tail -100
# Check orchestrator state
cat .loki/state/orchestrator.json
# Increase retries
LOKI_MAX_RETRIES=200 ./autonomy/run.sh ./docs/prd.md
```

Some files were not shown because too many files have changed in this diff Show More