4.0 KiB
newproject
Composes a project from the templates in this organization: infra at the root, then backend-python, frontend-svelte, blank and caddy on top, each with its own answers file in .copier/.
source ~/projects/templates/newproject/shell.sh
newproject ~/projects/my-thing
updateproject # every part
updateproject backend # one part
newproject asks for the description, the parts, the backend language, the frontend framework, how the frontend is served and the MCP servers for .mcp.json, then hands over to each template's own questions, and finally offers to create the Gitea repo. Every prompt has a flag for non-interactive use:
newproject ~/projects/my-thing --parts backend,frontend,caddy --backend python --frontend svelte --serve bun --mcp context7,svelte --defaults
other as the backend or the frontend renders the blank template: the part's compose files, Makefile and .env.example with no code, for a stack that has no template of its own, next to any other part.
One part alone is rendered at the root of the project; two parts live in backend/ and frontend/. After rendering, make env creates .env and every docker-compose.override.yml from their examples. updateproject needs a clean working tree and commits each part's update separately, refreshing uv.lock and bun.lock first, so the next part starts from a clean tree again. When copier leaves conflicts it stops before committing and lists the files: resolve, commit, run it again. Templates are cloned from https://git.kotikot.com/templates unless TEMPLATES_DIR points at a directory with local checkouts; TEMPLATES_REF=HEAD renders their working trees instead of the latest tag. Either way the answers in .copier/ point at Gitea, not at the local checkout, so updateproject works on any machine; it always updates from Gitea, so push a template change before updating projects with it.
Gitea
giteaproject # asks for the organization and the name
giteaproject ms-agents/my-thing
Run in the project directory. It creates the repo if it does not exist (private, main as the default branch, the description from .copier/infra.yml), adds it as origin over ssh, and when the repo is still empty and there are local commits, pushes main and dev and switches to dev. An existing origin that points elsewhere is left alone. When the repo already has commits and the project has none yet (a fresh newproject for code that lives in Gitea already), the project lands on top of it: the repo's history becomes the local one, the rendered files stay as uncommitted changes against it, and files the templates do not render come back as they are in the repo. Review with git status and git diff, keep what is yours, commit the rest. newproject asks for the organization at the end, or takes --repo org/name; without a terminal and without --repo it creates nothing.
The organization defaults to org from the config, else to the name of the parent directory when it matches an organization. ~/.config/templates/config.toml:
gitea_url = "https://git.kotikot.com"
remote = "ssh"
private = true
org = "ms-agents"
The token comes from GITEA_TOKEN or ~/.config/gitea/token.
The same command prepares the repo for Renovate: the renovate, wait-3d and deps-code labels (Renovate fails on a label that does not exist), write access for the organization's renovate team, and, for an existing repo without one, a renovate.jsonc committed on the server that extends the shared preset in templates/renovate. Projects rendered by newproject carry that file from the infra template already.
Extending the preset does not subscribe the repo to anything. The bot walks
an explicit list, so the repo also has to be added to repositories in
projects/personal/renovate/renovate-config.js of infra/komodo. Miss that step
and the config sits there doing nothing, silently.
Requires uv; bun, docker and pre-commit are used by the generated projects.