Ideon Logo
Ideon

Git Repository Sync

Keep a project canvas in Git alongside the files and documentation it describes. Ideon stores managed board data in a hidden .ideon/ directory so the rest of the repository remains untouched.

Use repository sync to review canvas changes in commits, restore a project from files, or trigger a server-side sync from a CI workflow. It does not replace Git or merge text line by line.

Repository Layout

An exported project contains only the managed directory:

.ideon/
  manifest.json
  blocks/
    <stable-block-id>.json
  links/
    <stable-link-id>.json
  notes/
    <stable-block-id>.md
  diagrams/
    <stable-block-id>.mmd
  assets/
    <file-name>
  canvases.json

The manifest records the project identity, block and link identities, canvas membership, positions, dimensions, parent relationships, and paths to each data file. File entries include a content type, byte size, and SHA-256 checksum. Stable repository IDs are mapped to local database IDs during import.

Positions and dimensions are part of the versioned structure. Moving a block changes its manifest entry; editing a note changes its Markdown file. Sub-canvas documents, rich note snapshots, and viewport state are preserved in canvases.json.

Text blocks are stored as Markdown. Mermaid blocks are stored as .mmd source files. PlantUML .puml files are available when the PlantUML block is supported by the deployed version.

Only files under .ideon/ are read, replaced, or committed by repository sync. Other repository files are left unchanged. Assets are stored as flat files under .ideon/assets/.

Connect a Repository

Add a Git token under Account Settings for private repositories. Ideon encrypts the token using the existing per-user token store; repository settings never contain a token. Public repositories can be used without a token.

Configure the project with an authenticated PATCH /api/projects/{projectId}/repository-sync request:

{
  "repositoryUrl": "https://github.com/example/architecture-board.git",
  "repositoryUsername": "x-access-token",
  "branch": "main",
  "repositoryPath": "docs/board"
}

Omit repositoryPath or set it to an empty string to use the repository root. Do not put credentials in the repository URL. repositoryUsername is optional; Ideon uses provider defaults when it is omitted.

For self-hosted Git servers on private networks, allow the exact host (including a non-default port) with GIT_SYNC_ALLOWED_HOSTS, for example git.internal.example,git.internal.example:8443. Requests use HTTPS, disable redirects, and pin DNS results for the duration of the Git operation.

Use GET /api/projects/{projectId}/repository-sync to read the non-secret settings. Use DELETE on the same endpoint to unlink the repository and remove its sync baseline.

Synchronize

The authenticated project export endpoint returns a ZIP containing .ideon/:

GET /api/projects/{projectId}/repository-sync/export

Import or update from a ZIP with Content-Type: application/zip:

POST /api/projects/{projectId}/repository-sync?mode=manual

The request is validated before any project state is changed. A successful import updates the same project and preserves its local database IDs through the stable identity map.

To pull, merge, and commit directly to the configured branch, use:

POST /api/projects/{projectId}/repository-sync/remote?mode=manual

The direct operation fetches the configured branch, commits only .ideon/ (or the configured subdirectory's .ideon/), and pushes without force. A branch update rejected as non-fast-forward returns a conflict response; retry after reviewing the new remote state.

Conflict Modes

Ideon compares the last synchronized baseline, the current canvas, and the incoming repository state. Changes made independently on one side are combined automatically. Select a mode for changes to the same item:

ModeConflicting item
manualReport the conflict and make no changes to either side.
git-winsUse the repository version.
ideon-winsUse the current canvas version.

Non-conflicting changes are still combined in the two resolving modes. Conflicts are field- or file-level, not line-level: a structural conflict is reported on the specific field that diverged (for example, a block's position.x when both sides moved the same block independently), while independent field changes on the same item are merged automatically. Structural conflicts are reported separately from Markdown and asset conflicts. A delete-versus-edit is a conflict; an item is never silently removed when the other side changed it.

The sync operation is explicit. It does not watch the remote continuously. A failed validation, unresolved manual conflict, or failed push does not apply a partial canvas update. If a remote commit succeeds but local persistence fails, retrying the sync replays the committed state idempotently.

Use MCP from CI

Create an Ideon API key for an owner of the project and store it as a CI secret. Configure the project repository once, then trigger sync after the relevant Git change:

curl --fail-with-body "$IDEON_URL/api/mcp" \
  -H "Authorization: Bearer $IDEON_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  --data '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"sync_project_repository","arguments":{"projectId":"'"$IDEON_PROJECT_ID"'","mode":"manual"}}}'

The MCP tools get_project_repository_sync and sync_project_repository require owner access. manual is the recommended CI mode: a conflict returns an error without changing either side. Use git-wins or ideon-wins only when the workflow intentionally establishes that source of truth.

Safety Limits

Ideon rejects unsupported manifest versions, undeclared or missing files, duplicate identities, broken references, unsafe paths, symbolic links, invalid geometry, checksum mismatches, and unknown block types. ZIP extraction is streamed and limited to 10,000 files, 100 MiB per file, 500 MiB total, and a 2 MiB manifest.

Repository access requires HTTPS. Private network hosts are blocked unless explicitly allowlisted by the server administrator. Repository credentials are not exported or returned by the settings endpoint or MCP status tool.