Skip to content

t2721: Add user-configurable feature toggles#2728

Merged
alex-solovyev merged 1 commit intomainfrom
feature/feature-toggles
Mar 2, 2026
Merged

t2721: Add user-configurable feature toggles#2728
alex-solovyev merged 1 commit intomainfrom
feature/feature-toggles

Conversation

@marcusquinn
Copy link
Copy Markdown
Owner

Summary

  • Adds a unified feature toggle system (aidevops config) so users can disable auto-updates, opt out of opencode.json/claude config management, supervisor pulse, repo-sync, onboarding prompts, and safety hooks — without needing /onboarding
  • Config lives in ~/.config/aidevops/feature-toggles.conf (shell-sourceable key=value), with documented defaults shipped at .agents/configs/feature-toggles.conf.defaults
  • Priority order: environment variables > user config > defaults — existing env var overrides (e.g., AIDEVOPS_AUTO_UPDATE=false) continue to work

Changes

New files

  • .agents/configs/feature-toggles.conf.defaults — All 17 toggles with documentation
  • .agents/scripts/feature-toggle-helper.sh — CLI helper for list, get, set, reset, path, help

Modified files

  • shared-constants.sh — Added _load_feature_toggles(), get_feature_toggle(), is_feature_enabled() with env var mapping
  • aidevops.sh — Added config command routing in main() + help text
  • setup.sh — Guards for auto-update, supervisor pulse, repo-sync, onboarding prompt, safety hooks, and config management calls
  • setup-modules/config.sh — Guards for update_opencode_config() and update_claude_config()
  • auto-update-helper.sh — Replaced raw env var checks with is_feature_enabled for skill, tool, and openclaw sub-updates

Testing

  • ShellCheck clean on all modified files
  • Functional testing: aidevops config list, get, set, reset, path, help all verified
  • Priority chain verified: env var > user config > defaults
  • is_feature_enabled verified in bash context

Closes #2721

@github-actions github-actions bot added the enhancement Auto-created from TODO.md tag label Mar 2, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 2, 2026

Warning

Rate limit exceeded

@alex-solovyev has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 7 minutes and 14 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 6ca4967 and 767c97e.

📒 Files selected for processing (7)
  • .agents/configs/feature-toggles.conf.defaults
  • .agents/scripts/auto-update-helper.sh
  • .agents/scripts/feature-toggle-helper.sh
  • .agents/scripts/shared-constants.sh
  • aidevops.sh
  • setup-modules/config.sh
  • setup.sh
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/feature-toggles

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
Copy Markdown
Contributor

github-actions bot commented Mar 2, 2026

🔍 Code Quality Report

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

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

�[0;34m[INFO]�[0m Recent monitoring activity:
Mon Mar 2 18:10:12 UTC 2026: Code review monitoring started
Mon Mar 2 18:10:12 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 111

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 111
  • VULNERABILITIES: 0

Generated on: Mon Mar 2 18:10:14 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, 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 introduces a comprehensive feature toggle system for aidevops, providing users with greater control over various functionalities. It includes a default configuration file, a CLI helper for managing toggles, and modifications to existing scripts to respect the toggle settings. This enhancement allows users to customize their aidevops experience and disable features as needed.

Highlights

  • Feature Toggles: Introduced a unified feature toggle system, allowing users to disable various functionalities like auto-updates, opencode.json/claude config management, supervisor pulse, repo-sync, onboarding prompts, and safety hooks.
  • Configuration: The configuration is managed through ~/.config/aidevops/feature-toggles.conf, with defaults provided in .agents/configs/feature-toggles.conf.defaults. Environment variables take precedence over user configurations and defaults.
  • CLI Helper: Added a CLI helper (.agents/scripts/feature-toggle-helper.sh) for listing, getting, setting, and resetting feature toggles.
Activity
  • New files added: .agents/configs/feature-toggles.conf.defaults and .agents/scripts/feature-toggle-helper.sh.
  • Modified files: shared-constants.sh, aidevops.sh, setup.sh, setup-modules/config.sh, and auto-update-helper.sh.
  • Testing: ShellCheck clean, functional testing of CLI commands, priority chain verification, and is_feature_enabled verification.
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.

@alex-solovyev
Copy link
Copy Markdown
Collaborator

PR has merge conflicts after #2727 was merged (both touch shared-constants.sh, auto-update-helper.sh, and setup.sh). Dispatching worker to rebase and resolve conflicts.

Copy link
Copy Markdown

@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 introduces a unified feature toggle system, a significant improvement for user configuration and managing application features. However, it introduces critical security concerns. Specifically, the use of sed with unvalidated input for writing configuration values can lead to command injection, and the use of eval to set variables from user-configurable files poses a critical risk of arbitrary code execution. A lack of newline validation also allows for configuration injection. Additionally, the implementation has widespread issues with error suppression (2>/dev/null) that could mask important problems, and there's an opportunity to improve maintainability by dynamically generating toggle keys instead of hardcoding them.

# Validate key is alphanumeric + underscore
[[ "$key" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]] || continue
# Store as _FT_<key>
eval "_FT_${key}=\"\${value}\""
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

Using eval to set variables from a user-configurable file is a security risk. A malicious value in feature-toggles.conf.defaults could lead to arbitrary code execution. For example, a value like true"; rm -rf /; echo "pwned would be executed. Please use a safer method like printf -v to assign the value.

Suggested change
eval "_FT_${key}=\"\${value}\""
printf -v "_FT_${key}" "%s" "${value}"
References
  1. Do not use 'eval' to execute dynamically constructed commands in shell scripts due to security risks; use bash arrays and 'read -ra' to store and execute command parts safely, passing complex arguments like JSON payloads as separate elements.

key="${line%%=*}"
value="${line#*=}"
[[ "$key" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]] || continue
eval "_FT_${key}=\"\${value}\""
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

Using eval to set variables from a user-configurable file (~/.config/aidevops/feature-toggles.conf) is a security risk. A malicious value in the config file could lead to arbitrary code execution. For example, a value like true"; rm -rf /; echo "pwned would be executed. Please use a safer method like printf -v to assign the value.

Suggested change
eval "_FT_${key}=\"\${value}\""
printf -v "_FT_${key}" "%s" "${value}"
References
  1. Do not use 'eval' to execute dynamically constructed commands in shell scripts due to security risks; use bash arrays and 'read -ra' to store and execute command parts safely, passing complex arguments like JSON payloads as separate elements.

return 0
fi

if grep -qE "^${key}=" "$USER_CONFIG" 2>/dev/null; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Suppressing stderr with 2>/dev/null can hide important errors, such as file permission issues. The file's existence is checked before this line, but it might not be readable. It's better to let the script fail with a clear error message if grep cannot read the file.

Suggested change
if grep -qE "^${key}=" "$USER_CONFIG" 2>/dev/null; then
if grep -qE "^${key}=" "$USER_CONFIG"; then
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

# Validate key exists in defaults
local default_val
default_val=$(_get_default "$key")
if [[ -z "$default_val" ]] && ! grep -qE "^${key}=" "$DEFAULTS_CONFIG" 2>/dev/null; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Suppressing stderr with 2>/dev/null can hide important errors, such as file permission issues with $DEFAULTS_CONFIG. Since set -e is active, it's better to let the script fail with a clear error message rather than continuing with potentially incorrect assumptions.

Suggested change
if [[ -z "$default_val" ]] && ! grep -qE "^${key}=" "$DEFAULTS_CONFIG" 2>/dev/null; then
if [[ -z "$default_val" ]] && ! grep -qE "^${key}=" "$DEFAULTS_CONFIG"; then
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

if [[ "${AIDEVOPS_TOOL_AUTO_UPDATE:-}" == "false" ]]; then
log_info "Tool auto-update disabled via AIDEVOPS_TOOL_AUTO_UPDATE=false"
# Opt-out via feature toggle (env var or config file)
if ! is_feature_enabled tool_auto_update 2>/dev/null; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Suppressing stderr with 2>/dev/null can hide important errors. If the is_feature_enabled function is not found, this will be silenced, making debugging difficult. It's better to let the script fail with a clear error message, as set -e is active.

Suggested change
if ! is_feature_enabled tool_auto_update 2>/dev/null; then
if ! is_feature_enabled tool_auto_update; then
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

else
print_info "OpenCode config management disabled via feature toggle"
fi
if is_feature_enabled manage_claude_config 2>/dev/null; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Suppressing stderr with 2>/dev/null can hide important errors. If the is_feature_enabled function is not found, this will be silenced, making debugging difficult. It's better to let the script fail with a clear error message, as set -e is active.

Suggested change
if is_feature_enabled manage_claude_config 2>/dev/null; then
if is_feature_enabled manage_claude_config; then
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

local auto_update_script="$HOME/.aidevops/agents/scripts/auto-update-helper.sh"
if [[ -x "$auto_update_script" ]] && [[ "${AIDEVOPS_AUTO_UPDATE:-true}" != "false" ]]; then
if [[ -x "$auto_update_script" ]] && is_feature_enabled auto_update 2>/dev/null; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Suppressing stderr with 2>/dev/null can hide important errors. If the is_feature_enabled function is not found, this will be silenced, making debugging difficult. It's better to let the script fail with a clear error message, as set -e is active.

Suggested change
if [[ -x "$auto_update_script" ]] && is_feature_enabled auto_update 2>/dev/null; then
if [[ -x "$auto_update_script" ]] && is_feature_enabled auto_update; then
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

@@ -700,7 +723,8 @@ main() {
# macOS: launchd plist invoking wrapper | Linux: cron entry invoking wrapper
# The plist is ALWAYS regenerated on setup.sh to pick up config changes (env vars,
# thresholds). Only the first-install prompt is gated on _pulse_installed.
if [[ "${AIDEVOPS_SUPERVISOR_PULSE:-true}" != "false" ]]; then
# Respects feature toggle: aidevops config set supervisor_pulse false
if is_feature_enabled supervisor_pulse 2>/dev/null; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Suppressing stderr with 2>/dev/null can hide important errors. If the is_feature_enabled function is not found, this will be silenced, making debugging difficult. It's better to let the script fail with a clear error message, as set -e is active.

Suggested change
if is_feature_enabled supervisor_pulse 2>/dev/null; then
if is_feature_enabled supervisor_pulse; then
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

Comment on lines +1358 to +1368
local toggle_keys="auto_update update_interval skill_auto_update skill_freshness_hours tool_auto_update tool_freshness_hours tool_idle_hours supervisor_pulse repo_sync openclaw_auto_update openclaw_freshness_hours manage_opencode_config manage_claude_config session_greeting safety_hooks shell_aliases onboarding_prompt"
local tk env_var env_val
for tk in $toggle_keys; do
env_var=$(_ft_env_map "$tk")
if [[ -n "$env_var" ]]; then
env_val="${!env_var:-}"
if [[ -n "$env_val" ]]; then
eval "_FT_${tk}=\"\${env_val}\""
fi
fi
done
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The list of toggle_keys is hardcoded. This creates a maintenance burden, as this list must be manually updated whenever a new toggle with an environment variable mapping is added to feature-toggles.conf.defaults. To improve maintainability, consider generating this list dynamically by parsing the keys from the $FEATURE_TOGGLES_DEFAULTS file.

Comment on lines +208 to +211
if [[ -z "$key" || -z "$value" ]]; then
print_error "Usage: aidevops config set <key> <value>"
return 1
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security-medium medium

The value argument in cmd_set is not validated for newlines. An attacker can inject newlines to add arbitrary key-value pairs to the configuration file, bypassing the key validation check performed at the beginning of the function. Since these values are later processed by eval in shared-constants.sh (though currently safely quoted), this could lead to unexpected behavior or future vulnerabilities.

Recommendation: Validate that the value argument does not contain newlines before processing it.

Suggested change
if [[ -z "$key" || -z "$value" ]]; then
print_error "Usage: aidevops config set <key> <value>"
return 1
fi
if [[ -z "$key" || -z "$value" ]]; then
print_error "Usage: aidevops config set <key> <value>"
return 1
fi
if [[ "$value" == *$'\n'* ]]; then
print_error "Value cannot contain newlines"
return 1
fi

@smashah
Copy link
Copy Markdown

smashah commented Mar 2, 2026

These configs are not enough. EVERYTHING needs to be configurable. The skills used, every question in onboarding, every question in setup.sh, which agents aidevops injects its context into, which skills/commands are downloaded/updated, which tools are installed, etc. etc. etc.

@smashah
Copy link
Copy Markdown

smashah commented Mar 2, 2026

Also it should be jsonc, not .conf

@alex-solovyev
Copy link
Copy Markdown
Collaborator

Killed stuck worker (PID 2723667, 3h+ uptime, 5375 messages, 0 commits — thrashing). Supervisor will resolve conflicts directly via git rebase and push.

@alex-solovyev alex-solovyev force-pushed the feature/feature-toggles branch from b1b9f5d to 22e868e Compare March 2, 2026 18:21
@alex-solovyev
Copy link
Copy Markdown
Collaborator

Supervisor resolved merge conflicts directly via git rebase. Conflicts were in setup.sh, shared-constants.sh, and auto-update-helper.sh — all three had the same pattern: main added inline settings.json jq checks in PR #2727, this PR replaces them with is_feature_enabled calls. Kept the feature-toggles version throughout (strictly better). Branch force-pushed, waiting for CI.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 2, 2026

🔍 Code Quality Report

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

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

�[0;34m[INFO]�[0m Recent monitoring activity:
Mon Mar 2 18:21:54 UTC 2026: Code review monitoring started
Mon Mar 2 18:21:54 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 111

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 111
  • VULNERABILITIES: 0

Generated on: Mon Mar 2 18:21:57 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@alex-solovyev
Copy link
Copy Markdown
Collaborator

Killed thrashing worker (PID 2737838, uptime 1h52m, struggle_ratio 417 — 417 messages, 0 commits). PR #2729 is already merged. PR #2728 has all CI checks passing but has a merge conflict. Pulse supervisor is taking over to resolve the conflict and merge.

@marcusquinn marcusquinn force-pushed the feature/feature-toggles branch from 22e868e to 031a5ba Compare March 2, 2026 18:25
@marcusquinn
Copy link
Copy Markdown
Owner Author

Rebased onto main after PR #2729 merged. Resolved conflict in setup.sh: kept both init_settings_json (from #2729) and the feature-toggle gating for setup_safety_hooks (from this PR). Force-pushed to update.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 2, 2026

🔍 Code Quality Report

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

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

�[0;34m[INFO]�[0m Recent monitoring activity:
Mon Mar 2 18:25:54 UTC 2026: Code review monitoring started
Mon Mar 2 18:25:54 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 111

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 111
  • VULNERABILITIES: 0

Generated on: Mon Mar 2 18:25:57 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

Add a unified feature toggle system so users can disable auto-updates,
opt out of opencode.json/claude config management, and control other
opinionated behaviours without needing /onboarding.

New files:
- .agents/configs/feature-toggles.conf.defaults: documented defaults
- .agents/scripts/feature-toggle-helper.sh: CLI for aidevops config

Modified:
- shared-constants.sh: _load_feature_toggles(), get_feature_toggle(),
  is_feature_enabled() with env var > user config > defaults priority
- aidevops.sh: config command routing + help text
- setup.sh: guards for auto-update, supervisor pulse, repo-sync,
  onboarding prompt, safety hooks, and config management
- setup-modules/config.sh: guards for opencode + claude config
- auto-update-helper.sh: replaced raw env var checks with
  is_feature_enabled for skill, tool, and openclaw sub-updates

Config: ~/.config/aidevops/feature-toggles.conf (shell-sourceable)
CLI: aidevops config [list|get|set|reset|path|help]

Closes #2721
@alex-solovyev alex-solovyev force-pushed the feature/feature-toggles branch from 031a5ba to 767c97e Compare March 2, 2026 18:28
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 2, 2026

🔍 Code Quality Report

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

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

�[0;34m[INFO]�[0m Recent monitoring activity:
Mon Mar 2 18:29:15 UTC 2026: Code review monitoring started
Mon Mar 2 18:29:16 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 111

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 111
  • VULNERABILITIES: 0

Generated on: Mon Mar 2 18:29:18 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Mar 2, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Auto-created from TODO.md tag

Projects

None yet

Development

Successfully merging this pull request may close these issues.

lack of sensible on-the-fly configurability breaks everything constantly.

3 participants