base

Step 1: Ask about the project

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "base" with this command: npx skills add kvnwolf/devtools/kvnwolf-devtools-base

Step 1: Ask about the project

Ask the user to describe what the project is about. Use their response to populate <project-name> and <project-description> in later steps.

Step 2: Install dependencies

bun add -d @biomejs/biome @types/bun @typescript/native-preview knip simple-git-hooks taze turbo ultracite vitest

Step 3: Create package.json

{ "name": "<project-name>", "version": "0.1.0", "private": true, "type": "module", "scripts": { "lint": "biome check", "types": "tsgo --build", "test": "vitest run", "unused": "knip", "update": "taze --interactive" }, "dependencies": {}, "devDependencies": {}, "simple-git-hooks": { "pre-commit": "make validate" }, "knip": { "ignoreDependencies": [ "turbo" ], "ignoreBinaries": [ "make" ] }, "packageManager": "bun@<current-bun-version>" }

Replace <current-bun-version> with the output of bun --version .

Step 4: Create scripts/setup.ts

import { file, spawn } from "bun";

await installDependencies(); await installGitHooks(); await setupRemoteCache();

export async function installDependencies() { await spawn(["bun", "install"]).exited; console.log("Dependencies installed"); }

export async function installGitHooks() { await spawn(["bunx", "simple-git-hooks"]).exited; console.log("Git hooks installed"); }

export async function setupRemoteCache(isRetry?: boolean) { const config = file(".turbo/config.json");

if (!((await config.exists()) && (await config.json()).teamId)) { const stdio = isRetry ? "inherit" : "pipe"; const link = spawn(["turbo", "link"], { stdio: [stdio, stdio, stdio] });

if ((await link.exited) !== 0) {
  const error = await new Response(link.stderr).text();
  if (error.includes("User not found")) {
    await spawn(["turbo", "login"]).exited;
    await setupRemoteCache();
    return;
  }
  if (error.includes("IO error")) {
    await setupRemoteCache(true);
    return;
  }
}

}

console.log("Turbo remote cache configured"); }

Step 5: Create scripts/setup.test.ts

import { beforeEach, describe, expect, test, vi } from "vitest";

const mockSpawn = vi.fn().mockReturnValue({ exited: Promise.resolve(0), stderr: new Blob([""]), });

const mockFile = vi.fn().mockReturnValue({ exists: () => Promise.resolve(false), json: () => Promise.resolve({}), });

vi.mock("bun", () => ({ spawn: (...args: unknown[]) => mockSpawn(...args), file: (...args: unknown[]) => mockFile(...args), }));

const { installDependencies, installGitHooks, setupRemoteCache } = await import("./setup");

function spawnReturns(exitCode: number, stderr = "") { return mockSpawn.mockReturnValue({ exited: Promise.resolve(exitCode), stderr: new Blob([stderr]), }); }

function configReturns(exists: boolean, json: Record<string, unknown> = {}) { mockFile.mockReturnValue({ exists: () => Promise.resolve(exists), json: () => Promise.resolve(json), }); }

beforeEach(() => { mockSpawn.mockClear(); mockFile.mockClear(); spawnReturns(0); configReturns(false); });

describe("installDependencies", () => { test("runs bun install", async () => { await installDependencies(); expect(mockSpawn).toHaveBeenCalledWith(["bun", "install"]); }); });

describe("installGitHooks", () => { test("runs bunx simple-git-hooks", async () => { await installGitHooks(); expect(mockSpawn).toHaveBeenCalledWith(["bunx", "simple-git-hooks"]); }); });

describe("setupRemoteCache", () => { test("skips linking when config already has teamId", async () => { configReturns(true, { teamId: "team_123" }); mockSpawn.mockClear();

await setupRemoteCache();

expect(mockSpawn).not.toHaveBeenCalledWith(["turbo", "link"], expect.anything());

});

test("runs turbo link with piped stdio on first attempt", async () => { await setupRemoteCache();

expect(mockSpawn).toHaveBeenCalledWith(["turbo", "link"], {
  stdio: ["pipe", "pipe", "pipe"],
});

});

test("runs turbo login then retries on 'User not found' error", async () => { mockSpawn .mockReturnValueOnce({ exited: Promise.resolve(1), stderr: new Blob(["User not found"]), }) .mockReturnValueOnce({ exited: Promise.resolve(0) }) .mockReturnValueOnce({ exited: Promise.resolve(0) }); configReturns(false);

await setupRemoteCache();

expect(mockSpawn).toHaveBeenCalledWith(["turbo", "login"]);

});

test("retries with inherited stdio on 'IO error'", async () => { mockSpawn .mockReturnValueOnce({ exited: Promise.resolve(1), stderr: new Blob(["IO error"]), }) .mockReturnValueOnce({ exited: Promise.resolve(0) });

await setupRemoteCache();

expect(mockSpawn).toHaveBeenCalledWith(["turbo", "link"], {
  stdio: ["inherit", "inherit", "inherit"],
});

}); });

Step 6: Create Makefile

setup: bun run scripts/setup.ts

validate: bun run turbo validate

Step 7: Create turbo.json

{ "$schema": "https://turbo.build/schema.json", "tasks": { "lint": {}, "types": {}, "test": {}, "unused": {}, "validate": { "dependsOn": ["lint", "types", "test", "unused"] } } }

Step 8: Create tsconfig.json

{ "compilerOptions": { "allowImportingTsExtensions": true, "allowJs": true, "allowSyntheticDefaultImports": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "incremental": true, "isolatedModules": true, "lib": ["esnext"], "module": "esnext", "moduleDetection": "force", "moduleResolution": "bundler", "noEmit": true, "noUncheckedIndexedAccess": true, "noUncheckedSideEffectImports": true, "skipLibCheck": true, "strict": true, "target": "esnext", "verbatimModuleSyntax": false }, "exclude": ["node_modules"], "include": ["**/*.ts"] }

Step 9: Create biome.jsonc

{ "$schema": "node_modules/@biomejs/biome/configuration_schema.json", "extends": ["ultracite/core"], "formatter": { "lineWidth": 100 }, "linter": { "rules": { "correctness": { "noUnusedImports": "warn" } } } }

Step 10: Create .gitignore

base

.local *.tsbuildinfo .DS_Store .turbo node_modules

Step 11: Create .github/workflows/ci.yml

name: CI

on: push:

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

jobs: check: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v1 - name: Cache Bun dependencies uses: actions/cache@v4 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- - name: Install dependencies run: bun install - name: Validate run: make validate env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ vars.TURBO_TEAM }}

Step 12: Create vitest.config.ts

import { defineConfig } from "vitest/config";

export default defineConfig({ test: { projects: [ { extends: true, test: { name: "unit", include: ["**/*.test.ts"], environment: "node", }, }, ], }, });

Step 13: Create AGENTS.md

<project-name>

<project-description>

Tech Stack

  • Package manager: Bun
  • Testing: Vitest

Conventions

<!-- Add project-specific conventions here as the codebase evolves -->

Then create a symlink so tools that look for CLAUDE.md find the same file:

ln -s AGENTS.md CLAUDE.md

Step 14: Create README.md

<project-name>

<project-description>

Development

  1. Clone this repo
  2. Run make setup

License

MIT

Step 15: Create .agents/commit.config.yml

files:

  • path: AGENTS.md update_when:
    • When changes in package.json alter the tech stack (not minor version bumps)
    • When new learnings from a task would benefit future agents (conventions, corrections to avoid repeating mistakes)

Acceptance checklist

  • Asked user for project name and description

  • Created package.json with correct name, scripts, simple-git-hooks, and knip config

  • Installed devDependencies (@biomejs/biome , @types/bun , @typescript/native-preview , knip , simple-git-hooks , taze , turbo , ultracite , vitest )

  • Created Makefile with setup and validate commands

  • Created scripts/setup.ts with install, git hooks, and remote cache setup

  • Created scripts/setup.test.ts with tests for setup functions

  • Created turbo.json with lint, types, test, unused, and validate tasks

  • Created tsconfig.json

  • Created biome.jsonc with ultracite preset

  • Created .gitignore

  • Created .github/workflows/ci.yml

  • Created vitest.config.ts

  • Created AGENTS.md with tech stack, commands, and conventions

  • Created CLAUDE.md symlink to AGENTS.md

  • Created README.md

  • Created .agents/commit.config.yml with AGENTS.md tracked

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

commit

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

unit-testing

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

convex

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

create-skill

No summary provided by upstream source.

Repository SourceNeeds Review