PRJ Spec direnv lib

After some rounds of feedback, a direnv lib for the PRJ Specification has been merged under ./contrib/direnv.

Feel free to try it out in your .envrc:

{ # PRJ Base Directory Specification: 
         # shellcheck source=/dev/null 
         source "$( 
                 fetchurl \ 
                         "" \ 

PRJ Spec is a specification that aims at providing stable environment variables inside a project development environment (i.e. repo) modeled almost 1:1 after the XDG specification.

The following env variables and their target folders are available:

 export PRJ_ROOT 
 export PRJ_ID # if set state is maintained inside their matching XDG_ dirs globally, e.g. for sharing between worktrees
 export PRJ_PATH # prepended to `PATH`
 export PRJ_DATA_HOME 

Useage Ideas:

  • PRJ_DATA_HOME, for example, is a great location to place a repository’s gc roots.

  • Concerned with cache control, if you want to teach your favorit build tool some cache isolation tricks, point it to PRJ_CACHE_HOME.

  • Have executable build outputs placed in PRJ_PATH for convenience and devX.

  • Keep dev service PIDs and Unix Domain sockets at your fingertips in PRJ_RUNTIME_DIR

  • Keep your dev secrets in-tree under PRJ_CONFIG_HOME

Future Work:

I’ve been starting a go reference implementation so that tools can leverage language libraries to more easily leverage this specification


What does PRJ stand for?

“Project”, most likely.


Odd if true. They could have just called it that then. Now I have to wonder who or what the PRJ is.

I don’t find it particularly odd. I believe it’s inherited from the numtide devshell environment variables, in any case. In the context of looking at project environment variables while working on a project, I think it would be fairly intuitive to understand “PRJ” as “project”. If you know to use these variables, you should already know what they represent: project environment variables. I think the idea is to avoid clobbering other variables with a prefix, since you might be typing this frequently it makes sense to abbreviate it.

1 Like

I suppose it’s also inspired by the XDG base directory specification, which similarly uses a three letter prefix.

Abbreviations are generally bad, and only initialisms should look like initialisms, subjectively.

1 Like

Project Root Justification, obviously :upside_down_face:
(Justifiction borrowed from typography to mean alignment)


I’ll do you one better: PRJ Root Justification.


Oh god it’s GNU and XDA all over again :see_no_evil:

1 Like

These aren’t mentioned in the spec. Are the norms being drafted (read: not documented) or is this just a preemptive effort (read: tacked on)?

These are tacked-on by analogy with the XDG.

However, PRJ_STATE_HOME has been removed as the distinction with PRJ_DATA_HOME was just too shallow.

A future iteration on the spec may or may not take them into account.

On the subject of acronyms (or any “coined” term for that matter).

What they probably really are is a preemptive attempt of tokenization of a concept into a language.

Now that works only beyond a critical mass adopted by speakers, of course.

So before that critical mass they’re always odd and may even feel intrusive.

Form a spec perspective it’s also a bit of a chicken and egg problem, because at the aspirational core of a spec lies adoption, that’s their raison-d’etre.

My 2 cents.

1 Like

Are you sure that .envrc is correct? What is “fetchurl”? This is what I see when using it:

❯ direnv allow
direnv: loading ~/code/nix-browser/.envrc
direnv: error Get "%20": unsupported protocol scheme ""
./.envrc:9: No such file or directory
./.envrc:10: sha256-54YaaGly6Q0E8GhFT9fB/h9tN1PDERo2/4R4X0Pdi/c=: No such file or directory
./.envrc:8: : No such file or directory

Not sure what’s going on there, has been working fine so far. :person_shrugging:

fetchurl is from the direnv stdlib here.