# Global vs Project

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](/docs/configuration/workflow-sources),
[roscoe.yaml](/docs/configuration/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](/docs/reference/mcp-tools#project-scoping-cwd--global).
- 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](/docs/configuration/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](/docs/configuration/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](/docs/troubleshooting/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`](/docs/reference/mcp-tools) 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

- [Workflow sources](/docs/configuration/workflow-sources) — full resolution
  rules, `--source` overrides, MCP `source` parameter.
- [roscoe.yaml](/docs/configuration/roscoe-yaml) — config schema and merge
  semantics.
- [Environment variables](/docs/configuration/environment) — `ROSCOE_HOME`,
  `ROSCOE_REPO_HOME`.
