Requires CUE v0.17.0 or later

This guide demonstrates how to use a replace directive to point one of your module’s dependencies at a local directory, so that you can develop the dependency and the module that consumes it side by side without publishing the dependency first.

Replace directives are written to a cue.mod/local-module.cue file. This file holds development-time configuration only: it is never part of a published module, so a replacement you add here cannot leak into the version of your module that others consume.

1

Start with a module that depends on, and imports, another module – example.com/greeting@v0:

module: "app.example/hello@v0"
language: version: "v0.17.0"
deps: {
	"example.com/greeting@v0": {
		v: "v0.1.0"
	}
}
package hello

import "example.com/greeting@v0:greeting"

message: greeting.message

Ordinarily cue would fetch example.com/greeting@v0 from a registry. In this guide we will instead point it at a local checkout that we are editing.

2

Create that local checkout. It is an ordinary module directory, complete with its own cue.mod/module.cue file, holding the in-progress version of the dependency:

module: "example.com/greeting@v0"
language: version: "v0.17.0"
package greeting

message: "Hello from my local checkout"
3

Add a replace directive that substitutes the local ./greeting directory for the example.com/greeting@v0 dependency, using cue mod edit:

TERMINAL
$ cue mod edit --replace example.com/greeting@v0=./greeting

This creates a cue.mod/local-module.cue file holding the directive:

TERMINAL
$ cat cue.mod/local-module.cue
deps: {
	"example.com/greeting@v0": {
		replace: "./greeting"
	}
}

Your cue.mod/module.cue file is left untouched, so the module’s published requirements are unaffected:

TERMINAL
$ cat cue.mod/module.cue
module: "app.example/hello@v0"
language: {
	version: "v0.17.0"
}
deps: {
	"example.com/greeting@v0": {
		v: "v0.1.0"
	}
}
4

Evaluating the module now uses the contents of the local ./greeting directory in place of the dependency:

TERMINAL
$ cue export .
{
    "message": "Hello from my local checkout"
}

You can edit the files under ./greeting and immediately see the effect on your module, with no need to publish a new version of the dependency.

5

When you are finished, remove the replace directive again with --drop-replace:

TERMINAL
$ cue mod edit --drop-replace example.com/greeting@v0

Because it held the only replace directive, the cue.mod/local-module.cue file is removed entirely, leaving just cue.mod/module.cue:

TERMINAL
$ ls cue.mod
module.cue

The replacement does not have to be a local directory. A replacement value that is a module path with a version – for example example.com/greeting-fork@v0.1.0 – substitutes that module version for the dependency instead, which is useful for testing against a fork. See the cue.mod/local-module.cue files reference for full details.