Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: CI

on:
pull_request:
branches: [main]
push:
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
backend:
name: backend (ruff · mypy · pytest)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "0.5.x"

- name: Install project (+ dev extras)
run: uv sync --extra dev

- name: ruff
run: uv run ruff check skillforge

- name: mypy
run: uv run mypy skillforge

- name: pytest
# Live tests are gated behind SKILLFORGE_LIVE_TESTS=1 and stay opt-in.
env:
SKILLFORGE_LIVE_TESTS: "0"
run: uv run pytest tests/ --tb=short

frontend:
name: frontend (eslint · prettier · tsc · vitest)
runs-on: ubuntu-latest
timeout-minutes: 10
defaults:
run:
working-directory: frontend
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: frontend/package-lock.json

- name: npm install
run: npm ci

- name: eslint
run: npm run lint

- name: prettier
run: npm run format:check

- name: typecheck + build
run: npm run build

- name: vitest
run: npm run test
46 changes: 46 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.4
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
# Formatter is opt-in per-file for now (Wave 2 will enable broadly).
# Running with `--check` would bloat this PR; leaving ruff lint
# as the gate for now.
stages: [manual]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.13.0
hooks:
- id: mypy
name: mypy (skillforge)
files: ^skillforge/
args: [--config-file=pyproject.toml]
additional_dependencies:
- pydantic>=2.9
- types-PyYAML

- repo: local
hooks:
- id: prettier
name: prettier (frontend)
entry: bash -c 'cd frontend && npx prettier --check .'
language: system
files: ^frontend/.*\.(ts|tsx|js|json|css|md)$
pass_filenames: false

- id: eslint
name: eslint (frontend)
entry: bash -c 'cd frontend && npx eslint .'
language: system
files: ^frontend/.*\.(ts|tsx)$
pass_filenames: false

- id: vitest
name: vitest (frontend)
entry: bash -c 'cd frontend && npm run test'
language: system
files: ^frontend/src/.*\.(ts|tsx)$
pass_filenames: false
stages: [manual] # opt-in — vitest is full suite, too slow for every commit
5 changes: 5 additions & 0 deletions frontend/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dist
node_modules
coverage
*.min.js
*.min.css
8 changes: 8 additions & 0 deletions frontend/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"printWidth": 100,
"singleQuote": false,
"trailingComma": "all",
"semi": true,
"arrowParens": "always",
"plugins": ["prettier-plugin-tailwindcss"]
}
36 changes: 36 additions & 0 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";
import prettier from "eslint-config-prettier";

export default tseslint.config(
{ ignores: ["dist", "node_modules", "coverage"] },
{
files: ["**/*.{ts,tsx}"],
extends: [js.configs.recommended, ...tseslint.configs.recommended, prettier],
languageOptions: {
ecmaVersion: 2022,
globals: globals.browser,
},
plugins: {
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": ["warn", { allowConstantExport: true }],

// Clean-code doc enforcement (see docs/clean-code.md §8 React/TS)
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unused-vars": [
"warn",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
],
"no-console": ["warn", { allow: ["warn", "error"] }],
eqeqeq: ["error", "always", { null: "ignore" }],
"prefer-const": "error",
},
},
);
84 changes: 67 additions & 17 deletions frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,38 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<title>SKLD.run — Evolve Claude Agent Skills</title>
<meta name="description" content="SKLD evolves Claude Agent Skills through atomic variants, multi-layer fitness scoring, and generational breeding. Browse evolved skills, inspect rich package contents, and download production-ready skill directories." />
<meta
name="description"
content="SKLD evolves Claude Agent Skills through atomic variants, multi-layer fitness scoring, and generational breeding. Browse evolved skills, inspect rich package contents, and download production-ready skill directories."
/>

<!-- Open Graph (Discord / Slack / iMessage / LinkedIn / Facebook) -->
<meta property="og:type" content="website" />
<meta property="og:site_name" content="SKLD" />
<meta property="og:title" content="SKLD — Evolve Claude Agent Skills" />
<meta property="og:description" content="Skill Kinetics through Layered Darwinism. Atomic variants, fitness scoring, generational breeding. Browse evolved skills + download rich packages." />
<meta
property="og:description"
content="Skill Kinetics through Layered Darwinism. Atomic variants, fitness scoring, generational breeding. Browse evolved skills + download rich packages."
/>
<meta property="og:url" content="https://skld.run/" />
<meta property="og:image" content="https://skld.run/og-image.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="SKLD — Skill Kinetics through Layered Darwinism. Evolutionary breeding platform for Claude Agent Skills." />
<meta
property="og:image:alt"
content="SKLD — Skill Kinetics through Layered Darwinism. Evolutionary breeding platform for Claude Agent Skills."
/>

<!-- Twitter / X -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="SKLD — Evolve Claude Agent Skills" />
<meta name="twitter:description" content="Skill Kinetics through Layered Darwinism. Atomic variants, fitness scoring, generational breeding." />
<meta
name="twitter:description"
content="Skill Kinetics through Layered Darwinism. Atomic variants, fitness scoring, generational breeding."
/>
<meta name="twitter:image" content="https://skld.run/og-image.png" />
<meta name="twitter:image:alt" content="SKLD — Skill Kinetics through Layered Darwinism" />

Expand All @@ -34,7 +46,7 @@
<script>
// No-flash theme boot. Runs synchronously before React mounts.
// Reads the `skld-theme` cookie; falls back to system preference.
(function() {
(function () {
try {
var m = document.cookie.match(/(?:^|; )skld-theme=(\w+)/);
var t = m ? m[1] : "system";
Expand All @@ -50,21 +62,59 @@
</head>
<body>
<div id="root">
<main style="max-width:720px;margin:4rem auto;padding:0 1.5rem;font-family:system-ui,sans-serif;line-height:1.6;">
<main
style="
max-width: 720px;
margin: 4rem auto;
padding: 0 1.5rem;
font-family: system-ui, sans-serif;
line-height: 1.6;
"
>
<h1>SKLD — Skill Kinetics through Layered Darwinism</h1>
<p><strong>SKLD evolves Claude Agent Skills.</strong> It decomposes a skill into focused atomic variants, evolves each under targeted selection pressure with multi-layer fitness scoring, and assembles the winners into a composite skill you can download and install.</p>
<p>
<strong>SKLD evolves Claude Agent Skills.</strong> It decomposes a skill into focused
atomic variants, evolves each under targeted selection pressure with multi-layer fitness
scoring, and assembles the winners into a composite skill you can download and install.
</p>
<h2>What you can do here</h2>
<ul>
<li><strong>Registry</strong> — browse evolved skills, inspect each variant's fitness breakdown, and download production-ready skill directories.</li>
<li><strong>SKLD-bench</strong> — controlled evaluation environments for Elixir lighthouse families (Phoenix LiveView, Ecto, Oban, and more) with hundreds of graded challenges.</li>
<li><strong>Taxonomy</strong> — explore the Domain → Focus → Language → Skill → Variant hierarchy that organizes every evolved package.</li>
<li><strong>Research</strong> — the problem SKLD is solving, the prior work it builds on, methodology, evaluation, findings so far, and the open questions.</li>
<li><strong>Evolution runs</strong> — watch the pipeline live: Taxonomist, Scientist, Spawner, Competitor, Reviewer, Breeder, Engineer agents collaborating over generations.</li>
<li><strong>Journal</strong> — the narrative record of how SKLD was built, session by session.</li>
<li>
<strong>Registry</strong> — browse evolved skills, inspect each variant's fitness
breakdown, and download production-ready skill directories.
</li>
<li>
<strong>SKLD-bench</strong> — controlled evaluation environments for Elixir lighthouse
families (Phoenix LiveView, Ecto, Oban, and more) with hundreds of graded challenges.
</li>
<li>
<strong>Taxonomy</strong> — explore the Domain → Focus → Language → Skill → Variant
hierarchy that organizes every evolved package.
</li>
<li>
<strong>Research</strong> — the problem SKLD is solving, the prior work it builds on,
methodology, evaluation, findings so far, and the open questions.
</li>
<li>
<strong>Evolution runs</strong> — watch the pipeline live: Taxonomist, Scientist,
Spawner, Competitor, Reviewer, Breeder, Engineer agents collaborating over generations.
</li>
<li>
<strong>Journal</strong> — the narrative record of how SKLD was built, session by
session.
</li>
</ul>
<h2>How it works</h2>
<p>Each evolution run picks a skill family, decomposes it into foundation and capability dimensions, spawns a small population of variants per dimension, scores each against focused challenges, breeds survivors across generations, and assembles the winning traits into a final SKILL.md package — all observable in real time via WebSocket streams.</p>
<p>If you're reading this message, JavaScript is disabled or still loading. The interactive app requires JavaScript.</p>
<p>
Each evolution run picks a skill family, decomposes it into foundation and capability
dimensions, spawns a small population of variants per dimension, scores each against
focused challenges, breeds survivors across generations, and assembles the winning traits
into a final SKILL.md package — all observable in real time via WebSocket streams.
</p>
<p>
If you're reading this message, JavaScript is disabled or still loading. The interactive
app requires JavaScript.
</p>
</main>
</div>
<script type="module" src="/src/main.tsx"></script>
Expand Down
Loading
Loading