Add container-native scheduled task system with timezone support
All checks were successful
Build App / build-linux (push) Successful in 2m39s
Build App / build-windows (push) Successful in 3m43s
Build Container / build-container (push) Successful in 16s

Introduces a cron-based scheduler that lets Claude set up recurring and
one-time tasks inside containers. Tasks run as separate Claude Code agents
and persist across container recreation via the named volume.

New files:
- container/triple-c-scheduler: CLI for add/remove/enable/disable/list/logs/run/notifications
- container/triple-c-task-runner: cron wrapper with flock, logging, notifications, auto-cleanup

Key changes:
- Dockerfile: add cron package and COPY both scripts
- entrypoint.sh: timezone setup, cron daemon, crontab restore, env saving
- container.rs: init=true for zombie reaping, TZ env, scheduler instructions, timezone recreation check
- image.rs: embed scheduler scripts in build context
- app_settings.rs + types.ts: timezone field
- settings_commands.rs: detect_host_timezone via iana-time-zone crate
- SettingsPanel.tsx: timezone input with auto-detection

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 15:57:22 +00:00
parent 06be613e36
commit 2e81b52205
15 changed files with 781 additions and 1 deletions

View File

@@ -160,6 +160,7 @@ pub async fn start_project_container(
&project,
settings.global_claude_instructions.as_deref(),
&settings.global_custom_env_vars,
settings.timezone.as_deref(),
)
.await
.unwrap_or(false);
@@ -175,6 +176,7 @@ pub async fn start_project_container(
&settings.global_aws,
settings.global_claude_instructions.as_deref(),
&settings.global_custom_env_vars,
settings.timezone.as_deref(),
).await?;
docker::start_container(&new_id).await?;
new_id
@@ -191,6 +193,7 @@ pub async fn start_project_container(
&settings.global_aws,
settings.global_claude_instructions.as_deref(),
&settings.global_custom_env_vars,
settings.timezone.as_deref(),
).await?;
docker::start_container(&new_id).await?;
new_id

View File

@@ -29,6 +29,33 @@ pub async fn pull_image(
.await
}
#[tauri::command]
pub async fn detect_host_timezone() -> Result<String, String> {
// Try the iana-time-zone crate first (cross-platform)
match iana_time_zone::get_timezone() {
Ok(tz) => return Ok(tz),
Err(e) => log::debug!("iana_time_zone::get_timezone() failed: {}", e),
}
// Fallback: check TZ env var
if let Ok(tz) = std::env::var("TZ") {
if !tz.is_empty() {
return Ok(tz);
}
}
// Fallback: read /etc/timezone (Linux)
if let Ok(tz) = std::fs::read_to_string("/etc/timezone") {
let tz = tz.trim().to_string();
if !tz.is_empty() {
return Ok(tz);
}
}
// Default to UTC if detection fails
Ok("UTC".to_string())
}
#[tauri::command]
pub async fn detect_aws_config() -> Result<Option<String>, String> {
if let Some(home) = dirs::home_dir() {