← Files Compound WritingARCHIVED FILE

skills/cw-setup-project/scripts/create_project.py

2.62 KB · Oct 5, 2026 · 18:34 UTC

↓ Download file

#!/usr/bin/env python3
"""Create the canonical Compound Writing writing-home structure without overwriting files."""

from __future__ import annotations

import argparse
import shutil
from pathlib import Path


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description="Create VOICE.md, STYLE.md, examples/, and drafts/ for one writing home."
    )
    parser.add_argument("target", type=Path, help="Writing-home folder to create or initialize")
    parser.add_argument(
        "--with-audience",
        action="store_true",
        help="Include an optional AUDIENCE.md template when no shared audience guide is used",
    )
    parser.add_argument(
        "--add-missing",
        action="store_true",
        help="Add only missing template items to a non-empty existing folder",
    )
    return parser.parse_args()


def main() -> int:
    args = parse_args()
    target = args.target.expanduser().resolve()
    template = Path(__file__).resolve().parents[3] / "defaults" / "project-template"

    if not template.is_dir():
        raise SystemExit(f"Project template not found: {template}")
    if target.exists() and not target.is_dir():
        raise SystemExit(f"Target exists and is not a folder: {target}")

    existing = list(target.iterdir()) if target.exists() else []
    if existing and not args.add_missing:
        raise SystemExit(
            "Target folder is not empty. Inspect it first, then rerun with --add-missing "
            "to create absent items without overwriting anything."
        )

    target.mkdir(parents=True, exist_ok=True)
    created: list[str] = []
    skipped: list[str] = []

    for source in sorted(template.rglob("*")):
        relative = source.relative_to(template)
        if relative == Path("AUDIENCE.md") and not args.with_audience:
            continue
        destination = target / relative
        if source.is_dir():
            if not destination.exists():
                destination.mkdir(parents=True)
                created.append(f"{relative}/")
            continue
        if destination.exists() or destination.is_symlink():
            skipped.append(str(relative))
            continue
        destination.parent.mkdir(parents=True, exist_ok=True)
        shutil.copy2(source, destination)
        created.append(str(relative))

    print(f"Writing home ready: {target}")
    if created:
        print("Created:")
        for item in created:
            print(f"  - {item}")
    if skipped:
        print("Preserved existing:")
        for item in skipped:
            print(f"  - {item}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

SHA-256: 4a632153b87c79191ffad710d7aab2e79fc112d5ed64aaa89e9b9fdbd4b248ae