Metadata-Version: 2.4
Name: piagentsync
Version: 0.5.1rc3
Summary: Sync OpenCode agents and skills from an Obsidian vault to workspace directories
License: MIT
License-File: LICENSE
Requires-Python: >=3.13
Requires-Dist: pydantic-settings>=2.3
Requires-Dist: pydantic>=2.7
Requires-Dist: python-frontmatter>=1.1
Requires-Dist: rich>=13
Requires-Dist: typer>=0.12
Description-Content-Type: text/markdown

# piagentsync

Sync OpenCode agents and skills from an Obsidian vault to workspace directories.

## Install

```bash
uv add piagentsync
# or
pip install piagentsync
```

## Quick start

1. Initialize a new project in your vault:

```bash
piagentsync init myproject --workspace ~/workspace/myproject
```

2. Pull the synced files to your workspace:

```bash
piagentsync pull myproject
```

3. If you made edits in the workspace and want to push them back into the vault:

```bash
piagentsync push myproject
```

## Configuration

Environment variables (also configurable via `.env` file):

| Variable | Default | Description |
|----------|---------|-------------|
| `PIAGENTSYNC_VAULT_PATH` | `~/vault` | Path to Obsidian vault |
| `PIAGENTSYNC_GLOBAL_OPENCODE_PATH` | `~/.config/opencode` | Path to global OpenCode config |
| `PIAGENTSYNC_VAULT_GITHUB_USER` | `Piwero` | GitHub username for vault repository (used in clone instructions) |

## CLI reference

### `piagentsync pull <project>`

Sync a single project from vault to workspace.

Options:
- `--dry-run` / `--no-dry-run` — preview changes without writing
- `--global` / `--no-global` — also sync global agents
- `--all` — sync all discovered projects

### `piagentsync push <project>`

Sync a single project from workspace back to the vault. This is the inverse of `pull` and is intended for bootstrapping the vault from existing workspaces or pushing emergency/local edits back into the vault (the user is expected to review and commit the vault afterwards).

Options:
- `--dry-run` — preview what would be pushed without writing
- `--global` — also push global agents from your local global opencode config into `vault/agents/global/`
- `--all` — push all discovered projects

Behavior notes:
- Direction: workspace (`.opencode/`) → vault
- Conflict rule: workspace wins (files in the vault will be overwritten if different)
- Unchanged files are skipped using hash comparison
- After a successful push the CLI will print a reminder to run:
  `cd ~/vault && git add -A && git commit -m "..." && git push`

### `piagentsync sync <project>`

Bidirectional sync with automatic conflict detection and resolution.

Performs intelligent two-way sync:
- Files unchanged in both locations: synced normally
- Files changed only in one location: synced from that location
- Files changed in both locations: resolved by conflict resolution strategy

#### Conflict resolution strategies:

- `--strategy vault-wins` — vault version always wins (push workspace edits → conflicts resolve to vault)
- `--strategy workspace-wins` — workspace version always wins (pull edits → conflicts resolve to workspace)
- `--strategy ask` — **default** — report conflicts without auto-resolving (human review required)

**Examples:**

```bash
# Show conflicts without auto-resolving (default):
piagentsync sync myproject

# Auto-resolve to vault version:
piagentsync sync myproject --strategy vault-wins

# Auto-resolve to workspace version:
piagentsync sync myproject --strategy workspace-wins

# Sync all projects with auto-resolution:
piagentsync sync --all --strategy workspace-wins
```

**Legacy flags** (still supported but deprecated):
- `--vault-wins` — equivalent to `--strategy vault-wins`
- `--workspace-wins` — equivalent to `--strategy workspace-wins`

Do not mix old and new flags (will error).

Options:
- `--dry-run` / `--no-dry-run` — preview changes without writing
- `--global` / `--no-global` — also sync global agents
- `--all` — sync all discovered projects

### `piagentsync status [project]`

Show sync status (differences between vault and workspace).

By default shows both project agents and global agents. Use `--no-global` to show only project agents.

Options:
- `--global` / `--no-global` — toggle global agent display (default: shows global agents)

**Examples:**

```bash
# Show status for all projects (includes global agents by default):
piagentsync status

# Show status for a specific project (includes global agents by default):
piagentsync status myproject

# Show only project agents (exclude global agents):
piagentsync status --no-global

# Show only global agents:
piagentsync status --no-global myproject  # won't work - you need a project
# Instead, use this approach if you only want global info - check the table output
```

### `piagentsync init <project>`

Scaffold a new project in the vault.

Options:
- `--workspace PATH` — required, workspace directory
- `--notion-board-id TEXT` — optional Notion DB ID
- `--notion-project-filter TEXT` — optional Notion project filter (defaults to project slug)

### `piagentsync bootstrap`

Bootstrap machine from an existing vault. This is a one‑time setup to configure OpenCode and install global agents.

Options:
- `--force` — overwrite existing `opencode.json` if present

Steps performed:
1. Verifies that the vault exists (`PIAGENTSYNC_VAULT_PATH`). If missing, prints a helpful `git clone` command.
2. Writes `{PIAGENTSYNC_GLOBAL_OPENCODE_PATH}/opencode.json` with Notion and Obsidian MCPs and disables tool globs. Skips if file exists unless `--force` is used.
3. Runs `opencode mcp auth notion` interactively to authenticate with Notion. If `opencode` is not on PATH, a warning is printed and the step is skipped.
4. Copies `{vault}/agents/global/chief-pm.md` to `{PIAGENTSYNC_GLOBAL_OPENCODE_PATH}/agents/chief-pm.md`, overwriting if the content has changed.

All steps produce clear Rich output and non‑critical warnings. The command exits 1 only if the vault is missing or a file write fails.

### `--version`

Print version and exit.

## AGENTS.md manifest format

Each project must have an `AGENTS.md` file in its root with YAML frontmatter:

```yaml
---
project: myproject
workspace: ~/workspace/myproject
notion_board_id: 3305f9479a8d8055b3c3e86a9006cf91
notion_project_filter: myproject
---
```

The body below the frontmatter is the OpenCode routing table.

## Expected vault structure

```
vault/
├── agents/
│   └── global/
│       └── *.md
└── projects/
    └── {project}/
        ├── AGENTS.md           # manifest with frontmatter
        ├── context.md          # optional context file
        ├── decisions.md        # optional decisions log
        ├── agents/
        │   └── *.md
        └── skills/
            └── *.md
```

## Contributing

Development setup:

```bash
uv sync
uv run pytest
```

Lint and format:

```bash
uv run ruff check src/ tests/
uv run ruff format src/ tests/
```

Type checking (MyPy)
--------------------

We use strict mypy checks for the codebase. To run type checking locally:

```bash
uv run mypy src/ tests/ --strict
```

Notes:
- The repository includes a `py.typed` marker so the package is PEP-561 compatible.
- Pre-commit runs `ruff` (format + lint). Running mypy in pre-commit was avoided due to isolated pre-commit environments — instead run mypy manually or add it to CI for consistent enforcement.

All commits follow [Conventional Commits](https://www.conventionalcommits.org/).

### Publishing (maintainers)

This repository uses GitHub Actions for CI and automated releases.

#### One-time PyPI setup (trusted publisher)

1. Enable OIDC on PyPI for the repository:
   - Publisher: GitHub Actions
   - Repository owner: `Piwero`
   - Repository name: `piagentsync`
   - Workflow filename: `release.yml`
   - Environment name: (leave blank)

2. The Release workflow handles everything: bump version, create tag, build, publish to PyPI, and create a GitHub Release.

#### Release process

```text
git push → ci.yml passes
   → trigger release.yml (choose MAJOR/MINOR/PATCH/RC)
       → tests re-run → changelog generated → version bumped → tag pushed
       → GitHub Release created with assets → package published to PyPI
```

## License

MIT
