Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/sync-policies-cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@shelve/cli": minor
"@shelve/app": minor
---

Add sync policies for push/pull conflict handling, `shelve diff` and `shelve sync`, server-side protected environments on projects, and consolidate published agent skills into a single comprehensive `shelve` skill (remove `shelve-app`).
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ More details (progressive disclosure):
- [Build env and outputs](docs/agents/build-env.md)
- [Reference docs](docs/agents/docs-links.md)
- [AI collaboration rules](docs/agents/ai-workflow.md)
- [Shelve CLI for agents & automation](docs/agents/cli.md) — install skill: `npx skills add https://shelve.cloud`
- [Shelve CLI for agents & automation](docs/agents/cli.md) — install the Shelve skill: `npx skills add https://shelve.cloud`
4 changes: 2 additions & 2 deletions apps/lp/content/docs/3.cli/10.agents-automation.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,13 @@ shelve --debug run --env preview -- pnpm build

## Install the agent skill

Shelve publishes [Agent Skills](https://docus.dev/en/ai/skills) at `/.well-known/skills/` on [shelve.cloud](https://shelve.cloud) (`shelve` + `shelve-app`):
Shelve publishes a single [Agent Skill](https://docus.dev/en/ai/skills) at `/.well-known/skills/` on [shelve.cloud](https://shelve.cloud) (`shelve` — CLI, platform, and sync policies):

```bash [terminal]
npx skills add https://shelve.cloud
```

The skill teaches agents the correct Shelve workflows, flags, and security rules (prefer `run`, avoid disk writes, use `SHELVE_*` env vars).
The skill teaches agents Shelve end-to-end: platform model (teams, tokens, UI), CLI workflows, sync policies, and security rules (prefer `run`, avoid disk writes, use `SHELVE_*` env vars). Reference files ship alongside `SKILL.md` (`cli-commands.md`, `platform.md`, `sync-policies.md`, `agent-workflows.md`).

## Local testing (contributors)

Expand Down
6 changes: 5 additions & 1 deletion apps/lp/content/docs/3.cli/11.troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ shelve --json doctor
| `FETCH_FAILED` | Network/API failure, no cache | Go online once, or use `--offline` if cache exists |
| `FORBIDDEN` | Token lacks scope | Create a token with read/write for the team/project |
| `PROJECT_NOT_FOUND` | Project missing | Enable `autoCreateProject` or `shelve create` |
| `PUSH_BLOCKED` | Push disabled for this env | Check `sync.protectedEnvironments` or `allowPush` |
| `PULL_BLOCKED` | Pull disabled for this env | Set `sync.environments.<env>.allowPull` |
| `SYNC_CONFLICT` | Diverging keys and `onPushConflict: fail` | Run `shelve diff`, align values, or change policy |
| `ENV_PROTECTED` | Server blocked write to protected env | Update project sync policy in Shelve settings |

See also `shelve --help` for the full list of structured error codes.

Expand Down Expand Up @@ -122,4 +126,4 @@ Install the published skills:
npx skills add https://shelve.cloud
```

Catalog: `https://shelve.cloud/.well-known/skills/index.json` (skills: `shelve`, `shelve-app`).
Catalog: `https://shelve.cloud/.well-known/skills/index.json` (skill: `shelve`).
103 changes: 103 additions & 0 deletions apps/lp/content/docs/3.cli/12.sync-policies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
---
title: Sync policies
description: Control who wins when local .env and Shelve diverge — push guards, pull merge, and diff.
---

Sync policies live under `sync` in `shelve.json` (and can be enforced on the server per project). They answer: **should a push from my laptop overwrite production?** **Does pull replace my whole `.env` or merge?**

## Quick example

```json [shelve.json]
{
"$schema": "https://shelve.cloud/schema.json",
"slug": "my-team",
"project": "my-app",
"defaultEnv": "development",
"sync": {
"protectedEnvironments": ["production", "preview"],
"default": {
"onPushConflict": "overwrite",
"pullMode": "replace"
},
"environments": {
"development": {
"sourceOfTruth": "local",
"onPushConflict": "overwrite"
},
"production": {
"sourceOfTruth": "remote",
"allowPush": false,
"pullMode": "merge"
}
}
}
}
```

## Policy fields

| Field | Values | Effect |
|-------|--------|--------|
| `sourceOfTruth` | `remote` \| `local` | Hint for [`shelve sync`](/docs/cli/sync-policies#sync-command): pull when `remote`, push when `local`. |
| `onPushConflict` | `overwrite` \| `skip` \| `fail` \| `prompt` | When a key exists on Shelve with a **different** value than local. Default: `overwrite`. |
| `pullMode` | `replace` \| `merge` | `replace`: rewrite `.env` (legacy). `merge`: remote keys win; **local-only** keys are kept. |
| `allowPush` / `allowPull` | `boolean` | Hard block with `PUSH_BLOCKED` / `PULL_BLOCKED`. |
| `protectedEnvironments` | `string[]` | Sets `allowPush: false` for listed env names. |
| `requireConfirmation` | `boolean` | Extra confirmation even if `confirmChanges` is false. |

Per-environment overrides go in `sync.environments.<name>`. Defaults apply via `sync.default`.

## Server policies

Project **Settings → Sync policy** stores `syncPolicy` on the project. Server rules **cannot be relaxed** from `shelve.json`: if the server sets `allowPush: false`, the CLI cannot override it.

Protected environments reject API writes with `ENV_PROTECTED`.

## Commands

### `shelve diff`

Compare local `envFileName` with Shelve (no writes). Safe for agents with `--json` (no secret values).

```bash [terminal]
shelve diff --env staging
shelve --json diff --env staging
shelve diff --env staging --show-values
```

### `shelve sync` {#sync-command}

Apply the effective policy for the environment:

- `sourceOfTruth: remote` → pull (respects `pullMode`)
- `sourceOfTruth: local` → push (respects `onPushConflict`)

```bash [terminal]
shelve sync --env development
shelve sync --env production --dry-run
shelve sync --yes --env staging
```

`--dry-run` reports the planned action and diff without writing.

## Environment variables

| Variable | Effect |
|----------|--------|
| `SHELVE_SYNC_ALLOW_PUSH=0` | Disables push for all environments in this process |
| `SHELVE_SYNC_ALLOW_PULL=0` | Disables pull for all environments |

## Error codes

| Code | Meaning |
|------|---------|
| `PUSH_BLOCKED` | `allowPush: false` or protected environment |
| `PULL_BLOCKED` | `allowPull: false` |
| `SYNC_CONFLICT` | `onPushConflict: fail` (or `prompt` in non-interactive mode) |
| `ENV_PROTECTED` | Server rejected a write to a protected environment |

See [Troubleshooting](/docs/cli/troubleshooting).

## Monorepos

Put `protectedEnvironments` in the **root** `shelve.json`; package-level files can override `sync.environments` for each app.
2 changes: 2 additions & 0 deletions apps/lp/content/docs/3.cli/2.index.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pnpm add -D @shelve/cli
| [`login`](/docs/cli/login-logout) / [`logout`](/docs/cli/login-logout) | Manage stored credentials |
| [`me`](/docs/cli/login-logout) | Show the logged-in user |
| [`push`](/docs/cli/push-pull) / [`pull`](/docs/cli/push-pull) | Sync secrets with Shelve |
| [`diff`](/docs/cli/sync-policies) / [`sync`](/docs/cli/sync-policies) | Compare or apply sync policy |
| [`create`](/docs/cli/create) | Create a project + `shelve.json` |
| [`config`](/docs/cli/config) | Show merged configuration |
| [`generate`](/docs/cli/generate) | Generate `.env.example` or ESLint config |
Expand Down Expand Up @@ -98,6 +99,7 @@ Commands always run in the **current directory** — they do not automatically e
| `envFileName` | `string` | `.env` | Local env file name |
| `autoUppercase` | `boolean` | `true` | Uppercase keys on push |
| `autoCreateProject` | `boolean` | `true` | Create project if missing |
| `sync` | `object` | — | [Sync policies](/docs/cli/sync-policies) (per-env push/pull rules) |

## Environment variables

Expand Down
10 changes: 10 additions & 0 deletions apps/lp/content/docs/3.cli/5.push-pull.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,13 @@ Set `defaultEnv` to skip passing `--env` every time:
## confirmChanges

When `confirmChanges: true` in `shelve.json`, push and pull ask before writing. Skip with `--yes` or global `--yes` / `--non-interactive` automation flags.

## Sync policies

Configure **who wins** when local and Shelve differ, block pushes to production, or merge on pull. See [Sync policies](/docs/cli/sync-policies).

```bash [terminal]
shelve diff --env staging
shelve push --env staging
shelve sync --dry-run --env production
```
3 changes: 2 additions & 1 deletion apps/lp/content/docs/3.cli/7.config.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ The token is always **redacted** as `"***"` in JSON mode.
- Resolved `project`, `slug`, `url`, `defaultEnv`
- Credential metadata (`username`, `email`) when logged in
- Monorepo detection (`isMonoRepo`, `workspaceDir`, `monorepo.paths`)
- Effective flags (`confirmChanges`, `envFileName`, …)
- Effective flags (`confirmChanges`, `envFileName`, `sync`, …)
- Resolved sync policy per environment when `sync` is configured (see [Sync policies](/docs/cli/sync-policies))

If required fields are missing and you are in non-interactive mode, the command fails with `MISSING_SLUG`, `MISSING_PROJECT`, or `AUTH_REQUIRED` instead of prompting.

Expand Down
9 changes: 2 additions & 7 deletions apps/lp/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,10 @@ export default defineNuxtConfig({
href: 'https://shelve.cloud/.well-known/skills/index.json',
},
{
title: 'CLI skill (shelve)',
description: 'Shelve CLI workflows, flags, and security rules',
title: 'Shelve agent skill',
description: 'CLI, platform, sync policies, tokens, and agent workflows',
href: '/.well-known/skills/shelve/SKILL.md',
},
{
title: 'App skill (shelve-app)',
description: 'Shelve platform, tokens, teams, and audit logs',
href: '/.well-known/skills/shelve-app/SKILL.md',
},
{
title: 'CLI agents & automation',
description: 'Global flags, JSON output, CI patterns',
Expand Down
Loading
Loading