buttercut 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c4de766d8aca2ec00b99b20abd177310ade3b5145424677bf6b3e515487960b2
4
+ data.tar.gz: 97429c1df91a51ef44a921a0d2f3e8140adfa2c6c0943abf643d0967cea2e4bc
5
+ SHA512:
6
+ metadata.gz: a6c30d9d4038725ef7b63cc15d5de34a8fc85e775bb3907896dae7d1bbde9f87abe7da263dec07ce0a27c7ec6b6d5940db00dc1bf40b24763a49c5381a9961b4
7
+ data.tar.gz: '029612e07d6fb9e806aecd10f5d89a95557d23e151a4fe53cb3ab393cd05b45ad89908881c982f6b7922e6227399306cbc51a4ef257404637b84f51a52c5e757'
@@ -0,0 +1,24 @@
1
+ # Create Worktree with Library
2
+
3
+ Create a new git worktree with all libraries and media from main.
4
+
5
+ ## Arguments
6
+
7
+ `<branch-name>` - The name for the new branch and worktree
8
+
9
+ Example: `/worktree feature-test`
10
+
11
+ User provided: $ARGUMENTS
12
+
13
+ ## Instructions
14
+
15
+ 1. Parse the branch name from arguments
16
+ 2. Always use the main branch worktree at `/Users/andrew/code/buttercut` as the source
17
+ 3. Create a new git worktree at `../<branch-name>` with a new branch of the same name
18
+ 4. Copy the entire `libraries/` directory from main: `/Users/andrew/code/buttercut/libraries/`
19
+ 5. Copy the `media/` directory from main (if it exists): `/Users/andrew/code/buttercut/media/`
20
+ 6. Run `mise trust` in the new worktree to trust the mise config
21
+ 7. Run `bundle install` in the new worktree to install Ruby dependencies
22
+ 8. Confirm success with the paths created
23
+
24
+ If the branch name is missing, ask the user to provide it: `/worktree <branch-name>`
@@ -0,0 +1,31 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Skill(backup-library)",
5
+ "Skill(release)",
6
+ "Skill(update-buttercut)",
7
+ "Skill(setup)",
8
+ "Skill(transcribe-audio)",
9
+ "Skill(roughcut)",
10
+ "Skill(analyze-video)",
11
+ "Read(libraries/**)",
12
+ "Edit(libraries/**)",
13
+ "Write(libraries/**)",
14
+ "Read(templates/**)",
15
+ "Read(.claude/**)",
16
+ "Bash(ffprobe:*)",
17
+ "Bash(ffmpeg:*)",
18
+ "Bash(whisperx:*)",
19
+ "Bash(ruby:.claude/**)",
20
+ "Bash(mkdir:libraries/**)",
21
+ "Bash(mkdir:tmp/**)",
22
+ "Bash(rm:tmp/**)",
23
+ "Bash(ls:*)",
24
+ "Bash(zip:*)",
25
+ "Bash(cp:libraries/**)",
26
+ "Bash(unzip:backups/**)"
27
+ ],
28
+ "deny": [],
29
+ "ask": []
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(./.claude/skills/roughcut/combine_visual_transcripts.rb:*)",
5
+ "Bash(./.claude/skills/roughcut/export_to_fcpxml.rb:*)",
6
+ "Skill(backup-library)",
7
+ "Skill(release)",
8
+ "Skill(update-buttercut)",
9
+ "Skill(setup)",
10
+ "Skill(transcribe-audio)",
11
+ "Skill(roughcut)",
12
+ "Skill(analyze-video)",
13
+ "Bash(ruby:*)",
14
+ "Bash(/Users/andrew/code/buttercut/.claude/skills/roughcut/combine_visual_transcripts.rb programmer-story-vlog ai_jobs_responses_c)",
15
+ "Bash(/Users/andrew/code/buttercut/.claude/skills/roughcut/combine_visual_transcripts.rb programmer-story-vlog ai_jobs_responses_a)",
16
+ "Bash(/Users/andrew/code/buttercut/.claude/skills/roughcut/combine_visual_transcripts.rb:*)",
17
+ "Bash(awk:*)",
18
+ "Read(libraries/**)",
19
+ "Edit(libraries/**)",
20
+ "Write(libraries/**)",
21
+ "Bash(whisperx:*)",
22
+ "Bash(git worktree add:*)",
23
+ "Bash(cat:*)",
24
+ "Bash(python3:*)",
25
+ "Bash(gh api:*)"
26
+ ],
27
+ "deny": [],
28
+ "ask": []
29
+ },
30
+ "outputStyle": "default"
31
+ }
@@ -0,0 +1,89 @@
1
+ ---
2
+ name: analyze-video
3
+ description: Adds visual descriptions to transcripts by extracting and analyzing video frames with ffmpeg. Creates visual transcript with periodic visual descriptions of the video clip. Use when all files have audio transcripts present (transcript) but don't yet have visual transcripts created (visual_transcript).
4
+ ---
5
+
6
+ # Skill: Analyze Video
7
+
8
+ Add visual descriptions to audio transcripts by extracting JPG frames with ffmpeg and analyzing them. **Never read video files directly** - extract frames first.
9
+
10
+ ## Prerequisites
11
+
12
+ Videos must have audio transcripts. Run **transcribe-audio** skill first if needed.
13
+
14
+ ## Workflow
15
+
16
+ ### 1. Copy & Clean Audio Transcript
17
+
18
+ Don't read the audio transcript, just copy it and then prepare it by using the prepare_visual_script.rb file. This removes word-level timing data and prettifies the JSON for easier editing:
19
+
20
+ ```bash
21
+ cp libraries/[library]/transcripts/video.json libraries/[library]/transcripts/visual_video.json
22
+ ruby .claude/skills/analyze-video/prepare_visual_script.rb libraries/[library]/transcripts/visual_video.json
23
+ ```
24
+
25
+ ### 2. Extract Frames (Binary Search)
26
+
27
+ Create frame directory: `mkdir -p tmp/frames/[video_name]`
28
+
29
+ **Videos ≤30s:** Extract one frame at 2s
30
+ **Videos >30s:** Extract start (2s), middle (duration/2), end (duration-2s)
31
+
32
+ ```bash
33
+ ffmpeg -ss 00:00:02 -i video.mov -vframes 1 -vf "scale=1280:-1" tmp/frames/[video_name]/start.jpg
34
+ ```
35
+
36
+ **Subdivide when:** Footage start, middle and end have different subjects, setting or angle changes
37
+ **Stop when:** The footage no longer seems to be changing or only has minor changes
38
+ **Never sample** more frequently than once per 30 seconds
39
+
40
+ ### 3. Add Visual Descriptions
41
+
42
+ Read the visual video json file that you created earlier.
43
+
44
+ **Read the JPG frames** from `tmp/frames/[video_name]/` using Read tool, then **Edit** `visual_video.json`:
45
+
46
+ Do these incrementally. You don't need to create a program or script to do this, just incrementally edit the json whenever you read new frames.
47
+
48
+ **Dialogue segments - add `visual` field:**
49
+ ```json
50
+ {
51
+ "start": 2.917,
52
+ "end": 7.586,
53
+ "text": "Hey, good afternoon everybody.",
54
+ "visual": "Man in red shirt speaking to camera in medium shot. Home office with bookshelf. Natural lighting.",
55
+ "words": [...]
56
+ }
57
+ ```
58
+
59
+ **B-roll segments - insert new entries:**
60
+ ```json
61
+ {
62
+ "start": 35.474,
63
+ "end": 56.162,
64
+ "text": "",
65
+ "visual": "Green bicycle parked in front of building. Urban street with trees.",
66
+ "b_roll": true,
67
+ "words": []
68
+ }
69
+ ```
70
+
71
+ **Guidelines:**
72
+ - Descriptions should be 3 sentences max.
73
+ - First segment: detailed (subject, setting, shot type, lighting, camera style)
74
+ - Continuing shots: brief if similar, otherwise can be up to 3 sentences if drastically different.
75
+
76
+ ### 4. Cleanup & Return
77
+
78
+ ```bash
79
+ rm -rf tmp/frames/[video_name]
80
+ ```
81
+
82
+ Return structured response:
83
+ ```
84
+ ✓ [video_filename.mov] analyzed successfully
85
+ Visual transcript: libraries/[library]/transcripts/visual_video.json
86
+ Video path: /full/path/to/video_filename.mov
87
+ ```
88
+
89
+ **DO NOT update library.yaml** - parent agent handles this to avoid race conditions in parallel execution.
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ require 'json'
3
+
4
+ abort "Usage: ruby prepare_visual_script.rb <json_file>" if ARGV.empty?
5
+ abort "Error: File not found: #{ARGV[0]}" unless File.exist?(ARGV[0])
6
+
7
+ begin
8
+ data = JSON.parse(File.read(ARGV[0]))
9
+
10
+ data['segments']&.each { |s| s.delete('words') }
11
+ data.delete('word_segments')
12
+
13
+ # Reorder keys: language and video_path first, then segments, then everything else
14
+ reordered = {}
15
+ reordered['language'] = data['language'] if data['language']
16
+ reordered['video_path'] = data['video_path'] if data['video_path']
17
+ reordered['segments'] = data['segments'] if data['segments']
18
+ # Add any other keys that might exist
19
+ data.each { |k, v| reordered[k] = v unless reordered.key?(k) }
20
+
21
+ File.write(ARGV[0], JSON.pretty_generate(reordered))
22
+ puts "Prettified: #{ARGV[0]} (word-level timing removed)"
23
+ rescue JSON::ParserError => e
24
+ abort "Error: Invalid JSON - #{e.message}"
25
+ end
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: backup-library
3
+ description: Creates compressed ZIP backups of libraries directory. Backs up library.yaml, transcripts, and roughcuts (not video files). This skill can also be useful when you need to restore a library.
4
+ ---
5
+
6
+ # Skill: Backup Library
7
+
8
+ Verify libraries directory exists:
9
+ ```bash
10
+ ls -la libraries/
11
+ ```
12
+
13
+ Run backup:
14
+ ```bash
15
+ ruby .claude/skills/backup-library/backup_libraries.rb
16
+ ```
17
+
18
+ Creates `backups/libraries_YYYYMMDD_HHMMSS.zip` containing the entire libraries directory.
19
+
20
+ ## Restore Library
21
+
22
+ To restore from a backup, extract the ZIP file to the project root.
23
+ ```bash
24
+ unzip backups/libraries_timestamp.zip -d .
25
+ ```
26
+ This restores all libraries to their original locations.
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Library Backup Utility
5
+ # Creates compressed ZIP backups of the entire libraries directory
6
+
7
+ require 'fileutils'
8
+ require 'time'
9
+ require 'zip'
10
+
11
+ class LibraryBackup
12
+ def initialize(project_root = Dir.pwd)
13
+ @libraries_dir = File.join(project_root, 'libraries')
14
+ @backups_dir = File.join(project_root, 'backups')
15
+ end
16
+
17
+ def backup
18
+ unless Dir.exist?(@libraries_dir)
19
+ puts "❌ No libraries directory found"
20
+ return nil
21
+ end
22
+
23
+ FileUtils.mkdir_p(@backups_dir)
24
+
25
+ timestamp = Time.now.strftime('%Y%m%d_%H%M%S')
26
+ backup_path = File.join(@backups_dir, "libraries_#{timestamp}.zip")
27
+
28
+ puts "📦 Creating backup: #{backup_path}"
29
+
30
+ files = Dir.glob(File.join(@libraries_dir, '**', '*')).select { |f| File.file?(f) }
31
+
32
+ Zip::File.open(backup_path, Zip::File::CREATE) do |zipfile|
33
+ files.each do |file|
34
+ zipfile.add(file.sub("#{File.dirname(@libraries_dir)}/", ''), file)
35
+ end
36
+ end
37
+
38
+ puts "✅ Backed up #{files.size} files"
39
+ backup_path
40
+ end
41
+ end
42
+
43
+ # CLI
44
+ if __FILE__ == $PROGRAM_NAME
45
+ LibraryBackup.new.backup
46
+ end
@@ -0,0 +1,204 @@
1
+ ---
2
+ name: release
3
+ description: Creates a new ButterCut release with version bump, changelog, git tag, gem build, and GitHub release. Use when publishing a new version.
4
+ ---
5
+
6
+ # Skill: Release ButterCut
7
+
8
+ Guides through the complete release process: version bump, changelog, git operations, gem publishing, and GitHub release creation.
9
+
10
+ ## When to Use
11
+
12
+ - Publishing a new version of ButterCut
13
+ - After merging features or fixes that should be released
14
+ - Creating the first v0.1.0 release
15
+
16
+ ## Workflow
17
+
18
+ ### 1. Run Tests First
19
+
20
+ **CRITICAL: Always run tests before releasing. Never release if tests fail.**
21
+
22
+ ```bash
23
+ bundle exec rspec
24
+ ```
25
+
26
+ If any tests fail, STOP immediately and ask user to fix before proceeding with release.
27
+
28
+ ### 2. Check Current State
29
+
30
+ ```bash
31
+ # Read current version
32
+ cat lib/buttercut/version.rb
33
+
34
+ # Check git status (must be clean)
35
+ git status
36
+
37
+ # Check existing tags
38
+ git tag -l
39
+ ```
40
+
41
+ If git status is not clean, stop and ask user to commit or stash changes before proceeding.
42
+
43
+ ### 3. Determine New Version
44
+
45
+ Ask user what type of release following [Semantic Versioning](https://semver.org/):
46
+ - **MAJOR** (1.0.0): Breaking changes
47
+ - **MINOR** (0.2.0): New features, backward compatible
48
+ - **PATCH** (0.1.1): Bug fixes, backward compatible
49
+
50
+ Calculate new version number based on current version and release type.
51
+
52
+ ### 4. Update Version File
53
+
54
+ Edit `lib/buttercut/version.rb` with the new version:
55
+
56
+ ```ruby
57
+ class ButterCut
58
+ VERSION = "0.2.0" # Update this
59
+ end
60
+ ```
61
+
62
+ ### 5. Gather Changelog Notes
63
+
64
+ Ask user for release notes. Prompt with:
65
+ - What changed in this release?
66
+ - Any new features?
67
+ - Any bug fixes?
68
+ - Any breaking changes?
69
+
70
+ ### 6. Update or Create CHANGELOG.md
71
+
72
+ If `CHANGELOG.md` exists, prepend new entry. Otherwise create it:
73
+
74
+ ```markdown
75
+ # Changelog
76
+
77
+ All notable changes to ButterCut will be documented in this file.
78
+
79
+ ## [0.2.0] - 2025-01-21
80
+
81
+ ### Added
82
+ - Feature X
83
+ - Support for Y
84
+
85
+ ### Fixed
86
+ - Bug in Z
87
+
88
+ ### Changed
89
+ - Improved W
90
+ ```
91
+
92
+ ### 7. Commit Version Bump
93
+
94
+ ```bash
95
+ git add lib/buttercut/version.rb CHANGELOG.md
96
+ git commit -m "Bump version to 0.2.0"
97
+ ```
98
+
99
+ ### 8. Create and Push Git Tag
100
+
101
+ ```bash
102
+ git tag v0.2.0
103
+ git push origin main
104
+ git push origin v0.2.0
105
+ ```
106
+
107
+ ### 9. Build Gem
108
+
109
+ ```bash
110
+ gem build buttercut.gemspec
111
+ ```
112
+
113
+ This creates `buttercut-0.2.0.gem` file.
114
+
115
+ ### 10. Publish to RubyGems
116
+
117
+ **First time setup check:**
118
+
119
+ If this is the first release, verify RubyGems authentication:
120
+ ```bash
121
+ gem signin
122
+ ```
123
+
124
+ If not authenticated, provide instructions:
125
+ 1. Sign up at https://rubygems.org
126
+ 2. Run `gem signin` and follow prompts
127
+ 3. Store credentials for future releases
128
+
129
+ **Publish the gem:**
130
+ ```bash
131
+ gem push buttercut-0.2.0.gem
132
+ ```
133
+
134
+ This makes the gem available for `gem install buttercut` worldwide.
135
+
136
+ ### 11. Create GitHub Release
137
+
138
+ **Using GitHub CLI:**
139
+ ```bash
140
+ gh release create v0.2.0 \
141
+ --title "v0.2.0" \
142
+ --notes "[Release notes from changelog]" \
143
+ buttercut-0.2.0.gem
144
+ ```
145
+
146
+ **If `gh` CLI not available:**
147
+
148
+ Guide user through manual release creation:
149
+ 1. Go to https://github.com/andrewford/buttercut/releases/new
150
+ 2. Choose tag: v0.2.0
151
+ 3. Set title: v0.2.0
152
+ 4. Paste changelog notes in description
153
+ 5. Attach buttercut-0.2.0.gem file
154
+ 6. Click "Publish release"
155
+
156
+ Then wait for user confirmation that release is created before proceeding to cleanup.
157
+
158
+ ### 12. Cleanup
159
+
160
+ ```bash
161
+ # Remove local gem file (it's on RubyGems and GitHub now)
162
+ rm buttercut-0.2.0.gem
163
+ ```
164
+
165
+ ### 13. Verify Release
166
+
167
+ Check that everything worked:
168
+ - RubyGems page: https://rubygems.org/gems/buttercut
169
+ - GitHub releases: https://github.com/andrewford/buttercut/releases
170
+ - Git tags: `git tag -l`
171
+
172
+ ### 14. Return Success Response
173
+
174
+ Provide summary:
175
+ ```
176
+ ✓ ButterCut 0.2.0 released successfully
177
+
178
+ Version: 0.2.0
179
+ Git tag: v0.2.0
180
+ RubyGems: Published at https://rubygems.org/gems/buttercut
181
+ GitHub Release: https://github.com/andrewford/buttercut/releases/tag/v0.2.0
182
+
183
+ Installation:
184
+ gem install buttercut
185
+
186
+ Upgrade:
187
+ gem update buttercut
188
+ ```
189
+
190
+ ## Critical Principles
191
+
192
+ **Always run tests first** - Never release if tests fail
193
+ **Git must be clean** - No uncommitted changes before release
194
+ **Push before publish** - Tags must be pushed before creating GitHub release
195
+ **Semantic versioning** - Follow semver strictly for version numbers
196
+ **Changelog required** - Every release needs documented changes
197
+
198
+ ## Common Issues
199
+
200
+ **Tests failing:** Ask user to fix tests before proceeding
201
+ **Git not clean:** Ask user to commit or stash changes first
202
+ **Tag already exists:** Verify this isn't a duplicate release
203
+ **RubyGems authentication:** Guide through `gem signin` process
204
+ **GitHub CLI not installed:** Provide manual release instructions
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: roughcut
3
+ description: Creates video rough cut yaml file for use with Buttercut gem. Concatenates visual transcripts with file markers, creates a roughcut yaml with clip selections, then exports to XML format. Use this skill when users want a "roughcut", "sequence" or "scene" generated. These are all the same thing, just with different lengths.
4
+ ---
5
+
6
+ # Skill: Create Rough Cut
7
+
8
+ This skill handles the editorial process of creating rough cut timeline scripts from transcribed video footage. It launches a specialized agent that analyzes transcripts, makes editorial decisions, outputs a structured YAML rough cut, and exports it to Final Cut Pro XML format.
9
+
10
+ **Note:** This skill is used for both full-length rough cuts (multiple minutes) and short sequences (30-60 seconds).
11
+
12
+ ## Prerequisites Check
13
+
14
+ Before launching the roughcut agent, verify all transcripts are complete:
15
+
16
+ 1. **Check library exists:**
17
+ ```bash
18
+ ls libraries/[library-name]/library.yaml
19
+ ```
20
+
21
+ 2. **Verify visual transcripts:**
22
+ Read `libraries/[library-name]/library.yaml` and check that every video entry has both:
23
+ - `transcript` populated (audio transcript filename)
24
+ - `visual_transcript` populated (visual descriptions filename)
25
+
26
+ If any visual transcripts are missing:
27
+ - Inform user that transcript processing must be completed first
28
+ - Ask if they want Claude to finish transcript processing using the `transcribe-audio` and `analyze-video` skills
29
+ - Do not proceed with roughcut creation until all transcripts are complete
30
+
31
+ ## Launch Roughcut Agent
32
+
33
+ Once prerequisites are verified, launch the roughcut creation agent using the Task tool:
34
+
35
+ ```
36
+ Task tool with:
37
+ - subagent_type: "general-purpose"
38
+ - description: "Create rough cut from visual transcripts"
39
+ - prompt: [See agent prompt template below]
40
+ ```
41
+
42
+ ### Agent Prompt Template
43
+
44
+ When launching the agent, provide a detailed prompt with all necessary context:
45
+
46
+ ```
47
+ You are a video editor AI agent creating a rough cut or sequence for the "{library_name}" library.
48
+
49
+ USER REQUEST: {what_user_asked_for}
50
+
51
+ LIBRARY CONTEXT:
52
+ {paste relevant content from library.yaml - footage_summary, user_context, etc.}
53
+
54
+ YOUR TASK:
55
+ 1. Read the roughcut creation instructions from .claude/skills/roughcut/agent_instructions.md
56
+ 2. Follow those instructions to create the rough cut
57
+ 3. Return the paths to the created YAML and XML files when complete
58
+
59
+ DELIVERABLES:
60
+ - Rough cut YAML file at: libraries/{library_name}/roughcuts/{roughcut_name}_{datetime}.yaml
61
+ - Exported XML file for user's chosen video editor
62
+ - Backup created via backup-library skill
63
+
64
+ Begin by reading the agent instructions file.
65
+ ```
66
+
67
+ ## After Agent Completes
68
+
69
+ When the agent returns:
70
+ 1. Inform the user of the created roughcut file (the xml file, not the yaml file) and its location
71
+ 2. Confirm the rough cut is ready to import into their video editor
@@ -0,0 +1,109 @@
1
+ # Roughcut Agent Instructions
2
+
3
+ You are a video editor AI agent. Analyze footage, make editorial decisions based on user requests, and produce a YAML timing based rough cut.
4
+
5
+ ## Workflow
6
+
7
+ ### 1. Gather Preferences (if needed)
8
+
9
+ - **Only ask questions if the user's initial request is vague or lacks critical details**
10
+ - If the user has already provided clear instructions about structure, duration and pacing, skip questions and proceed directly to step 2
11
+ - If clarification is needed, use AskUserQuestion tool to ask about whatever is missing, ie:
12
+ - Narrative structure preference
13
+ - Target duration
14
+ - Pacing preference
15
+
16
+ ### 2. Create Combined Visual Transcript
17
+
18
+ Combine all visual transcripts into a single file:
19
+
20
+ ```bash
21
+ mkdir -p tmp/[library-name] && cat libraries/[library-name]/transcripts/visual_*.json > tmp/[library-name]/[roughcut_name]_combined_visual_transcript.json
22
+ ```
23
+
24
+ This outputs to `tmp/[library-name]/[roughcut_name]_combined_visual_transcript.json` in NDJSON format (one JSON object per line per video):
25
+ ```json
26
+ {
27
+ "language": "en",
28
+ "video_path": "/full/path/to/video.mov",
29
+ "segments": [
30
+ {"start": 2.917, "end": 7.586, "text": "Hey, good afternoon.", "visual": "Man speaking to camera outdoors."},
31
+ {"start": 8.307, "end": 10.551, "text": "Today is going to be different."},
32
+ {"start": 10.551, "end": 15.0, "text": "", "visual": "Walking shot, buildings in background.", "b_roll": true}
33
+ ]
34
+ }
35
+ ```
36
+
37
+ **Segment fields:**
38
+ - `start`, `end`: Timestamps in seconds
39
+ - `text`: Dialogue (empty string `""` for silent segments)
40
+ - `visual`: Shot description (only present when visual changes)
41
+ - `b_roll`: `true` when segment is silent B-roll (only present when true)
42
+
43
+ ### 3. Read and Analyze Combined Transcript
44
+
45
+ **Count lines and plan reading:**
46
+ ```bash
47
+ wc -l tmp/[library-name]/[roughcut_name]_combined_visual_transcript.json
48
+ ```
49
+
50
+ **Read the combined transcript in 5000-line chunks** using the Read tool with offset and limit parameters.
51
+
52
+ After reading through footage sequentially, you can spend a little time thinking, and then create the roughcut yaml file.
53
+
54
+ ### 4. Create Rough Cut YAML
55
+
56
+ **Generate a timestamp** using `date +%Y%m%d_%H%M%S` and use the resulting value as a literal string in all filenames for this roughcut session (YAML and XML).
57
+
58
+ **Setup:**
59
+ ```bash
60
+ cp templates/roughcut_template.yaml "libraries/[library-name]/roughcuts/[roughcut_name]_[timestamp].yaml"
61
+ ```
62
+
63
+ **Build clips based on user's request:**
64
+ - Use the user's stated goals to guide editorial decisions
65
+ - Convert timestamps from seconds to `HH:MM:SS.ss` format (hundredths of second precision)
66
+ - Reference video files using `source_file` from the combined JSON
67
+
68
+ **CRITICAL - Timecode Logic:**
69
+ - `in_point`: Start time of FIRST segment you want
70
+ - `out_point`: End time of LAST segment you want
71
+ - Use `start` and `end` from segments directly (preserve sub-second precision)
72
+ - Example: segment at 2.849s-29.63s → in_point: `00:00:02.85`, out_point: `00:00:29.63`
73
+
74
+ **CRITICAL - Required Fields:**
75
+ Each clip needs:
76
+ - `dialogue`: Spoken words from transcript (or `""` if silent B-roll)
77
+ - `visual_description`: Shot description from visual transcript
78
+
79
+ **Metadata:**
80
+ - `created_date`: `YYYY-MM-DD HH:MM:SS`
81
+ - `total_duration`: Sum of all clips in `HH:MM:SS.ss` format
82
+
83
+ ### 5. Export to Video Editor
84
+
85
+ Check `library.yaml` for the `editor` field. If it's set, use that value. If it's not set or empty, ask the user for their editor choice (Final Cut Pro X, Adobe Premiere Pro, or DaVinci Resolve), then save their choice back to `library.yaml` (`fcpx`, `premiere`, or `resolve`).
86
+
87
+ Export based on choice:
88
+ ```bash
89
+ # Final Cut Pro X:
90
+ bundle exec ./.claude/skills/roughcut/export_to_fcpxml.rb libraries/[library-name]/roughcuts/[roughcut_name]_[datetime].yaml libraries/[library-name]/roughcuts/[roughcut_name]_[datetime].fcpxml fcpx
91
+
92
+ # Premiere Pro:
93
+ bundle exec ./.claude/skills/roughcut/export_to_fcpxml.rb libraries/[library-name]/roughcuts/[roughcut_name]_[datetime].yaml libraries/[library-name]/roughcuts/[roughcut_name]_[datetime].xml premiere
94
+
95
+ # DaVinci Resolve:
96
+ bundle exec ./.claude/skills/roughcut/export_to_fcpxml.rb libraries/[library-name]/roughcuts/[roughcut_name]_[datetime].yaml libraries/[library-name]/roughcuts/[roughcut_name]_[datetime].xml resolve
97
+ ```
98
+
99
+ ### 6. Create Backup
100
+
101
+ Run the `backup-library` skill to preserve the completed work.
102
+
103
+ ### 7. Report Results
104
+
105
+ Provide summary with:
106
+ - Rough cut name and duration
107
+ - Number of clips included
108
+ - File path for XML
109
+ - Backup confirmation