Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .agents/scripts/aidevops-update-check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,51 @@ get_git_context() {
return 0
}

is_headless() {
# Detect non-interactive/headless mode from multiple signals.
# The --interactive flag overrides all headless detection (used by
# AGENTS.md greeting flow when the model intentionally wants the
# full update check despite running inside a Bash tool with no TTY).
local arg
for arg in "$@"; do
if [[ "$arg" == "--interactive" ]]; then
return 1
fi
done
# 1. Explicit env vars set by dispatch systems
if [[ "${FULL_LOOP_HEADLESS:-}" == "true" ]]; then
return 0
fi
if [[ "${OPENCODE_HEADLESS:-}" == "true" ]]; then
return 0
fi
if [[ "${AIDEVOPS_HEADLESS:-}" == "true" ]]; then
return 0
fi
# 2. CLI flag: --headless passed to this script
for arg in "$@"; do
if [[ "$arg" == "--headless" ]]; then
return 0
fi
done
# 3. No TTY on stdin (piped input, e.g. opencode run / claude -p)
# This catches cases where the model ignores AGENTS.md skip rules.
if [[ ! -t 0 ]]; then
return 0
fi
return 1
}
Comment on lines +130 to +163

Choose a reason for hiding this comment

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

medium

The is_headless function can be made more efficient and readable. It currently iterates over the script's arguments twice to check for --interactive and --headless flags. This can be done in a single pass, improving loop efficiency and aligning with best practices for robust CLI argument parsing. Additionally, the multiple if statements for checking environment variables can be consolidated into one for conciseness.

is_headless() {
	# Detect non-interactive/headless mode from multiple signals.
	# The --interactive flag overrides all headless detection (used by
	# AGENTS.md greeting flow when the model intentionally wants the
	# full update check despite running inside a Bash tool with no TTY).
	local interactive=false
	local headless=false
	local arg
	for arg in "$@" ; do
		case "$arg" in
			--interactive) interactive=true ;;
			--headless) headless=true ;;
		esac
	done

	if [[ "$interactive" == "true" ]]; then
		return 1
	}

	# 1. Explicit env vars set by dispatch systems
	if [[ "${FULL_LOOP_HEADLESS:-}" == "true" || "${OPENCODE_HEADLESS:-}" == "true" || "${AIDEVOPS_HEADLESS:-}" == "true" ]]; then
		return 0
	}

	# 2. CLI flag
	if [[ "$headless" == "true" ]]; then
		return 0
	}

	# 3. No TTY on stdin (piped input, e.g. opencode run / claude -p)
	#    This catches cases where the model ignores AGENTS.md skip rules.
	if [[ ! -t 0 ]]; then
		return 0
	}

	return 1
}
References
  1. When parsing CLI command strings to extract specific arguments, use a robust method that accounts for different flag formats (e.g., '--flag value', '--flag=value', and valueless flags) by maintaining a whitelist of flags known to consume an additional argument. This rule emphasizes using robust methods for parsing CLI arguments, which includes efficient single-pass processing of flags like --interactive and --headless.
  2. In shell scripts, move the calculation of loop-invariant variables outside of loops to improve efficiency. This rule promotes improving loop efficiency by avoiding redundant iterations, such as processing the same argument list multiple times when a single pass suffices.


main() {
# In headless/non-interactive mode, skip the network call entirely.
# This is the #1 fix for "update check kills non-interactive sessions".
if is_headless "$@"; then
local current
current=$(get_version)
echo "aidevops v$current (headless - skipped update check)"
return 0
fi

local current remote app_info app_name app_version git_context
current=$(get_version)
remote=$(get_remote_version)
Expand Down
Loading