Global vs Project

Two homes for workflows and config, when to use each, and how they layer.

Roscoe keeps two parallel directories on disk. A global one lives in your home folder, for personal use. A project one lives inside each repo, for things your team should share. Workflows and roscoe.yaml both live in this two-tier structure. The database is global-only. Know which directory holds what, and which one wins on collision, and you'll never wonder "why did my workflow disappear?"

This page is the conceptual overview. Once you've read it, the configuration deep-dives (workflow sources, roscoe.yaml) make a lot more sense.

The two directories#

Directory What lives there Scope
~/.roscoe/ Personal config, your scratch workflows, the DB Per-user, cross-project
<repo>/.roscoe/ Team-shared workflows, repo-specific overrides Per-repo, committed (or not)

Both are scaffolded by roscoe init when run inside a git repo; outside a repo, only ~/.roscoe/ is created. How the repo root is detected depends on which surface you're calling from:

  • CLI (roscoe run, list, history, …): always derives from the current working directory's git root. The roscoe serve UI's "active project" doesn't influence one-shot CLI commands.
  • MCP (Model Context Protocol): each tool call passes either a cwd argument, resolved to that call's git root, or global: true to use the global store. See MCP project scoping.
  • Web UI / roscoe serve: uses the registry's active project, set via the project switcher. Add a project with the switcher's + button (or roscoe register). Remove one with its row's trash icon (or roscoe unregister). That only drops the registry entry: no files are deleted. Remove the active project and the workspace falls back to Global, a first-class workspace with no active project. It scopes the UI to the global store, and it's where cwd-less runs from the Claude desktop app live.
  • ROSCOE_REPO_HOME is a last-resort fallback for environments without a cwd-derived root (e.g. running CLI commands outside any git repo).

The home dir can be moved with ROSCOE_HOME.

What goes where#

Workflows#

File Source
~/.roscoe/workflows/*.yaml Global
<repo>/.roscoe/workflows/*.yaml Project

Both are scanned on every list, lookup, and run. Repo wins on collision: when the same workflow id exists in both, the project copy is what runs. The global one is listed as [shadowed by repo]. Override per-run with roscoe run <id> --source global|repo.

roscoe init seeds the demo workflows that ship with Roscoe, demo-1-the-panel through demo-9-check-one-claim, into Global only. Project starts empty so the team can fill it deliberately.

Full details: workflow sources.

Configuration (roscoe.yaml)#

File Role
~/.roscoe/roscoe.yaml Your personal defaults
<repo>/.roscoe/roscoe.yaml Team-pinned overrides committed to the repo

These layer: project values override global on a per-section basis. The models.available list replaces wholesale, so a repo can pin its team to a specific model set. ports and defaults shallow-merge field by field.

Use the project file to pin things the whole team should share:

  • a fixed default model
  • a fixed port for roscoe serve, so everyone agrees on the URL
  • shared maxRetries / timeoutMs defaults

Leave personal preferences in the global file.

Full schema: roscoe.yaml.

The database#

File Source
~/.roscoe/roscoe.db Global only, always

Run history is per-user, not per-repo. The workflow_runs.workflow_source column records which source ('global' or 'repo') a given run executed against. That way you can audit history across repos without losing track of where each run came from.

If the DB ever gets corrupted, see database recovery.

When to put a workflow in project vs global#

Reach for the project directory when:

  • The workflow is part of your team's shared process for this codebase (for example, an approval flow gated on shared rules).
  • You want the same behaviour for every contributor, including CI.
  • The workflow references repo-specific paths or scripts.

Reach for the global directory when:

  • It's a personal experiment or scratch workflow.
  • You want it available everywhere on your machine, regardless of which repo you're in.
  • It's a starter / template you'll copy into a project later.

Move workflows between sources from the web UI's kebab menu (Move to Project / Move to Global) or via the move_workflow MCP tool.

Committing the project directory#

<repo>/.roscoe/ is yours to commit: it holds only shareable source (the database lives in the global home, ~/.roscoe/, never here). roscoe init leaves your repo's root .gitignore alone. It drops a .roscoe/.gitignore instead. That file already excludes the regenerated, version-pinned schema files (roscoe-config.schema.json, workflow.schema.json) and a stray roscoe.db. So to share workflows with the team, you don't need to edit any ignore rules. Commit:

  1. .roscoe/workflows/*.workflow.yaml — the workflows you want shared. Anything you'd rather keep personal stays in the global directory.
  2. .roscoe/roscoe.yaml — project config (models, defaults). Keep machine-specific bits like port overrides in the environment (e.g. ROSCOE_PORT), not here.
  3. .roscoe/.gitignore itself — so teammates inherit the same rules.

If you'd rather commit the schema files (e.g. for editor autocomplete on a fresh clone without running roscoe init), delete their lines from .roscoe/.gitignore. init won't re-add them.

See also#

View this page as Markdown

Predictable workflows from unpredictable AI