- Git dir:
./.git - Tracks: everything
- Used for: day-to-day app development
- Commands:
git …
You can delete .geet/ and keep working normally at any time.
Each layer is a self-contained template repo:
- Git dir:
./.<layer>/dot-git - Tracks: only specified files (via include/exclude lists)
- Used for: shared evolution
- Commands:
./.<layer>/lib/cli.sh …
All repos operate on the same files, same paths.
MyApp/
.git/ # app repo (normal)
.geet/ # base template layer
dot-git/ # template git database (ignored by app repo)
.geetinclude # whitelist (OR use .geetexclude for blacklist)
lib/
cli.sh # single entrypoint
git.sh # git wrapper (template view)
init.sh # convert clone → app + layer
tree.sh # inspect what the layer includes
split.sh # export template-visible files
session.sh # split → run → optional copy-back
doctor.sh # sanity checks
gh.sh # GitHub CLI integration
post-init.sh # optional one-time setup hook
Only dot-git/ is ignored by the app repo.
Everything else in .geet/ is committed so collaborators get the tooling.
Think of layers as lenses:
- App lens: "Everything here belongs to this project."
- Template lens: "Only these files exist."
The filesystem never changes. Only Git's interpretation does.
Converts a freshly-cloned template repo into an app with a template layer:
- Moves
.git→.geet/dot-git(preserves template git database) - Creates new app repo at
.git - Adds
dot-git/to.gitignore - Runs post-init hook if present
Idempotent: Safe to run multiple times. If already initialized, runs refresh instead.
The refresh command (also callable as checkout) handles template repo setup and ref switching:
geet refresh # Refresh to current tracked ref (from env vars)
geet checkout main # Switch to branch
geet checkout v1.2.3 # Switch to tag
geet checkout abc123 # Switch to commitWhat it does:
- Clones template repo if
dot-git/doesn't exist - Adds origin remote if missing (SSH preferred, HTTPS fallback)
- Fetches latest refs from origin
- Safety check: refuses to switch if template has uncommitted changes
- Pre-cleanup: removes template-only files that won't exist in new ref
- Updates template HEAD to target ref (branch-like or detached)
- Exports snapshot of target ref to temp directory
- Applies
.geetincludefile mappings to working tree - Syncs managed blocks in
.gitignoreand.git/info/exclude
Use cases:
- First-time setup when cloning an app repo that already tracks a template
- Switching between template branches, tags, or commits
- Recovering from template setup issues
- Ensuring template is synced with latest remote refs
- Teams maintaining multiple similar apps
- Templates that must live at canonical paths
- Developers who want git-native updates
- Anyone burned by starter kits drifting over time
If your template can't afford to move files, this is the least-bad solution.