> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nikaplanet.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Your First Worker: Step-by-Step

> Download a ready-made GeoEngine worker, apply it locally, and push it to the cloud — all in a few commands.

export const platform_3 = "Linux"

export const platform_2 = "macOS"

export const platform_1 = "Linux"

export const platform_0 = "macOS"

This guide walks you through deploying your first GeoEngine worker from start to finish. Every command is ready to copy and paste — just follow the steps in order. A couple of surprises are built in along the way, so don't skip ahead.

<Note>
  This guide assumes you have already installed GeoEngine and logged in. If you haven't, complete the [Installation & Setup](/guides/custom-geoprocess-deployment/installation) guide first.
</Note>

***

## Introduction

We will be deploying a simple geoprocessing worker that creates a grid around a vector input. The script is written in Python.

***

<div id="platform-selector" />

## Step 1 — Download the Starter Script

<a href="https://github.com/NikaGeospatial/geoengine/releases/download/docs-downloads/grid_creation.py" download>Download the starter worker script</a> and save it in an isolated folder somewhere on your machine — your home directory or Desktop works fine.

<Tabs>
  <Tab title="macOS">
    For this example, we will assume you created a directory in `/Users/<user>/Downloads/grid-creator`. Place the script into this directory.
  </Tab>

  <Tab title="Windows">
    For this example, we will assume you created a directory in `C:/Users/<user>/Downloads/grid-creator`. Place the script into this directory.
  </Tab>

  <Tab title="Linux">
    For this example, we will assume you created a directory in `/home/<user>/Downloads/grid-creator`. Place the script into this directory.
  </Tab>
</Tabs>

You should now have a folder called `grid-creator` in your current directory.

***

## Step 2 — Navigate Into the Directory

```bash theme={null}
cd ~/Downloads/grid-creator
```

All GeoEngine commands from here on must be run from inside this folder.

***

## Step 3 - Initialise the Worker

First, you have to generate the worker artifact templates. Run the following in the same terminal.

```bash theme={null}
geoengine init --env py
```

Here, we specify the `--env` flag to create a Python-centric dependencies template. If you were to use an R script, use `--env r` instead.

When GeoEngine asks whether to create a `tests/` folder, choose **Yes**. If you skipped it, the testing step below shows the exact files to create.

***

## Step 4 — Inspect the Files

Take a moment to look at what's inside before running anything:

### Main Script

* **`grid_creation.py`** — the Python script that does the actual geoprocessing work

### GeoEngine Worker Configurations

The following files can be edited to customize the worker:

* **`pixi.toml`** — declares all the Python/conda dependencies GeoEngine will install into the Docker container
* **`geoengine.yaml`** — the worker configuration: its name, version, local tag, command, and inputs

### GeoEngine Worker Build Artifacts

The following files are automatically generated by GeoEngine, and should not be edited unless you know what you're doing:

* **`.dockerignore`** — tells Docker which files to ignore when building the image
* **`geoengine.lock`** - the ID of the worker (do not touch this)
* **`tests/`** — local worker test scaffold, if you chose to create it during init

The **`Dockerfile`** is generated during `geoengine apply` for normal Python/R workers. Once it exists, treat it as a GeoEngine-managed build artifact.

***

## Step 5 - Wire up the Script

Ensure that your script has an argparser set up. If you look at the script, you will notice it is already done. So now, we just need to wire up the config files to match the script.

### Add Dependencies

Open up `pixi.toml` in an editor of your choice.

Here, you can edit the `[workspace]` section if you wish. This will not be reflected anywhere, but is just a mere requirement of Pixi.

You will notice an empty `[dependencies]` section. The GeoEngine runtime image already includes common geospatial packages such as GDAL, pandas, NumPy, GeoPandas, and Shapely, which are sufficient for this script. If your own worker needs extra conda-forge packages, add only those extras here.

### Edit the Config File

Open up `geoengine.yaml` in an editor of your choice.

Here, you will define the worker's details: its name, description, local tag, command, and input parameters.

* The template creates the worker `name` based on your directory folder, but feel free to change it as you wish.
* The `version` field is the cloud-facing semantic version. For now you can leave it at `1.0.0`.
* The `local_tag` field labels this local production build. Use it to provide short but informative information about the local version.
* The `description` field will be write-up on your worker's workings. Optional, but good to have.
* The `command` section details out the running requirements of your worker. The inputs should match the arguments set up in the argparser in your script.
* Inputs marked with `output: true` are writable output paths. Other file and folder inputs are mounted read-only.

For this example, copy and paste the below configuration wholesale into the `geoengine.yaml`.

```yaml theme={null}
name: grid-creator
version: "1.0.0"
local_tag: "my-first-tag"
description: Create square, rectangle, or diamond grids from an input vector extent
command:
  program: python
  script: grid_creation.py
  inputs:
  - name: input-file
    type: file
    required: true
    description: Input vector file used to derive the grid extent
  - name: grid-type
    type: enum
    required: false
    default: square
    description: Grid geometry type
    enum_values:
    - square
    - rectangle
    - diamond
  - name: cell-width
    type: number
    required: true
    description: Grid cell width in CRS units (or meters when auto-reproject is true)
  - name: cell-height
    type: number
    required: false
    description: Grid cell height for rectangle grids (optional for square/diamond)
  - name: output-file
    type: string
    required: false
    default: regular_grid
    description: Output file name without extension (GeoJSON will be written)
  - name: output-dir
    type: folder
    required: true
    description: Output folder for the generated GeoJSON grid
    output: true
  - name: auto-reproject
    type: boolean
    required: false
    default: true
    description: Auto-reproject geographic CRS inputs to UTM while generating the grid
  - name: add-id
    type: boolean
    required: false
    default: true
    description: Add a grid_id column to the output
```

***

## Step 6 — Apply the Worker Locally

First, run the semantic config checks:

```bash theme={null}
geoengine lint
```

Then build and apply the worker in development mode:

```bash theme={null}
geoengine apply --dev
```

GeoEngine will resolve dependencies, build the Docker image, and register the worker on your machine. The first apply takes the longest — pixi is downloading and locking all the packages declared in `pixi.toml`.

<Tip>
  The first `geoengine apply --dev` can take several minutes while pixi installs dependencies into the Docker image. Subsequent applies are much faster because the image layers are cached. This is completely normal — let it run.
</Tip>

When it finishes, you should see output like this:

```
=> Building worker 'grid-creator'...
✓ Successfully built image: geoengine-local/<uuid>:latest
✓ Registered worker 'grid-creator'
✓ Apply complete for worker 'grid-creator'
```

The worker is now built and registered! You can check details of the worker by running while still in the `grid-creator` directory:

```bash theme={null}
geoengine describe
```

***

## Step 7 — Add a First Worker Test

Before opening GIS, add a tiny local contract test. This gives you a repeatable way to prove the worker still builds a grid after future edits.

If `tests/fixtures/` does not exist yet, create it. Then add a file at `tests/fixtures/small_extent.geojson`:

```json theme={null}
{
  "type": "FeatureCollection",
  "name": "small_extent",
  "crs": {
    "type": "name",
    "properties": {
      "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
    }
  },
  "features": [
    {
      "type": "Feature",
      "properties": {
        "id": 1
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [0.0, 0.0],
            [0.0, 0.002],
            [0.002, 0.002],
            [0.002, 0.0],
            [0.0, 0.0]
          ]
        ]
      }
    }
  ]
}
```

Now replace `tests/geoengine.test.yaml` with this first smoke test:

```yaml theme={null}
version: 1
cases:
  - name: square-grid-smoke
    inputs:
      input-file: fixtures/small_extent.geojson
      grid-type: square
      cell-width: 0.001
      output-file: square_grid
      output-dir: outputs
      auto-reproject: false
      add-id: true
    expect:
      exit_code: 0
      files:
        - path: outputs/square_grid.geojson
          exists: true
          min_size: 1
          extension: .geojson
```

Run the test:

```bash theme={null}
geoengine test
```

GeoEngine runs the applied worker through the same runtime path as `geoengine run --actor CLI --json`. The fixture path is resolved from `tests/`, and the output path is created under `.geoengine-test/square-grid-smoke/`.

<Tip>
  Use `geoengine test --keep-workdir` if you want to inspect the generated output folder after the run.
</Tip>

***

## Step 8 — GIS Testing

<div id="gis-selector" />

If you want to run this worker from QGIS or ArcGIS Pro, install the local GIS plugin once:

```bash theme={null}
geoengine setup plugins
```

After the plugin is installed, it discovers applied workers from the local GeoEngine registry.

<Tabs>
  <Tab title="QGIS">
    ### Enable the Plugin in QGIS

    After `geoengine setup plugins --qgis` installs the plugin, enable it inside QGIS once:

    1. In the QGIS top bar, click **Plugins** > **Manage and Install Plugins...**
    2. Go to the **Installed** tab
    3. Find **GeoEngine** in the list and check the box next to it
    4. Close the dialog

    <Note>
      You only need to enable the plugin once. Future applies and updates will not require you to do this again.
    </Note>

    ### Processing Toolbox

    The GeoEngine plugin should now be available in the **Processing Toolbox**. Open it from the top bar **Processing > Toolbox**.

    <Tabs>
      <Tab title="macOS">
        Alternatively, you can use the short cut `⌥`+`⌘`+`T`.
      </Tab>

      <Tab title="Windows">
        Alternatively, you can use the short cut `Ctrl`+`Alt`+`T`.
      </Tab>

      <Tab title="Linux">
        Alternatively, you can use the short cut `Ctrl`+`Alt`+`T`.
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="ArcGIS Pro">
    <Tabs>
      <Tab title="Windows">
        ### Enable the Plugin in ArcGIS Pro

        After `geoengine setup plugins --arcgis` installs the toolbox, add it inside each ArcGIS Pro project:

        1. Copy the `GeoEngineTools.pyt` path printed by `geoengine setup plugins --arcgis`
        2. In ArcGIS Pro, navigate to the **Catalog** pane and right-click **Toolboxes** > **Add Toolbox**
        3. Paste the path reference to the plugin in the file dialog and click **OK**
        4. **GeoEngine Tools** should now be available in your Toolboxes

        <Note>
          You need to add the GeoEngine toolbox once per ArcGIS Pro project.
        </Note>

        ### Processing Toolbox

        The GeoEngine plugin should now be available as a Toolbox. Go on to **Catalog** to check it out.

        If the worker list looks stale, right-click the `GeoEngineTools.pyt` toolbox and click **Refresh Toolbox**.
      </Tab>

      <Tab title="macOS">
        <Note>
          ArcGIS Pro is not supported on {platform_0}.
        </Note>
      </Tab>

      <Tab title="Linux">
        <Note>
          ArcGIS Pro is not supported on {platform_1}.
        </Note>
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

***

## Step 9 — Run the Worker from GIS

<Tabs>
  <Tab title="QGIS">
    In the **Processing Toolbox**, expand **GeoEngine** and find **grid-creator (\*latest)**. Double-click it to open the tool dialog.

    Load a vector layer as the **Input Layer** — any polygon or line layer you have on hand works for a first test run. You can even load in a vector file. Click **Run**.

    GeoEngine executes the script inside the Docker container and streams the output back to QGIS. When it finishes, a result layer will appear in your **Layers** panel and render on the map canvas.

    <Tip>
      If the tool dialog does not appear or the worker shows an error, check the **GeoEngine Log** panel (View > Panels > GeoEngine Log) for the full output from inside the container.
    </Tip>
  </Tab>

  <Tab title="ArcGIS Pro">
    <Tabs>
      <Tab title="macOS">
        <Note>
          ArcGIS Pro is not supported on {platform_2}.
        </Note>
      </Tab>

      <Tab title="Windows">
        In the **Geoprocessing** pane, search for **GeoEngine** or browse to **Toolboxes > GeoEngine Tools**. Open **grid-creator**, fill in the parameters, and click **Run**.

        Container logs appear in the Geoprocessing messages panel. When the run completes, output files are added to your map automatically when ArcGIS Pro can read the output format.
      </Tab>

      <Tab title="Linux">
        <Note>
          ArcGIS Pro is not supported on {platform_3}.
        </Note>
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

***

## Step 10 — Push to the Cloud

Once you're happy with how the worker runs locally, publish it so your whole team can access it. Pushing requires a production apply, so first make sure `geoengine.yaml` has a valid `version` and `local_tag`, then rerun the local checks:

```bash theme={null}
geoengine lint
geoengine test
```

Then apply in production mode:

```bash theme={null}
geoengine apply
```

Then push the image to the cloud:

```bash theme={null}
geoengine push
```

GeoEngine pushes the most recently applied production `local_tag` and publishes it with the semantic `version` from `geoengine.yaml`. If you have access to multiple teams, you will be prompted to select the team you wish to push to.

<Note>
  After pushing, the worker is available to everyone in your Nika organisation — in QGIS, ArcGIS Pro, and the Nika web platform — without them needing to run `geoengine apply` themselves.
</Note>

***

## Next Steps

You've gone from a zip file to a live cloud-deployed geoprocessing worker. Here's where to go from here:

* [Running Workers in ArcGIS Pro & QGIS](/guides/custom-geoprocess-deployment/running-in-gis) — inputs, outputs, and layer handling in detail
* [Designing Worker Tests](/guides/custom-geoprocess-deployment/test-designing) — fixtures, expected outputs, and semantic comparisons
* [Versioning](/guides/custom-geoprocess-deployment/versioning) — how to version, tag, and roll back workers
* [Cloud Push & Deployment](/guides/custom-geoprocess-deployment/cloud-push) — advanced push options and CI/CD integration
