diff --git a/Dockerfile b/Dockerfile index e45ddf24..c32b1764 100644 --- a/Dockerfile +++ b/Dockerfile @@ -55,6 +55,10 @@ RUN npm run build:packages && npm run build --workspace=apps/server # ============================================================================= FROM node:22-slim AS server +# Build argument for tracking which commit this image was built from +ARG GIT_COMMIT_SHA=unknown +LABEL automaker.git.commit.sha="${GIT_COMMIT_SHA}" + # Install git, curl, bash (for terminal), gosu (for user switching), and GitHub CLI (pinned version, multi-arch) RUN apt-get update && apt-get install -y --no-install-recommends \ git curl bash gosu ca-certificates openssh-client \ @@ -184,6 +188,10 @@ RUN npm run build:packages && npm run build --workspace=apps/ui # ============================================================================= FROM nginx:alpine AS ui +# Build argument for tracking which commit this image was built from +ARG GIT_COMMIT_SHA=unknown +LABEL automaker.git.commit.sha="${GIT_COMMIT_SHA}" + # Copy built files COPY --from=ui-builder /app/apps/ui/dist /usr/share/nginx/html diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 00000000..87ac6bf6 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,80 @@ +# Automaker Development Dockerfile +# For development with live reload via volume mounting +# Source code is NOT copied - it's mounted as a volume +# +# Usage: +# docker compose -f docker-compose.dev.yml up + +FROM node:22-slim + +# Install build dependencies for native modules (node-pty) and runtime tools +RUN apt-get update && apt-get install -y --no-install-recommends \ + python3 make g++ \ + git curl bash gosu ca-certificates openssh-client \ + && GH_VERSION="2.63.2" \ + && ARCH=$(uname -m) \ + && case "$ARCH" in \ + x86_64) GH_ARCH="amd64" ;; \ + aarch64|arm64) GH_ARCH="arm64" ;; \ + *) echo "Unsupported architecture: $ARCH" && exit 1 ;; \ + esac \ + && curl -L "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_${GH_ARCH}.tar.gz" -o gh.tar.gz \ + && tar -xzf gh.tar.gz \ + && mv gh_${GH_VERSION}_linux_${GH_ARCH}/bin/gh /usr/local/bin/gh \ + && rm -rf gh.tar.gz gh_${GH_VERSION}_linux_${GH_ARCH} \ + && rm -rf /var/lib/apt/lists/* + +# Install Claude CLI globally +RUN npm install -g @anthropic-ai/claude-code + +# Create non-root user +RUN groupadd -g 1001 automaker && \ + useradd -u 1001 -g automaker -m -d /home/automaker -s /bin/bash automaker && \ + mkdir -p /home/automaker/.local/bin && \ + mkdir -p /home/automaker/.cursor && \ + chown -R automaker:automaker /home/automaker && \ + chmod 700 /home/automaker/.cursor + +# Install Cursor CLI as automaker user +USER automaker +ENV HOME=/home/automaker +RUN curl https://cursor.com/install -fsS | bash || true +USER root + +# Add PATH to profile for Cursor CLI +RUN mkdir -p /etc/profile.d && \ + echo 'export PATH="/home/automaker/.local/bin:$PATH"' > /etc/profile.d/cursor-cli.sh && \ + chmod +x /etc/profile.d/cursor-cli.sh + +# Add to user bashrc files +RUN echo 'export PATH="/home/automaker/.local/bin:$PATH"' >> /home/automaker/.bashrc && \ + chown automaker:automaker /home/automaker/.bashrc +RUN echo 'export PATH="/home/automaker/.local/bin:$PATH"' >> /root/.bashrc + +WORKDIR /app + +# Create directories with proper permissions +RUN mkdir -p /data /projects && chown automaker:automaker /data /projects + +# Configure git for mounted volumes +RUN git config --system --add safe.directory '*' && \ + git config --system credential.helper '!gh auth git-credential' + +# Copy entrypoint script +COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + +# Environment variables +ENV PORT=3008 +ENV DATA_DIR=/data +ENV HOME=/home/automaker +ENV PATH="/home/automaker/.local/bin:${PATH}" + +# Expose both dev ports +EXPOSE 3007 3008 + +# Use entrypoint for permission handling +ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] + +# Default command - will be overridden by docker-compose +CMD ["npm", "run", "dev:web"] diff --git a/README.md b/README.md index 9ca0f368..8bfd2a0a 100644 --- a/README.md +++ b/README.md @@ -117,24 +117,16 @@ cd automaker # 2. Install dependencies npm install -# 3. Build shared packages (Now can be skipped npm install / run dev does it automaticly) +# 3. Build shared packages (can be skipped - npm run dev does it automatically) npm run build:packages -# 4. Start Automaker (production mode) -npm run start +# 4. Start Automaker +npm run dev # Choose between: # 1. Web Application (browser at localhost:3007) # 2. Desktop Application (Electron - recommended) ``` -**Note:** The `npm run start` command will: - -- Check for dependencies and install if needed -- Build the application if needed -- Kill any processes on ports 3007/3008 -- Present an interactive menu to choose your run mode -- Run in production mode (no hot reload) - **Authentication Setup:** On first run, Automaker will automatically show a setup wizard where you can configure authentication. You can choose to: - Use **Claude Code CLI** (recommended) - Automaker will detect your CLI credentials automatically @@ -150,7 +142,7 @@ export ANTHROPIC_API_KEY="sk-ant-..." echo "ANTHROPIC_API_KEY=sk-ant-..." > .env ``` -**For Development:** If you want to develop on Automaker with Vite live reload and hot module replacement, use `npm run dev` instead. This will start the development server with fast refresh and instant updates as you make changes. +**For Development:** `npm run dev` starts the development server with Vite live reload and hot module replacement for fast refresh and instant updates as you make changes. ## How to Run @@ -194,9 +186,6 @@ npm run dev:web ```bash # Build for web deployment (uses Vite) npm run build - -# Run production build -npm run start ``` #### Desktop Application diff --git a/apps/ui/src/components/views/board-view.tsx b/apps/ui/src/components/views/board-view.tsx index 1dc99b05..2c82261b 100644 --- a/apps/ui/src/components/views/board-view.tsx +++ b/apps/ui/src/components/views/board-view.tsx @@ -1151,8 +1151,6 @@ export function BoardView() { onDetailLevelChange={setKanbanCardDetailLevel} boardViewMode={boardViewMode} onBoardViewModeChange={setBoardViewMode} - isSelectionMode={isSelectionMode} - onToggleSelectionMode={toggleSelectionMode} /> {/* View Content - Kanban or Graph */} @@ -1175,7 +1173,6 @@ export function BoardView() { onManualVerify={handleManualVerify} onMoveBackToInProgress={handleMoveBackToInProgress} onFollowUp={handleOpenFollowUp} - onCommit={handleCommitFeature} onComplete={handleCompleteFeature} onImplement={handleStartImplementation} onViewPlan={(feature) => setViewPlanFeature(feature)} @@ -1186,8 +1183,6 @@ export function BoardView() { }} featuresWithContext={featuresWithContext} runningAutoTasks={runningAutoTasks} - shortcuts={shortcuts} - onStartNextFeatures={handleStartNextFeatures} onArchiveAllVerified={() => setShowArchiveAllVerifiedDialog(true)} pipelineConfig={ currentProject?.path ? pipelineConfigByProject[currentProject.path] || null : null @@ -1196,6 +1191,7 @@ export function BoardView() { isSelectionMode={isSelectionMode} selectedFeatureIds={selectedFeatureIds} onToggleFeatureSelection={toggleFeatureSelection} + onToggleSelectionMode={toggleSelectionMode} /> ) : ( void; boardViewMode: BoardViewMode; onBoardViewModeChange: (mode: BoardViewMode) => void; - isSelectionMode?: boolean; - onToggleSelectionMode?: () => void; } export function BoardControls({ @@ -35,8 +24,6 @@ export function BoardControls({ onDetailLevelChange, boardViewMode, onBoardViewModeChange, - isSelectionMode = false, - onToggleSelectionMode, }: BoardControlsProps) { if (!isMounted) return null; @@ -88,24 +75,6 @@ export function BoardControls({ - {/* Selection Mode Toggle */} - - - - - -

{isSelectionMode ? 'Exit Select Mode' : 'Select Mode'}

-
-
- {/* Board Background Button */} diff --git a/apps/ui/src/components/views/board-view/kanban-board.tsx b/apps/ui/src/components/views/board-view/kanban-board.tsx index 5cef1aa9..2962852d 100644 --- a/apps/ui/src/components/views/board-view/kanban-board.tsx +++ b/apps/ui/src/components/views/board-view/kanban-board.tsx @@ -2,13 +2,11 @@ import { useMemo } from 'react'; import { DndContext, DragOverlay } from '@dnd-kit/core'; import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'; import { Button } from '@/components/ui/button'; -import { HotkeyButton } from '@/components/ui/hotkey-button'; import { KanbanColumn, KanbanCard } from './components'; import { Feature } from '@/store/app-store'; -import { FastForward, Archive, Plus, Settings2 } from 'lucide-react'; -import { useKeyboardShortcutsConfig } from '@/hooks/use-keyboard-shortcuts'; +import { Archive, Settings2, CheckSquare, GripVertical } from 'lucide-react'; import { useResponsiveKanban } from '@/hooks/use-responsive-kanban'; -import { getColumnsWithPipeline, type Column, type ColumnId } from './constants'; +import { getColumnsWithPipeline, type ColumnId } from './constants'; import type { PipelineConfig } from '@automaker/types'; interface KanbanBoardProps { @@ -37,7 +35,6 @@ interface KanbanBoardProps { onManualVerify: (feature: Feature) => void; onMoveBackToInProgress: (feature: Feature) => void; onFollowUp: (feature: Feature) => void; - onCommit: (feature: Feature) => void; onComplete: (feature: Feature) => void; onImplement: (feature: Feature) => void; onViewPlan: (feature: Feature) => void; @@ -45,8 +42,6 @@ interface KanbanBoardProps { onSpawnTask?: (feature: Feature) => void; featuresWithContext: Set; runningAutoTasks: string[]; - shortcuts: ReturnType; - onStartNextFeatures: () => void; onArchiveAllVerified: () => void; pipelineConfig: PipelineConfig | null; onOpenPipelineSettings?: () => void; @@ -54,6 +49,7 @@ interface KanbanBoardProps { isSelectionMode?: boolean; selectedFeatureIds?: Set; onToggleFeatureSelection?: (featureId: string) => void; + onToggleSelectionMode?: () => void; } export function KanbanBoard({ @@ -74,7 +70,6 @@ export function KanbanBoard({ onManualVerify, onMoveBackToInProgress, onFollowUp, - onCommit, onComplete, onImplement, onViewPlan, @@ -82,14 +77,13 @@ export function KanbanBoard({ onSpawnTask, featuresWithContext, runningAutoTasks, - shortcuts, - onStartNextFeatures, onArchiveAllVerified, pipelineConfig, onOpenPipelineSettings, isSelectionMode = false, selectedFeatureIds = new Set(), onToggleFeatureSelection, + onToggleSelectionMode, }: KanbanBoardProps) { // Generate columns including pipeline steps const columns = useMemo(() => getColumnsWithPipeline(pipelineConfig), [pipelineConfig]); @@ -133,20 +127,26 @@ export function KanbanBoard({ Complete All ) : column.id === 'backlog' ? ( - columnFeatures.length > 0 && ( - - - Make - - ) + ) : column.id === 'in_progress' ? (