Easily manage hundreds of projects and millions of planning documents. Part of Festival. Camp handles the workspace: your projects, tools, intents, and context. fest handles the planning and execution inside it.
Camp manages your camps. A camp is one context in your life: your job, a side project, your taxes. Each camp holds the projects you work on and hosts the festivals you run in them. A camp, previously called a campaign, is one such workspace: create them instantly, then move between camps, projects, and workstations without losing your place.
cgo: jump anywhere in the workspace with fuzzy matching, from any shell.
camp wi: one queue for every kind of work in the camp.
go install github.com/Obedience-Corp/camp/cmd/camp@latestgit clone https://github.com/Obedience-Corp/camp
cd camp
just install stableAdd to your shell config to enable the cgo navigation function and tab completion:
Zsh (~/.zshrc):
eval "$(camp shell-init zsh)"Bash (~/.bashrc):
eval "$(camp shell-init bash)"Fish (~/.config/fish/config.fish):
camp shell-init fish | sourceThe eval hook provides:
cgofunction - Shell-native navigation with actualcdbehavior- Tab completion - Context-aware completion for categories, projects, and commands
campcompletion - Full command completion for the camp CLI
After adding the eval line, restart your shell or run source ~/.zshrc (or equivalent).
Shell integration defines camp as a shell function (so camp go / cgo can cd in your current shell). That means plain which camp usually prints the function body, not a filesystem path.
Use these instead:
# zsh: path of the external binary (skips shell functions)
whence -p camp
# or: which -p camp
# bash
type -P camp
# show the function plus every binary on PATH
type -a camp
# resolve symlinks to the real file
realpath "$(whence -p camp)" # zsh
realpath "$(type -P camp)" # bashTo run the binary without the wrapper (scripts, debugging): command camp version.
# 1. Create a camp (prompts for description and mission in a terminal;
# in scripts pass them with -d and -m)
mkdir my-camp && cd my-camp
camp init -d "My first camp" -m "Learn the Festival stack"
# Camp stores its state in the .campaign/ directory. That name is stable:
# do not rename it to .camp/ (see "Names That Stay the Same" below).
# 2. Add shell integration (restart shell after)
echo 'eval "$(camp shell-init zsh)"' >> ~/.zshrc
# 3. Navigate!
cgo p # Jump to projects/
cgo f # Jump to festivals/
cgo p api # Fuzzy find "api" in projects/- Navigation: Category shortcuts, fuzzy finding, pins, and a cached index for instant project lookups (
go,pin,shortcuts,cache) - Project Management: Git submodules, linked local workspaces, camp-owned directories, worktrees, and scaffolding (
project add/link/list/new/rename/remote/remove/run/unlink/worktree/prune) - Planning: Intents, promotion, dungeon for deprioritized work, and a unified work-item dashboard (
intent,promote,dungeon,gather,workitem) - Productivity: Leverage scoring to identify high-impact work (
leverage) - Git Integration: camp-level git operations with submodule fan-out (
stage,commit,log,push [all],pull [all],status [all],fresh [all],refs-sync) - Camp Ops: Health checks, file operations, cross-camp tools (
doctor,copy,move,sync,transfer) - Shell Integration: Native
cdbehavior with zsh, bash, and fish (shell-init) - Tab Completion: Smart completion for categories, projects, and paths
- Plugins: Discover camp plugins on
PATH(plugins)
Note: flow is a hidden low-level status engine. Use camp promote for lifecycle promotion.
Navigate instantly with single-letter shortcuts:
| Shortcut | Directory | Description |
|---|---|---|
p |
projects/ | Project subdirectories |
f |
festivals/ | Festival methodology |
w |
workflow/ | Workflow directory |
d |
docs/ | Human documentation |
i |
.campaign/intents/ | Intents via camp intent |
settings |
.campaign/ | Camp settings directory |
wt |
projects/worktrees/ | Git worktrees |
du |
dungeon/ | Archived work |
r |
workflow/reviews/ | Review materials |
de |
workflow/design/ | Design documents |
ex |
workflow/explore/ | Exploratory notes |
cgo i remains available as an operator shortcut into the hidden intent state,
but the normal human interface is camp intent.
The cgo shell function is your primary interface:
# Jump to camp root
cgo
# Jump to category
cgo p # projects/
cgo f # festivals/
# Fuzzy search within category
cgo p api # projects/api-* (matches api-service, api-gateway, etc.)
cgo f fest # festivals/*fest*
# Run command from category (without changing directory)
cgo -c p ls # List contents of projects/
cgo -c f fest status # Run fest status from festivals/Pins: Pin frequently visited directories, jump to them with camp go or cgo, then use toggle to bounce back:
camp pin code # Pin current directory
camp pin design workflow/design/my-project # Pin a matching design directory
camp go code # Resolve a pin through camp go
cgo design # Shell jump to a pin
cgo t # Jump back to the previous location
camp pins # List all pins
camp unpin design # Remove a pinShortcuts: View all category shortcuts and custom shortcuts:
camp shortcuts # List all available shortcutscamp create <name> # Create a new camp in the default camps directory
camp create <name> --path ~/Dev/sandbox # Create under a specific camps directory
camp init # Initialize current directory
camp init my-camp # Create and initialize new directory
camp clone <url> # Clone a camp with full submodule setupProjects can be added inside the camp as a git submodule, or linked to the camp if they're already on your machine.
camp project add <url> # Add as a git submodule
camp project link <path> # Link an existing local directory as a project
camp project rename old new # Rename a managed project and its camp referencesUse submodules via camp project add (or camp p add) if you plan to use
your camp on multiple devices. Linked projects must exist in the same location
on each device in order to work.
When an upstream repository was renamed too, pass the new URL explicitly:
camp project rename old new --remote-url git@github.com:org/new.gitCamp preserves dirty checkouts and conventional Camp worktrees, migrates
typed settings and work-item references, and reports historical prose it
intentionally leaves unchanged. Use --dry-run to inspect the transaction.
For the rest of the project surface (list, remove, unlink, stage,
commit, run, worktree, prune, remote, new), see
docs/cli-reference/.
Some directories belong to a camp for context but aren't full projects
(notes, reference repos, scratch dirs). After creating a symlink to one
inside the camp tree, run camp attach on the symlink to bind its
target so detection works from inside it. The same attachment can be bound
to multiple camps; each camp-local symlink selects its own context:
ln -s ~/Dev/external-repo docs/examples/external-repo
camp attach docs/examples/external-repo
# From another camp, attach the same resolved target again. The flag keeps its
# spelling, --campaign, and takes the target camp:
camp attach /path/to/external-repo --campaign other-camp
# Force the camp picker instead of using the current camp:
camp attach docs/examples/external-repo --campaign
# now you can pin and navigate to it:
cd docs/examples/external-repo
camp pin external-repo
cgo external-repocamp detach <path> removes the marker. Linked projects keep using
camp project link / camp project unlink.
When a shared attachment is accessed directly rather than through a
camp-local symlink, camp resolves it to the first bound camp, recorded under
the compatibility key active_campaign_id. Detaching that fallback camp makes
the next bound camp active.
Intents, promotion, and the dungeon provide lightweight planning tools:
# Intents - capture ideas, goals, and work items
camp intent # Manage camp intents
camp intent add --campaign other-camp "Capture idea" # Cross-camp capture (add only)
camp gather # Import external data into the intent system
# Promotion - move intents, workitems, and festivals through lifecycle stages
camp promote # Resolve context and dispatch to the right promote command
# Dungeon - archive deprioritized work
camp dungeon # Move items to/from the dungeon
# Work items - a unified dashboard across intents, designs, explore, and festivals
camp workitem # Interactive TUI dashboard of active work
camp workitem --json # Machine-readable outputThe dungeon triage crawl honors a .crawlignore file alongside the dungeon
directory. See docs/crawlignore.md for syntax and
placement.
# Leverage scoring - identify high-impact work
camp leverage # Compute leverage scores for the camp's projectsSee docs/leverage-score.md for details on the scoring algorithm.
Git operations across the camp:
camp stage # Stage changes (same scope as commit) without committing
camp stage --include-refs # Also stage submodule ref updates at the camp root
camp commit # Commit changes in the camp root
camp log # Show git log of the camp
camp push # Push camp changes to remote
camp push all # Push all submodules with unpushed changes
camp pull # Pull latest changes
camp pull all # Pull all submodules
camp status # Show git status of the camp
camp status all # Dashboard of all submodules (branch, dirty/clean, push status, unmerged branches)
camp status all --view # Interactive TUI viewer with per-repo detail
camp fresh # Post-merge branch cycling: fetch, safely sync default, prune, optional new branch
camp fresh all # Same cycle across every project in the campcamp doctor # Diagnose and fix camp health issues
camp sync # Safely synchronize submodules
camp refs-sync # Update the camp's recorded submodule pointers to each submodule's HEAD
camp copy # Copy a file or directory within the camp
camp move # Move a file or directory within the camp
camp run # Execute command from the camp root, or just recipe in a project
camp root # Print the current camp root
camp id # Print the current camp ID
camp concepts # List configured concepts (picker/completion concepts)
camp cache info # Show navigation cache status and metadata
camp cache rebuild # Force rebuild the navigation cache
camp cache clear # Delete the navigation cachecamp list # List camps (active only by default; grouped by org)
camp list --org obey # Filter by org; also --tag (AND), --status, --all, --group/--no-group
camp switch # Switch to a different camp
camp transfer # Copy files between camps
camp register # Register a camp in the global registry
camp unregister # Remove a camp from the registry
camp registry # Maintain ~/.obey/campaign/registry.json (prune, sync, check)Camps carry three orthogonal organizational axes in the registry, kept in Camp
user configuration at ~/.obey/campaign/registry.json, filesystem + git only,
no database:
- org: single membership; every camp is in exactly one org (default
default). Group related camps; reassign by adding to a new org. - tags: a single global pool of labels; a camp can carry any number, and the same tag crosses orgs freely.
- status: lifecycle, one of
active/inactive/reference. The defaultcamp listandcamp switchsurfaces show onlyactive; use--allor--statusto include inactive/reference camps. The lifecycle command iscamp lifecycle, notcamp status(which stays the git-status wrapper).
A camp at its defaults (org default, no tags, active) stores no extra
keys, so existing registries are untouched until you organize something.
camp org add obey c1 c2 # Assign camps to an org (also reassigns)
camp org remove c1 # Return camps to the default org
camp org rename obey obedience# Rename an org, reassigning all members atomically
camp org list # Orgs with member + active counts
camp org show obey # Member camps of an org
camp org # Print the current camp's org
camp tag add c1 paid-work q3 # Add tags (set semantics; re-adding is a no-op)
camp tag rm c1 q3 # Remove tags
camp tag list # Global tag pool with counts
camp lifecycle set c1 reference # Set status: active | inactive | reference
camp lifecycle list # Status counts
camp festivals --org obey # Festivals across an org's camps (composes 'fest list')All of these accept --json. camp festivals filters camps by org/tag and
composes fest list --json per camp; it does not modify fest list.
Camp centralizes skill bundles in .campaign/skills/ and projects them into
tool ecosystems (Claude, agents, etc.) as per-bundle symlinks so a single
source of truth stays in the camp while provider-native skills
directories keep working.
camp skills # Manage camp skill bundle projection (link/unlink/status)camp settings # Manage camp configuration (interactive)
camp plugins # List discovered camp plugins on PATH
camp date # Append date suffix to file or directory name
camp version # Show version informationcamp shell-init zsh # Output zsh init script
camp shell-init bash # Output bash init script
camp shell-init fish # Output fish init scriptThe eval hook dynamically generates and executes shell code at startup:
# What happens when you add this to ~/.zshrc:
eval "$(camp shell-init zsh)"
# 1. camp shell-init zsh outputs shell code (functions, completions)
# 2. eval executes that code in your current shell
# 3. The cgo function and completions become available- Version sync - Always uses functions matching your installed camp version
- No file management - Nothing to update when camp is upgraded
- Shell detection - Camp can detect your shell environment dynamically
The shell-init script provides:
# 1. The cgo navigation function
cgo p # Runs: cd "$(camp go p --print)"
cgo p api # Runs: cd "$(camp go p api --print)"
cgo -c p ls # Runs: camp go p -c ls (no cd)
# 2. Quick capture helpers
cint "new feature idea" # Runs: camp intent add "new feature idea"
cnote "meeting note" # Runs: camp intent note "meeting note"
# 3. Tab completion for cgo
cgo <TAB> # Completes categories: p f w d i wt du cr pi de ex
cgo p <TAB> # Completes project names
# 4. Tab completion for camp commands
camp <TAB> # Completes: init go project list register...
camp project <TAB> # Completes: add commit link list new prune remote remove run unlink worktree# Verify the camp binary is on PATH. Do not use plain `which camp`:
# after shell-init it prints the wrapper function, not the binary path.
whence -p camp # zsh: external binary only
type -P camp # bash: external binary only
type -a camp # function + every binary on PATH
realpath "$(whence -p camp)" # follow symlinks to the real install
# Test shell-init output
camp shell-init zsh
# Manually reload
source ~/.zshrc
# Check if cgo is defined
type cgoA camp provides a standardized layout for AI development:
my-camp/
├── .campaign/ # Camp configuration and system state
│ ├── campaign.yaml
│ ├── watchers.yaml
│ ├── intents/ # System-managed intents (camp intent, cgo i)
│ │ ├── inbox/
│ │ ├── active/
│ │ ├── ready/
│ │ └── dungeon/
│ ├── settings/ # Camp-local settings and defaults
│ ├── skills/ # Camp skill bundles (camp skills)
│ ├── leverage/ # Leverage snapshots and cache (camp leverage)
│ └── cache/ # Navigation index cache
├── projects/ # Git submodules and linked workspaces
│ ├── api-service/ # Git submodule
│ ├── web-app/ # Git submodule
│ ├── my-local-repo -> /Users/you/code/my-local-repo # Linked workspace (symlink)
│ └── worktrees/ # Git worktrees (cgo wt)
│ └── api-service/
│ ├── feature-x/
│ └── bugfix-y/
├── festivals/ # Festival methodology (cgo f)
│ ├── planning/
│ ├── active/
│ ├── ready/
│ ├── ritual/
│ └── dungeon/ # completed/, archived/, someday/
├── workflow/ # Workflow resources (cgo w)
│ ├── design/ # Design documents (cgo de)
│ ├── explore/ # Exploratory notes (cgo ex)
│ └── reviews/ # Review materials (cgo r)
├── docs/ # Human documentation (cgo d)
└── dungeon/ # Archived work (cgo du)
Camps used to be called campaigns, and the earlier name is still what the files, flags, and machine-readable output are spelled with. Both words mean the same thing to Camp, in commands and in agent prompts alike.
- Should I rename
.campaign/? No. It is the stable metadata directory and Camp expects it. - Is
.campthe new metadata directory? No..campis an attachment marker written into linked external directories, not a workspace directory. - Do my scripts using
--campaignorcampaign_rootstill work? Yes. Nothing about flags, selectors, or machine-readable output changed. - Why do internal files still say campaign? They are stable compatibility contracts that protect your existing data and integrations.
See docs/terminology.md for the full vocabulary contract.
Navigate git worktrees with @ syntax:
cgo wt # Jump to worktrees/
cgo wt api-service@ # Show branches for api-service
cgo wt api-service@feat # Jump to api-service@feature-xThe shell integration includes intelligent tab completion:
# Navigation
cgo <TAB> # Shows: p f w d i wt du cr pi de ex
cgo p <TAB> # Shows: api-service web-app cli-tool
cgo p api<TAB> # Completes to: api-service api-gateway
cgo wt api@<TAB> # Shows worktree branches
# --project flag (all project commands)
camp project commit -p <TAB> # Shows project names from project list
camp project worktree add -p <TAB> # Same project name completionCamp configuration lives in the compatibility filename campaign.yaml, inside
the camp metadata directory, .campaign/:
name: my-camp
type: product
description: My awesome projectProjects can define shortcuts to jump directly to subdirectories within the project. The default shortcut is used when navigating to the project without specifying a sub-path.
Add a projects section to .campaign/campaign.yaml:
projects:
- name: festival-methodology
path: projects/festival-methodology
shortcuts:
default: fest/ # Jump here by default
cli: fest/cmd/fest/ # Named sub-shortcut
- name: api-service
path: projects/api-service
shortcuts:
default: src/Usage:
cgo p fest # Jumps to projects/festival-methodology/fest/ (uses default)
cgo p fest cli # Jumps to projects/festival-methodology/fest/cmd/fest/
cgo p api # Jumps to projects/api-service/src/ (uses default)Without a default shortcut, navigation jumps to the project root.
Camp uses a small set of configuration and state files:
~/.obey/campaign/config.json, Camp user configuration, for global preferences such as editor, theme,no_color, andverbose.campaign/campaign.yamlfor camp metadata, project entries, and picker concepts.campaign/settings/jumps.yamlfor camp-local navigation paths and shortcuts.campaign/settings/fresh.yamlfor optionalcamp freshdefaults.campaign/watchers.yamlfor the camp/fest watcher contract
See docs/campaign-settings-files.md for the
full file-by-file reference, including which files are scaffolded by
camp init and which are only created on first use.
- CLI Reference: complete reference for every command and flag
- Terminology: the vocabulary contract for Camp and everything built on it
.campaign/Directory Reference: the hidden camp metadata layout and ownership- Camp Settings Files: global and local config/state files explained
- Leverage Scoring: how leverage scores are computed
- Shortcuts: category shortcuts reference
- Shell Integration: detailed shell setup guide
.crawlignoreSyntax: excluding paths from dungeon triage
Migration guides for behavior changes live under docs/migrations/.
Individual command docs are in docs/cli-reference/ (auto-generated via just docs).
just # List all commands
just build-camp # Build camp binary (vet + build)
just build # Show all build recipes (profiles, cross-platform)
just test # Show all test recipes
just test all # Run all tests
just install # Show install options (stable, dev, current)
just install stable # Install stable profile to $GOBIN
just gate-fast # Run the local quality gate on demand
just docs # Regenerate CLI reference docs
just docs-check # Fail if committed CLI reference is stale
just run <args> # Run with argumentsCamp has no hosted CI. Quality gates run locally, on demand:
just gate-push # quick smoke: whitespace, build, vet, lint, short dev tests
just gate-fast # broader: both-profile build, vet, lint, CLI docs check, full dev unit tests
just gate # full matrix: gate-fast plus stable unit testsEvery release recipe runs just gate before tagging, so releases are always
gated (including just docs-check: generated docs/cli-reference/ must match
the current command surface). There is no pre-push hook; run a gate when you
want a signal. Changing pack/unbundle/clone/transport (or any) command help
requires just docs and a commit of the regenerated reference.
If you previously ran just hooks-install, run git config --unset core.hooksPath
once to fully revert that local setting, it now points at a removed directory.
Camp is one half of Festival, the current product from Obedience Corp.
- camp: workspace and context. One place for all your projects, tools, intents, agents, and work.
- fest: planning and execution. Hierarchical: festival → phase → sequence → task.
- Festival: combined distribution of camp + fest. Full docs at fest.build.
Find camp useful? Star the repo so others can find it.
Apache License 2.0 - See LICENSE for details.


