Skip to content

feat(config): add Jean worktree setup script#764

Merged
FelixTJDietrich merged 4 commits into
mainfrom
jean-worktree-setup
Feb 25, 2026
Merged

feat(config): add Jean worktree setup script#764
FelixTJDietrich merged 4 commits into
mainfrom
jean-worktree-setup

Conversation

@FelixTJDietrich
Copy link
Copy Markdown
Collaborator

@FelixTJDietrich FelixTJDietrich commented Feb 25, 2026

Summary

  • Add jean.json so Jean automatically runs a setup script when creating worktrees
  • Add scripts/jean-setup.sh that copies local config files (.env, application-local.yml, etc.) from the root checkout and runs npm install
  • Missing config files are skipped gracefully — no errors for files that don't exist yet

Test plan

  • Create a worktree via Jean TUI on this branch
  • Verify existing local config files were copied into the worktree
  • Verify missing files show "skipped (not found in root)" without errors
  • Confirm node_modules/ exists and npm ls succeeds in the worktree

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Added setup script and configuration file for automated project initialization.

Add jean.json and scripts/jean-setup.sh so new worktrees created via
Jean automatically get local config files copied and npm dependencies
installed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@FelixTJDietrich FelixTJDietrich requested a review from a team as a code owner February 25, 2026 21:42
Copilot AI review requested due to automatic review settings February 25, 2026 21:42
@FelixTJDietrich FelixTJDietrich enabled auto-merge (squash) February 25, 2026 21:42
@github-actions github-actions Bot added size:M This PR changes 30-99 lines, ignoring generated files. feature New feature or enhancement labels Feb 25, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

Introduces a new configuration file jean.json that defines a setup command, paired with a new Bash setup script scripts/jean-setup.sh that initializes worktree environments, copies configuration files from a central JEAN_ROOT_PATH location, and installs npm dependencies with basic error handling.

Changes

Cohort / File(s) Summary
Configuration
jean.json
Adds scripts.setup command pointing to jean-setup.sh for worktree initialization.
Setup Script
scripts/jean-setup.sh
New Bash script with strict mode, conditional config file copying via helper function, npm dependency installation, and error handling for missing paths/files.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A worktree born from scripts so neat,
Config copies, dependencies complete,
Jean's setup hops with practiced grace,
Making each environment a perfect place!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a Jean worktree setup script. It directly corresponds to the two files added (jean.json and jean-setup.sh) and their primary purpose of automating worktree setup.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jean-worktree-setup

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Jean worktree automation to streamline development workflow by automatically configuring new git worktrees. Jean is a worktree management tool that can execute setup scripts when creating new worktrees, and this PR configures it to copy local configuration files and install dependencies automatically.

Changes:

  • Add jean.json configuration to trigger automatic setup when Jean creates worktrees
  • Add scripts/jean-setup.sh that copies local config files from the main checkout and runs npm install
  • Enable isolated worktree development with independent configuration files

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
jean.json Configures Jean to invoke the setup script using the JEAN_ROOT_PATH environment variable
scripts/jean-setup.sh Bash script that copies local configuration files (.env, application-local.yml, etc.) from root and installs npm dependencies

Comment thread scripts/jean-setup.sh
Comment on lines +10 to +30
echo " JEAN_ROOT_PATH is not set — skipping config file copy."
else
copy_if_exists() {
local src="$JEAN_ROOT_PATH/$1"
if [ -f "$src" ]; then
mkdir -p "$(dirname "$1")"
cp "$src" "$1"
echo " copied $1"
else
echo " skipped $1 (not found in root)"
fi
}

echo "Copying local config files..."
copy_if_exists "server/application-server/src/main/resources/application-local.yml"
copy_if_exists "server/application-server/src/test/resources/application-live-local.yml"
copy_if_exists "server/application-server/.env"
copy_if_exists "server/intelligence-service/.env"
copy_if_exists "server/webhook-ingest/.env"
copy_if_exists "docker/.env"
copy_if_exists ".claude/settings.local.json"
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script uses 2-space indentation, but all other bash scripts in the repository (codex-setup.sh, codex-maintenance.sh, local-postgres.sh, db-utils.sh) consistently use 4-space indentation. Update the indentation to use 4 spaces to match the established codebase convention.

Suggested change
echo " JEAN_ROOT_PATH is not set — skipping config file copy."
else
copy_if_exists() {
local src="$JEAN_ROOT_PATH/$1"
if [ -f "$src" ]; then
mkdir -p "$(dirname "$1")"
cp "$src" "$1"
echo " copied $1"
else
echo " skipped $1 (not found in root)"
fi
}
echo "Copying local config files..."
copy_if_exists "server/application-server/src/main/resources/application-local.yml"
copy_if_exists "server/application-server/src/test/resources/application-live-local.yml"
copy_if_exists "server/application-server/.env"
copy_if_exists "server/intelligence-service/.env"
copy_if_exists "server/webhook-ingest/.env"
copy_if_exists "docker/.env"
copy_if_exists ".claude/settings.local.json"
echo " JEAN_ROOT_PATH is not set — skipping config file copy."
else
copy_if_exists() {
local src="$JEAN_ROOT_PATH/$1"
if [ -f "$src" ]; then
mkdir -p "$(dirname "$1")"
cp "$src" "$1"
echo " copied $1"
else
echo " skipped $1 (not found in root)"
fi
}
echo "Copying local config files..."
copy_if_exists "server/application-server/src/main/resources/application-local.yml"
copy_if_exists "server/application-server/src/test/resources/application-live-local.yml"
copy_if_exists "server/application-server/.env"
copy_if_exists "server/intelligence-service/.env"
copy_if_exists "server/webhook-ingest/.env"
copy_if_exists "docker/.env"
copy_if_exists ".claude/settings.local.json"

Copilot uses AI. Check for mistakes.
Comment thread scripts/jean-setup.sh
Comment on lines +9 to +14
if [ -z "${JEAN_ROOT_PATH:-}" ]; then
echo " JEAN_ROOT_PATH is not set — skipping config file copy."
else
copy_if_exists() {
local src="$JEAN_ROOT_PATH/$1"
if [ -f "$src" ]; then
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script uses single brackets [ ] for test conditions (line 9, 14), but all other bash scripts in the repository consistently use double brackets [[ ]] which is the bash-specific, more feature-rich test operator. Update to use [[ ]] for consistency with scripts/codex-setup.sh, scripts/codex-maintenance.sh, and scripts/local-postgres.sh.

Suggested change
if [ -z "${JEAN_ROOT_PATH:-}" ]; then
echo " JEAN_ROOT_PATH is not set — skipping config file copy."
else
copy_if_exists() {
local src="$JEAN_ROOT_PATH/$1"
if [ -f "$src" ]; then
if [[ -z "${JEAN_ROOT_PATH:-}" ]]; then
echo " JEAN_ROOT_PATH is not set — skipping config file copy."
else
copy_if_exists() {
local src="$JEAN_ROOT_PATH/$1"
if [[ -f "$src" ]]; then

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
scripts/jean-setup.sh (2)

12-21: Consider moving copy_if_exists to the top level.

Defining a function inside an else block is unusual. While Bash scopes functions globally regardless of where they're defined, placing the function at the script's top level improves readability and makes the structure more conventional.

♻️ Proposed refactor
 #!/usr/bin/env bash
 set -euo pipefail

 echo "Setting up Jean worktree..."

+copy_if_exists() {
+  local src="${JEAN_ROOT_PATH}/$1"
+  if [ -f "$src" ]; then
+    mkdir -p "$(dirname "$1")"
+    cp "$src" "$1"
+    echo "  copied $1"
+  else
+    echo "  skipped $1 (not found in root)"
+  fi
+}
+
 # JEAN_ROOT_PATH is set by Jean to the main repo checkout.
 # We copy local config files from there into this worktree so each
 # worktree can be modified independently.
 if [ -z "${JEAN_ROOT_PATH:-}" ]; then
   echo "  JEAN_ROOT_PATH is not set — skipping config file copy."
 else
-  copy_if_exists() {
-    local src="$JEAN_ROOT_PATH/$1"
-    if [ -f "$src" ]; then
-      mkdir -p "$(dirname "$1")"
-      cp "$src" "$1"
-      echo "  copied $1"
-    else
-      echo "  skipped $1 (not found in root)"
-    fi
-  }
-
   echo "Copying local config files..."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/jean-setup.sh` around lines 12 - 21, Move the copy_if_exists function
out of the else block and define it at the script's top level so it is
immediately visible and conventional; keep the same signature and behavior
(local src="$JEAN_ROOT_PATH/$1", mkdir -p, cp, echo messages) and ensure
JEAN_ROOT_PATH is already set before any calls to copy_if_exists are made; after
relocating, update no other logic — just call copy_if_exists(...) where it was
previously invoked.

12-21: Move copy_if_exists to the top level, outside the else block.

Defining a function inside a conditional branch is valid Bash but non-idiomatic. The function would be globally scoped anyway once that else branch executes — lifting it to the script's top level makes the intent clearer and the structure easier to follow.

♻️ Proposed refactor
 #!/usr/bin/env bash
 set -euo pipefail
 
 echo "Setting up Jean worktree..."
 
+copy_if_exists() {
+  local src="${JEAN_ROOT_PATH:-}/$1"
+  if [ -f "$src" ]; then
+    mkdir -p "$(dirname "$1")"
+    cp "$src" "$1"
+    echo "  copied $1"
+  else
+    echo "  skipped $1 (not found in root)"
+  fi
+}
+
 # JEAN_ROOT_PATH is set by Jean to the main repo checkout.
 # We copy local config files from there into this worktree so each
 # worktree can be modified independently.
 if [ -z "${JEAN_ROOT_PATH:-}" ]; then
   echo "  JEAN_ROOT_PATH is not set — skipping config file copy."
 else
-  copy_if_exists() {
-    local src="$JEAN_ROOT_PATH/$1"
-    if [ -f "$src" ]; then
-      mkdir -p "$(dirname "$1")"
-      cp "$src" "$1"
-      echo "  copied $1"
-    else
-      echo "  skipped $1 (not found in root)"
-    fi
-  }
-
   echo "Copying local config files..."
   copy_if_exists "server/application-server/src/main/resources/application-local.yml"

Note: with the function at the top level, src uses ${JEAN_ROOT_PATH:-} as a safe default; the [ -f "$src" ] check already handles the empty-prefix case gracefully (the path won't resolve to a real file).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/jean-setup.sh` around lines 12 - 21, Move the copy_if_exists function
out of the conditional branch and define it at the top level of the script so it
isn’t declared inside the else block; update its src calculation to use a safe
default like "${JEAN_ROOT_PATH:-}/$1" and keep the existing checks (the [ -f
"$src" ] test and mkdir/cp logic) intact, referencing the copy_if_exists
function and JEAN_ROOT_PATH variable so callers later in the script can reliably
invoke copy_if_exists regardless of which branch ran.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/jean-setup.sh`:
- Around line 33-34: Guard the npm install step so the script doesn't abort
under set -e when npm or package.json is missing: before the existing "npm
install" invocation check for the presence of package.json and that npm is on
PATH (same pattern used for config propagation), and only run the "npm install"
command when both checks pass; otherwise log a clear skip/warning and continue.
Ensure you update the block that currently contains the echo "Installing npm
dependencies..." / npm install to use these checks and a non-failing fallback so
partial setup isn't discarded.
- Line 30: Add a short comment above the copy_if_exists
".claude/settings.local.json" call explaining that this copies a developer-local
Claude settings file (non-committed, may contain credentials) for convenience;
then update the repository .gitignore to include either
".claude/settings.local.json" or the entire ".claude/" directory to prevent
accidental commits of credentials. Ensure the comment references copy_if_exists
and the filename ".claude/settings.local.json" so future readers understand
intent, and commit the .gitignore change alongside the script update.
- Line 30: Add an inline comment immediately above the call to copy_if_exists
for ".claude/settings.local.json" that explains this file may contain sensitive
credentials, notes that the repo’s existing "*.local" .gitignore pattern does
not match ".json" filenames (so this specific filename must be ignored elsewhere
or handled securely), states the assumption under which it's safe to copy
silently (e.g., that developers have configured a repo-level or global ignore or
secrets manager), and instructs maintainers to ensure .gitignore or other
controls explicitly exclude this file if that assumption is not met; reference
the copy_if_exists call and the literal ".claude/settings.local.json" when
adding the comment.

---

Nitpick comments:
In `@scripts/jean-setup.sh`:
- Around line 12-21: Move the copy_if_exists function out of the else block and
define it at the script's top level so it is immediately visible and
conventional; keep the same signature and behavior (local
src="$JEAN_ROOT_PATH/$1", mkdir -p, cp, echo messages) and ensure JEAN_ROOT_PATH
is already set before any calls to copy_if_exists are made; after relocating,
update no other logic — just call copy_if_exists(...) where it was previously
invoked.
- Around line 12-21: Move the copy_if_exists function out of the conditional
branch and define it at the top level of the script so it isn’t declared inside
the else block; update its src calculation to use a safe default like
"${JEAN_ROOT_PATH:-}/$1" and keep the existing checks (the [ -f "$src" ] test
and mkdir/cp logic) intact, referencing the copy_if_exists function and
JEAN_ROOT_PATH variable so callers later in the script can reliably invoke
copy_if_exists regardless of which branch ran.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad65cb0 and 064b0f4.

📒 Files selected for processing (2)
  • jean.json
  • scripts/jean-setup.sh

Comment thread scripts/jean-setup.sh
copy_if_exists "server/intelligence-service/.env"
copy_if_exists "server/webhook-ingest/.env"
copy_if_exists "docker/.env"
copy_if_exists ".claude/settings.local.json"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether .claude/settings.local.json is covered by any .gitignore in the repo
rg -n "settings\.local\.json" --glob ".gitignore" --glob "**/.gitignore"

Repository: ls1intum/Hephaestus

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Also check for broader .claude directory patterns in .gitignore
rg -n "\.claude" --glob ".gitignore" --glob "**/.gitignore"

Repository: ls1intum/Hephaestus

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Examine the context around line 30 in scripts/jean-setup.sh
cat -n scripts/jean-setup.sh | sed -n '20,40p'

Repository: ls1intum/Hephaestus

Length of output: 729


🏁 Script executed:

#!/bin/bash
# Check if there's a .claude directory and settings.local.json file in the repo
find . -type d -name ".claude" 2>/dev/null
find . -type f -name "settings.local.json" 2>/dev/null

Repository: ls1intum/Hephaestus

Length of output: 72


Add documentation and ensure .claude/settings.local.json is in .gitignore.

This file is being copied to every new worktree without explanation or protection. .claude/settings.local.json is not currently covered by any .gitignore rule, creating a risk that developers could accidentally commit credentials if the file is staged in a worktree commit. Add a comment above line 30 explaining the intent, and add .claude/settings.local.json (or .claude/) to the project's .gitignore.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/jean-setup.sh` at line 30, Add a short comment above the
copy_if_exists ".claude/settings.local.json" call explaining that this copies a
developer-local Claude settings file (non-committed, may contain credentials)
for convenience; then update the repository .gitignore to include either
".claude/settings.local.json" or the entire ".claude/" directory to prevent
accidental commits of credentials. Ensure the comment references copy_if_exists
and the filename ".claude/settings.local.json" so future readers understand
intent, and commit the .gitignore change alongside the script update.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Check if .claude/settings.local.json is covered by any .gitignore
rg -n "settings\.local\.json" --glob "*.gitignore" --glob ".gitignore"

Repository: ls1intum/Hephaestus

Length of output: 45


🏁 Script executed:

# Check for .gitignore files in the repo
fd -H ".gitignore" -x cat -n {}

Repository: ls1intum/Hephaestus

Length of output: 9525


🏁 Script executed:

# Examine the jean-setup.sh script around line 30
cat -n scripts/jean-setup.sh | head -50

Repository: ls1intum/Hephaestus

Length of output: 1431


Add an inline comment explaining the security implications of copying .claude/settings.local.json.

The file .claude/settings.local.json is not explicitly covered by any .gitignore pattern in the repository (the *.local pattern does not match filenames ending in .json). Since this file can contain sensitive credentials, it should have an inline comment explaining why it's safe to copy silently into worktrees, and the assumption that .gitignore coverage is in place elsewhere should be documented.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/jean-setup.sh` at line 30, Add an inline comment immediately above
the call to copy_if_exists for ".claude/settings.local.json" that explains this
file may contain sensitive credentials, notes that the repo’s existing "*.local"
.gitignore pattern does not match ".json" filenames (so this specific filename
must be ignored elsewhere or handled securely), states the assumption under
which it's safe to copy silently (e.g., that developers have configured a
repo-level or global ignore or secrets manager), and instructs maintainers to
ensure .gitignore or other controls explicitly exclude this file if that
assumption is not met; reference the copy_if_exists call and the literal
".claude/settings.local.json" when adding the comment.

Comment thread scripts/jean-setup.sh
Comment on lines +33 to +34
echo "Installing npm dependencies..."
npm install
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard npm install against a missing package.json.

With set -e, a failed npm install (e.g., no package.json at the worktree root, or npm not on PATH) aborts the entire setup ungracefully. The rest of the script — file copying, config propagation — will have succeeded, so a hard failure here discards useful partial work. At minimum, skip gracefully when there's no manifest; alternatively mirror the same pattern used for config files.

🛡️ Proposed fix
-echo "Installing npm dependencies..."
-npm install
+if [ -f "package.json" ]; then
+  echo "Installing npm dependencies..."
+  npm install
+else
+  echo "  skipped npm install (no package.json found)"
+fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
echo "Installing npm dependencies..."
npm install
if [ -f "package.json" ]; then
echo "Installing npm dependencies..."
npm install
else
echo " skipped npm install (no package.json found)"
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/jean-setup.sh` around lines 33 - 34, Guard the npm install step so
the script doesn't abort under set -e when npm or package.json is missing:
before the existing "npm install" invocation check for the presence of
package.json and that npm is on PATH (same pattern used for config propagation),
and only run the "npm install" command when both checks pass; otherwise log a
clear skip/warning and continue. Ensure you update the block that currently
contains the echo "Installing npm dependencies..." / npm install to use these
checks and a non-failing fallback so partial setup isn't discarded.

@FelixTJDietrich FelixTJDietrich merged commit 06003c1 into main Feb 25, 2026
16 checks passed
@FelixTJDietrich FelixTJDietrich deleted the jean-worktree-setup branch February 25, 2026 22:16
@github-actions
Copy link
Copy Markdown
Contributor

📚 Documentation Preview

Preview has been removed (PR closed)

@FelixTJDietrich
Copy link
Copy Markdown
Collaborator Author

🎉 This PR is included in version 0.20.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@FelixTJDietrich FelixTJDietrich added the released Included in a published release label Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or enhancement released Included in a published release size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants