# Managing Clip Linking and Sync‑Lock Track Relationships in Palmier Pro

> Master clip linking and sync-lock tracks in Palmier Pro. Learn how these orthogonal mechanisms ensure audio-video sync during timeline edits and preserve editorial invariants.

- Repository: [Palmier/palmier-pro](https://github.com/palmier-io/palmier-pro)
- Tags: how-to-guide
- Published: 2026-07-27

---

**Palmier Pro maintains audio‑video synchronization through orthogonal mechanisms: clip linking groups related media via `linkGroupId` while sync‑lock tracks use the `syncLocked` boolean to control ripple edit participation, with both systems interacting during timeline mutations to preserve editorial invariants.**

The Palmier Pro video editor manages complex timeline relationships through two distinct but complementary systems. Understanding how **clip linking** and **sync‑lock track relationships** interact is essential for maintaining synchronization across audio and video elements while controlling which tracks move during ripple edits. This guide examines the source code implementation to show exactly how these mechanisms function.

## Clip Linking Mechanics

Clip linking in Palmier Pro operates at the clip level, treating associated media as a single logical unit for editing operations.

### Link Groups and the `linkGroupId`

A **link group** is identified by a `linkGroupId` stored on each `Clip` instance. All clips sharing the same identifier are treated as a single unit for selection, movement, trimming, and deletion. In `Sources/PalmierPro/Editor/ViewModel/EditorViewModel+Linking.swift`, the `linkIndex` property builds a reverse mapping from group IDs to clip IDs in a single pass over every track, operating at `O(tracks·clips)` complexity (lines 17‑26).

### Expanding Selections and Finding Partners

The linking system provides several utility methods for working with groups:

- **`expandToLinkGroup(_:)`** – Expands a partial selection to include the full link group, ensuring commands affect the entire set (lines 37‑55)
- **`linkedPartnerIds(of:)`** – Returns the other members of a clip’s group, excluding the clip itself (lines 57‑63)

### Propagating Moves and Timing Changes

When you manipulate a linked clip, Palmier Pro automatically computes transformations for partners:

- **`partnerMoves(forMoveOf:toFrame:)`** – Calculates the same frame delta for every partner clip, preserving audio/video sync when moving linked media (lines 65‑77)
- **`timingPropagationPartners(of:)`** – Returns all clips requiring uniform duration, trim, or speed changes when any group member is edited (lines 79‑88)
- **`linkGroupOffsets()`** – Scans both plain link groups and multicam groups to compute per‑clip offsets when members drift apart after operations like trimming (lines 91‑139)

### Link Management Commands

The editor exposes explicit commands for managing groups:

```swift
// Create a new link group from selected clips
let selectedIds: Set<String> = ["clipA", "clipB"]
editor.linkClips(ids: selectedIds)  // Creates UUID, stamps clips, merges existing groups

```

In `EditorViewModel+Linking.swift`, **`linkClips(ids:)`** creates a new UUID, stamps it on every clip in the set, and merges any pre‑existing groups (lines 141‑148). Conversely, **`unlinkClips(ids:)`** expands the selection to the full group and clears `linkGroupId` on each member (lines 150‑157).

### Trim and Slip Propagation

When committing a trim operation, the system optionally expands the edit set to linked partners via the `propagateToLinked` parameter. The `commitTrim` method calls `trimClips` with computed start/end frames after expanding the selection (lines 66‑86).

For slip operations, `commitSlip` works on *slip‑eligible* clips (audio/video content that is not image or text based and not part of a multicam group). It propagates the source‑frame shift only to partners that also satisfy eligibility checks through `slipPropagationPartnerIds` (lines 98‑118).

## Track Sync‑Lock Mechanics

While linking controls relationships between clips, sync‑lock controls track behavior during ripple edits.

### The `syncLocked` Property

Each track stores a `syncLocked` boolean flag (defaulting to `true`). When `syncLocked` is **true**, the track moves in lock‑step with ripple edits that shift nearby tracks; when **false**, the track remains independent. This property is defined in [`Sources/PalmierPro/Models/Timeline.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Models/Timeline.swift) and decodes with a fallback default of `true` for legacy projects (lines 88‑126).

The UI exposes this through a toggle button in [`TimelineHeaderView.swift`](https://github.com/palmier-io/palmier-pro/blob/main/TimelineHeaderView.swift), displaying a "link" symbol for locked tracks and "personalhotspot.slash" for unlocked tracks (lines 90‑94).

### Ripple Editing Integration

During ripple insertion (`rippleInsertClips` in `EditorViewModel+Ripple.swift`), the engine first gathers the set of locked tracks using `timeline.tracks.filter(\.syncLocked)` (lines 65‑95). It then computes left‑room and right‑room constraints only for those tracks.

If a track is locked but does not contain clips being inserted, the edit still reserves space on that track via `syncLockedLeftRoom` to maintain visual and audio alignment (lines 95‑106). When deleting or shifting gaps, the ripple logic respects the `syncLocked` flag to ensure locked tracks move together while unlocked tracks remain stationary (lines 152‑181).

Toggle the flag programmatically using the generic helper:

```swift
// Toggle sync‑lock on track 2
editor.toggleTrackFlag(
    trackIndex: 2,
    keyPath: \.syncLocked,
    onName: "Sync Lock Track",
    offName: "Unlock Track Sync"
)

```

This method resides in `Sources/PalmierPro/Editor/ViewModel/EditorViewModel+Tracks.swift` (lines 98‑105).

### Agent Tool Integration

The Agent system exposes `syncLocked` as a mutable property in the `manage_tracks` command. In `ToolExecutor+Timeline.swift`, the default track configuration includes `"syncLocked": true` (lines 129‑130). Validation logic in `ToolExecutor+Clips.swift` enforces that at least one of `muted`, `hidden`, or `syncLocked` is supplied when altering track flags (lines 1123‑1134).

## How Linking and Sync‑Lock Work Together

Although linking operates at the clip level and sync‑lock at the track level, both mechanisms cooperate during ripple editing:

1. **Linked clips may span multiple tracks.** When a linked clip moves, `partnerMoves` ensures every partner receives the same frame delta, regardless of the tracks’ `syncLocked` state.

2. **Sync‑locked tracks guarantee that ripples shifting one track also shift other locked tracks**, preserving the temporal relationship of linked clips across tracks.

For example, dragging a linked video clip on a locked video track triggers the ripple engine to shift the locked audio track, while the linked‑clip logic applies the same frame delta to the audio clip partner.

## Summary

- **Clip linking** uses `linkGroupId` to bind related clips into logical units, with automatic propagation of moves, trims, and slips via methods in `EditorViewModel+Linking.swift`
- **Sync‑lock** tracks use the `syncLocked` boolean (default `true` in [`Timeline.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Timeline.swift)) to determine participation in ripple edits, with constraints calculated in `EditorViewModel+Ripple.swift`
- **Cross‑track synchronization** is maintained when linked groups span multiple tracks and those tracks are sync‑locked, ensuring audio‑video alignment during complex edits
- **Agent API** exposes both mechanisms, allowing automated tools to manage track sync states and clip relationships

## Frequently Asked Questions

### What happens when linked clips span tracks with different sync‑lock states?

The clip linking mechanism operates independently of track sync‑lock states. When you move a linked clip, `partnerMoves` calculates the same frame delta for all partners regardless of their track's `syncLocked` value. However, if the edit triggers a ripple operation, only tracks with `syncLocked` set to `true` will shift together. The moved clip’s partners outside the ripple zone maintain their relative positions through the link group offset calculations.

### How does Palmier Pro handle unlinking when only one clip in a group is selected?

The `unlinkClips(ids:)` method automatically expands the selection to include the full link group before clearing the `linkGroupId` on each member. As implemented in `EditorViewModel+Linking.swift` (lines 150‑157), passing a single clip ID effectively unlinks the entire group, removing the association between all previously linked clips.

### Can sync‑locked tracks be edited without affecting ripple operations?

Yes. The `syncLocked` flag only controls behavior during ripple edits (insertions, deletions, and gap shifts). Direct edits like moving clips, trimming, or slipping content on a sync‑locked track do not trigger automatic shifts in other tracks unless those edits specifically involve ripple operations. For non‑ripple workflows, sync‑locked tracks behave identically to unlocked tracks.

### How does the Agent API expose sync‑lock functionality?

The Agent tool executor exposes `syncLocked` through the `manage_tracks` command in `ToolExecutor+Timeline.swift`. When updating track properties via the Agent, you must supply at least one of `muted`, `hidden`, or `syncLocked` according to the validation logic in `ToolExecutor+Clips.swift` (lines 1123‑1134). The property defaults to `true` in the `trackDefaults` dictionary, ensuring new tracks maintain synchronization with the timeline by default.