Skip to content

Getting started

This walks through detecting a project root with workspace, from install to a working command.

Install

go get gitlab.com/phpboyscout/go/workspace

The module needs Go 1.26 or newer.

Detect from the current directory

The common case: a tool run from somewhere inside a project wants the project root. DetectFromCWD starts the walk at the process working directory.

package main

import (
    "fmt"

    "github.com/spf13/afero"
    "gitlab.com/phpboyscout/go/workspace"
)

func main() {
    ws, err := workspace.DetectFromCWD(afero.NewOsFs(), workspace.DefaultMarkers)
    if err != nil {
        fmt.Println("not inside a project:", err)
        return
    }

    fmt.Println("Project root:", ws.Root)
    fmt.Println("Detected via:", ws.Marker)
}

Run it from any subdirectory of a Go module and it prints the module root and go.mod.

Detect from an explicit directory

When you already have a path — a flag value, an argument — use Detect and pass the start directory yourself. It takes the same marker set and options.

ws, err := workspace.Detect(afero.NewOsFs(), startDir, workspace.DefaultMarkers)

startDir is resolved to an absolute path before the walk begins, so a relative path works fine.

Handle "not found"

When no marker is seen before the filesystem root (or the depth bound), detection returns workspace.ErrNotFound. Check for it with errors.Is:

ws, err := workspace.DetectFromCWD(afero.NewOsFs(), workspace.DefaultMarkers)
switch {
case errors.Is(err, workspace.ErrNotFound):
    return errors.New("run this inside a project directory")
case err != nil:
    return err
default:
    // use ws.Root
}

Next steps