Skip to content

t1266: Add daily OpenClaw auto-update to housekeeping routine#1995

Merged
marcusquinn merged 2 commits intomainfrom
feature/t1266-openclaw-auto-update
Feb 20, 2026
Merged

t1266: Add daily OpenClaw auto-update to housekeeping routine#1995
marcusquinn merged 2 commits intomainfrom
feature/t1266-openclaw-auto-update

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Feb 20, 2026

Summary

  • Adds check_openclaw_freshness() to auto-update-helper.sh — daily 24h-gated OpenClaw update check, same pattern as the existing skill freshness check
  • Silently skips if openclaw CLI is not installed (no-op for users without it)
  • Respects user's configured channel (beta/dev/stable) by parsing openclaw update status
  • Opt-out via AIDEVOPS_OPENCLAW_AUTO_UPDATE=false; frequency via AIDEVOPS_OPENCLAW_FRESHNESS_HOURS
  • State tracked in auto-update-state.json (last_openclaw_check); visible in aidevops auto-update status

Testing

  • ShellCheck: zero new violations (only pre-existing SC1091)
  • bash -n: syntax OK
  • Verified openclaw update --yes --no-restart works correctly (updated 2026.2.15 -> 2026.2.19-2)
  • Channel detection tested against openclaw update status table output

Closes #1994

Summary by CodeRabbit

  • New Features

    • Added automatic daily OpenClaw update checks (24-hour frequency).
    • Made auto-update checks opt-out via environment variable configuration.
    • Added configurable freshness interval for update checks.
    • Extended status output to display OpenClaw version and last check timestamp.
  • Documentation

    • Updated help text and environment variable documentation with OpenClaw auto-update settings.

Add check_openclaw_freshness() to auto-update-helper.sh with the same
24h-gated pattern as skill freshness checks. When openclaw CLI is
installed, runs 'openclaw update --yes --no-restart' daily, respecting
the user's configured channel (beta/dev/stable).

- New env vars: AIDEVOPS_OPENCLAW_AUTO_UPDATE, AIDEVOPS_OPENCLAW_FRESHNESS_HOURS
- State tracked in auto-update-state.json (last_openclaw_check)
- Status display shows OpenClaw version and last check time
- Silently skips if openclaw is not installed
@gemini-code-assist
Copy link

Summary of Changes

Hello @marcusquinn, 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 integrates an automated daily update routine for the OpenClaw CLI into the existing housekeeping script. It ensures OpenClaw stays current by checking for updates every 24 hours, respecting user preferences for update channels and providing configurable options for disabling or adjusting the update frequency. The update status is also made visible through the 'aidevops auto-update status' command.

Highlights

  • OpenClaw Auto-Update: Introduced a daily, 24-hour gated auto-update mechanism for the OpenClaw CLI.
  • Conditional Execution: The update process silently skips if the 'openclaw' CLI is not installed on the system.
  • Channel Awareness: The auto-update respects the user's configured OpenClaw update channel (beta/dev/stable).
  • Configurability: Provides an opt-out mechanism via the 'AIDEVOPS_OPENCLAW_AUTO_UPDATE=false' environment variable and allows frequency adjustment with 'AIDEVOPS_OPENCLAW_FRESHNESS_HOURS'.
  • State Management and Reporting: Tracks the last OpenClaw check timestamp in 'auto-update-state.json' and makes it visible through the 'aidevops auto-update status' command.
Changelog
  • .agents/scripts/auto-update-helper.sh
    • Updated script header comments to include OpenClaw auto-update functionality.
    • Added new environment variables 'AIDEVOPS_OPENCLAW_AUTO_UPDATE' and 'AIDEVOPS_OPENCLAW_FRESHNESS_HOURS' for configuration.
    • Defined 'DEFAULT_OPENCLAW_FRESHNESS_HOURS' constant.
    • Implemented the 'check_openclaw_freshness' function to manage the update logic, including installation checks, freshness gating, channel detection, and update execution.
    • Implemented the 'update_openclaw_check_timestamp' function to record the last check time in the state file.
    • Integrated calls to 'check_openclaw_freshness' into the 'cmd_check' function's various execution paths.
    • Enhanced the 'cmd_status' function to display the last OpenClaw check timestamp and the installed OpenClaw version.
    • Added a status note in 'cmd_status' if OpenClaw auto-update is disabled via environment variables.
    • Expanded documentation sections for 'ENVIRONMENT', 'HOW IT WORKS', and 'RATE LIMITS' to reflect the new OpenClaw auto-update features.
Activity
  • Performed ShellCheck, resulting in zero new violations beyond pre-existing SC1091.
  • Verified 'bash -n' for syntax correctness of the script.
  • Confirmed 'openclaw update --yes --no-restart' functionality by successfully updating OpenClaw from version 2026.2.15 to 2026.2.19-2.
  • Tested OpenClaw channel detection against 'openclaw update status' table output.
  • Closed issue t1266: Add openclaw auto-update to daily housekeeping in auto-update-helper.sh #1994, addressing the need for OpenClaw auto-updates.
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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 20, 2026

Warning

Rate limit exceeded

@marcusquinn has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 39 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.

Walkthrough

This PR adds automated daily OpenClaw update checking to the auto-update-helper script. It implements a 24-hour freshness gate, timestamp tracking, environment-variable configuration for opt-out and freshness interval, and integrates the check into existing update flows while updating status outputs.

Changes

Cohort / File(s) Summary
OpenClaw Auto-Update Integration
.agents/scripts/auto-update-helper.sh
Added check_openclaw_freshness() and update_openclaw_check_timestamp() functions implementing 24-hour gated update checks. Integrated OpenClaw version and last-check timestamp into status/log outputs. Added environment variables AIDEVOPS_OPENCLAW_AUTO_UPDATE and AIDEVOPS_OPENCLAW_FRESHNESS_HOURS with help/docs updates.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • PR #1591: Implements analogous skill freshness gate pattern with 24-hour timestamp tracking and helper functions, establishing the precedent this PR follows for OpenClaw.
  • PR #955: Extends auto-update-helper.sh infrastructure with OpenClaw-specific checks and state management functions integrated into update workflows.

Poem

🔄 When dawn breaks bright, the OpenClaw stirs,
Twenty-four hours since the last refresh whirs,
Update flows dance with timestamps kept true,
Freshness gated, automation brand-new!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding daily OpenClaw auto-update to the housekeeping routine, which aligns perfectly with the changeset.
Linked Issues check ✅ Passed The PR fully implements all coding requirements from #1994: check_openclaw_freshness() function, 24-hour gating, opt-out via AIDEVOPS_OPENCLAW_AUTO_UPDATE, configurable freshness via AIDEVOPS_OPENCLAW_FRESHNESS_HOURS, channel detection, and state tracking.
Out of Scope Changes check ✅ Passed All changes directly support the linked issue #1994 objectives: OpenClaw auto-update implementation, helper functions, state tracking, and documentation updates align with the defined scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/t1266-openclaw-auto-update

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.

@github-actions
Copy link

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 30 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Fri Feb 20 02:05:19 UTC 2026: Code review monitoring started
Fri Feb 20 02:05:19 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 30

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 30
  • VULNERABILITIES: 0

Generated on: Fri Feb 20 02:05:21 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

Copy link

@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

The pull request introduces daily OpenClaw auto-update functionality to the housekeeping routine, mirroring the existing skill freshness check. The changes include adding a new function check_openclaw_freshness, updating the cmd_check function to call it, and adding relevant environment variables and status output. The implementation generally follows the established patterns for auto-updates within the script. I've identified a few areas for improvement regarding error handling and adherence to the shell scripting style guide.

# Read last openclaw check timestamp from state file
local last_openclaw_check=""
if [[ -f "$STATE_FILE" ]] && command -v jq &>/dev/null; then
last_openclaw_check=$(jq -r '.last_openclaw_check // empty' "$STATE_FILE" 2>/dev/null || true)

Choose a reason for hiding this comment

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

medium

The jq command is used here to parse JSON, but its output is then used in a shell if condition. If jq fails (e.g., due to malformed JSON or if the key doesn't exist and // empty is not sufficient), the last_openclaw_check variable might contain an unexpected value or be empty, which could lead to incorrect logic or runtime errors later. While || true is used to guard against set -e, it doesn't ensure the content is valid for subsequent operations. It's better to explicitly check the output of jq for validity.

Suggested change
last_openclaw_check=$(jq -r '.last_openclaw_check // empty' "$STATE_FILE" 2>/dev/null || true)
last_openclaw_check=$(jq -r '.last_openclaw_check // empty' "$STATE_FILE" 2>/dev/null)
if [[ -z "$last_openclaw_check" || "$last_openclaw_check" == "null" ]]; then
last_openclaw_check=""
fi

local -a update_cmd=(openclaw update --yes --no-restart)
# Check if user has a channel preference in openclaw config
local openclaw_channel=""
openclaw_channel=$(openclaw update status 2>/dev/null | grep "Channel" | sed 's/[^a-zA-Z]*Channel[^a-zA-Z]*//' | awk '{print $1}' || true)

Choose a reason for hiding this comment

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

medium

The sed command used here is quite complex and relies on specific output formatting from openclaw update status. Parsing human-readable output from another command is generally fragile and can break if the output format changes. While the general rules state this is acceptable as a temporary measure with a robust fallback, the current implementation might be brittle. Consider if there's a more robust way to get the channel, perhaps openclaw has a machine-readable output option (e.g., JSON) or a dedicated command for this.

Suggested change
openclaw_channel=$(openclaw update status 2>/dev/null | grep "Channel" | sed 's/[^a-zA-Z]*Channel[^a-zA-Z]*//' | awk '{print $1}' || true)
openclaw_channel=$(openclaw update status --json 2>/dev/null | jq -r '.channel // empty' || true)
References
  1. Parsing human-readable output from another script is acceptable as a temporary measure if a robust fallback mechanism is implemented to mitigate the risk of the output format changing.

Comment on lines +575 to +577
jq --arg ts "$timestamp" \
'. + {last_openclaw_check: $ts}' \
"$STATE_FILE" >"$tmp_state" 2>/dev/null && mv "$tmp_state" "$STATE_FILE"

Choose a reason for hiding this comment

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

medium

The jq command here uses 2>/dev/null && mv "$tmp_state" "$STATE_FILE". If the jq command fails (e.g., due to malformed JSON in $STATE_FILE), the mv command will not execute, leaving the $STATE_FILE unchanged. However, the tmp_state file will still be created and then removed by the trap. This is generally fine, but it might be clearer to explicitly handle the jq failure and log a warning if the state file couldn't be updated.

Suggested change
jq --arg ts "$timestamp" \
'. + {last_openclaw_check: $ts}' \
"$STATE_FILE" >"$tmp_state" 2>/dev/null && mv "$tmp_state" "$STATE_FILE"
if jq --arg ts "$timestamp" \
'. + {last_openclaw_check: $ts}' \
"$STATE_FILE" >"$tmp_state" 2>/dev/null; then
mv "$tmp_state" "$STATE_FILE"
else
log_warn "Failed to update OpenClaw check timestamp in $STATE_FILE"
fi

Copy link
Contributor

@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

🧹 Nitpick comments (4)
.agents/scripts/auto-update-helper.sh (4)

350-363: Minor follow-up: update_state() initial document omits last_openclaw_check: null.

When update_state first creates the state file, it seeds last_skill_check: null but has no corresponding entry for last_openclaw_check. All readers handle the missing key gracefully (// empty, // "never"), so this is not a runtime bug — just a small inconsistency worth closing out.

♻️ One-liner fix in `update_state` else-branch
 			'{
                   enabled: true,
                   last_action: $action,
                   last_version: $version,
                   last_status: $status,
                   last_timestamp: $ts,
                   last_skill_check: null,
-                  skill_updates_applied: 0
+                  skill_updates_applied: 0,
+                  last_openclaw_check: null
               }' >"$STATE_FILE"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/auto-update-helper.sh around lines 350 - 363, The initial
state document created by update_state is missing the last_openclaw_check key;
update the else-branch that writes to STATE_FILE (the jq -n JSON block) to
include "last_openclaw_check: null" alongside last_skill_check: null so the
seeded document contains both fields (refer to the update_state function and
STATE_FILE write site).

350-363: Minor follow-up: update_state() initial document omits last_openclaw_check: null.

When update_state creates the state file from scratch (first ever run), it seeds last_skill_check: null but has no corresponding entry for last_openclaw_check. All readers handle the missing key gracefully (// empty, // "never"), so this is not a runtime bug, but it's inconsistent with the pattern established for the skill check.

♻️ Optional one-liner fix in `update_state` else-branch
 			'{
                   enabled: true,
                   last_action: $action,
                   last_version: $version,
                   last_status: $status,
                   last_timestamp: $ts,
                   last_skill_check: null,
-                  skill_updates_applied: 0
+                  skill_updates_applied: 0,
+                  last_openclaw_check: null
               }' >"$STATE_FILE"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/auto-update-helper.sh around lines 350 - 363, The initial
state document created by update_state() omits last_openclaw_check, creating an
inconsistency with the seeded last_skill_check field; update the else-branch
that writes to STATE_FILE so the JSON object also includes
"last_openclaw_check": null alongside last_skill_check: null (keep the other
keys unchanged) to ensure the initial state is consistent for readers expecting
that key.

958-965: Alignment nit — Last OpenClaw check: has one trailing space where peers use three.

  Last skill check:   $last_skill_check       ← 3 spaces
  Skill updates:      $skill_updates …        ← 6 spaces
  Last OpenClaw check: $last_openclaw_check   ← 1 space  ⚠️
  OpenClaw version:   $openclaw_ver           ← 3 spaces
🎨 Proposed fix
-		echo "  Last OpenClaw check: $last_openclaw_check"
+		echo "  Last OpenClaw check:  $last_openclaw_check"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/auto-update-helper.sh around lines 958 - 965, Summary: The
"Last OpenClaw check:" echo is misaligned (one space) compared to peers which
use three spaces; update the echo that prints last_openclaw_check to use the
same spacing/column alignment as other status lines. Locate the echo that
references the variable last_openclaw_check in the auto-update-helper.sh snippet
and change its formatting so there are three spaces after the colon (match the
spacing used by "Last skill check:" and "OpenClaw version:"), or switch to a
printf-based fixed-width field for consistent alignment across status lines.

958-965: Alignment nit — Last OpenClaw check: has one trailing space where peers use three.

  Last skill check:   $last_skill_check      ← 3 spaces
  Skill updates:      $skill_updates …       ← 6 spaces
  Last OpenClaw check: $last_openclaw_check  ← 1 space  ⚠️
  OpenClaw version:   $openclaw_ver          ← 3 spaces
🎨 Proposed fix — pad to match existing column
-		echo "  Last OpenClaw check: $last_openclaw_check"
+		echo "  Last OpenClaw check:  $last_openclaw_check"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/auto-update-helper.sh around lines 958 - 965, Adjust the
spacing in the echo that prints the Last OpenClaw check so the column lines up
with the other entries: update the echo using the variable last_openclaw_check
(the line that currently reads `echo "  Last OpenClaw check:
$last_openclaw_check"`) to use three spaces after the colon like the other
labels so it aligns with `Last skill check:` and `OpenClaw version:` output.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.agents/scripts/auto-update-helper.sh:
- Around line 541-545: The current channel extraction for openclaw
(openclaw_channel) is brittle and may pass arbitrary tokens to update_cmd;
change the parsing to explicitly whitelist only "stable", "beta", or "dev"
(case-insensitive) when reading output from `openclaw update status`, e.g.,
extract with a regex that matches only those three values and assign to
openclaw_channel; only set update_cmd=(openclaw update --channel
"$openclaw_channel" --yes --no-restart) when openclaw_channel is exactly "beta"
or "dev" (or non-empty and in the whitelist), otherwise leave update_cmd without
--channel so the persisted config is used; also ensure
update_openclaw_check_timestamp is not called unconditionally after a failed
parse — call it only after a successful update invocation or when you
intentionally decided to skip passing a channel.
- Around line 541-545: The channel extraction is fragile and may pass invalid
tokens to update_cmd; modify the logic around the openclaw_channel variable to
validate the extracted value against a whitelist of the three supported channels
("stable", "beta", "dev") before assigning update_cmd, so only those exact
values will set update_cmd=(openclaw update --channel "$openclaw_channel" --yes
--no-restart); if the extracted token is empty or not one of the three, leave
update_cmd unset (fall back to default) and do not call
update_openclaw_check_timestamp based on a bad parse. Use the existing
openclaw_channel variable and update_cmd symbol names to locate and change the
parsing/validation block.

---

Nitpick comments:
In @.agents/scripts/auto-update-helper.sh:
- Around line 350-363: The initial state document created by update_state is
missing the last_openclaw_check key; update the else-branch that writes to
STATE_FILE (the jq -n JSON block) to include "last_openclaw_check: null"
alongside last_skill_check: null so the seeded document contains both fields
(refer to the update_state function and STATE_FILE write site).
- Around line 350-363: The initial state document created by update_state()
omits last_openclaw_check, creating an inconsistency with the seeded
last_skill_check field; update the else-branch that writes to STATE_FILE so the
JSON object also includes "last_openclaw_check": null alongside
last_skill_check: null (keep the other keys unchanged) to ensure the initial
state is consistent for readers expecting that key.
- Around line 958-965: Summary: The "Last OpenClaw check:" echo is misaligned
(one space) compared to peers which use three spaces; update the echo that
prints last_openclaw_check to use the same spacing/column alignment as other
status lines. Locate the echo that references the variable last_openclaw_check
in the auto-update-helper.sh snippet and change its formatting so there are
three spaces after the colon (match the spacing used by "Last skill check:" and
"OpenClaw version:"), or switch to a printf-based fixed-width field for
consistent alignment across status lines.
- Around line 958-965: Adjust the spacing in the echo that prints the Last
OpenClaw check so the column lines up with the other entries: update the echo
using the variable last_openclaw_check (the line that currently reads `echo " 
Last OpenClaw check: $last_openclaw_check"`) to use three spaces after the colon
like the other labels so it aligns with `Last skill check:` and `OpenClaw
version:` output.

Prevents garbage from a parse failure being passed to --channel flag,
which would fail and burn the 24h gate. Only beta and dev need the
explicit flag; stable is the default.
@github-actions
Copy link

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 30 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Fri Feb 20 02:14:55 UTC 2026: Code review monitoring started
Fri Feb 20 02:14:55 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 30

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 30
  • VULNERABILITIES: 0

Generated on: Fri Feb 20 02:14:58 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

@marcusquinn
Copy link
Owner Author

@coderabbitai resolve

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 20, 2026

✅ Actions performed

Comments resolved and changes approved.

@marcusquinn marcusquinn merged commit 1550b64 into main Feb 20, 2026
11 checks passed
@marcusquinn marcusquinn deleted the feature/t1266-openclaw-auto-update branch February 21, 2026 01:59
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.

t1266: Add openclaw auto-update to daily housekeeping in auto-update-helper.sh

1 participant