Skip to content
Draft
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
122 changes: 17 additions & 105 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,108 +10,20 @@ permissions:
contents: read

jobs:
root-checks:
name: Root checks
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10

- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
with:
node-version: 20.19.5
cache: npm

- name: Install dependencies
run: npm ci

- name: Lint
run: npm run lint

- name: Test
run: npm test

- name: Audit dependencies
run: npm audit --audit-level=moderate

- name: Package dry-run
run: npm pack --dry-run

site-checks:
name: Site checks
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10

- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: 1.3.11

- name: Install dependencies
working-directory: site
run: bun install --frozen-lockfile

- name: Audit dependencies
working-directory: site
run: bun audit

- name: Lint
working-directory: site
run: bun run lint

- name: Typecheck
working-directory: site
run: bun run typecheck

- name: Build
working-directory: site
run: bun run build

secret-scan:
name: Secret scan
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10
with:
fetch-depth: 0

- name: Install Gitleaks
env:
GITLEAKS_VERSION: 8.30.1
run: |
set -euo pipefail
archive="gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/${archive}" -o "$RUNNER_TEMP/${archive}"
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_checksums.txt" -o "$RUNNER_TEMP/gitleaks_checksums.txt"
grep " ${archive}$" "$RUNNER_TEMP/gitleaks_checksums.txt" > "$RUNNER_TEMP/gitleaks.sha256"
(cd "$RUNNER_TEMP" && sha256sum -c gitleaks.sha256)
mkdir -p "$RUNNER_TEMP/gitleaks"
tar -xzf "$RUNNER_TEMP/${archive}" -C "$RUNNER_TEMP/gitleaks"

- name: Gitleaks
run: "$RUNNER_TEMP/gitleaks/gitleaks detect --source . --redact --verbose"

codeql:
name: CodeQL
runs-on: ubuntu-24.04
permissions:
security-events: write
packages: read
actions: read
contents: read
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10

- name: Initialize CodeQL
uses: github/codeql-action/init@fee9466b8957867761f2d78f922ab084e3e2dd17
with:
languages: javascript-typescript
build-mode: none

- name: Analyze
uses: github/codeql-action/analyze@fee9466b8957867761f2d78f922ab084e3e2dd17
root:
name: Root package
uses: raintree-technology/.github/.github/workflows/ci.yml@3256afba6d5c060f8b00f1bbf96887d253b0e9e1
with:
package-manager: npm
node-version: "22"
working-directory: "."
standard-ref: 3256afba6d5c060f8b00f1bbf96887d253b0e9e1

site:
name: Marketing site
uses: raintree-technology/.github/.github/workflows/ci.yml@3256afba6d5c060f8b00f1bbf96887d253b0e9e1
with:
package-manager: bun
bun-version: "1.3.11"
working-directory: site
standard-ref: 3256afba6d5c060f8b00f1bbf96887d253b0e9e1
30 changes: 30 additions & 0 deletions .github/workflows/drift-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Drift Check

on:
workflow_dispatch:
schedule:
- cron: "17 6 * * 1"
pull_request:
paths:
- ".github/workflows/**"
- ".npmrc"
- ".nvmrc"
- "biome*.json*"
- "package.json"
- "package-lock.json"
- "renovate.json"
- "site/biome*.json*"
- "site/package.json"
- "site/bun.lock"
- "site/tsconfig.json"
- "site/tsconfig.base.json"

permissions:
contents: read

jobs:
drift:
name: Standard drift
uses: raintree-technology/.github/.github/workflows/drift-check.yml@3256afba6d5c060f8b00f1bbf96887d253b0e9e1
with:
standard-ref: 3256afba6d5c060f8b00f1bbf96887d253b0e9e1
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
save-exact=true
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22
51 changes: 50 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,61 @@
# agent-starter

An opinionated multi-agent skill pack for Claude Code, Codex, and Cursor. Deep, handwritten skills for HCI usability modeling, Apple HIG Doctor guidance, copywriting, code cleanup, and TOON token savings.
Raintree Technology's opinionated multi-agent skill pack for Claude Code, Codex, and Cursor. Deep, handwritten skills for HCI usability modeling, Apple HIG Doctor guidance, copywriting, code cleanup, and TOON token savings.

No orchestration framework. No aspirational YAML. Just agent-native project files generated from one shared skill source.

[![status: live](https://img.shields.io/badge/status-live-brightgreen.svg)](https://github.com/raintree-technology/agent-starter)
[![CI](https://github.com/raintree-technology/agent-starter/actions/workflows/ci.yml/badge.svg)](https://github.com/raintree-technology/agent-starter/actions/workflows/ci.yml)
[![npm version](https://img.shields.io/npm/v/create-agent-starter.svg)](https://www.npmjs.com/package/create-agent-starter)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Status

This repository is live. It contains the published `create-agent-starter` npm package and the `claude.raintree.technology` marketing site.

## Stack

- Root package: Node.js ESM CLI/library, npm, `node:test`, ESLint, Biome.
- Site: Next.js 16 App Router, React 19, TypeScript, Bun, Tailwind CSS, shadcn/ui primitives.
- CI: Raintree Technology reusable CI and drift-check workflows pinned to the org standard commit.

## Setup

```bash
npm ci
cd site
bun install --frozen-lockfile
```

Use Node.js 22 for repository development (`.nvmrc`), while the published root package keeps its existing `>=18.0.0` runtime contract.

## Scripts

Root package:

```bash
npm run check
npm run lint
npm test
npm pack --dry-run
```

Marketing site:

```bash
cd site
bun run check
bun run lint
bun run typecheck
bun run build
```

## Environment And Deploy

The root package does not require runtime environment variables. The site documents its public local URL in `site/.env.example`.

The npm package is published from the root package. The site is intended for Vercel deployment at `claude.raintree.technology`.

## What you get

**29 shipped skills**:
Expand Down
7 changes: 5 additions & 2 deletions bench/generate-workloads.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Generate reproducible sample workloads for TOON vs JSON benchmarking.
// Deterministic output — seeded PRNG — so measurements are stable across runs.

import { writeFileSync, mkdirSync } from 'node:fs';
import { mkdirSync, writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

Expand All @@ -11,7 +11,10 @@ const OUT = join(__dirname, 'workloads');
mkdirSync(OUT, { recursive: true });

let seed = 42;
const rand = () => ((seed = (seed * 1103515245 + 12345) & 0x7fffffff) / 0x7fffffff);
const rand = () => {
seed = (seed * 1103515245 + 12345) & 0x7fffffff;
return seed / 0x7fffffff;
};
const pick = (arr) => arr[Math.floor(rand() * arr.length)];
const int = (lo, hi) => Math.floor(lo + rand() * (hi - lo));

Expand Down
9 changes: 5 additions & 4 deletions bench/run.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Uses gpt-tokenizer (OpenAI BPE) as a proxy for Claude's tokenizer.
// Writes RESULTS.md with a markdown table.

import { readFileSync, writeFileSync, readdirSync } from 'node:fs';
import { readdirSync, readFileSync, writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { encode as toonEncode } from '@toon-format/toon';
Expand All @@ -15,7 +15,9 @@ const RESULTS = join(__dirname, 'RESULTS.md');

const countTokens = (text) => gptEncode(text).length;

const files = readdirSync(WORKLOADS).filter((f) => f.endsWith('.json')).sort();
const files = readdirSync(WORKLOADS)
.filter((f) => f.endsWith('.json'))
.sort();

const rows = files.map((f) => {
const path = join(WORKLOADS, f);
Expand All @@ -24,7 +26,6 @@ const rows = files.map((f) => {

let toonStr;
let toonTokens;
let savedPct;
let encodeError = null;
try {
toonStr = toonEncode(data);
Expand All @@ -37,7 +38,7 @@ const rows = files.map((f) => {

const jsonTokens = countTokens(raw);
const delta = toonTokens !== null ? jsonTokens - toonTokens : null;
savedPct = delta !== null && jsonTokens ? (delta / jsonTokens) * 100 : null;
const savedPct = delta !== null && jsonTokens ? (delta / jsonTokens) * 100 : null;

return {
file: f,
Expand Down
23 changes: 13 additions & 10 deletions bin/cli.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#!/usr/bin/env node

import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { program } from 'commander';
import { addMcp, addSkill } from '../src/commands/add.js';
import { init } from '../src/commands/init.js';
import { sync } from '../src/commands/sync.js';
import { status } from '../src/commands/status.js';
import { addMcp, addSkill } from '../src/commands/add.js';
import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { sync } from '../src/commands/sync.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
Expand All @@ -24,24 +24,27 @@ program
.option('-y, --yes', 'Skip confirmation prompts')
.option('-f, --force', 'Overwrite existing files')
.option('--agent <list>', 'Agent target(s): claude, codex, cursor, or all', 'claude')
.option('--profile <name>', 'Use preset profile (all, apple-hig, design-hci, minimal, next-saas, next, node, base)')
.option(
'--profile <name>',
'Use preset profile (all, apple-hig, design-hci, minimal, next-saas, next, node, base)',
)
.option('--skills <list>', 'Comma-separated skills to install')
.option('--no-toon', 'Skip TOON utilities')
.action(init);

program
.command('sync [dir]')
.description('Write native agent config (skills, MCP servers) for every target declared in agent.json')
.description(
'Write native agent config (skills, MCP servers) for every target declared in agent.json',
)
.action(sync);

program
.command('status [dir]')
.description('Diff agent.json against the native config of each target; exits 1 on drift')
.action(status);

const add = program
.command('add')
.description('Add an entry to agent.json and re-sync');
const add = program.command('add').description('Add an entry to agent.json and re-sync');

add
.command('mcp <name>')
Expand Down
32 changes: 32 additions & 0 deletions biome.base.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Raintree Technology — canonical Biome base.
// Vendored into each repo as biome.base.jsonc; the repo's biome.json extends it:
// { "extends": ["./biome.base.jsonc"], ... }
// This base enforces org invariants (VCS integration, recommended lint rules,
// organized imports). Formatter style (tabs/spaces, quotes, line width) is a
// per-repo choice and intentionally not set here.
{
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true
},
"formatter": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"assist": {
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}
Loading
Loading