# Set up your dev environment

Let's get up and running with a dev environment, so you can make code changes without affecting production. By the end of this guide, you will have:

1. Set up Docker to run the containerized dev environment
2. Cloned the public protohaven\_api repository where our code is hosted
3. Set up pre-commit to automatically format and check code changes for problems
4. Initialized NocoDB - our development database - to run locally with testing data
5. Verified that both CLI commands and the web service works.
6. Successfully made edits to both the CLI and web service.

### Install Docker

We rely heavily on using docker containers to run the various services in a dev environment - make sure Docker is [installed](https://docs.docker.com/engine/install/) first before continuing.

Once docker is installed, run `sudo docker run hello-world` and verify that it pulls a container image, starts the container, prints a status message and exits with no errors:

[![image.png](https://wiki.protohaven.org/uploads/images/gallery/2025-10/scaled-1680-/6KOimage.png)](https://wiki.protohaven.org/uploads/images/gallery/2025-10/6KOimage.png)

### Clone the repository &amp; set up pre-commit

Next, let's grab the code and set up [pre-commit](https://pre-commit.com/), which autoformats our code and identifies errors before we try to submit changes. Log into GitHub, then go to [https://github.com/protohaven/protohaven\_api](https://github.com/protohaven/protohaven_api). You should see a "fork" option on the repository, towards the right of the screen:

[![image.png](https://wiki.protohaven.org/uploads/images/gallery/2025-10/scaled-1680-/TQoimage.png)](https://wiki.protohaven.org/uploads/images/gallery/2025-10/TQoimage.png)

 Follow the onscreen process for forking the repository, then perform the steps below.

```bash
# Clone the repository - be sure to substitute your username!
git clone git@github.com:<YOUR_GITHUB_USERNAME>/protohaven_api.git

# Set up a virtual environment so we can run tests and pre-commit stuff
python3 -m venv venv
source ./venv/bin/activate
pip install -r requirements.txt
pip install -e .

# Set up pre-commit validation hooks
pip install pre-commit
cd protohaven_api && pre-commit install
```

After pre-commit finishes installing, run it on all files (with `pre-commit run --all-files`) and verify everything passes:

[![image.png](https://wiki.protohaven.org/uploads/images/gallery/2025-10/scaled-1680-/Qbhimage.png)](https://wiki.protohaven.org/uploads/images/gallery/2025-10/Qbhimage.png)

### Load Data (NocoDB)

We use [NocoDB](https://www.nocodb.com/) to provide local testing data. **Nocodb must be running in order to run other local dev services** like Flask and the svelte frontend, **and we must prefill it** with tables and dev data so that it behaves as expected locally.

To initialize NocoDB with testing data - **or wipe and re-populate the data if it's already installed** - run this command:

```bash
# Must run in the root of the protohaven_api repository, or it will fail
cd path/to/protohaven_api

./nocodb/init_or_update_nocodb.sh
```

Follow the prompts in the script, which should have you browse to [http://localhost:9090](http://localhost:9090) and login with:

- Username: <admin@example.com>
- Password: `password`

Verify you see something like this and can click around into various bases and tables and see test data:

[![image.png](https://wiki.protohaven.org/uploads/images/gallery/2025-10/scaled-1680-/16kimage.png)](https://wiki.protohaven.org/uploads/images/gallery/2025-10/16kimage.png)

### Start services

With NocoDB now up, let's run the other containers that host our various services:

```
docker compose up --build --watch
```

Wait for the build and setup process to finish up - this may take a few minutes.

You'll know it's done when you see something like this in your console:

[![image.png](https://wiki.protohaven.org/uploads/images/gallery/2025-10/scaled-1680-/4lrimage.png)](https://wiki.protohaven.org/uploads/images/gallery/2025-10/4lrimage.png)

<p class="callout warning">Take particular note of `Watch enabled` - if that's not present, things won't auto reload when you make a change.</p>

<p class="callout info">For dev work in specific areas (e.g. working with the svelte webpages) you can start a subset of containers to reduce excess load, e.g. `docker compose up flask nocodb_frontend nocodb_db svelte --build --watch`</p>

Now browse to: [https://localhost:5173/](https://localhost:5173/) and verify you can access the dev landing page:

[![image.png](https://wiki.protohaven.org/uploads/images/gallery/2025-10/scaled-1680-/72Kimage.png)](https://wiki.protohaven.org/uploads/images/gallery/2025-10/72Kimage.png)

Using your editor of choice, open `svelte/src/routes/+page.svelte` in the repository you cloned. Add a little text to the file, then save it.

[![image.png](https://wiki.protohaven.org/uploads/images/gallery/2025-10/scaled-1680-/Ud8image.png)](https://wiki.protohaven.org/uploads/images/gallery/2025-10/Ud8image.png)

In your console, you'll see `Syncing service "svelte" after 1 changes were detected` as docker notices the changed file.

Reload the landing page and confirm the change propagated:

[![image.png](https://wiki.protohaven.org/uploads/images/gallery/2025-10/scaled-1680-/aIXimage.png)](https://wiki.protohaven.org/uploads/images/gallery/2025-10/aIXimage.png)

### Run the CLI

Our codebase includes an extensible CLI. We issue these commands on a regular schedule with [Cronicle](https://wiki.protohaven.org/books/software-developers-handbook/page/cronicle "Cronicle"), and can run one-offs for troubleshooting and special actions.

Let's make sure the CLI works so we can test local changes to CLI commands:

```bash
# Test your setup - you should see a YAML formatted message reminding instructors to schedule classes 
docker compose exec flask python3 -m protohaven_api.cli gen_instructor_schedule_reminder
```

<p class="callout warning">**Important:** All services must be running in order to execute CLI commands</p>

Verify you see something like the following output (no errors):[![image.png](https://wiki.protohaven.org/uploads/images/gallery/2025-10/scaled-1680-/opBimage.png)](https://wiki.protohaven.org/uploads/images/gallery/2025-10/opBimage.png)

Let's confirm that changes to CLI code are runnable. Edit `protohaven_api/commands/classes.py`, adding a log statement to the `gen_instructor_schedule_reminder` method

[![image.png](https://wiki.protohaven.org/uploads/images/gallery/2025-10/scaled-1680-/tjEimage.png)](https://wiki.protohaven.org/uploads/images/gallery/2025-10/tjEimage.png)

Save the file, then rerun the exec command above. Verify that you see `INFO:cli.classes:Hello world` in the console output.

### Run Tests

We use [pytest](https://docs.pytest.org/en/stable/) for unit testing code changes.

Run `python -m pytest -vv` and observe all tests passing, possibly with some deprecation warnings:

[![image.png](https://wiki.protohaven.org/uploads/images/gallery/2025-10/scaled-1680-/vCBimage.png)](https://wiki.protohaven.org/uploads/images/gallery/2025-10/vCBimage.png)

<p class="callout info">**Protip:** You can optionally use `-k test_substring` as an argument to run a specific test.</p>

### Well Done

[![image.png](https://wiki.protohaven.org/uploads/images/gallery/2025-10/scaled-1680-/XlSimage.png)](https://wiki.protohaven.org/uploads/images/gallery/2025-10/XlSimage.png)

Congrats on making it through dev environment setup! Now let's put it to work and make [your first contribution.](https://wiki.protohaven.org/books/software-developers-handbook/page/your-first-contribution "Your First Contribution")