Skip to content
Draft
18 changes: 4 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,10 @@ SHELL ["/bin/ash", "-o", "pipefail", "-c"]
ARG BUILD_ARCH
WORKDIR /usr/src

# Install rlwrap
ARG RLWRAP_VERSION
RUN apk add --no-cache --virtual .build-deps \
build-base \
readline-dev \
ncurses-dev \
&& curl -L -s "https://github.com/hanslub42/rlwrap/releases/download/${RLWRAP_VERSION}/rlwrap-${RLWRAP_VERSION}.tar.gz" \
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Removing this makes RLWRAP_VERSION in the build.yaml obsolete.

| tar zxvf - -C /usr/src/ \
&& cd rlwrap-${RLWRAP_VERSION} \
&& ./configure \
&& make \
&& make install \
&& apk del .build-deps \
&& rm -rf /usr/src/*
# Install dependencies
RUN apk add --no-cache \
bash-completion
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It provides some of the functions used by the completion script, I'll take another look but pretty sure its needed

# No longer need rlwrap; base image already provides Bash/readline

# Install CLI
ARG CLI_VERSION
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# CLI for the Home Assistant Operating System

This is for the Home Assistant Operating System and is the login shell.
This is for the Home Assistant Operating System and is the login shell.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit; but looks like some newline issue after the revert, this change shouldn't be here.

84 changes: 84 additions & 0 deletions rootfs/etc/ha-cli/.repl_rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# ha REPL rcfile


# History configuration
HISTFILE=/tmp/.cli_history
HISTSIZE=1000
HISTFILESIZE=2000
PROMPT_COMMAND='history -a; history -c; history -r'
Comment thread
ikifar2012 marked this conversation as resolved.
Outdated

# Prompt
PS1='\[\e[32m\]ha > \[\e[0m\]'

# Intercept unknown commands and pass them to 'ha'
command_not_found_handle() {
# Execute as 'ha <command> <args>'
ha "$@"
return $?
}

# Friendly helpers
help() {
echo 'Note: Use "login" to enter operating system shell'
echo ''
echo '--------------------------------'
ha help
}
login() {
echo 'Entering OS shell...'
exit 10;
}
Comment on lines +14 to +24
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Some formatting issues here.


# Load bash-completion core and ha completion if available
if command -v ha >/dev/null 2>&1; then
if [ -f /etc/bash_completion.d/ha ]; then
# Load from standard location (native HA completion registers itself for 'ha')
. /etc/bash_completion.d/ha

# Wrapper function to inject 'ha' as first argument for all completions
if declare -F __start_ha >/dev/null 2>&1; then
__start_ha >/dev/null 2>&1 || true
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What's the point of this line?


# Clear ALL existing completions to ensure our wrapper is used
while read -r cmd; do
complete -r "$cmd" 2>/dev/null || true
done < <(complete -p | awk '{print $NF}')

# Universal completion handler - wraps everything as 'ha ...'
__ha_repl_complete() {
local cur prev words cword
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These variables are not used anywhere.


# Handle empty command line specially
if [[ ${#COMP_WORDS[@]} -eq 0 || ( ${#COMP_WORDS[@]} -eq 1 && -z "${COMP_WORDS[0]}" ) ]]; then
COMP_LINE="ha "
COMP_POINT=3
COMP_WORDS=(ha "")
COMP_CWORD=1
else
# Prepend 'ha' to existing words
COMP_LINE="ha $COMP_LINE"
COMP_POINT=$((COMP_POINT + 3))
COMP_WORDS=(ha "${COMP_WORDS[@]}")
COMP_CWORD=$((COMP_CWORD + 1))
fi

COMPREPLY=()
__start_ha
}

# Register our completion as the default for EVERYTHING
complete -D -F __ha_repl_complete # Default for any command
complete -E -F __ha_repl_complete # Empty command line
complete -I -F __ha_repl_complete 2>/dev/null || true # Initial word (bash 5+)
fi

fi

# Note: __start_ha is defined by the ha completion script
Comment thread
ikifar2012 marked this conversation as resolved.
Outdated

# Use native completion only; no implicit injection or extra bindings.
else
echo 'Warning: ha command not found; commands will fail' >&2
fi

# Use commands with explicit 'ha' prefix; native completion supports 'ha ...'
Comment thread
ikifar2012 marked this conversation as resolved.
Outdated
33 changes: 15 additions & 18 deletions rootfs/usr/bin/cli.sh
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
#!/bin/bash

# Print banner (best-effort)
ha banner || true

# Run CLI
COMMAND=""
while true; do
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Previously EOF (Ctrl+D) didn't exit this loop, while it does exit the REPL in the current implementation. We should also set set -o ignoreeof so only Ctrl+C exits it.

COMMAND="$(rlwrap -S $'\e[32mha > \e[0m' -H /tmp/.cli_history -o cat)"
# Create a minimal rcfile to drive an interactive Bash as our REPL
Comment thread
ikifar2012 marked this conversation as resolved.
Outdated
RC_FILE=/etc/ha-cli/.repl_rc
HISTFILE=/tmp/.cli_history

# Abort to host?
if [ "$COMMAND" == "help" ]; then
echo "Note: Use \"login\" to enter operating system shell"
elif [ "$COMMAND" == "login" ]; then
exit 10
elif [ "$COMMAND" == "exit" ]; then
exit
elif [ -z "${COMMAND##ha *}" ]; then
echo "Note: Leading 'ha' is not necessary in this HA CLI"
COMMAND=$(echo "$COMMAND" | cut -b 3-)
fi
# Ensure history file exists
touch "$HISTFILE" 2>/dev/null || true
Comment thread
ikifar2012 marked this conversation as resolved.
Outdated
if command -v ha >/dev/null 2>&1; then
completion_file_content=$(ha completion bash 2>/dev/null || true)
if [ -n "$completion_file_content" ]; then
echo "$completion_file_content" >/etc/bash_completion.d/ha 2>/dev/null || true
fi
fi

echo "$COMMAND" | xargs -o ha
echo ""
done

# Start interactive bash with our rcfile; no user profiles
exec bash --noprofile --rcfile "$RC_FILE" -i