[MISC] Add worktree setup script for automated env file copying#1756
[MISC] Add worktree setup script for automated env file copying#1756chandrasekharan-zipstack merged 7 commits intomainfrom
Conversation
- Add scripts/worktree-setup.sh to automate copying .env files when creating new worktrees for the unstract repo - Update .gitignore to exclude worktree directories from tracking This helps developers quickly set up isolated development environments with all necessary configuration files. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a new Git Worktree skill: documentation ( Changes
Sequence Diagram(s)sequenceDiagram
participant User as User
participant CLI as "worktree-setup.sh"
participant Git as Git
participant FS as Filesystem
User->>CLI: invoke with source & target paths
CLI->>FS: resolve absolute paths, validate dirs
CLI->>Git: (optional) create git worktree from origin/main
CLI->>FS: copy config files (env, docker, etc.) with content checks
CLI->>FS: copy backend settings (exclude tracked files)
CLI->>FS: copy `.claude/skills` directories (including hidden files)
CLI->>User: print summary (copied/updated/skipped/missing) and next steps
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- Add .claude/skills/worktree/SKILL.md with instructions for creating git worktrees with automatic env file copying - Update .gitignore to allow .claude/skills/ to be tracked This skill helps developers create isolated worktrees for parallel development with automatic configuration file setup. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move worktree-setup.sh into skill folder - Add gitignored backend settings copy - Streamline skill to end after worktree creation - Output copyable claude command and docker build/watch commands - Detect services from user request keywords Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @.claude/skills/worktree/SKILL.md:
- Around line 38-74: Update the Markdown to satisfy markdownlint: add spaces
around table pipes in the Keywords → Services table so each cell is separated
like " | " (fix header and rows), and mark the example summary fenced code block
as language "text" by changing the opening fence to ```text and ensuring the
closing ``` remains; specifically edit the "Match keywords in user's request to
services" table and the "Print summary with commands" fenced block to apply
these changes.
🧹 Nitpick comments (2)
.claude/skills/worktree/worktree-setup.sh (2)
25-39: Add a guard to ensure the target is a git worktree.Without a check, a typo can copy secrets into an unintended directory. Consider failing fast if the target isn’t a worktree.
🔒 Suggested guard
TARGET_PATH="$1" SOURCE_PATH="${2:-$(cd "$(dirname "$0")/../../.." && pwd)}" if [ -z "$TARGET_PATH" ]; then show_usage 1 fi @@ SOURCE_PATH=$(cd "$SOURCE_PATH" && pwd) + +# Ensure target is a git worktree before copying secrets +if [ ! -d "$TARGET_PATH" ] || ! git -C "$TARGET_PATH" rev-parse --is-inside-work-tree > /dev/null 2>&1; then + echo "Error: target path is not a git worktree: $TARGET_PATH" >&2 + exit 1 +fi
63-150: Separate “updated” from “copied” in the summaries.Right now updates are counted as copies, which makes the final counts misleading.
♻️ Suggested counter split
-copied=0 +copied=0 +updated=0 skipped=0 missing=0 @@ if ! diff -q "$src" "$dest" > /dev/null 2>&1; then cp "$src" "$dest" echo " [updated] $file" - copied=$((copied + 1)) + updated=$((updated + 1)) else echo " [skipped] $file (unchanged)" skipped=$((skipped + 1)) fi @@ -echo "Env files: Copied=$copied, Skipped=$skipped, Missing=$missing" +echo "Env files: Copied=$copied, Updated=$updated, Skipped=$skipped, Missing=$missing" @@ -settings_copied=0 +settings_copied=0 +settings_updated=0 settings_skipped=0 @@ if [ -f "$dest" ]; then if ! diff -q "$file" "$dest" > /dev/null 2>&1; then cp "$file" "$dest" echo " [updated] $filename" - settings_copied=$((settings_copied + 1)) + settings_updated=$((settings_updated + 1)) else echo " [skipped] $filename (unchanged)" settings_skipped=$((settings_skipped + 1)) fi @@ -echo "Settings: Copied=$settings_copied, Skipped=$settings_skipped" +echo "Settings: Copied=$settings_copied, Updated=$settings_updated, Skipped=$settings_skipped"
The setup script now copies .claude/skills/ directories from the source repo, ensuring skills like playwright-cli and pr-address-comments are available in worktrees. Includes hidden files/dirs and is idempotent. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
.claude/skills/worktree/worktree-setup.sh (2)
9-9: Consider addingset -u(and optionallyset -o pipefail).
set -ealone won't catch unbound variable references (e.g., a typo like$TAGET_PATH) — they silently expand to empty strings.set -ucauses an immediate exit on any unset variable.set -o pipefailadditionally catches failures in piped commands.♻️ Suggested hardening
-set -e +set -euo pipefail🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.claude/skills/worktree/worktree-setup.sh at line 9, The script currently uses only "set -e" which misses unset-variable and piped-command failures; update the shell options in worktree-setup.sh by adding "set -u" to treat unset variables as errors and optionally "set -o pipefail" to ensure failures inside pipelines are propagated — modify the line containing "set -e" (or the shell option block around it) to include these flags so functions and variable references in the script fail fast.
179-182:if [ -d "$dest_dir" ]is always true —skills_copiedis always incremented.
mkdir -p "$dest_dir"on line 175 always succeeds (and creates the directory), so the subsequent directory check is a no-op guard. If bothcpcalls fail silently (e.g., empty skill dir), the counter still increments, overstating the summary.🔧 Proposed fix
mkdir -p "$dest_dir" - cp -r "$skill_dir"* "$dest_dir/" 2>/dev/null || true - # Copy hidden files/dirs too (e.g. .playwright-cli) - cp -r "$skill_dir".* "$dest_dir/" 2>/dev/null || true - if [ -d "$dest_dir" ]; then - echo " [copied] $skill_name/" - skills_copied=$((skills_copied + 1)) - fi + if cp -r "$skill_dir." "$dest_dir/" 2>/dev/null; then + echo " [copied] $skill_name/" + skills_copied=$((skills_copied + 1)) + else + echo " [warning] $skill_name/ (copy may be incomplete)" + fi🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.claude/skills/worktree/worktree-setup.sh around lines 179 - 182, The skills_copied counter is incremented unconditionally because mkdir -p creates dest_dir, so change the logic to only increment skills_copied when the copy actually succeeded: after the cp commands that copy files into "$dest_dir" check the cp exit status ($?) or test dest_dir for non-empty content (e.g., use [ "$(find "$dest_dir" -maxdepth 0 -type d -empty)" ] or check for files with shopt -s nullglob and count files) and only increment skills_copied when files were copied; update the block around dest_dir, cp, and skills_copied to use that conditional check so the summary reflects real copies.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.claude/skills/worktree/worktree-setup.sh:
- Line 39: Validate SOURCE_PATH before running cd: check that the variable
SOURCE_PATH is non-empty and that [ -d "$SOURCE_PATH" ] is true in
worktree-setup.sh, and if not print the friendly usage/error message and exit
with a non-zero status instead of letting cd "$SOURCE_PATH" fail under set -e;
update the block around the SOURCE_PATH assignment (the line using
SOURCE_PATH=$(cd "$SOURCE_PATH" && pwd)) to perform the existence/dir check
first, then canonicalize with cd/pwd only after validation.
- Line 37: Replace the brittle realpath -m usage for TARGET_PATH with a portable
resolution: try realpath -m if available, otherwise use a Python-based absolute
path resolver (e.g., python3 -c using os.path.abspath/os.path.normpath on the
provided TARGET_PATH) so relative paths become absolute and subsequent cp/mkdir
-p operate in the intended location; ensure the fallback errors clearly if no
resolver (realpath or python3) is present. Reference: the TARGET_PATH assignment
line where TARGET_PATH is computed.
- Around line 176-178: The cp of hidden files uses the pattern "$skill_dir".*
which expands to . and .. and can copy the parent directory; update the
hidden-file copy to use the trailing-dot idiom so cp only copies the directory's
contents (including dotfiles) without matching .. — change the second cp that
references "$skill_dir".* to use "$skill_dir." and keep redirection/|| true
behavior around the existing cp to preserve error suppression; reference the
variables skill_dir and dest_dir and the two cp invocations in the fix.
---
Nitpick comments:
In @.claude/skills/worktree/worktree-setup.sh:
- Line 9: The script currently uses only "set -e" which misses unset-variable
and piped-command failures; update the shell options in worktree-setup.sh by
adding "set -u" to treat unset variables as errors and optionally "set -o
pipefail" to ensure failures inside pipelines are propagated — modify the line
containing "set -e" (or the shell option block around it) to include these flags
so functions and variable references in the script fail fast.
- Around line 179-182: The skills_copied counter is incremented unconditionally
because mkdir -p creates dest_dir, so change the logic to only increment
skills_copied when the copy actually succeeded: after the cp commands that copy
files into "$dest_dir" check the cp exit status ($?) or test dest_dir for
non-empty content (e.g., use [ "$(find "$dest_dir" -maxdepth 0 -type d -empty)"
] or check for files with shopt -s nullglob and count files) and only increment
skills_copied when files were copied; update the block around dest_dir, cp, and
skills_copied to use that conditional check so the summary reflects real copies.
- Use set -euo pipefail for stricter error handling - Replace realpath -m with portable path resolution (macOS compat) - Validate SOURCE_PATH before cd to give friendly error - Fix .* glob matching .. by using trailing-dot copy idiom - Fix markdownlint: table spacing and fenced code block language Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
.claude/skills/worktree/SKILL.md (1)
14-14: Optional: quote the inner command substitution to prevent word-splitting.
$(git config --get remote.origin.url)is unquoted insidebasename; afile://remote path with spaces would cause word-splitting and break the command. The2>/dev/nullalso applies tobasename, not togit config, so a failure fromgit configwould still print to stderr.✨ Suggested fix
- REPO_NAME=$(basename -s .git $(git config --get remote.origin.url) 2>/dev/null || basename $(pwd)) + REPO_NAME=$(basename -s .git "$(git config --get remote.origin.url 2>/dev/null)" || basename "$(pwd)")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.claude/skills/worktree/SKILL.md at line 14, The REPO_NAME assignment uses basename with an unquoted command substitution and misapplied redirection; update the expression so the git command substitution is quoted to prevent word-splitting (refer to the $(git config --get remote.origin.url) part) and move the 2>/dev/null redirection to apply to git (so errors from git are suppressed, not basename). Ensure the outer basename arguments are also safely quoted where appropriate so file:// paths with spaces are handled correctly and failures from git don’t leak to stderr.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.claude/skills/worktree/worktree-setup.sh:
- Around line 21-29: The script currently uses set -u and directly references
"$1" and "$2" (in TARGET_PATH and SOURCE_PATH) which causes an "unbound
variable" error when no args are passed; modify the argument handling in
worktree-setup.sh to avoid direct expansion of unset positional parameters by
either (a) checking $# (e.g., if [ $# -lt 1 ] || ... ) before accessing "$1", or
(b) use safe parameter expansion like TARGET_PATH="${1:-}" and
SOURCE_PATH="${2:-$(cd "$(dirname "$0")/../../.." && pwd)}", then call
show_usage 1 when TARGET_PATH is empty; keep references to show_usage and the
existing help flag logic intact.
- Around line 37-38: The TARGET_PATH assignment uses command substitutions with
cd but relies on a trailing "|| TARGET_PATH=..." which never runs because
variable assignment returns success; fix by explicitly testing the parent dir
before building the absolute path: capture dirname via DIR="$(dirname
"$TARGET_PATH")", test [ -d "$DIR" ] (or try cd "$DIR" and check its exit), and
then set TARGET_PATH to "$(cd "$DIR" && pwd)/$(basename "$TARGET_PATH")" on
success or to "$(pwd)/$TARGET_PATH" on failure; update the code around the
TARGET_PATH assignment and the cd/dirname usages so the fallback executes
correctly when the parent dir does not exist.
---
Duplicate comments:
In @.claude/skills/worktree/SKILL.md:
- Around line 40-53: Summary: Markdownlint issues were fixed (table pipe spacing
around "Keywords | Services" and fenced code block language tag corrected); no
code changes required. Action: confirm and approve the PR by marking the
resolved lint changes as accepted and merge; specifically verify the table
header row containing "Keywords" and "Services" and the fenced code block
language tag are preserved exactly as in the diff, then apply the
[approve_code_changes] state or merge the branch.
In @.claude/skills/worktree/worktree-setup.sh:
- Around line 168-185: The trailing-dot copy approach is correct so no code
change is needed; keep the loop in worktree-setup.sh as written (referencing
skill_dir, skill_name, dest_dir and the cp -r "$skill_dir." "$dest_dir/"
invocation), since "$skill_dir." reliably copies the directory contents
including hidden files without matching .. and thus resolves the previous glob
issue.
- Around line 40-44: Validation for SOURCE_PATH is correct and should remain:
ensure the existence check if [ ! -d "$SOURCE_PATH" ]; then ... show_usage 1 fi
runs before changing directory, then set SOURCE_PATH=$(cd "$SOURCE_PATH" &&
pwd); keep this ordering and the use of show_usage and absolute path resolution
to preserve the behavior.
---
Nitpick comments:
In @.claude/skills/worktree/SKILL.md:
- Line 14: The REPO_NAME assignment uses basename with an unquoted command
substitution and misapplied redirection; update the expression so the git
command substitution is quoted to prevent word-splitting (refer to the $(git
config --get remote.origin.url) part) and move the 2>/dev/null redirection to
apply to git (so errors from git are suppressed, not basename). Ensure the outer
basename arguments are also safely quoted where appropriate so file:// paths
with spaces are handled correctly and failures from git don’t leak to stderr.
Test ResultsSummary
Runner Tests - Full Report
SDK1 Tests - Full Report
|
|



What
scripts/worktree-setup.shscript to automate copying .env files when creating new worktrees.claude/skills/worktree/SKILL.md- a Claude Code skill for creating git worktrees.gitignoreto exclude worktree directories and allow.claude/skills/to be trackedWhy
How
Setup Script (
scripts/worktree-setup.sh):Copies necessary configuration files from the source repository to a new worktree:
backend/.envplatform-service/.envprompt-service/.envx2text-service/.envdocker/essentials.envworkers/.envUsage:
scripts/worktree-setup.sh <worktree_path> <source_repo_path>Worktree Skill (
.claude/skills/worktree/SKILL.md):A Claude Code skill that provides instructions for:
fix/,feat/,misc/prefixes)Can this PR break any existing features?
No, this adds new utility scripts and a skill. No existing functionality is affected.
Database Migrations
Env Config
Relevant Docs
Related Issues or PRs
Dependencies Versions
Notes on Testing
git worktree add -b test/branch ../test-worktree origin/mainscripts/worktree-setup.sh ../test-worktree ./worktreeskill in Claude Code (requires Claude Code CLI)Screenshots
🤖 Generated with Claude Code