Skip to content

Conversation

@webdevcody
Copy link
Collaborator

@webdevcody webdevcody commented Jan 5, 2026

…Docker setup

  • Introduced a new markdown file summarizing various attempts to install the Cursor CLI in Docker, detailing approaches, results, and key learnings.
  • Updated Dockerfile to ensure proper installation of Cursor CLI for the non-root user, including necessary PATH adjustments for interactive shells.
  • Enhanced entrypoint script to manage OAuth tokens for both Claude and Cursor CLIs, ensuring correct permissions and directory setups.
  • Added scripts for extracting OAuth tokens from macOS Keychain and Linux JSON files for seamless integration with Docker.
  • Updated docker-compose files to support persistent storage for CLI configurations and authentication tokens.

These changes improve the development workflow and provide clear guidance on CLI installation and authentication processes.

Summary by CodeRabbit

  • New Features

    • Claude and Cursor CLI support with improved auth detection, live CLI/auth status refresh, and automated Docker rebuild detection when sources change
  • Documentation

    • Expanded multi-platform CLI authentication guidance, macOS token extraction scripts, and troubleshooting updates
  • Chores

    • Docker runtime updated to persist CLI credentials, add env vars, a non-root user, and PATH/installation persistence for local CLIs
  • Tools

    • Added host token extraction utilities for Claude and Cursor

✏️ Tip: You can customize this high-level summary in your review settings.

…Docker setup

- Introduced a new markdown file summarizing various attempts to install the Cursor CLI in Docker, detailing approaches, results, and key learnings.
- Updated Dockerfile to ensure proper installation of Cursor CLI for the non-root user, including necessary PATH adjustments for interactive shells.
- Enhanced entrypoint script to manage OAuth tokens for both Claude and Cursor CLIs, ensuring correct permissions and directory setups.
- Added scripts for extracting OAuth tokens from macOS Keychain and Linux JSON files for seamless integration with Docker.
- Updated docker-compose files to support persistent storage for CLI configurations and authentication tokens.

These changes improve the development workflow and provide clear guidance on CLI installation and authentication processes.
@coderabbitai
Copy link

coderabbitai bot commented Jan 5, 2026

Warning

Rate limit exceeded

@webdevcody has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 8 minutes and 47 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between bd51761 and 84b582f.

📒 Files selected for processing (3)
  • dev.mjs
  • scripts/launcher-utils.mjs
  • start.mjs
📝 Walkthrough

Walkthrough

Migrates container base to Debian-slim, installs Claude/Cursor CLIs, creates a non-root automaker user with persisted CLI config and env-driven credential injection, adds host token extraction scripts, updates entrypoint to write credentials, and adds logic to detect and conditionally rebuild Docker images.

Changes

Cohort / File(s) Summary
Dockerfiles & Compose
Dockerfile, docker-compose.yml, docker-compose.override.yml.example
Switch base to node:22-slim; replace apk → apt-get flows; add CLAUDE_OAUTH_CREDENTIALS and CURSOR_AUTH_TOKEN env vars; mount automaker-cursor-config; add commented credential mount/docs.
Server image setup & user
Dockerfile (SERVER stage), docker-entrypoint.sh
Add non-root automaker user, create/home dirs, install gh/claude/cursor CLIs (apt/npm), persist PATH/profile entries, create .local & .cursor, set ownership/permissions, replace su-exec with gosu.
Credential extraction scripts
scripts/get-claude-token.sh, scripts/get-cursor-token.sh
New host scripts to extract Claude (macOS Keychain) and Cursor (macOS Keychain or Linux config) tokens; platform checks, explicit errors, stdout JSON/token output.
Entrypoint credential handling
docker-entrypoint.sh
Ensure directories, write CLAUDE_OAUTH_CREDENTIALS → /home/automaker/.claude/.credentials.json (600) and CURSOR_AUTH_TOKEN → /home/automaker/.config/cursor/auth.json (600), set ownership to automaker.
Docker rebuild detection
dev.mjs, start.mjs
New shouldRebuildDockerImages comparing mtimes of Dockerfile/package.json to image creation times; sanitize project name; conditionally pass --build to docker compose up and log decisions.
UI: CLI auth/status
apps/ui/src/components/views/settings-view/hooks/use-cli-status.ts, apps/ui/src/components/views/setup-view/hooks/use-cli-status.ts
Add refreshAuthStatus to fetch/map Claude auth state and unify refresh flows; move/create module-level logger to avoid re-creation on renders; improved error logging.
Platform credential detection
libs/platform/src/system-paths.ts
Broaden Claude credential parsing to support claudeAiOauth.accessToken, legacy oauth_token / access_token, and api_key; compute hasOAuthToken accordingly.
Docs
docs/docker-isolation.md
Add multi-platform CLI auth guidance, macOS token extraction examples, env/mount options, and Cursor auth troubleshooting updates.

Sequence Diagram

sequenceDiagram
    autonumber
    actor Developer
    participant Host as Host OS
    participant Scripts as Token Scripts
    participant Docker as Docker Engine
    participant Image as Built Image
    participant Container as Server Container
    participant Entrypoint as docker-entrypoint.sh
    participant CLIs as Claude & Cursor CLIs
    participant UI as Web UI

    Developer->>Scripts: run get-claude-token / get-cursor-token
    Scripts->>Host: query Keychain or config files
    Host-->>Scripts: return credentials/token
    Scripts->>Developer: output JSON/token

    Developer->>Docker: docker-compose up (env or mounts)
    Docker->>Image: start / build (conditional)
    Image->>Container: create & start
    Container->>Entrypoint: execute entrypoint
    Entrypoint->>Entrypoint: ensure dirs & perms for automaker
    alt CLAUDE_OAUTH_CREDENTIALS present
        Entrypoint->>Container: write .claude/.credentials.json (600) owned by automaker
    end
    alt CURSOR_AUTH_TOKEN present
        Entrypoint->>Container: write .config/cursor/auth.json (600) owned by automaker
    end
    Entrypoint->>CLIs: initialize CLIs with persisted creds
    CLIs-->>Container: CLIs ready
    UI->>Container: api.setup.getClaudeStatus
    Container-->>UI: return mapped Claude auth status
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

Enhancement, Testers-Requested

Poem

🐰 I hopped from Alpine to Debian-slim,

tucked tokens safe beneath my whim,
Claude and Cursor snug in a non-root den,
perms locked tight, configs owned again,
and now builds wake only when sources trim.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title is truncated ('add Cursor CLI installation attempts documentation and enhance …') and does not fully convey the main objective. Provide the complete, untruncated pull request title so it can be properly evaluated for clarity and relevance to the changeset.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @webdevcody, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refines the Docker development experience by enhancing the integration and authentication of both Cursor and Claude CLIs. It introduces a more robust Docker setup, including a base image change and improved dependency management. Key changes involve streamlining how OAuth tokens are handled, allowing them to be extracted from host systems (macOS Keychain, Linux JSON) and securely passed into the Docker container, ensuring persistent authentication. Furthermore, the PR adds intelligent logic to automatically rebuild Docker images when source files change and updates the UI to reflect Claude CLI authentication status, all contributing to a smoother and more efficient development workflow within the Dockerized environment.

Highlights

  • Enhanced Docker Setup: Significant improvements to the Docker environment, including switching to node:22-slim, using apt-get, and integrating gosu for better user management.
  • Cursor CLI Integration: Added full support for installing and managing the Cursor CLI within the Docker container for the non-root automaker user, including PATH adjustments.
  • Streamlined CLI Authentication: Implemented robust mechanisms for passing Claude and Cursor CLI OAuth tokens from the host machine (macOS Keychain, Linux JSON) into the Docker container via environment variables and an enhanced entrypoint script.
  • Persistent CLI Configurations: Configured Docker volumes in docker-compose.yml to ensure Claude and Cursor CLI authentication and configurations persist across container restarts.
  • Automated Docker Image Rebuilds: Introduced logic in dev.mjs and start.mjs to automatically detect changes in Dockerfile or package.json and trigger Docker image rebuilds when starting containers.
  • Improved Documentation: Added comprehensive documentation in docs/docker-isolation.md detailing CLI authentication methods for both macOS and Linux/Windows users.
  • UI for Claude Auth Status: The UI now refreshes Claude CLI authentication status, supporting various credential formats.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request significantly enhances the Docker setup by adding support for Cursor CLI installation and authentication. It introduces scripts for extracting OAuth tokens, updates the Dockerfile for proper installation, and enhances the entrypoint script to manage tokens. The changes improve the development workflow and provide clearer documentation. My review includes suggestions to reduce Docker image layers, refactor duplicated code in a React hook and build scripts, simplify shell script logic, and improve documentation clarity and consistency.

Comment on lines +101 to +106
# Add to automaker's .bashrc for bash interactive shells
RUN echo 'export PATH="/home/automaker/.local/bin:$PATH"' >> /home/automaker/.bashrc && \
chown automaker:automaker /home/automaker/.bashrc

# Also add to root's .bashrc since docker exec defaults to root
RUN echo 'export PATH="/home/automaker/.local/bin:$PATH"' >> /root/.bashrc
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

To reduce Docker image layers and group related commands, you can combine the RUN instructions for updating .bashrc files into a single instruction. This makes the Dockerfile more efficient and easier to maintain.

# Add to automaker's and root's .bashrc for bash interactive shells
RUN echo 'export PATH="/home/automaker/.local/bin:$PATH"' >> /home/automaker/.bashrc && \
    chown automaker:automaker /home/automaker/.bashrc && \
    echo 'export PATH="/home/automaker/.local/bin:$PATH"' >> /root/.bashrc

Comment on lines 107 to 146
// Also refresh auth status
if (api?.setup?.getClaudeStatus) {
try {
const result = await api.setup.getClaudeStatus();
if (result.success && result.auth) {
const auth = result.auth as typeof result.auth & {
oauthTokenValid?: boolean;
apiKeyValid?: boolean;
};
const validMethods = [
'oauth_token_env',
'oauth_token',
'api_key',
'api_key_env',
'credentials_file',
'cli_authenticated',
'none',
] as const;
type AuthMethod = (typeof validMethods)[number];
const method: AuthMethod = validMethods.includes(auth.method as AuthMethod)
? (auth.method as AuthMethod)
: auth.authenticated
? 'api_key'
: 'none';
const authStatus = {
authenticated: auth.authenticated,
method,
hasCredentialsFile: auth.hasCredentialsFile ?? false,
oauthTokenValid:
auth.oauthTokenValid || auth.hasStoredOAuthToken || auth.hasEnvOAuthToken,
apiKeyValid: auth.apiKeyValid || auth.hasStoredApiKey || auth.hasEnvApiKey,
hasEnvOAuthToken: auth.hasEnvOAuthToken,
hasEnvApiKey: auth.hasEnvApiKey,
};
setClaudeAuthStatus(authStatus);
}
} catch (error) {
logger.error('Failed to refresh Claude auth status:', error);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The logic to refresh the Claude auth status inside handleRefreshClaudeCli is a duplicate of the logic inside the useEffect hook (lines 51-92). To improve maintainability and avoid code duplication, this logic should be extracted into a separate useCallback function. This new function can then be called from both useEffect and handleRefreshClaudeCli.

dev.mjs Outdated
Comment on lines 64 to 90
let serverImageName, uiImageName;
try {
const composeConfig = execSync('docker compose config --format json', {
encoding: 'utf-8',
cwd: __dirname,
});
const config = JSON.parse(composeConfig);

// Docker Compose generates image names as <project>_<service>
// Get project name from config or default to directory name
const projectName =
config.name ||
path
.basename(__dirname)
.toLowerCase()
.replace(/[^a-z0-9]/g, '');
serverImageName = `${projectName}_server`;
uiImageName = `${projectName}_ui`;
} catch (error) {
// Fallback to default naming convention
const projectName = path
.basename(__dirname)
.toLowerCase()
.replace(/[^a-z0-9]/g, '');
serverImageName = `${projectName}_server`;
uiImageName = `${projectName}_ui`;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There's code duplication in how projectName, serverImageName, and uiImageName are determined. The logic for generating these names is repeated in both the try and catch blocks. You can refactor this to avoid repetition and improve readability.

    let serverImageName, uiImageName;
    let projectName;
    try {
      const composeConfig = execSync('docker compose config --format json', {
        encoding: 'utf-8',
        cwd: __dirname,
      });
      const config = JSON.parse(composeConfig);
      projectName = config.name;
    } catch (error) {
      // Fallback to default naming convention below
    }

    // Use project name from config or default to directory name
    const finalProjectName =
      projectName ||
      path
        .basename(__dirname)
        .toLowerCase()
        .replace(/[^a-z0-9]/g, '');

    serverImageName = `${finalProjectName}_server`;
    uiImageName = `${finalProjectName}_ui`;

Comment on lines 20 to 32
# Fix permissions on Cursor CLI config directory if it exists
# This handles the case where a volume is mounted and owned by root
if [ -d "/home/automaker/.claude" ]; then
chown -R automaker:automaker /home/automaker/.claude
chmod -R 755 /home/automaker/.claude
if [ -d "/home/automaker/.cursor" ]; then
chown -R automaker:automaker /home/automaker/.cursor
chmod -R 700 /home/automaker/.cursor
fi

# Ensure the directory exists with correct permissions if volume is empty
if [ ! -d "/home/automaker/.claude" ]; then
mkdir -p /home/automaker/.claude
chown automaker:automaker /home/automaker/.claude
chmod 755 /home/automaker/.claude
if [ ! -d "/home/automaker/.cursor" ]; then
mkdir -p /home/automaker/.cursor
chown automaker:automaker /home/automaker/.cursor
chmod 700 /home/automaker/.cursor
fi
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This block of code for setting up the .cursor directory is a bit redundant. It checks for the directory's existence, sets permissions, and then checks for its non-existence to create it and set permissions again. This can be simplified into a single, more logical block that handles both cases (mounted volume or new directory).

Suggested change
# Fix permissions on Cursor CLI config directory if it exists
# This handles the case where a volume is mounted and owned by root
if [ -d "/home/automaker/.claude" ]; then
chown -R automaker:automaker /home/automaker/.claude
chmod -R 755 /home/automaker/.claude
if [ -d "/home/automaker/.cursor" ]; then
chown -R automaker:automaker /home/automaker/.cursor
chmod -R 700 /home/automaker/.cursor
fi
# Ensure the directory exists with correct permissions if volume is empty
if [ ! -d "/home/automaker/.claude" ]; then
mkdir -p /home/automaker/.claude
chown automaker:automaker /home/automaker/.claude
chmod 755 /home/automaker/.claude
if [ ! -d "/home/automaker/.cursor" ]; then
mkdir -p /home/automaker/.cursor
chown automaker:automaker /home/automaker/.cursor
chmod 700 /home/automaker/.cursor
fi
# Ensure Cursor CLI config directory exists with correct permissions
if [ ! -d "/home/automaker/.cursor" ]; then
mkdir -p /home/automaker/.cursor
fi
chown -R automaker:automaker /home/automaker/.cursor
chmod -R 700 /home/automaker/.cursor

Comment on lines +103 to +110
**Option 2: Bind mount credential directories directly**

```yaml
# In docker-compose.override.yml
volumes:
- ~/.claude:/home/automaker/.claude
- ~/.config/cursor:/home/automaker/.config/cursor
```
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There appears to be an inconsistency in the documentation for mounting Cursor CLI directories. Here, you suggest mounting ~/.config/cursor, but in docker-compose.override.yml.example and other parts of this document, ~/.cursor is mentioned. Please clarify which directory should be mounted or if both are needed for different purposes (e.g., auth vs. config) to avoid confusion.

start.mjs Outdated
Comment on lines 73 to 99
let serverImageName, uiImageName;
try {
const composeConfig = execSync('docker compose config --format json', {
encoding: 'utf-8',
cwd: __dirname,
});
const config = JSON.parse(composeConfig);

// Docker Compose generates image names as <project>_<service>
// Get project name from config or default to directory name
const projectName =
config.name ||
path
.basename(__dirname)
.toLowerCase()
.replace(/[^a-z0-9]/g, '');
serverImageName = `${projectName}_server`;
uiImageName = `${projectName}_ui`;
} catch (error) {
// Fallback to default naming convention
const projectName = path
.basename(__dirname)
.toLowerCase()
.replace(/[^a-z0-9]/g, '');
serverImageName = `${projectName}_server`;
uiImageName = `${projectName}_ui`;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There's code duplication in how projectName, serverImageName, and uiImageName are determined. The logic for generating these names is repeated in both the try and catch blocks. You can refactor this to avoid repetition and improve readability.

    let serverImageName, uiImageName;
    let projectName;
    try {
      const composeConfig = execSync('docker compose config --format json', {
        encoding: 'utf-8',
        cwd: __dirname,
      });
      const config = JSON.parse(composeConfig);
      projectName = config.name;
    } catch (error) {
      // Fallback to default naming convention below
    }

    // Use project name from config or default to directory name
    const finalProjectName =
      projectName ||
      path
        .basename(__dirname)
        .toLowerCase()
        .replace(/[^a-z0-9]/g, '');

    serverImageName = `${finalProjectName}_server`;
    uiImageName = `${finalProjectName}_ui`;

Copy link

@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: 4

Fix all issues with AI Agents 🤖
In @docker-compose.override.yml.example:
- Around line 25-29: The env var name is inconsistent: the example uses
CURSOR_API_KEY while docker-compose.yml and scripts/get-cursor-token.sh use
CURSOR_AUTH_TOKEN; update the example line to use CURSOR_AUTH_TOKEN (or vice
versa everywhere) so the extraction script, docker-compose.yml and
docker-compose.override.yml.example all reference the same variable name
(CURSOR_AUTH_TOKEN) and ensure any documentation/comments mention that exact
symbol.

In @docker-entrypoint.sh:
- Around line 37-48: The script writes CURSOR_AUTH_TOKEN directly into auth.json
which can produce invalid JSON if the token contains quotes, backslashes or
newlines; update the docker-entrypoint.sh logic that sets CURSOR_CONFIG_DIR and
writes auth.json to first escape the token (e.g., store an ESCAPED_TOKEN derived
from CURSOR_AUTH_TOKEN by escaping " and \ and/or stripping newlines) and then
write the JSON using the escaped value for "accessToken", or alternatively
validate that CURSOR_AUTH_TOKEN matches a safe charset (alphanumeric, -, _) and
fail early; ensure the chmod/chown steps remain unchanged and reference
CURSOR_AUTH_TOKEN, CURSOR_CONFIG_DIR and the auth.json write block.

In @Dockerfile:
- Around line 85-94: Avoid the curl|bash pipeline: instead fetch the installer
artifact first, verify its authenticity (checksum or signature) and only then
execute it as the automaker user; update the Dockerfile section that currently
uses "USER automaker"/"ENV HOME=/home/automaker" and the RUN that pipes curl to
bash to download the installer to a temporary file, validate a pinned version or
checksum/signature, then run that local script as automaker, and finally check
installation with "which cursor-agent" and "cursor-agent --version"; if no
signed artifact or pinned URL exists, document the risk and pin the installer
version or source before executing.

In @start.mjs:
- Around line 106-115: config.name is used directly to build serverImageName and
uiImageName and passed into execSync, enabling command injection; sanitize
config.name the same way as the fallback path before constructing
serverImageName/uiImageName and before any shell interpolation (i.e., convert to
lowercase and strip characters not matching [a-z0-9] using the existing regex),
then use that sanitized project name when forming the image names and in the
execSync calls that inspect the images.
🧹 Nitpick comments (4)
apps/ui/src/components/views/settings-view/hooks/use-cli-status.ts (1)

107-146: Extract duplicate auth status mapping logic into a helper function.

The auth mapping logic here (lines 107-146) duplicates the logic in the useEffect (lines 51-92). Consider extracting into a shared helper to improve maintainability:

🔎 Proposed refactor
// Add helper function outside the hook or at the top of useCliStatus
function mapAuthStatusFromResult(auth: {
  authenticated: boolean;
  method: string;
  hasCredentialsFile?: boolean;
  oauthTokenValid?: boolean;
  apiKeyValid?: boolean;
  hasStoredOAuthToken?: boolean;
  hasEnvOAuthToken?: boolean;
  hasStoredApiKey?: boolean;
  hasEnvApiKey?: boolean;
}) {
  const validMethods = [
    'oauth_token_env',
    'oauth_token',
    'api_key',
    'api_key_env',
    'credentials_file',
    'cli_authenticated',
    'none',
  ] as const;
  type AuthMethod = (typeof validMethods)[number];
  const method: AuthMethod = validMethods.includes(auth.method as AuthMethod)
    ? (auth.method as AuthMethod)
    : auth.authenticated
      ? 'api_key'
      : 'none';
  return {
    authenticated: auth.authenticated,
    method,
    hasCredentialsFile: auth.hasCredentialsFile ?? false,
    oauthTokenValid:
      auth.oauthTokenValid || auth.hasStoredOAuthToken || auth.hasEnvOAuthToken,
    apiKeyValid: auth.apiKeyValid || auth.hasStoredApiKey || auth.hasEnvApiKey,
    hasEnvOAuthToken: auth.hasEnvOAuthToken,
    hasEnvApiKey: auth.hasEnvApiKey,
  };
}

// Then use in both places:
// setClaudeAuthStatus(mapAuthStatusFromResult(auth));
docker-entrypoint.sh (1)

22-25: chmod -R 700 sets execute bit on files unnecessarily.

Using chmod -R 700 applies 700 to both directories and files. Credential files should be 600 (no execute), while directories should be 700. Consider separating directory and file permissions.

Proposed fix
 if [ -d "/home/automaker/.cursor" ]; then
     chown -R automaker:automaker /home/automaker/.cursor
-    chmod -R 700 /home/automaker/.cursor
+    chmod 700 /home/automaker/.cursor
+    find /home/automaker/.cursor -type f -exec chmod 600 {} \;
 fi
start.mjs (1)

62-140: Extract shouldRebuildDockerImages to shared module to eliminate duplication.

This function is duplicated verbatim in dev.mjs. Extract it to scripts/launcher-utils.mjs to maintain a single source of truth and reduce maintenance burden.

Dockerfile (1)

74-75: Pin Claude CLI version for reproducible builds.

The @anthropic-ai/claude-code package is installed without a version constraint. This can lead to non-reproducible builds and unexpected behavior if a breaking change is released. The latest available version is 1.0.100.

Proposed fix
 # Install Claude CLI globally (available to all users via npm global bin)
-RUN npm install -g @anthropic-ai/claude-code
+RUN npm install -g @anthropic-ai/claude-code@1.0.100
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d67556 and af39418.

📒 Files selected for processing (11)
  • Dockerfile
  • apps/ui/src/components/views/settings-view/hooks/use-cli-status.ts
  • dev.mjs
  • docker-compose.override.yml.example
  • docker-compose.yml
  • docker-entrypoint.sh
  • docs/docker-isolation.md
  • libs/platform/src/system-paths.ts
  • scripts/get-claude-token.sh
  • scripts/get-cursor-token.sh
  • start.mjs
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always import from shared packages (@automaker/*), never from old relative paths

Files:

  • libs/platform/src/system-paths.ts
  • apps/ui/src/components/views/settings-view/hooks/use-cli-status.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use resolveModelString() from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names

Files:

  • libs/platform/src/system-paths.ts
  • apps/ui/src/components/views/settings-view/hooks/use-cli-status.ts
🧬 Code graph analysis (1)
start.mjs (3)
dev.mjs (20)
  • dockerfilePath (55-55)
  • __dirname (37-37)
  • packageJsonPath (56-56)
  • dockerfileMtime (59-59)
  • packageJsonMtime (60-60)
  • latestSourceMtime (61-61)
  • serverImageName (64-64)
  • composeConfig (66-69)
  • config (70-70)
  • projectName (74-79)
  • projectName (84-87)
  • needsRebuild (93-93)
  • needsRebuild (262-262)
  • serverImageInfo (97-100)
  • uiImageInfo (103-106)
  • serverCreated (114-114)
  • uiCreated (115-115)
  • oldestImageTime (116-116)
  • buildFlag (263-263)
  • crossSpawn (34-34)
libs/platform/src/secure-fs.ts (1)
  • statSync (392-395)
scripts/launcher-utils.mjs (2)
  • log (88-90)
  • crossSpawn (24-24)
🪛 markdownlint-cli2 (0.18.1)
docs/docker-isolation.md

96-96: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


103-103: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e
🔇 Additional comments (11)
libs/platform/src/system-paths.ts (1)

803-812: LGTM! Well-documented credential format expansion.

The multi-format credential detection is cleanly implemented with clear comments explaining the three supported formats. The optional chaining on credentials.claudeAiOauth?.accessToken safely handles missing nested properties.

scripts/get-claude-token.sh (1)

1-34: LGTM! Clean macOS Keychain extraction script.

The script correctly validates platform and prerequisites before attempting credential extraction. Error messages provide helpful guidance for users.

scripts/get-cursor-token.sh (1)

1-69: LGTM! Well-structured cross-platform token extraction.

The script properly handles platform-specific credential storage (Keychain on macOS, JSON file on Linux) with appropriate prerequisite checks and helpful error messages. The XDG_CONFIG_HOME fallback on Linux follows the XDG Base Directory Specification correctly.

docs/docker-isolation.md (1)

60-111: LGTM! Comprehensive CLI authentication documentation.

The documentation clearly explains platform-specific token extraction methods and provides actionable commands. The two options for Linux/Windows (env vars vs bind mounts) give users flexibility based on their preferences.

docker-compose.yml (2)

39-48: LGTM! Well-documented environment variables for CLI credentials.

The new environment variables follow the established pattern with sensible empty defaults. The comments provide clear guidance on how to obtain the tokens using the companion scripts.


77-79: LGTM! Cursor configuration volume setup.

The volume mount at /home/automaker/.cursor aligns with the non-root user home directory established in the Dockerfile, and follows the same pattern used for Claude CLI configuration.

Also applies to: 100-103

docker-entrypoint.sh (1)

1-51: LGTM overall - credential handling follows good security practices.

The entrypoint properly creates directories with restrictive permissions (700), sets credential files to 600, and uses gosu for user switching. The ownership enforcement ensures mounted volumes work correctly with the non-root user.

start.mjs (1)

319-328: LGTM - Rebuild detection integration is clean.

The conditional logging and buildFlag construction provide clear user feedback about what's happening. The fallback behavior (rebuild when uncertain) is appropriately conservative.

dev.mjs (1)

260-270: LGTM - Consistent with start.mjs implementation.

The rebuild detection and user messaging follow the same pattern as start.mjs, maintaining consistency across dev and production modes.

Dockerfile (2)

56-72: LGTM - GitHub CLI installation with multi-arch support.

Good practice pinning GH_VERSION="2.63.2" and handling both amd64 and arm64 architectures with proper cleanup.


77-83: LGTM - User setup and PATH configuration are comprehensive.

The automaker user is created correctly with appropriate home directory structure. PATH is configured in multiple locations (profile.d, .bashrc for both users, ENV) ensuring cursor-agent is accessible in all shell contexts.

Also applies to: 96-106, 143-144

Comment on lines +25 to +29
# ===== macOS Users =====
# On macOS, OAuth tokens are stored in SQLite databases, not plain files.
# Extract your Cursor token with: ./scripts/get-cursor-token.sh
# Then set it here or in your .env file:
# - CURSOR_API_KEY=${CURSOR_API_KEY:-}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Environment variable name inconsistency.

Line 29 references CURSOR_API_KEY, but docker-compose.yml defines CURSOR_AUTH_TOKEN and the extraction script (scripts/get-cursor-token.sh) also uses CURSOR_AUTH_TOKEN.

🔎 Proposed fix
       # Extract your Cursor token with: ./scripts/get-cursor-token.sh
       # Then set it here or in your .env file:
-      # - CURSOR_API_KEY=${CURSOR_API_KEY:-}
+      # - CURSOR_AUTH_TOKEN=${CURSOR_AUTH_TOKEN:-}
📝 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
# ===== macOS Users =====
# On macOS, OAuth tokens are stored in SQLite databases, not plain files.
# Extract your Cursor token with: ./scripts/get-cursor-token.sh
# Then set it here or in your .env file:
# - CURSOR_API_KEY=${CURSOR_API_KEY:-}
# ===== macOS Users =====
# On macOS, OAuth tokens are stored in SQLite databases, not plain files.
# Extract your Cursor token with: ./scripts/get-cursor-token.sh
# Then set it here or in your .env file:
# - CURSOR_AUTH_TOKEN=${CURSOR_AUTH_TOKEN:-}
🤖 Prompt for AI Agents
In @docker-compose.override.yml.example around lines 25-29, The env var name is
inconsistent: the example uses CURSOR_API_KEY while docker-compose.yml and
scripts/get-cursor-token.sh use CURSOR_AUTH_TOKEN; update the example line to
use CURSOR_AUTH_TOKEN (or vice versa everywhere) so the extraction script,
docker-compose.yml and docker-compose.override.yml.example all reference the
same variable name (CURSOR_AUTH_TOKEN) and ensure any documentation/comments
mention that exact symbol.

Comment on lines +85 to +94
# Install Cursor CLI as the automaker user
# Set HOME explicitly and install to /home/automaker/.local/bin/
USER automaker
ENV HOME=/home/automaker
RUN curl https://cursor.com/install -fsS | bash && \
echo "=== Checking Cursor CLI installation ===" && \
ls -la /home/automaker/.local/bin/ && \
echo "=== PATH is: $PATH ===" && \
(which cursor-agent && cursor-agent --version) || echo "cursor-agent installed (may need auth setup)"
USER root
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Curl-pipe-to-bash pattern introduces supply chain risk.

Piping remote scripts directly to bash (curl ... | bash) is a security anti-pattern as it executes arbitrary code without verification. If cursor.com is compromised or serves different content, the build could be affected.

Consider:

  1. Downloading the script first and inspecting/checksumming it
  2. Pinning to a specific installer version if available
  3. Documenting this as an accepted risk if no alternative exists
🤖 Prompt for AI Agents
In @Dockerfile around lines 85-94, Avoid the curl|bash pipeline: instead fetch
the installer artifact first, verify its authenticity (checksum or signature)
and only then execute it as the automaker user; update the Dockerfile section
that currently uses "USER automaker"/"ENV HOME=/home/automaker" and the RUN that
pipes curl to bash to download the installer to a temporary file, validate a
pinned version or checksum/signature, then run that local script as automaker,
and finally check installation with "which cursor-agent" and "cursor-agent
--version"; if no signed artifact or pinned URL exists, document the risk and
pin the installer version or source before executing.

Shironex and others added 4 commits January 6, 2026 00:58
- Moved the logger creation outside the hook to prevent infinite re-renders.
- Updated dependencies in the checkStatus function to remove logger from the dependency array.

These changes enhance performance and maintainability of the useCliStatus hook.
- Added a `sanitizeProjectName` function to ensure project names are safe for shell commands and Docker image names by converting them to lowercase and removing non-alphanumeric characters.
- Updated `dev.mjs` and `start.mjs` to utilize the new sanitization function when determining Docker image names, enhancing security and consistency.
- Refactored the Docker entrypoint script to ensure proper permissions for the Cursor CLI config directory, improving setup reliability.
- Clarified documentation regarding the storage location of OAuth tokens for the Cursor CLI on Linux.

These changes improve the robustness of the Docker setup and enhance the overall development workflow.
Copy link

@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: 2

Fix all issues with AI Agents 🤖
In @apps/ui/src/components/views/setup-view/hooks/use-cli-status.ts:
- Around line 10-14: Remove the duplicate declaration of the logger constant:
keep a single const logger = createLogger('CliStatus') declaration (the one
intended "outside the hook") and delete the other redeclaration so there is only
one logger variable in use-cli-status (referencing the createLogger('CliStatus')
call and the logger identifier).

In @docker-entrypoint.sh:
- Around line 31-42: The current docker-entrypoint.sh writes CURSOR_AUTH_TOKEN
directly into the heredoc for "$CURSOR_CONFIG_DIR/auth.json", which can produce
invalid JSON if the token contains quotes, backslashes, or newlines; instead
serialize/escape the token when producing the JSON (e.g., replace the heredoc
write with a JSON-safe serialization using jq or Python's json.dumps) so that
CURSOR_AUTH_TOKEN is properly escaped before writing to auth.json, and keep the
mkdir, chmod 600 and chown automaker:automaker steps for CURSOR_CONFIG_DIR.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
start.mjs (1)

1-1: Address Prettier formatting issues.

The pipeline indicates Prettier formatting issues in this file. Run prettier --write start.mjs to fix.

dev.mjs (1)

1-1: Address Prettier formatting issues.

The pipeline indicates Prettier formatting issues in this file. Run prettier --write dev.mjs to fix.

🧹 Nitpick comments (4)
apps/ui/src/components/views/settings-view/hooks/use-cli-status.ts (1)

5-6: Import statement should be grouped with other imports at the top.

The import on line 6 appears after the const logger declaration on line 5. Move the import to the top of the file with the other imports for consistent organization.

🔎 Proposed fix
 import { useState, useEffect, useCallback } from 'react';
 import { createLogger } from '@automaker/utils/logger';
 import { useSetupStore } from '@/store/setup-store';
+import { getElectronAPI } from '@/lib/electron';

 const logger = createLogger('CliStatus');
-import { getElectronAPI } from '@/lib/electron';
docs/docker-isolation.md (1)

96-103: Consider using proper headings instead of bold emphasis.

The static analysis tool flags lines 96 and 103 as using emphasis instead of headings. For better document structure and accessibility, consider converting these to proper markdown headings.

🔎 Proposed fix
-**Option 1: Extract tokens to environment variables (recommended)**
+### Option 1: Extract tokens to environment variables (recommended)

 ```bash
 # Linux: Extract tokens to .env
 echo "CURSOR_AUTH_TOKEN=$(jq -r '.accessToken' ~/.config/cursor/auth.json)" >> .env

-Option 2: Bind mount credential directories directly
+### Option 2: Bind mount credential directories directly

</details>

</blockquote></details>
<details>
<summary>start.mjs (1)</summary><blockquote>

`59-140`: **Consider extracting shared utilities to avoid code duplication.**

The `sanitizeProjectName` and `shouldRebuildDockerImages` functions are duplicated verbatim in both `start.mjs` and `dev.mjs`. Consider extracting these to `scripts/launcher-utils.mjs` to maintain a single source of truth.

</blockquote></details>
<details>
<summary>dev.mjs (1)</summary><blockquote>

`50-131`: **Code duplication with start.mjs.**

As noted in the start.mjs review, `sanitizeProjectName` and `shouldRebuildDockerImages` are identical in both files. Extract to a shared module in `scripts/launcher-utils.mjs`.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used**: defaults

**Review profile**: CHILL

**Plan**: Pro

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 2a0719e00c07cc1ae34ae353d977ca6de7dc4302 and 49f32c4d59b48c7b83a8a4f7ed678953a3f47fd1.

</details>

<details>
<summary>📒 Files selected for processing (6)</summary>

* `apps/ui/src/components/views/settings-view/hooks/use-cli-status.ts`
* `apps/ui/src/components/views/setup-view/hooks/use-cli-status.ts`
* `dev.mjs`
* `docker-entrypoint.sh`
* `docs/docker-isolation.md`
* `start.mjs`

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (2)</summary>

<details>
<summary>**/*.{ts,tsx,js,jsx}</summary>


**📄 CodeRabbit inference engine (CLAUDE.md)**

> Always import from shared packages (@automaker/*), never from old relative paths

Files:
- `apps/ui/src/components/views/settings-view/hooks/use-cli-status.ts`
- `apps/ui/src/components/views/setup-view/hooks/use-cli-status.ts`

</details>
<details>
<summary>**/*.{ts,tsx}</summary>


**📄 CodeRabbit inference engine (CLAUDE.md)**

> Use `resolveModelString()` from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names

Files:
- `apps/ui/src/components/views/settings-view/hooks/use-cli-status.ts`
- `apps/ui/src/components/views/setup-view/hooks/use-cli-status.ts`

</details>

</details><details>
<summary>🧬 Code graph analysis (2)</summary>

<details>
<summary>apps/ui/src/components/views/settings-view/hooks/use-cli-status.ts (1)</summary><blockquote>

<details>
<summary>apps/ui/src/lib/electron.ts (1)</summary>

* `getElectronAPI` (839-848)

</details>

</blockquote></details>
<details>
<summary>apps/ui/src/components/views/setup-view/hooks/use-cli-status.ts (2)</summary><blockquote>

<details>
<summary>libs/utils/src/logger.ts (1)</summary>

* `createLogger` (127-219)

</details>
<details>
<summary>libs/utils/src/index.ts (1)</summary>

* `createLogger` (44-44)

</details>

</blockquote></details>

</details><details>
<summary>🪛 Biome (2.1.2)</summary>

<details>
<summary>apps/ui/src/components/views/setup-view/hooks/use-cli-status.ts</summary>

[error] 13-13: Shouldn't redeclare 'logger'. Consider to delete it or rename it.

'logger' is defined here:


(lint/suspicious/noRedeclare)

</details>

</details>
<details>
<summary>🪛 GitHub Actions: Format Check</summary>

<details>
<summary>start.mjs</summary>

[warning] 1-1: Prettier formatting issues found in this file. Run 'prettier --write' to fix.

</details>
<details>
<summary>dev.mjs</summary>

[warning] 1-1: Prettier formatting issues found in this file. Run 'prettier --write' to fix.

</details>

</details>
<details>
<summary>🪛 GitHub Actions: PR Build Check</summary>

<details>
<summary>apps/ui/src/components/views/setup-view/hooks/use-cli-status.ts</summary>

[error] 13-13: The symbol "logger" has already been declared.

</details>

</details>
<details>
<summary>🪛 markdownlint-cli2 (0.18.1)</summary>

<details>
<summary>docs/docker-isolation.md</summary>

96-96: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

---

103-103: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (7)</summary><blockquote>

<details>
<summary>apps/ui/src/components/views/setup-view/hooks/use-cli-status.ts (1)</summary><blockquote>

`23-72`: **Callback logic looks correct.**

The `checkStatus` implementation properly validates auth methods, constructs status objects, and handles errors. The dependency array correctly excludes `logger` since it's now module-scoped (once the duplicate declaration is fixed).

</blockquote></details>
<details>
<summary>apps/ui/src/components/views/settings-view/hooks/use-cli-status.ts (2)</summary><blockquote>

`35-80`: **Good extraction of shared auth refresh logic.**

The `refreshAuthStatus` callback properly centralizes the auth status fetching logic, addressing the code duplication concern. The method validation, field mapping, and error handling are well-implemented.

---

`83-120`: **LGTM on the shared refresh logic usage.**

Both `useEffect` and `handleRefreshClaudeCli` now properly use the shared `refreshAuthStatus` callback, eliminating the duplication flagged in previous reviews. The dependency arrays are correct.

</blockquote></details>
<details>
<summary>docker-entrypoint.sh (1)</summary><blockquote>

`4-26`: **LGTM on the directory setup logic.**

The consolidated approach for creating directories, setting permissions, and fixing ownership is clean and handles both mounted volumes and fresh directories correctly. The use of `chmod 700` for directories and `chmod 600` for credential files follows security best practices.

</blockquote></details>
<details>
<summary>start.mjs (2)</summary><blockquote>

`106-115`: **LGTM on command injection mitigation.**

The previous concern about command injection from `config.name` has been addressed. The `sanitizeProjectName` function now ensures that project names only contain lowercase alphanumeric characters before being used in shell commands, preventing injection attacks.

---

`319-347`: **LGTM on conditional Docker rebuild logic.**

The integration of `shouldRebuildDockerImages` with appropriate logging and conditional `--build` flag is well implemented. The fallback to rebuilding on errors is a safe default.

</blockquote></details>
<details>
<summary>dev.mjs (1)</summary><blockquote>

`260-288`: **LGTM on Docker rebuild integration.**

The conditional rebuild logic is correctly integrated with appropriate user feedback. The implementation mirrors start.mjs, ensuring consistent behavior between development and production modes.

</blockquote></details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment on lines +31 to 42
if [ -n "$CURSOR_AUTH_TOKEN" ]; then
CURSOR_CONFIG_DIR="/home/automaker/.config/cursor"
mkdir -p "$CURSOR_CONFIG_DIR"
# Write auth.json with the access token
cat > "$CURSOR_CONFIG_DIR/auth.json" << EOF
{
"accessToken": "$CURSOR_AUTH_TOKEN"
}
EOF
chmod 600 "$CURSOR_CONFIG_DIR/auth.json"
chown -R automaker:automaker /home/automaker/.config
fi
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Token escaping issue remains unaddressed.

The CURSOR_AUTH_TOKEN is directly interpolated into the JSON heredoc without escaping. If the token contains ", \, or newlines, the resulting JSON will be malformed. This was flagged in a previous review.

🔎 Proposed fix using sed escaping
 if [ -n "$CURSOR_AUTH_TOKEN" ]; then
     CURSOR_CONFIG_DIR="/home/automaker/.config/cursor"
     mkdir -p "$CURSOR_CONFIG_DIR"
+    # Escape special JSON characters in the token
+    ESCAPED_TOKEN=$(printf '%s' "$CURSOR_AUTH_TOKEN" | sed 's/[\"\\]/\\&/g' | tr -d '\n')
     # Write auth.json with the access token
     cat > "$CURSOR_CONFIG_DIR/auth.json" << EOF
 {
-  "accessToken": "$CURSOR_AUTH_TOKEN"
+  "accessToken": "$ESCAPED_TOKEN"
 }
 EOF
     chmod 600 "$CURSOR_CONFIG_DIR/auth.json"
     chown -R automaker:automaker /home/automaker/.config
 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
if [ -n "$CURSOR_AUTH_TOKEN" ]; then
CURSOR_CONFIG_DIR="/home/automaker/.config/cursor"
mkdir -p "$CURSOR_CONFIG_DIR"
# Write auth.json with the access token
cat > "$CURSOR_CONFIG_DIR/auth.json" << EOF
{
"accessToken": "$CURSOR_AUTH_TOKEN"
}
EOF
chmod 600 "$CURSOR_CONFIG_DIR/auth.json"
chown -R automaker:automaker /home/automaker/.config
fi
if [ -n "$CURSOR_AUTH_TOKEN" ]; then
CURSOR_CONFIG_DIR="/home/automaker/.config/cursor"
mkdir -p "$CURSOR_CONFIG_DIR"
# Escape special JSON characters in the token
ESCAPED_TOKEN=$(printf '%s' "$CURSOR_AUTH_TOKEN" | sed 's/[\"\\]/\\&/g' | tr -d '\n')
# Write auth.json with the access token
cat > "$CURSOR_CONFIG_DIR/auth.json" << EOF
{
"accessToken": "$ESCAPED_TOKEN"
}
EOF
chmod 600 "$CURSOR_CONFIG_DIR/auth.json"
chown -R automaker:automaker /home/automaker/.config
fi
🤖 Prompt for AI Agents
In @docker-entrypoint.sh around lines 31-42, The current docker-entrypoint.sh
writes CURSOR_AUTH_TOKEN directly into the heredoc for
"$CURSOR_CONFIG_DIR/auth.json", which can produce invalid JSON if the token
contains quotes, backslashes, or newlines; instead serialize/escape the token
when producing the JSON (e.g., replace the heredoc write with a JSON-safe
serialization using jq or Python's json.dumps) so that CURSOR_AUTH_TOKEN is
properly escaped before writing to auth.json, and keep the mkdir, chmod 600 and
chown automaker:automaker steps for CURSOR_CONFIG_DIR.

- Eliminated redundant logger declaration within the useCliStatus hook to improve code clarity and prevent potential performance issues.
- This change enhances the maintainability of the code by ensuring the logger is created only once outside the hook.
…functions

- Removed redundant Docker image rebuilding logic from `dev.mjs` and `start.mjs`, centralizing it in the new `launchDockerContainers` function within `launcher-utils.mjs`.
- Introduced `sanitizeProjectName` and `shouldRebuildDockerImages` functions to improve project name handling and Docker image management.
- Updated the Docker launch process to provide clearer logging and ensure proper handling of environment variables, enhancing the overall development experience.
@webdevcody webdevcody merged commit 8a6a83b into main Jan 6, 2026
6 checks passed
@webdevcody webdevcody deleted the cursor-docker-oauth branch January 6, 2026 02:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants