diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index df728ac..31b28eb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -66,7 +66,7 @@ jobs: X64_SHA=$(sha256sum dist/wd-macos-x64.tar.gz | cut -d' ' -f1) VERSION=${GITHUB_REF_NAME#v} gh workflow run update-formula.yml \ - --repo kerdofficial/homebrew-tap \ + --repo kerddotdev/homebrew-tap \ -f version="$VERSION" \ -f sha256_arm64="$ARM64_SHA" \ -f sha256_x64="$X64_SHA" diff --git a/README.md b/README.md index ac61ae6..eead0f5 100644 --- a/README.md +++ b/README.md @@ -36,14 +36,14 @@ When you have dozens (or hundreds) of projects spread across multiple directorie - [Bun](https://bun.sh) - for building from source - [OrbStack](https://orbstack.dev) or Docker Desktop - for Docker features (optional) -> **Linux support is experimental.** Terminal tab opening has been tested on Ubuntu with Ptyxis, Konsole, tmux, and Zellij. If you encounter issues on your distribution, please [open an issue](https://github.com/kerdofficial/wd/issues). +> **Linux support is experimental.** Terminal tab opening has been tested on Ubuntu with Ptyxis, Konsole, tmux, and Zellij. If you encounter issues on your distribution, please [open an issue](https://github.com/kerddotdev/wd/issues). ## Installation ### Homebrew (recommended) ```sh -brew install kerdofficial/tap/wd +brew install kerddotdev/tap/wd ``` Then run first-time setup: @@ -63,7 +63,7 @@ brew update && brew upgrade wd ### Manual ```sh -git clone https://github.com/kerdofficial/wd +git clone https://github.com/kerddotdev/wd cd wd bun install bun run build @@ -157,7 +157,7 @@ Multiplexers (tmux, Zellij) are detected first, so they work inside any terminal - **[cmux](https://cmux.com) support** - native integration with cmux's Unix socket API for workspace/pane/tab management, purpose-built for AI coding agent workflows - **Redesigned workspace tab layout** - a new tab configuration system in the Project Constructor, designed to take advantage of cmux's workspace/pane hierarchy and split views -`wd new` loads templates from a default remote source, merges them with local templates from `~/.config/wd/templates/`, caches remote templates locally, and then runs the selected template command with your chosen options. +`wd new` loads templates from [the default remote catalog](docs/templates.json), merges them with local templates from `~/.config/wd/templates/`, caches remote templates locally, and then runs the selected template command with your chosen options. ## Configuration diff --git a/USAGE.md b/USAGE.md index 1a18884..a6aedb0 100644 --- a/USAGE.md +++ b/USAGE.md @@ -493,7 +493,7 @@ If a project path no longer exists, `wd open` exits with a clear error. - macOS asks for Automation permission the first time `wd` opens tabs with AppleScript. **Linux notes:** -- Linux terminal support is experimental. If you encounter issues, please [open an issue](https://github.com/kerdofficial/wd/issues). +- Linux terminal support is experimental. If you encounter issues, please [open an issue](https://github.com/kerddotdev/wd/issues). - **kitty** requires remote control to be enabled. Add `allow_remote_control yes` to `~/.config/kitty/kitty.conf` and restart kitty. See [kitty remote control docs](https://sw.kovidgoyal.net/kitty/remote-control/). - **Konsole** uses D-Bus for tab management when `qdbus` is available (pre-installed on most KDE systems). Falls back to CLI otherwise. - **GNOME Terminal / Ptyxis**: On Ubuntu 24.04+, the default terminal is Ptyxis (not `gnome-terminal`). `wd` auto-detects which binary is available. @@ -1061,7 +1061,7 @@ Linux terminal support is experimental. Known limitations: - Konsole CLI fallback (without `qdbus`): may open a new window instead of a tab - Tab commands in GNOME Terminal / Ptyxis run via `sh -c`, so shell aliases are not available -If you encounter issues with terminal tab opening on Linux, please [open an issue](https://github.com/kerdofficial/wd/issues) with your distribution, terminal emulator, and the output of `env | grep -iE 'term|vte|konsole|zellij|tmux|kitty'`. +If you encounter issues with terminal tab opening on Linux, please [open an issue](https://github.com/kerddotdev/wd/issues) with your distribution, terminal emulator, and the output of `env | grep -iE 'term|vte|konsole|zellij|tmux|kitty'`. **`wd open` changed directory but my editor stayed in the old place** diff --git a/docs/templates.json b/docs/templates.json new file mode 100644 index 0000000..0c376d5 --- /dev/null +++ b/docs/templates.json @@ -0,0 +1,479 @@ +[ + { + "id": "nextjs", + "name": "Next.js", + "description": "React framework with SSR, App Router and file-based routing", + "hidden": false, + "variants": [ + { + "type": "default", + "name": "Default", + "command": "{PACKAGE_MANAGER.command} create-next-app@latest {PROJECT_NAME} --yes", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ] + }, + { + "type": "shadcn", + "name": "shadcn/ui", + "command": "{PACKAGE_MANAGER.command} shadcn@latest init -t next -n {PROJECT_NAME} --preset {PRESET}", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ], + "additionalParameters": [ + { + "id": "preset", + "optional": false, + "description": "shadcn/ui Preset", + "type": "select", + "options": [ + "nova", + "vega", + "maia", + "lyra", + "mira" + ], + "parameterKey": "PRESET", + "wizardParameter": { + "default": "preset", + "shorthand": "p" + } + } + ] + } + ] + }, + { + "id": "react-vite", + "name": "React + Vite", + "description": "React with Vite bundler and TypeScript", + "hidden": false, + "variants": [ + { + "type": "default", + "name": "Default", + "command": "{PACKAGE_MANAGER.command} create-vite@latest {PROJECT_NAME} -- --template react-ts", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ] + }, + { + "type": "shadcn", + "name": "shadcn/ui", + "command": "{PACKAGE_MANAGER.command} shadcn@latest init -t vite -n {PROJECT_NAME} --preset {PRESET}", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ], + "additionalParameters": [ + { + "id": "preset", + "optional": false, + "description": "shadcn/ui Preset", + "type": "select", + "options": [ + "nova", + "vega", + "maia", + "lyra", + "mira" + ], + "parameterKey": "PRESET", + "wizardParameter": { + "default": "preset", + "shorthand": "p" + } + } + ] + } + ] + }, + { + "id": "tanstack-start", + "name": "TanStack Start", + "description": "Full-stack React framework by TanStack", + "hidden": false, + "variants": [ + { + "type": "default", + "name": "Default", + "command": "{PACKAGE_MANAGER.command} @tanstack/cli@latest create {PROJECT_NAME}", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ] + }, + { + "type": "shadcn", + "name": "shadcn/ui", + "command": "{PACKAGE_MANAGER.command} shadcn@latest init -t start -n {PROJECT_NAME} --preset {PRESET}", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ], + "additionalParameters": [ + { + "id": "preset", + "optional": false, + "description": "shadcn/ui Preset", + "type": "select", + "options": [ + "nova", + "vega", + "maia", + "lyra", + "mira" + ], + "parameterKey": "PRESET", + "wizardParameter": { + "default": "preset", + "shorthand": "p" + } + } + ] + } + ] + }, + { + "id": "tanstack-router", + "name": "TanStack Router", + "description": "Type-safe router for React applications", + "hidden": false, + "variants": [ + { + "type": "default", + "name": "Default", + "command": "{PACKAGE_MANAGER.command} create-tsrouter-app@latest {PROJECT_NAME}", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ] + }, + { + "type": "shadcn", + "name": "shadcn/ui + Tailwind", + "command": "{PACKAGE_MANAGER.command} create-tsrouter-app@latest {PROJECT_NAME} --template file-router --tailwind --add-ons shadcn", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ] + } + ] + }, + { + "id": "react-router", + "name": "React Router", + "description": "Full-stack React framework built on React Router v7", + "hidden": false, + "variants": [ + { + "type": "default", + "name": "Default", + "command": "{PACKAGE_MANAGER.command} create-react-router@latest {PROJECT_NAME}", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ] + }, + { + "type": "shadcn", + "name": "shadcn/ui", + "command": "{PACKAGE_MANAGER.command} shadcn@latest init -t react-router -n {PROJECT_NAME} --preset {PRESET}", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ], + "additionalParameters": [ + { + "id": "preset", + "optional": false, + "description": "shadcn/ui Preset", + "type": "select", + "options": [ + "nova", + "vega", + "maia", + "lyra", + "mira" + ], + "parameterKey": "PRESET", + "wizardParameter": { + "default": "preset", + "shorthand": "p" + } + } + ] + } + ] + }, + { + "id": "astro", + "name": "Astro", + "description": "Content-focused web framework with island architecture", + "hidden": false, + "variants": [ + { + "type": "default", + "name": "Default", + "command": "{PACKAGE_MANAGER.command} create-astro@latest {PROJECT_NAME}", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ] + }, + { + "type": "tailwind-react", + "name": "Tailwind + React", + "command": "{PACKAGE_MANAGER.command} create-astro@latest {PROJECT_NAME} -- --template with-tailwindcss --install --add react --git", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ] + } + ] + }, + { + "id": "sveltekit", + "name": "SvelteKit", + "description": "Full-stack framework built on Svelte", + "hidden": false, + "variants": [ + { + "type": "default", + "name": "Default", + "command": "{PACKAGE_MANAGER.command} sv@latest create {PROJECT_NAME}", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ] + } + ] + }, + { + "id": "remix", + "name": "Remix", + "description": "Full-stack web framework focused on web standards", + "hidden": false, + "variants": [ + { + "type": "default", + "name": "Default", + "command": "{PACKAGE_MANAGER.command} create-remix@latest {PROJECT_NAME}", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ] + } + ] + }, + { + "id": "hono", + "name": "Hono", + "description": "Fast, lightweight web framework for the Edge", + "hidden": false, + "variants": [ + { + "type": "default", + "name": "Default", + "command": "{PACKAGE_MANAGER.command} create-hono@latest {PROJECT_NAME}", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ] + } + ] + }, + { + "id": "elysia", + "name": "Elysia", + "description": "Ergonomic TypeScript framework for Bun (Bun only)", + "hidden": false, + "variants": [ + { + "type": "default", + "name": "Default", + "command": "mkdir -p {PROJECT_NAME} && cd {PROJECT_NAME} && bun create elysia app", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bun", + "commandParam": "bun" + } + ] + } + ] + }, + { + "id": "expo", + "name": "Expo", + "description": "React Native framework for iOS and Android", + "hidden": false, + "variants": [ + { + "type": "default", + "name": "Default", + "command": "{PACKAGE_MANAGER.command} create-expo-app@latest {PROJECT_NAME}", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ] + } + ] + }, + { + "id": "tauri", + "name": "Tauri", + "description": "Build desktop apps with web frontend and Rust backend", + "hidden": false, + "variants": [ + { + "type": "default", + "name": "Default", + "command": "{PACKAGE_MANAGER.command} create-tauri-app@latest {PROJECT_NAME} --yes --manager {PACKAGE_MANAGER.commandParam}", + "supportedPackageManagers": [ + { + "name": "bun", + "command": "bunx --bun", + "commandParam": "bun" + }, + { + "name": "pnpm", + "command": "pnpm dlx", + "commandParam": "pnpm" + } + ] + } + ] + } +] \ No newline at end of file diff --git a/src/core/__tests__/template-catalog.test.ts b/src/core/__tests__/template-catalog.test.ts new file mode 100644 index 0000000..91084e7 --- /dev/null +++ b/src/core/__tests__/template-catalog.test.ts @@ -0,0 +1,14 @@ +import { expect, test } from "bun:test"; +import { z } from "zod"; +import { TemplateSchema } from "../../config/schema"; + +test("default template catalog contains valid templates with unique IDs", async () => { + const catalog: unknown = await Bun.file( + new URL("../../../docs/templates.json", import.meta.url), + ).json(); + const templates = z.array(TemplateSchema).min(1).parse(catalog); + + expect(new Set(templates.map((template) => template.id)).size).toBe( + templates.length, + ); +}); diff --git a/src/core/templates.ts b/src/core/templates.ts index 52b2c4e..090a927 100644 --- a/src/core/templates.ts +++ b/src/core/templates.ts @@ -1,5 +1,5 @@ /** - * Template loading: gist fetch + custom local templates + merge. + * Template loading: remote fetch + custom local templates + merge. * Custom template IDs must not collide with gist template IDs. * * Template source is determined by TEMPLATES_SOURCE_URL (constant below). @@ -22,7 +22,7 @@ import { // ─── Source URL ─────────────────────────────────────────────────────────────── export const TEMPLATES_SOURCE_URL = - "https://gist.githubusercontent.com/kerdofficial/8d6fc38b5427ed59a7fcc8964c70fd10/raw/"; + "https://raw.githubusercontent.com/kerddotdev/wd/main/docs/templates.json"; // ─── Template source fetch ────────────────────────────────────────────────────