Skip to content

Fix macOS extended attributes error in Docker container operations #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 25 additions & 48 deletions src/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -502,18 +502,6 @@ exec claude --dangerously-skip-permissions' > /start-claude.sh && \\
const { execSync } = require("child_process");
const fs = require("fs");

// Helper function to get tar flags safely
const getTarFlags = () => {
try {
// Test if --no-xattrs is supported by checking tar help
execSync("tar --help 2>&1 | grep -q no-xattrs", { stdio: "pipe" });
return "--no-xattrs";
} catch {
// --no-xattrs not supported, use standard tar
return "";
}
};

try {
// Get list of git-tracked files (including uncommitted changes)
const trackedFiles = execSync("git ls-files", {
Expand Down Expand Up @@ -590,19 +578,18 @@ exec claude --dangerously-skip-permissions' > /start-claude.sh && \\
// Also copy .git directory to preserve git history
console.log(chalk.blue("• Copying git history..."));
const gitTarFile = `/tmp/claude-sandbox-git-${Date.now()}.tar`;
// Exclude macOS resource fork files and .DS_Store when creating git archive
// Also strip extended attributes to prevent macOS xattr issues in Docker
const tarFlags = getTarFlags();
// On macOS, also exclude extended attributes that cause Docker issues
const additionalFlags = (process.platform as string) === "darwin" ? "--no-xattrs --no-fflags" : "";
const combinedFlags = `${tarFlags} ${additionalFlags}`.trim();
execSync(
`tar -cf "${gitTarFile}" --exclude="._*" --exclude=".DS_Store" ${combinedFlags} .git`,
{
cwd: workDir,
stdio: "pipe",
},
);

// On macOS, use --no-xattrs and --no-fflags to prevent extended attribute issues
let tarCommand = `tar -cf "${gitTarFile}" --exclude="._*" --exclude=".DS_Store"`;
if (process.platform === "darwin") {
tarCommand += " --no-xattrs --no-fflags";
}
tarCommand += " .git";

execSync(tarCommand, {
cwd: workDir,
stdio: "pipe",
});

try {
const gitStream = fs.createReadStream(gitTarFile);
Expand Down Expand Up @@ -636,18 +623,6 @@ exec claude --dangerously-skip-permissions' > /start-claude.sh && \\
const path = require("path");
const { execSync } = require("child_process");

// Helper function to get tar flags safely
const getTarFlags = () => {
try {
// Test if --no-xattrs is supported by checking tar help
execSync("tar --help 2>&1 | grep -q no-xattrs", { stdio: "pipe" });
return "--no-xattrs";
} catch {
// --no-xattrs not supported, use standard tar
return "";
}
};

try {
// First, try to get credentials from macOS Keychain if on Mac
if (process.platform === "darwin") {
Expand Down Expand Up @@ -779,24 +754,26 @@ exec claude --dangerously-skip-permissions' > /start-claude.sh && \\

// Copy .claude directory if it exists (but skip if we already copied from Keychain)
const claudeDir = path.join(os.homedir(), ".claude");
const skipClaudeDir = process.platform === "darwin";
if (
fs.existsSync(claudeDir) &&
fs.statSync(claudeDir).isDirectory() &&
process.platform !== "darwin"
!skipClaudeDir
) {
console.log(chalk.blue("• Copying .claude directory..."));

const tarFile = `/tmp/claude-dir-${Date.now()}.tar`;
const tarFlags = getTarFlags();
// On macOS, also exclude extended attributes that cause Docker issues
const additionalFlags = (process.platform as string) === "darwin" ? "--no-xattrs --no-fflags" : "";
const combinedFlags = `${tarFlags} ${additionalFlags}`.trim();
execSync(
`tar -cf "${tarFile}" ${combinedFlags} -C "${os.homedir()}" .claude`,
{
stdio: "pipe",
},
);

// On macOS, use --no-xattrs and --no-fflags to prevent extended attribute issues
let tarCommand = `tar -cf "${tarFile}"`;
if (process.platform === "darwin") {
tarCommand += " --no-xattrs --no-fflags";
}
tarCommand += ` -C "${os.homedir()}" .claude`;

execSync(tarCommand, {
stdio: "pipe",
});

const stream = fs.createReadStream(tarFile);
await container.putArchive(stream, {
Expand Down