Project Setup with GitHub, UV and Alembic
Commit the initial setup, configure team settings and commit attribution, then scaffold the FastAPI backend skeleton with uv and Alembic on a feature branch.
Time to start building. In this lesson we commit what we have so far, configure the team settings, and create the backend skeleton on the first feature branch.
Run git commands yourself with !
You can ask Claude to run git commands for you, and as a beginner that is helpful. But if you already know the command, asking Claude costs tokens for something you could type in two seconds.
Start your input with ! to enter shell mode. The command runs directly in your shell, without going through the model:
!git statusThe output appears in the conversation so Claude can see it too. Use shell mode for quick commands like git status, git add, git checkout.
Let Claude write the commit message
Writing good commit messages takes effort, because you have to summarise what changed and why. That is a great job to delegate. Review the changes first:
/diffThen ask:
Commit all the staged changes with a message explaining this is the initial project setup,
including CLAUDE.md, the settings file, the sub-agent definitions, and the spec files
generated by the sub-agents.Claude stages the files and writes a detailed, structured commit message.
Commit attribution: the "Co-Authored-By" line
By default, Claude Code adds a trailer to commits it makes:
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>Some teams want this, because it shows where AI helped. Others prefer not to include it. It is your decision, and it is configured in settings. Create a shared settings file for the team:
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"attribution": {
"commit": "",
"pr": ""
},
"permissions": {
"allow": [
"Bash(curl -sf http://localhost:8000/*)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)"
]
}
}| Key | Effect |
|---|---|
attribution.commit | Text added to commits. An empty string removes the trailer |
attribution.pr | Text added to pull request descriptions. Empty string removes it |
permissions.allow | Lets Claude hit our local backend with curl without asking every time |
permissions.deny | Keeps secrets out of Claude's reach |
Two gotchas we hit in the video
1. Deprecated key. The video uses "includeCoAuthoredBy": false. That key still works in older setups but is deprecated. Use attribution as shown above.
2. Wrong file name. The file was saved as .claude/.settings.json (with an extra dot). Claude Code does not read that file, which is exactly why the co-author line kept appearing until we told Claude directly. The correct name is .claude/settings.json.
If a setting does not seem to apply, run /status or /doctor to see which settings files were loaded.
Create the first feature branch
!git checkout -b feature/backend-setupAdd uv to CLAUDE.md
Before Claude creates any Python files, add the package manager rule to CLAUDE.md:
## UV package manager
Use uv as the package manager. All Python commands run through uv: `uv add` for packages,
`uv run pytest` for tests, `uv run python` for scripts. Never use pip or python directly.Make sure uv is installed on your machine. If it is not, follow the uv installation guide and check with:
uv --versionScaffold the backend skeleton
Now the prompt. Notice how specific it is: it points at the spec, names the conventions, lists the dependencies and, most importantly, says what not to do yet.
Read @specs/api-contract.md. Design the folder structure for the FastAPI backend.
Follow CLAUDE.md conventions: service layer, schemas folder, models folder,
no business logic in routes.
Use uv for the project setup. Create a pyproject.toml with these dependencies:
fastapi, uvicorn[standard], sqlalchemy[asyncio], aiosqlite,
alembic, pydantic, python-jose[cryptography], httpx, pytest, pytest-asyncio
Do not write any application code yet. Just the structure and dependencies.The @ mention
@specs/api-contract.md attaches that file to your prompt directly, so Claude reads it immediately instead of searching for it. Type @ and Claude Code suggests matching files.
Watch what Claude does and approve each step:
- Runs
uv initand pins Python 3.12 (requires-python = ">=3.12") - Adds dependencies with uv
- Creates the folder structure
- Initialises Alembic, the migration tool for SQLAlchemy. Alembic reads your models and generates the SQL to create or change tables, so you never write
CREATE TABLEby hand - Sets up the async database extras that SQLAlchemy needs for SQLite (
sqlalchemy[asyncio],aiosqlite)
The result is a skeleton with empty files where the real code will go:
backend/
├── alembic/ # migration scripts
├── alembic.ini
├── app/
│ ├── api/v1/tasks.py # routes (empty for now)
│ ├── core/
│ │ ├── config.py # settings (database URL, secrets)
│ │ └── database.py # async engine and session
│ ├── models/task.py # empty
│ ├── schemas/task.py # empty
│ ├── services/task_service.py # empty
│ └── main.py # FastAPI app
├── tests/
└── pyproject.tomlKeep an eye on the files Claude creates. Is there something you did not ask for? Something that should not exist? Reviewing a skeleton takes a minute. Untangling extra code later takes much longer.
Commit, merge, delete
Commit these changes. The message should explain this is the initial FastAPI backend
folder structure with uv configuration and dependencies.Check the commit message: with the correct settings file, there is no co-author line any more. Then merge and clean up using shell mode:
!git checkout main
!git merge feature/backend-setup
!git branch -d feature/backend-setupOfficial references
Written By: Shramik Masti
How is this guide?
Last updated on
Preparing Project Context
Pick the right model for implementation, read the context window like a battery indicator, and manage compaction yourself instead of leaving it to chance.
Implementing Backend Features - Part 1
Build the Task model, Pydantic v2 schemas and async database engine from the specs, configure Alembic for async SQLAlchemy, and run the first migration.
