Skip to content

Accept a path as the template value - #7

Merged
defkode merged 1 commit into
mainfrom
project-local-templates
Aug 30, 2026
Merged

defkode merged 1 commit into
mainfrom
project-local-templates

Conversation

@defkode

@defkode defkode commented Aug 30, 2026 •

Copy link
Copy Markdown
Owner

Closes #1.

Problem

.orbxrc is meant to be committed, but template only took a bare name resolved against per-user and bundled dirs (orbx::resolve_template). So a repo couldn't ship its own template — teammates cloning a project with template = my-custom got template "my-custom" not found unless they hand-copied the YAML into ~/.orbx/templates or exported ORBX_TEMPLATE_DIR. The one lever that worked lived outside the repo, so the repo still wasn't self-contained.

Change

1. template accepts a path. A path-shaped value — an explicit ./, ../, / or ~/ prefix, or a .yaml/.yml extension — skips the search path and is used as given, resolved against $PWD (the same anchor ./.orbxrc itself is read from):

# ./.orbxrc — committed
template = .orbx/rails-e2e.yaml

Commit .orbx/rails-e2e.yaml next to it and everyone who clones gets the same machine. --template ./experiment.yaml works for free, since the flag feeds the same function.

2. orbx templates now agrees with resolution. It scanned three dirs and omitted $ORBX_TEMPLATE_DIR, so a template orbx up would actually pick never appeared in the listing — a pre-existing bug, and one the path form would have made worse by hiding the active template entirely. It now walks the same four locations in the same order, labels the source distinctly, and gives a path-valued template its own row:

NAME             SOURCE
.orbx/rails.yaml project (active)
boxed            env
default          built-in

(active, missing) when the committed path points at a file that isn't there.

Why not a template_dir key

The issue proposed one. This is smaller and buys the same thing: no new config key, no effective_config/resolve_context changes, no precedence rules or missing-dir errors to define, and no anchor question to settle (the issue says "repo root", but orbx never walks up — .orbxrc is read from $PWD only). A repo almost always ships one template file, not a directory.

Backward compatible by construction. The trigger is an extension or an explicit path prefix, so every bare name keeps its meaning — including an undocumented sub/nested that resolves to ~/.orbx/templates/sub/nested.yaml. There's a regression test for exactly that, and another pinning the existing (active) marker on bare names.

Testing

13 new tests, each written first and watched fail before implementing:

  • test/template.bats (8) — relative, ./-prefixed, absolute and ~/ paths; .yml extension; the missing-path error; the bare-name regression guard; and an integration test driving orb create from a committed .orbxrc.
  • test/meta.bats (5) — $ORBX_TEMPLATE_DIR listed and labeled env; env shadowing a same-named user template; the project row and its (active) marker; (active, missing); and the bare-name marker guard.

Verification:

  • 70/70 bats pass
  • shellcheck bin/orbx test/helpers/orb-stub script/release clean
  • Checked end-to-end against the real binary in a scratch dir — committed path, flag form, orbx: template file /…/nope.yaml not found (exit 1), --template default still hitting the bundled dir, and all five listing states above

Note for review

A committed template is provisioning code — orbx up runs it as root in the VM. That's inherent to project-local templates under any design, and the machine is --isolated, but it does mount $PWD. Called out in the README rather than gated in code.

https://claude.ai/code/session_01QHfJqUbdwdcGfbkvP3XJja

`template` only ever took a bare name resolved against user/bundled dirs, so
a repo could not ship its own template: teammates cloning a project with
`template = my-custom` got "template not found" unless they hand-copied the
YAML into ~/.orbx/templates or exported ORBX_TEMPLATE_DIR.

Let the value be a path instead. A path-shaped value — an explicit ./ ../ /
or ~/ prefix, or a .yaml/.yml extension — skips the search path and is used
as given, resolved against $PWD, the same anchor as ./.orbxrc:

    # ./.orbxrc, committed
    template = .orbx/rails-e2e.yaml

The two forms are disjoint, so bare names keep their meaning — including an
undocumented `sub/nested` that resolves to ~/.orbx/templates/sub/nested.yaml.
`--template ./experiment.yaml` works for free, since the flag feeds the same
function.

Chosen over a separate `template_dir` key: no new config key, no precedence
rules to define, and a repo almost always ships one file rather than a
directory.

Closes #1

Claude-Session: https://claude.ai/code/session_01QHfJqUbdwdcGfbkvP3XJja
@defkode
defkode merged commit 37136db into main Aug 30, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support project-local (committed) templates

1 participant