---
url: https://docs.mochiexec.io/guides/discovery.md
description: >-
  Mochi finds the Makefile targets, npm scripts, Justfile recipes, Taskfile
  tasks, Compose services and scripts already in a repo, and makes them runnable
  and searchable without writing anything into it.
---

# Discovery

Most repos already say how to build, test, and run them, just in a dozen different
formats. Discovery reads those files and turns what it finds into executables you can
search, run, and document from Mochi, **without asking you to rewrite anything**.

* Nothing to port: Make still runs your Make targets, and npm still runs your scripts.
* Nothing written to your repo: your files stay exactly as they are.
* Side by side with flow: discovered tasks sit next to your hand-written flow executables
  and run the same way.

## How it works

Each **provider** recognizes one kind of file. Scanning again is quick, because files
that haven't changed are skipped. `mochi sync` re-scans the current workspace and every
workspace discovered before, so a task added to a file that was already discovered shows up
after the next sync, wherever you run it.

A discovered task's verb comes from its name: `docker-build` is a `build`, `deps` is an `install`, and a name with no verb in it is an
`exec`.

## Providers

| Provider | Looks for | Surfaces |
|---|---|---|
| `makefile` | `Makefile`, `makefile`, `GNUmakefile` | Make targets |
| `npm` | `package.json` | npm scripts |
| `justfile` | `Justfile`, `justfile`, `JUSTFILE` | Just recipes |
| `taskfile` | `Taskfile.yml`/`.yaml`, `taskfile.yml`/`.yaml` | Task tasks |
| `docker-compose` | `docker-compose.yml`/`.yaml`, `compose.yml`/`.yaml` | Compose services |
| `dockerfile` | `Dockerfile` | Image build |
| `cargo` | `Cargo.toml` | Cargo commands |
| `scripts` | `*.sh`, `*.bat`, `*.cmd`, `*.ps1` | Scripts |
| `python` | `*.py` | Python scripts |
| `github-actions` | `.github/workflows/*.yml` | Workflow jobs, **read-only** |

GitHub Actions jobs show up so you can see and document them in one place, but they can't
run locally.

## Scan a workspace

```sh
mochi discover                 # the current workspace
mochi discover my-project      # another workspace
mochi discover --dry-run       # preview without changing anything
```

| Flag | Effect |
|---|---|
| `--dry-run` | Preview discovered files |
| `--providers makefile,npm` | Only run these providers |
| `--only package.json` | Only these file names |
| `--force` | Re-scan even if nothing changed |
| `-o json` | Machine-readable output |

`mochi discover status` reports what the last scan found, without scanning again.

## Where discovered tasks live

Each provider's tasks get their own namespace, nested under `discovered`: npm scripts are in
`discovered/npm`, Make targets in `discovered/makefile`, and so on. Two files that both
define a `lint` task stay two tasks:

```sh
mochi lint my-project/discovered/makefile:lint
mochi lint my-project/discovered/npm:lint
mochi lint ./discovered/npm:lint           # `.` is the current workspace
```

A nested namespace needs its workspace spelled out, which is what `./` is for. To list
every discovered task at once, filter on the whole `discovered` subtree:

```sh
mochi browse -n 'discovered/*'
```

The same `discovered/*` form works in search and in the desktop's namespace filter, where it
appears as **discovered (all)**.

Set `MOCHI_DISCOVERY_NAMESPACE` to nest providers under a different namespace, or to `root`
to give each provider a top-level namespace of its own (`npm`, `makefile`).

## In the desktop app

Add a workspace with **New workspace** on the Workspaces page (or **+** in the sidebar):

1. **Source**: pick a **Folder** or a **Git repository** (with an optional branch or tag),
   and give it a name. Leave **Discover runnable task files** checked.
2. **Discover**: the task files Mochi found, grouped by type, each with its task count.
   Uncheck any you don't want, then choose **Add workspace**.

Discovered executables carry the `discovered` tag, so the **Tag** filter on the
Executables page shows just them. They're built from your files, so you change them by
editing those files, not in Mochi. Their descriptions are the exception: set one with
`mochi executable set-description` or [AI](/guides/ai).

To pick up new files later, use **Re-scan** in a workspace's **More actions** menu, or
run `mochi discover`.

## Discovery and `flow sync`

flow docs: [Imported executables](https://flowexec.io/guides/generated-config)

flow can already import executables from some of these files, declared by hand in a
workspace's `flow.yaml`. Mochi's discovery does it automatically for every provider above.
