Initialize a new project with bare git repo, beads, branch protection, agent instructions, and optional language-specific scaffolding. Supports multiple project types.
Set up a new project from scratch with the full development environment: bare git repo with worktrees, beads issue tracking, GitHub repo with branch protection, agent instruction files, and optional language-specific scaffolding.
/initialize-repo <project-name> [--type <type>] [description]
<project-name>: The project name (used for directory, GitHub repo, and package names)--type <type>: Project type (default: bare). See Project Types.[description]: Optional one-line description for GitHub repo and README| Type |
|---|
| What it adds |
|---|
bare | Just the infrastructure — git, beads, agents, planning. No language opinion. |
sui-dapp | Sui Move contracts, frontend skeleton, Nix flake with pinned Sui binary |
python | pyproject.toml (uv), pytest, src layout, Nix flake with Python |
rust | Cargo project, clippy/rustfmt config, Nix flake with Rust toolchain |
ocaml | Dune project, opam config, Nix flake with OCaml toolchain |
node | pnpm + TypeScript, Nix flake with Node.js |
go | Go module, Nix flake with Go toolchain |
~/Projects/<project-name>/
├── .git/ # Bare git repo
├── .beads/ # Beads issue database
└── master/ # Primary worktree
├── .beads/redirect # Points to bare root's .beads/
├── .claude/skills/ # Agent skills (copied from dotfiles)
├── .gitignore # Standard ignores
├── .planning/
│ └── PLANS.md # ExecPlan format guide
├── AGENTS.md # Agent instructions (source of truth)
├── CLAUDE.md -> AGENTS.md # Symlink for Claude Code
└── README.md # Project README
├── .envrc # Nix flake integration for direnv
├── contracts/<project-name>/ # Sui Move package
│ ├── Move.toml
│ ├── sources/
│ └── tests/
├── contracts/docs/
├── flake.nix # Nix dev environment with Sui
├── flake.lock
├── frontend/
│ ├── src/
│ ├── static/
│ └── docs/
└── zklogin-backend/ # Optional zkLogin service
├── .envrc
├── .python-version
├── flake.nix # Nix dev environment with Python + uv
├── flake.lock
├── pyproject.toml # uv-managed project
├── src/<project-name>/
│ └── __init__.py
└── tests/
└── test_placeholder.py
├── .envrc
├── flake.nix # Nix dev environment with Rust
├── flake.lock
├── Cargo.toml
├── rust-toolchain.toml
└── src/
└── lib.rs
├── .envrc
├── .ocamlformat # OCamlformat config
├── flake.nix # Nix dev environment with OCaml
├── flake.lock
├── dune-project # Dune build system config
├── <project-name>.opam # Generated by dune
├── bin/
│ ├── dune
│ └── main.ml
├── lib/
│ ├── dune
│ └── <project-name>.ml
└── test/
├── dune
└── test_<project-name>.ml
├── .envrc
├── flake.nix # Nix dev environment with Node.js
├── flake.lock
├── package.json # pnpm-managed project
├── tsconfig.json # TypeScript config
└── src/
└── index.ts
├── .envrc
├── flake.nix # Nix dev environment with Go
├── flake.lock
├── go.mod # Go module
├── main.go
└── main_test.go
When this skill is invoked, follow the steps in order: Part 1 (base), then Part 2 (type-specific, skip for bare), then Part 3 (finalization).
cd ~/Projects
mkdir <project-name>
cd <project-name>
git init --bare .git
git worktree add -b master master
cd master
The git worktree add -b master master command creates an orphan branch since there are no existing refs.
cd ~/Projects/<project-name>/master
mkdir -p .planning .claude/skills
Standard ignores for Nix, Node, Python, Rust, IDE, OS, and environment files:
# Nix
result
result-*
.direnv/
# Node
node_modules/
dist/
.next/
.nuxt/
# Python
__pycache__/
*.pyc
*.egg-info/
.venv/
.mypy_cache/
.pytest_cache/
.ruff_cache/
# Rust
target/
# OCaml
_build/
*.install
# Go
/vendor/
# IDE
.idea/
.vscode/
*.swp
*.swo
*~
# OS
.DS_Store
Thumbs.db
# Environment
.env
.env.local
.env.*.local
Fetch the ExecPlan format guide from the OpenAI cookbook:
gh api repos/openai/openai-cookbook/contents/articles/codex_exec_plans.md --jq '.content' | base64 -d
Extract the content inside the ~~~md code fence (starting with # Codex Execution Plans (ExecPlans):) and write it to .planning/PLANS.md. Do not include the article wrapper.
Copy the skill directories from ~/Projects/dotfiles/.claude/skills/ into the repo's .claude/skills/:
stacked-prs/ask-agent/spawn-agent/initialize-repo/ (this skill)Preserve executable permissions on scripts.
Run the section matching the selected --type. Skip this part entirely for bare.
cd ~/Projects/<project-name>/master
mkdir -p contracts/docs frontend/src frontend/static frontend/docs
cd ~/Projects/<project-name>/master/contracts
nix develop --command sui move new <project-name>
This generates Move.toml, sources/<project-name>.move, and tests/<project-name>_tests.move automatically. Do not write these by hand.
Write empty .gitkeep files in:
contracts/docs/.gitkeepfrontend/src/.gitkeepfrontend/static/.gitkeepfrontend/docs/.gitkeepWrite a Nix flake that provides a dev shell with the Sui CLI (pinned binary release), Node.js, pnpm, TypeScript, Rust toolchain, and general utilities. The flake should:
nixpkgs (nixos-unstable) and flake-utils as inputspkgs.fetchurlx86_64-linux and aarch64-linux with platform-specific hashesautoPatchelfHook for binary compatibility on NixOS/non-FHS systemsTo get the correct Sui version and hashes:
gh api repos/MystenLabs/sui/releases/latest --jq '.tag_name'nix hash to-sri --type sha256 $(nix-prefetch-url --unpack <url>)Content: use flake
Include these in the AGENTS.md written during Part 3:
nix develop --command sui move build, nix develop --command sui move test (from contracts dir)pnpm install, pnpm dev, pnpm build, pnpm testcd ~/Projects/<project-name>/master
mkdir -p src/<project-name> tests
[project]
name = "<project-name>"
version = "0.1.0"
description = "<description>"
requires-python = ">=3.12"
dependencies = []
[project.optional-dependencies]
dev = [
"pytest>=8.0",
"ruff>=0.4",
]
[tool.ruff]
target-version = "py312"
[tool.ruff.lint]
select = ["E", "F", "I", "UP"]
[tool.pytest.ini_options]
testpaths = ["tests"]
src/<project-name>/__init__.py: empty filetests/test_placeholder.py:
def test_placeholder():
pass
Content: 3.12
Write a Nix flake providing a dev shell with Python 3.12, uv, and ruff:
nixpkgs (nixos-unstable) and flake-utils as inputsx86_64-linux and aarch64-linuxContent: use flake
Include these in the AGENTS.md written during Part 3:
uv sync, uv add <pkg>uv run pytestuv run ruff check ., uv run ruff format .src/<project-name>/cd ~/Projects/<project-name>/master
nix develop --command cargo init --lib --name <project-name>
[toolchain]
channel = "stable"
components = ["rustfmt", "clippy"]
Write a Nix flake providing a dev shell with Rust (stable), cargo, clippy, rustfmt, and rust-analyzer:
nixpkgs (nixos-unstable) and flake-utils as inputsx86_64-linux and aarch64-linuxContent: use flake
Include these in the AGENTS.md written during Part 3:
cargo buildcargo testcargo clippy -- -D warningscargo fmtcd ~/Projects/<project-name>/master
mkdir -p bin lib test
(lang dune 3.0)
(name <project-name>)
(generate_opam_files true)
(package
(name <project-name>)
(synopsis "<description>")
(depends
(ocaml (>= 5.1))
(dune (>= 3.0))
(alcotest (and :with-test (>= 1.7)))))
lib/dune:
(library
(name <project-name>)
(public_name <project-name>))
lib/<project-name>.ml:
let greeting () = "Hello from <project-name>"
bin/dune:
(executable
(name main)
(public_name <project-name>)
(libraries <project-name>))
bin/main.ml:
let () = print_endline (<Project_name>.greeting ())
test/dune:
(test
(name test_<project-name>)
(libraries <project-name> alcotest))
test/test_<project-name>.ml:
let test_greeting () =
Alcotest.(check string) "greeting" "Hello from <project-name>"
(<Project_name>.greeting ())
let () =
Alcotest.run "<project-name>"
[ ("basic", [ Alcotest.test_case "greeting" `Quick test_greeting ]) ]
Note: <Project_name> uses OCaml module naming (capitalize first letter, underscores preserved).
profile = default
Write a Nix flake providing a dev shell with OCaml 5.1+, dune, opam, ocaml-lsp-server, ocamlformat, and utop:
nixpkgs (nixos-unstable) and flake-utils as inputspkgs.ocaml-ng.ocamlPackages_5_1 (or latest 5.x available)alcotest for testsx86_64-linux and aarch64-linuxContent: use flake
Include these in the AGENTS.md written during Part 3:
dune builddune testdune exec <project-name>dune fmtdune cleandune utop libcd ~/Projects/<project-name>/master
mkdir -p src
{
"name": "<project-name>",
"version": "0.1.0",
"description": "<description>",
"type": "module",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"test": "node --test dist/**/*.test.js",
"lint": "tsc --noEmit"
},
"devDependencies": {
"typescript": "^5.5"
}
}
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"declaration": true
},
"include": ["src"]
}
src/index.ts:
export function hello(): string {
return "Hello from <project-name>";
}
Write a Nix flake providing a dev shell with Node.js (LTS) and pnpm:
nixpkgs (nixos-unstable) and flake-utils as inputsx86_64-linux and aarch64-linuxContent: use flake
cd ~/Projects/<project-name>/master
nix develop --command pnpm install
This generates pnpm-lock.yaml.
Include these in the AGENTS.md written during Part 3:
pnpm installpnpm buildpnpm devpnpm testpnpm lintcd ~/Projects/<project-name>/master
nix develop --command go mod init github.com/tedks/<project-name>
package main
import "fmt"
func Greeting() string {
return "Hello from <project-name>"
}
func main() {
fmt.Println(Greeting())
}
package main
import "testing"
func TestGreeting(t *testing.T) {
got := Greeting()
want := "Hello from <project-name>"
if got != want {
t.Errorf("Greeting() = %q, want %q", got, want)
}
}
Write a Nix flake providing a dev shell with Go, gopls, and golangci-lint:
nixpkgs (nixos-unstable) and flake-utils as inputsx86_64-linux and aarch64-linuxContent: use flake
Include these in the AGENTS.md written during Part 3:
go build ./...go test ./...golangci-lint rungo run .Write agent instructions covering:
bare).planning/PLANS.mdbd ready, bd show, bd create, etc.)git worktree list --porcelain)cd ~/Projects/<project-name>/master
ln -s AGENTS.md CLAUDE.md
A user-facing README with:
bare)cd ~/Projects/<project-name>/master
nix develop --command echo "flake loaded"
This generates flake.lock and validates the flake works. Skip this step for bare.
cd ~/Projects/<project-name>/master
git add -A
git commit -m "Initial project scaffold: <project-name>
<type-specific summary of what was set up>"
gh repo create tedks/<project-name> --private --description "<description>"
cd ~/Projects/<project-name>/master
git remote add origin [email protected]:tedks/<project-name>.git
git push -u origin master
Note: gh repo create --source does not work from a worktree. Create the repo without --source, then add the remote manually.
Beads must be initialized from the bare repo root, not from a worktree:
cd ~/Projects/<project-name>
bd init --branch beads-metadata --prefix <project-name>
Then configure it:
.beads/config.yaml: set no-daemon: trueAGENTS.md that bd init creates at the bare root: rm ~/Projects/<project-name>/AGENTS.mdcd ~/Projects/<project-name>/master
mkdir -p .beads
printf '%s\n' ../.beads > .beads/redirect
git add .beads/redirect
git commit -m "Add beads issue tracking redirect for worktree"
git push
Create a GitHub ruleset requiring PRs for the master branch:
cd ~/Projects/<project-name>/master
gh api repos/tedks/<project-name>/rulesets -X POST --input - <<'RULES'
{
"name": "protect-master",
"target": "branch",
"enforcement": "active",
"conditions": {
"ref_name": {
"include": ["refs/heads/master"],
"exclude": []
}
},
"rules": [
{
"type": "pull_request",
"parameters": {
"required_approving_review_count": 0,
"dismiss_stale_reviews_on_push": false,
"require_code_owner_review": false,
"require_last_push_approval": false,
"required_review_thread_resolution": false
}
}
]
}
RULES
Run the following checks:
cd ~/Projects/<project-name>/master && git status — clean working treegit worktree list — shows bare root and master worktreebd ready — beads works (returns empty list)Type-specific checks (skip for bare):
nix develop --command echo "ok" — Nix shell loadssui-dapp: nix develop --command sui --version, nix develop --command sui move build (from contracts dir)python: nix develop --command python --version, nix develop --command uv run pytestrust: nix develop --command cargo --version, nix develop --command cargo testocaml: nix develop --command ocaml --version, nix develop --command dune build, nix develop --command dune testnode: nix develop --command node --version, nix develop --command pnpm build, nix develop --command pnpm testgo: nix develop --command go version, nix develop --command go test ./...Report the results to the user.
gh api repos/MystenLabs/sui/releases/latest for the current version.tedks. Adjust the gh repo create and remote URL if needed.~/Projects/dotfiles/.claude/skills/ for upstream updates periodically.