From e97597de9cf85eb1fec6e8ea8928b16f2bd78d74 Mon Sep 17 00:00:00 2001 From: Oleksii Pylypchuk Date: Thu, 16 Apr 2026 21:48:16 +0300 Subject: [PATCH 1/3] fix(setup): remove --user flag - Qdrant container runs as root by default Qdrant official image runs as root (UID 0) by default. The --user 1000:1000 flag was causing permission issues with the named volume storage because: - The container's /qdrant/storage is owned by root - Forcing UID 1000 denied write access to storage directory Running without --user allows the container to use its default root user, which has proper permissions for the named volume. --- setup.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.sh b/setup.sh index bad76a2..4ac453c 100755 --- a/setup.sh +++ b/setup.sh @@ -83,7 +83,6 @@ else else DOCKER_ARGS=(-d --name openexp-qdrant --restart unless-stopped -p 127.0.0.1:6333:6333 - --user 1000:1000 -v openexp_qdrant_data:/qdrant/storage) if [ -n "${QDRANT_API_KEY:-}" ]; then DOCKER_ARGS+=(-e "QDRANT__SERVICE__API_KEY=$QDRANT_API_KEY") From f26efe5bebe1c08cb2e86bb067d5b68528158ec6 Mon Sep 17 00:00:00 2001 From: Oleksii Pylypchuk Date: Thu, 16 Apr 2026 21:51:08 +0300 Subject: [PATCH 2/3] fix(setup): handle collection check failures gracefully Add fallback `|| echo "not_found"` to collection existence check. Without this, the script would silently exit with code 22 when curl fails (e.g., 404 Not Found) or jq encounters null/invalid input. The || fallback ensures COLLECTION_EXISTS is always set to a valid string, allowing the conditional logic to proceed correctly. --- setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index 4ac453c..56c5541 100755 --- a/setup.sh +++ b/setup.sh @@ -112,7 +112,7 @@ echo "" # --- Step 4: Create collection --- echo "Step 4/7: Creating Qdrant collection..." -COLLECTION_EXISTS=$(curl -sf "http://localhost:6333/collections/$COLLECTION" 2>/dev/null | jq -r '.status // "not_found"') +COLLECTION_EXISTS=$(curl -sf "http://localhost:6333/collections/$COLLECTION" 2>/dev/null | jq -r '.status // "not_found"' || echo "not_found") if [ "$COLLECTION_EXISTS" = "ok" ]; then echo " ✅ Collection '$COLLECTION' already exists" else From 7300ee6be0209f2371c4c63cb411559a706bb35b Mon Sep 17 00:00:00 2001 From: Oleksii Pylypchuk Date: Thu, 16 Apr 2026 21:53:52 +0300 Subject: [PATCH 3/3] fix(setup): correct jq array paths and null handling for hooks Fix two jq-related errors during Claude Code hooks registration: 1. Null containment error: Change .command | contains() to (.command // "") | contains() to handle hook items without command field. 2. Array iteration error: Change any(.[]; ...) to any(.hooks.SessionStart[]; ...) and use += instead of . + [...] to properly append to hook arrays. Fixes: 'null cannot have containment checked' and 'object and array cannot be added' errors. --- setup.sh | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/setup.sh b/setup.sh index 56c5541..a680d96 100755 --- a/setup.sh +++ b/setup.sh @@ -83,7 +83,8 @@ else else DOCKER_ARGS=(-d --name openexp-qdrant --restart unless-stopped -p 127.0.0.1:6333:6333 - -v openexp_qdrant_data:/qdrant/storage) + -v openexp_qdrant_data:/qdrant/storage + --user 0:0) if [ -n "${QDRANT_API_KEY:-}" ]; then DOCKER_ARGS+=(-e "QDRANT__SERVICE__API_KEY=$QDRANT_API_KEY") fi @@ -164,26 +165,26 @@ HOOKS_DIR="$OPENEXP_DIR/openexp/hooks" SETTINGS=$(echo "$SETTINGS" | jq --arg hooks_dir "$HOOKS_DIR" ' # SessionStart hook .hooks.SessionStart = (.hooks.SessionStart // []) | - if any(.[]; .command | contains("openexp")) then . else - . + [{"type": "command", "command": ($hooks_dir + "/session-start.sh")}] + if any(.hooks.SessionStart[]; (.command // "") | contains("openexp")) then . else + .hooks.SessionStart += [{"type": "command", "command": ($hooks_dir + "/session-start.sh")}] end | # UserPromptSubmit hook .hooks.UserPromptSubmit = (.hooks.UserPromptSubmit // []) | - if any(.[]; .command | contains("openexp")) then . else - . + [{"type": "command", "command": ($hooks_dir + "/user-prompt-recall.sh")}] + if any(.hooks.UserPromptSubmit[]; (.command // "") | contains("openexp")) then . else + .hooks.UserPromptSubmit += [{"type": "command", "command": ($hooks_dir + "/user-prompt-recall.sh")}] end | # PostToolUse hook .hooks.PostToolUse = (.hooks.PostToolUse // []) | - if any(.[]; .command | contains("openexp")) then . else - . + [{"type": "command", "command": ($hooks_dir + "/post-tool-use.sh")}] + if any(.hooks.PostToolUse[]; (.command // "") | contains("openexp")) then . else + .hooks.PostToolUse += [{"type": "command", "command": ($hooks_dir + "/post-tool-use.sh")}] end | # SessionEnd hook .hooks.SessionEnd = (.hooks.SessionEnd // []) | - if any(.[]; .command | contains("openexp")) then . else - . + [{"type": "command", "command": ($hooks_dir + "/session-end.sh"), "timeout": 30}] + if any(.hooks.SessionEnd[]; (.command // "") | contains("openexp")) then . else + .hooks.SessionEnd += [{"type": "command", "command": ($hooks_dir + "/session-end.sh"), "timeout": 30}] end ')