Conversation
- Add DaemonManager class with write_pid/read_pid/remove_pid/is_running - Register SIGTERM, SIGINT (and SIGHUP on POSIX) for graceful shutdown - Support optional shutdown callback (sync and async) - Context manager support for automatic PID cleanup - Integrate daemon lifecycle into main.py lifespan via HEADLESS env var Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ent tasks - Added `get_graceful_shutdown_handler` and `_cancel_all_running_tasks` to agent_runner.py - `_cancel_all_running_tasks` cancels all active asyncio tasks, awaits completion, and logs results - Updated main.py lifespan to await the shutdown handler before removing PID file - Ensures no agent tasks are left dangling when the server stops on SIGTERM Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Creates server_commands.py with handle_server_command dispatcher and individual handlers for managing the Auto Code web-backend daemon. Integrates with DaemonManager PID file conventions. Updates main.py with --server, --server-host, --server-port, and --server-log-lines arguments wired into the CLI dispatch loop. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ackend - Add auto-claude-server.service systemd unit file with security hardening (NoNewPrivileges, PrivateTmp, ProtectSystem, ProtectHome) - Add auto-claude-server.conf environment configuration template with documented settings for server, security, auth, logging, and agent config - Add deploy/README.md with quick-install guide, service management commands, configuration reference, and troubleshooting tips Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Creates metrics_collector.py with Prometheus counters for agent runs, errors, and latency histograms. Gracefully degrades when prometheus-client is not installed. Adds prometheus-client>=0.20.0 to requirements.txt. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ints Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Creates api/routes/metrics.py exposing application metrics in Prometheus text format. Includes uptime gauge, HTTP request counter/histogram, and agent task gauges. Registers router in main.py.
…runner - Add user_id parameter to start_agent_task and run_agent_async - Check per-user quota via ResourceManager.acquire_agent_slot before launching task - Raise QuotaExceededError when concurrent agent or daily run limit exceeded - Release agent slot in run_agent_async finally block on completion or failure - Update agents route to extract user_id from JWT sub claim - Handle QuotaExceededError as HTTP 429 in run_agent endpoint Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ectories
When user_id > 0, resolve specs from .auto-claude/users/{user_id}/specs/
instead of the shared .auto-claude/specs/ directory, providing workspace
isolation between users in multi-tenant deployments.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Added _JsonFormatter class to main.py emitting structured JSON log records - Added _configure_logging() helper selecting JSON or text formatter via LOG_FORMAT env var - Added LOG_LEVEL and LOG_FORMAT settings to core/config.py Settings class Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add HEADLESS_MODE, MAX_CONCURRENT_AGENTS, and AGENT_TIMEOUT_SECONDS to Settings class and .env.example for headless server operation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…gnatures - Add test_health_metrics_e2e.py with 24 tests covering /health/live, /health/ready, /health/detailed, and /metrics endpoints - Fix pre-existing test_api_agents.py failures caused by subtask-3-2 adding user_id param to start_agent_task (update 7 mock signatures) - All 193 tests pass (excluding cloud e2e integration tests) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
| # Stale PID file | ||
| try: | ||
| pid_file.unlink() | ||
| except OSError: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 22 days ago
In general, to fix an “empty except” you either (a) add an explanatory comment stating clearly why the exception is being ignored, or (b) perform some minimal handling such as logging, or (c) narrow the exception type and re-raise or propagate as appropriate. Here, we don’t want to change _is_running’s behavior—the function should still return False if the process doesn’t exist, regardless of whether PID file cleanup succeeds. The safest fix is to add explicit handling while keeping the return value the same.
The single best approach here is to keep the except OSError block but replace pass with either a short comment and/or a debug log. Since we’re told not to assume logging infrastructure beyond what’s visible in the snippet, and to avoid changing imports aside from well-known libraries, the minimal, non-invasive change is to add a comment explaining that failure to delete the PID file is intentionally ignored. This satisfies CodeQL’s requirement (the “does nothing but pass and there is no explanatory comment” part) without altering behavior.
Concretely, in apps/backend/cli/server_commands.py, inside _is_running, change the except OSError: block that currently just passes so that it includes an explanatory comment before pass, e.g. # Best-effort cleanup; ignore errors when removing stale PID file. No new imports or method definitions are needed.
| @@ -63,6 +63,7 @@ | ||
| try: | ||
| pid_file.unlink() | ||
| except OSError: | ||
| # Best-effort cleanup: ignore errors when removing a stale PID file. | ||
| pass | ||
| return False | ||
| except PermissionError: |
| print_status(f"Process {pid} not found; cleaning up PID file", "warning") | ||
| try: | ||
| pid_file.unlink() | ||
| except OSError: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 22 days ago
In general, empty except blocks should either (a) be removed so the exception can propagate, or (b) explicitly document and/or log why the exception is being ignored and, if appropriate, perform compensating actions. The goal is to avoid silently discarding information about errors.
For this specific case in handle_server_stop_command (apps/backend/cli/server_commands.py, around lines 188–191), we want to keep the “best-effort cleanup” behavior—i.e., a failure to delete the PID file should not cause the stop command itself to fail—but we should not ignore the exception silently. The most consistent fix with the existing code is:
- Catch
OSErrorasexc. - Use the already-imported
print_statushelper to log a warning that we could not remove the PID file, including the exception message for debugging. - Preserve the existing control flow: after handling the
OSError, still returnTruefrom the outerexcept ProcessLookupErrorblock.
No new imports or helper methods are needed; print_status is already available and used for status, warning, and error messages elsewhere in the file.
| @@ -187,8 +187,11 @@ | ||
| print_status(f"Process {pid} not found; cleaning up PID file", "warning") | ||
| try: | ||
| pid_file.unlink() | ||
| except OSError: | ||
| pass | ||
| except OSError as exc: | ||
| print_status( | ||
| f"Failed to remove PID file {pid_file}: {exc}", | ||
| "warning", | ||
| ) | ||
| return True | ||
| except PermissionError: | ||
| print_status( |
| import logging | ||
| import os | ||
| import signal | ||
| import sys |
Check notice
Code scanning / CodeQL
Unused import Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 22 days ago
The way to fix an unused import is to remove the unnecessary import statement, as it adds clutter and an unneeded dependency. In this file, only the sys module is reported as unused; other imports are clearly referenced in the shown code.
Concretely, in apps/web-backend/core/daemon.py, at the top of the file, remove the line import sys (line 12 in the snippet). No other code changes, new methods, or additional imports are required, since nothing in the provided code uses sys. This preserves all existing functionality while resolving the CodeQL warning.
| @@ -9,7 +9,6 @@ | ||
| import logging | ||
| import os | ||
| import signal | ||
| import sys | ||
| from pathlib import Path | ||
| from typing import Callable, Optional | ||
|
|
|
|
||
| if _daemon is not None: | ||
| _daemon.remove_pid() | ||
| _daemon = None |
Check notice
Code scanning / CodeQL
Unused global variable Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 22 days ago
In general, to fix an "unused global variable" warning, either (a) remove the global variable and keep only the side effects of its initialization, (b) rename it to an accepted "intentionally unused" pattern if it truly must remain unused, or (c) avoid using global and keep the variable local if it is only needed within a single function.
Here, _daemon is only used inside lifespan and does not need to be global. The best fix without changing functionality is:
- Remove the
global _daemonstatement. - Ensure
_daemonis always defined inlifespanbefore it is checked, by initializing it toNoneat the top of the function body. - Leave the existing uses of
_daemoninHEADLESSmode and the shutdown block unchanged.
Concretely, in apps/web-backend/main.py, in the lifespan function around lines 79–118:
- Delete the
global _daemon # noqa: PLW0603line. - Immediately after the docstring line (
"""Application lifespan handler..."""), add_daemon = Nonewith the same indentation as other local variables in the function.
No extra imports or helper methods are needed.
| @@ -80,7 +80,7 @@ | ||
| """ | ||
| Application lifespan handler for startup and shutdown events | ||
| """ | ||
| global _daemon # noqa: PLW0603 | ||
| _daemon = None | ||
|
|
||
| # Startup | ||
| logger.info("Starting Web Backend API") |
| are registered, respond correctly, and return expected formats. | ||
| """ | ||
|
|
||
| import pytest |
Check notice
Code scanning / CodeQL
Unused import Note test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 22 days ago
In general, to fix an unused-import issue you remove the import statement when the imported name is not referenced anywhere in the file, provided the framework or runtime does not require that import implicitly.
Here, the single best fix is to delete the line import pytest at the top of apps/web-backend/tests/test_health_metrics_e2e.py. No other code changes are necessary, because:
- All tests are plain functions or methods named
test_*, which pytest will discover without needing an explicitpytestimport. - No
pytestAPIs (e.g.,pytest.mark,pytest.raises) are used in the shown code.
This change preserves all existing behavior while cleaning up an unnecessary dependency.
Concretely, in apps/web-backend/tests/test_health_metrics_e2e.py, remove line 8 containing import pytest and leave the from fastapi.testclient import TestClient import intact.
| @@ -5,7 +5,6 @@ | ||
| are registered, respond correctly, and return expected formats. | ||
| """ | ||
|
|
||
| import pytest | ||
| from fastapi.testclient import TestClient | ||
|
|
||
|
|
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (18)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |


Run Auto Code as a background server with remote agent execution, accessible via API, CLI, or web UI for server and CI/CD environments.