Configuration file for default options
Is your feature request related to a problem? Please describe.
While the CLI gets complicated, configuration options can help easing it and allow better customization. For instance, a user may want to:
- always sandbox appimages
- always prevent the update of a certain app
- always install in appman mode
- always use
nolibfuseafter installing an appimage - always use
--alloption
Etc.
Describe the solution you'd like
A list of key-value pairs easily greppable in .config/appman/appman-config.
A simple yet rather general method could be the following:
- Each key correspond to a certain CLI flag (e.g.
all,sandbox, etc.) - If the value is
true, it is turned on in theAPP-MANAGERscript - If the value is anything else, it is added like
--flag value - Any other option can be added
The problem is that not all flag combinations are usable, so APP-MANAGER should pick them only when it makes sense.
Describe alternatives you've considered
JSON, wasily manageable with jq, but it would be an additional dependency
Asked Claude Sonnet 4 a help. Not tested!
I'll help you implement the configuration file feature for default options in the AM/AppMan script. Based on my analysis of the code and issue #1621, here's how we can implement this:
Implementation Plan
1. Configuration File Structure
The configuration file should be located at $APPMANCONFIG/appman-config and use a simple key-value format that's easily greppable:
# AM/AppMan Configuration File
# Set default options using key=value pairs
# Always sandbox AppImages
sandbox=true
# Always use --force-latest for installations
force-latest=true
# Always install in AppMan mode (for AM users)
user=true
# Always use nolibfuse after installing AppImages
nolibfuse=true
# Default to --all flag for certain operations
all=true
# Disable notifications by default
disable-notifications=true
# Custom icon theme handling
icons=true
# Lock specific apps from updates
lock=app1,app2,app3
2. Implementation Code
Here's the implementation to add to the APP-MANAGER script:
################################################################################################################################################################
# CONFIGURATION FILE SUPPORT
################################################################################################################################################################
# Configuration file path
CONFIG_FILE="$APPMANCONFIG/appman-config"
# Function to read configuration values
_read_config() {
local key="$1"
if [ -f "$CONFIG_FILE" ]; then
grep "^$key=" "$CONFIG_FILE" 2>/dev/null | cut -d'=' -f2- | head -1
fi
}
# Function to check if a config option is enabled (true)
_config_enabled() {
local key="$1"
local value=$(_read_config "$key")
[ "$value" = "true" ]
}
# Function to apply default configuration to command line arguments
_apply_default_config() {
local operation="$1"
shift
local args="$*"
# Initialize config flags
CONFIG_FLAGS=""
case "$operation" in
'install'|'-i'|'install-appimage'|'-ia'|'-ias'|'extra'|'-e')
# Apply installation-related defaults
_config_enabled "sandbox" && CONFIG_FLAGS="$CONFIG_FLAGS --sandbox"
_config_enabled "force-latest" && CONFIG_FLAGS="$CONFIG_FLAGS --force-latest"
_config_enabled "icons" && CONFIG_FLAGS="$CONFIG_FLAGS --icons"
_config_enabled "debug" && CONFIG_FLAGS="$CONFIG_FLAGS --debug"
_config_enabled "user" && [ "$AMCLI" = "am" ] && CONFIG_FLAGS="$CONFIG_FLAGS --user"
# Handle nolibfuse as post-install action
if _config_enabled "nolibfuse"; then
APPLY_NOLIBFUSE_AFTER_INSTALL="true"
fi
;;
'list'|'-l')
# Apply list-related defaults
_config_enabled "all" && CONFIG_FLAGS="$CONFIG_FLAGS --all"
_config_enabled "appimages" && CONFIG_FLAGS="$CONFIG_FLAGS --appimages"
_config_enabled "portable" && CONFIG_FLAGS="$CONFIG_FLAGS --portable"
;;
'query'|'-q')
# Apply query-related defaults
_config_enabled "all" && CONFIG_FLAGS="$CONFIG_FLAGS --all"
_config_enabled "appimages" && CONFIG_FLAGS="$CONFIG_FLAGS --appimages"
_config_enabled "portable" && CONFIG_FLAGS="$CONFIG_FLAGS --portable"
;;
'update'|'-u'|'-U')
# Apply update-related defaults
_config_enabled "all" && CONFIG_FLAGS="$CONFIG_FLAGS --all"
_config_enabled "apps" && CONFIG_FLAGS="$CONFIG_FLAGS --apps"
_config_enabled "debug" && CONFIG_FLAGS="$CONFIG_FLAGS --debug"
;;
esac
# Apply notification settings globally
if _config_enabled "disable-notifications"; then
touch "$AMDATADIR"/disable-notifications
fi
# Return the combined flags (original args + config flags)
echo "$args $CONFIG_FLAGS"
}
# Function to handle post-installation configuration actions
_apply_post_install_config() {
local installed_app="$1"
# Apply nolibfuse if configured
if [ "$APPLY_NOLIBFUSE_AFTER_INSTALL" = "true" ]; then
if [ -f "$APPSPATH/$installed_app/$installed_app" ]; then
echo " ◆ Applying nolibfuse conversion (from config)..."
"$MODULES_PATH/management.am" nolibfuse "$installed_app" 2>/dev/null || true
fi
fi
# Apply automatic locking if configured
local lock_list=$(_read_config "lock")
if [ -n "$lock_list" ]; then
if echo "$lock_list" | grep -q "$installed_app"; then
echo " ◆ Locking $installed_app from updates (from config)..."
"$MODULES_PATH/management.am" lock "$installed_app" 2>/dev/null || true
fi
fi
# Apply automatic sandboxing if configured and not already done during install
if _config_enabled "auto-sandbox" && [ "$operation" != "sandbox" ]; then
if [ -f "$APPSPATH/$installed_app/$installed_app" ] && file "$APPSPATH/$installed_app/$installed_app" | grep -q "AppImage"; then
echo " ◆ Setting up sandbox (from config)..."
"$MODULES_PATH/sandboxes.am" --sandbox "$installed_app" 2>/dev/null || true
fi
fi
}
# Function to create a default configuration file
_create_default_config() {
if [ ! -f "$CONFIG_FILE" ]; then
mkdir -p "$APPMANCONFIG"
cat > "$CONFIG_FILE" << 'HEREDOC'
# AM/AppMan Configuration File
# Set default options using key=value pairs
# Use 'true' to enable boolean flags, or specify values for other options
# Installation defaults
#sandbox=true # Always sandbox AppImages during installation
#force-latest=true # Always use latest releases
#icons=true # Always integrate with system icon themes
#debug=false # Show debug output during operations
#user=true # Always install in AppMan mode (AM only)
# Post-installation actions
#nolibfuse=true # Apply nolibfuse conversion after AppImage installation
#auto-sandbox=true # Automatically sandbox AppImages after installation
#lock=app1,app2 # Comma-separated list of apps to lock from updates
# List/Query defaults
#all=false # Use --all flag by default
#appimages=false # Show only AppImages by default
#portable=false # Show only portable apps by default
# Update defaults
#apps=false # Update only apps, skip AM/AppMan itself
# Global settings
#disable-notifications=false # Disable update notifications
HEREDOC
echo " ◆ Created default configuration file at $CONFIG_FILE"
echo " ◆ Edit this file to set your default options"
fi
}
3. Integration Points
Now we need to integrate this into the existing script. Here are the key modifications:
A. Add to the main case statement (around line 1350):
case "$1" in
'')
echo "$DIVIDING_LINE"
echo $" USAGE: $AMCLI [OPTION]"
echo $" $AMCLI [OPTION] [ARGUMENT]"
echo ""
echo $" Run the \"$AMCLI -h\" command to find out more"
echo "$DIVIDING_LINE"
exit 0
;;
# Add new config command
'config-init')
_create_default_config
exit 0
;;
# EXTERNAL OPTIONS / MODULES
'about'|'-a'|\
'files'|'-f'|'-fi'|\
'list'|'-l'|\
'query'|'-q')
MODULE="database.am"
# Apply configuration defaults
set -- $(_apply_default_config "$@")
_use_module "$@"
;;
# ... rest of the cases with config integration
B. Modify the module usage function:
# HANDLE ALL THE EXTERNAL MODULES
_use_module() {
local original_args="$@"
# Apply configuration defaults before using modules
set -- $(_apply_default_config "$@")
# Test if module exists
if [ ! -f "$MODULES_PATH/$MODULE" ]; then
if [ "$CLI" = am ] && [ -f "$APPMANCONFIG"/appman-mode ] && [ -f "/usr/lib/am/modules/$MODULE" ]; then
MODULES_PATH="/usr/lib/am/modules"
elif [ "$CLI" = am ] && [ -f "$APPMANCONFIG"/appman-mode ] && [ -f "$(realpath /opt)/am/modules/$MODULE" ]; then
MODULES_PATH="$(realpath /opt)/am/modules"
else
_online_check
if ! wget -q "$MODULES_SOURCE/$MODULE" -O "$MODULES_PATH/$MODULE"; then
echo $" Module not found, run \"$AMCLI -s\" to update \"$AMCLIUPPER\""
exit 1
fi
fi
fi
# Source module
if [ -n "$NO_COLOR" ]; then
source "$MODULES_PATH/$MODULE" "$@" | sed -e 's/\x1b\[[0-9;]*m//g'
elif [ -t 1 ]; then
source "$MODULES_PATH/$MODULE" "$@"
else
source "$MODULES_PATH/$MODULE" "$@" | sed -e 's/\x1b\[[0-9;]*m//g'
fi
}
C. Add help section:
# In the help section, add:
echo -e $"
${Gold}config-init\033[0m
${LightBlue}$AMCLI config-init\033[0m
Description: Create a default configuration file at $APPMANCONFIG/appman-config to set default options for various operations.
"
4. Usage Examples
After implementation, users can:
-
Create config file:
am config-init -
Edit the config file:
nano ~/.config/appman/appman-config -
Example config for always sandboxing:
sandbox=true icons=true -
The config will automatically apply:
am -i firefox # Will automatically add --sandbox --icons flags
5. Benefits
- Backward compatibility: Existing commands work unchanged
- CLI override: Command-line flags override config file settings
- Extensible: Easy to add new configuration options
- Simple format: No external dependencies like
jq - Contextual: Different defaults for different operations
This implementation addresses all the requirements from issue #1621 while maintaining the script's existing functionality and adding powerful customization options for users.
This would be much easier if AM had proper array parsing that set internal env variables instead of what is going on right now.
I agree that some config would be nice, but the good implementation of it is complex & needs to be carefully designed before being implemented.
Currently, all config is scattered in ~/.local/share/AM/ & ~/.config/appman/appman-config.
What is very important is that if this would get implemented, there would be a need to mitigate the transition period, to convert all scattered config to new one, while cleaning old the config up, so users wouldn't see the change. That must be tested, especially for users updating from much older AM to latest one.
For config, it's better to use neutral language, for example:
instead of disable-notifications=true, notify=false is better & less confusing.
I would also have multiple locations for config, from least to most preferred, something like:
/usr/share/am/am-config(for Linux distributions)/opt/am/am-config(for administrators)~/.config/am/am-config(for users)
Now, for what is going to be in the config, I think your suggestion is generally good already, with note that custom icon theming option is not global at the moment, it only applies for currently installed applications. This was recently true for notifications also, but thankfully, that option is global now.
Looking from administrator & distro POV, they would also like the ability to easily preinstall applications in easy config, in this case from AM, without need to manually write the program & service for reliably doing that.
I implemented this for flatpak in BlueBuild's default-flatpaks module, but it's not portable, as it uses systemd, relies on bash syntax & some dependencies like jq.
https://blue-build.org/reference/modules/default-flatpaks/
Flatpak also plans to do this officially as a preinstall.d feature, but it's not done yet.
AM can make this easier, like with am distrosetup command or similar, then it's up to the distribution or administrator on how would he trigger that (through systemd timer or something else).
While this would be also nice for AM, that's another can of worms, where you need to manage system applications vs user applications preference, so that preinstallation config is not that important right now.
The idea of enclosing all the configurations in a single file is brilliant, and it is perfectly feasible.
Sure, using test -f (or the substitution -f) is faster than grep, but perfectly feasible and can be summarized in these functions.
But as has been demonstrated several times, jq (and Json files in general) are not necessary in this project. I have seen a lot of interesting code in this issue, and I would need more time to read and analyze it... but what I have focused on, is this part
cat > "$CONFIG_FILE" << 'HEREDOC'
# AM/AppMan Configuration File
# Set default options using key=value pairs
# Use 'true' to enable boolean flags, or specify values for other options
# Installation defaults
#sandbox=true # Always sandbox AppImages during installation
#force-latest=true # Always use latest releases
#icons=true # Always integrate with system icon themes
#debug=false # Show debug output during operations
#user=true # Always install in AppMan mode (AM only)
# Post-installation actions
#nolibfuse=true # Apply nolibfuse conversion after AppImage installation
#auto-sandbox=true # Automatically sandbox AppImages after installation
#lock=app1,app2 # Comma-separated list of apps to lock from updates
# List/Query defaults
#all=false # Use --all flag by default
#appimages=false # Show only AppImages by default
#portable=false # Show only portable apps by default
# Update defaults
#apps=false # Update only apps, skip AM/AppMan itself
# Global settings
#disable-notifications=false # Disable update notifications
HEREDOC
what can I say but BEAUTIFUL? I like this style for a config file.
The only thing I would change (and here the XDG Lawyer will go against me, @Samueru-sama ) is the location of the file. I would place everything in $AMDATADIR (aka ~/.local/share/AM, for those who don't know the variables in use in AM). As it stands, appman-config would force AM users to create a local profile.
That said, I would like to see a draft applied. In my way of seeing things I think the code in use could be further reduced... but it is better to move from theory to practice, and advance tested and reliable proposals.
@00sapo Also, fill out the config file with ALL the options you want to configure. Maybe "devmode" deserves a space too.
I can try to do something, but I need some time though.
Regarding the path for the config file, I would also prefer it in an XDG-compliant directory. So ~/.config/AM would be cleaner from my perspective and easier to find for users
I was trying to analyze point by point the configurations you would like to have by default
#sandbox=true # Always sandbox AppImages during installation
this is doable, you should always set the --sandbox flag to -i, or better, set the use of -ias as "alias" for -i
#force-latest=true # Always use latest releases
it's risky, if I don't set it in the scripts, there's always a reason: often Linux apps (be they AppImages or portables) are not always in "latest", and just yesterday I had to remove "latest" from a script, because the Linux app was not downloaded at all, because not in that release
the priority in AM is to ensure that the Linux app is installed, and the risk of not installing it is always high, since AM installs portable apps from other repositories, and does not keep its own database of physical packages, as APT, RPM or any repository does
AM is like AUR, it uses scripts to download from the original source, and provides the sources to upstream, in order to report bugs. If I had to store the packages, I would never have apps perfectly updated and in line with upstream, not to mention that the bugs would not be solved immediately, once reported
#icons=true # Always integrate with system icon themes
this is also doable, the --icons flag should always be set in the installation options
#debug=false # Show debug output during operations
this is also doable, the --debug flag should always be set in the installation options and the update
#user=true # Always install in AppMan mode (AM only)
at this point, you need to run am --user, accept and... amen (or better... AMen)
#nolibfuse=true # Apply nolibfuse conversion after AppImage installation
it would therefore be necessary to always keep appimagetool installed by default, since it is downloaded, used and removed, if not installed in $PATH via AM
#auto-sandbox=true # Automatically sandbox AppImages after installation
I just had a dejavu... I think it's the first one you asked
#lock=app1,app2 # Comma-separated list of apps to lock from updates
I don't think it's necessary, just run the am lock command on the app you don't want to update, so you can hide the AM-updater
List/Query defaults #all=false # Use --all flag by default #appimages=false # Show only AppImages by default #portable=false # Show only portable apps by default
of course... it's a mess. Having all these flags in the same configuration file would make them incompatible and conflicting if only two of them were enabled at the same time.
Update defaults #apps=false # Update only apps, skip AM/AppMan itself
I think the most natural thing for a user is to run am update, since many distros use this (with sudo)... and in my experience, am -s is not very intuitive. People tend to use "update" or "-u" (I've seen people use "-S", capitalized, they thought they were using PacMan instead of AppMan)
The downside of this setting? AM updates, and especially "timely" ones, aimed at fixing a bug immediately.
I don't think it's a good idea to set this.
Global settings #disable-notifications=false # Disable update notifications
doable... but it seems to me that this has already been added recently by putting a file to "intercept" in DATADIR
all in all, it seems that the most necessary default settings are those related to the -i flags, which are more or less necessary if you want to be sure to install the Firefox AppImage instead of its original build
and especially the sandbox, which is more tempting (since you wrote me twice ;) )
but there is one last aspect to consider
you know, with the current approach I try not to create too many directories (in CONGIGDIR, DATADIR and CACHEDIR) and then insert the necessary files in those directories only, where I use test and similar, to identify the functions to be executed
each function, already has its own reference file that must be intercepted to be executed. see the notifications one or the developer mode... or even the AppMan mode, which instead of AMDATADIR uses APPMANCONFIG
in my opinion, the approach you suggest is certainly the most standard, ordinary and widely adopted in projects
but tell me... is it really necessary?
I mean, I'm not saying it because I don't want to. I'm simply saying... would things really work better? Or would this approach add more complication? Especially to AppMan users? Because let's face it, there is already a directory in CONFIGDIR for AppMan (even in AM, if the user wants it), but an AM directory, with configuration files... whereas in AMDATADIR there is already a control system on the functions, with files all grouped in one place, with a weight of 0 bytes and whose only purpose is to be "seen" by AM...well, I would think about it a bit.
Hey, consider that the second post in this thread was a code from the AI, not from me, it chose the configuration option itself, we can add/remove anything.
I mean, I'm not saying it because I don't want to. I'm simply saying... would things really work better? Or would this approach add more complication? Especially to AppMan users? Because let's face it, there is already a directory in CONFIGDIR for AppMan (even in AM, if the user wants it), but an AM directory, with configuration files... whereas in AMDATADIR there is already a control system on the functions, with files all grouped in one place, with a weight of 0 bytes and whose only purpose is to be "seen" by AM...well, I would think about it a bit.
The thing is that files inside a share directory are intended not to be edited by hand. Linux users expect those files to be edited by CLI or by the program itself. What should/can be edited by hand must go into .config or at most in a dot file in the user's home (e.g. .bashrc).
I'll try working on it a bit during the we
to avoid creating other directories, let's try to create and use the directory ~/.config/appman
the file must be .config, to avoid confusing it with appman-config
Sorry, I spent the we on other personal projects. I'll try to do something about this sooner or later, but feel free to propose something if anyone likes
As I explained, the current approach is something that already works well, and I don't like creating too many directories for my project in the user's HOME.
We already have an "am" and "appman" directory in ~/.cache, an "AM" directory in ~/.local/share with lists and files to identify depending on the modes (and it is shared between AM and AppMan) and an "appman" directory in ~/.config that is used by AppMan or by AM users if they decide to use AppMan mode (so for the latter it is optional).
The solution you are looking for would be more applicable with "aliases" in ~/.bashrc or ~/.profile (depending on whether you use BASH, ZSH or FISH as your default shell) or more concrete by adding empty files (with zero weight) to identify with test or [ -f "file" ], and without grep.
There is also an aspect to consider: by relying on configurations, there is the risk of taking for granted the functionality of such options, in new and clean configurations, in the future, neglecting the importance of the flags and dedicated options. Let me explain worse:
am -ias firefox
guarantees you to install a Firefox AppImage in a sandbox, while
am -i firefox
will install the official portable archive.
Always using an alias for -i that is instead -ias or -ias --debug (to show the complete output of wget) could become such a habitual operation to forget the correct functioning of AM, on new systems and clean installations of AM.
I, personally, would delegate all this to a GUI, if anyone ever came up with the idea of building one.
@00sapo I've thought about it for a long time, and @fiftydinar has already given a good exposition on the difficulties that should be faced, here https://github.com/ivan-hc/AM/issues/1621#issuecomment-2939544128
In fact, I had probably found the right conclusions in my previous comment, saying this
I, personally, would delegate all this to a GUI, if anyone ever came up with the idea of building one.
In brief, your suggestion is good, if applied to programs like Fastfetch or similar. But a program like AM would need a GUI with checkboxes to enable all the configurations. Manually editing a text file would be a mess, given the immensity of options and flags present in AM.
On the other hand, AM is designed to be CLI, and is much more similar to MPV or FFMPEG in this sense.
When I started writing AM after the first "prototype" of AppMan, the first difficulty I found was "giving it a name".
I already had an AppMan repository, and many people were already using it and it worked very differently from now, for example, it did not respect Linux standards, installing everything from root in /opt/bin. So I wanted to write something from scratch.
The name "AM" was born from the need to have an extremely synthetic command, like apt and dnf, so much more synthetic already in the writing... and the options had to be equally synthetic, since I provide -i for install, -r or -R for remove... so in the space of 5-6 characters you already had a starting point to start any process, and depending on your habits, regardless of the system package manager, you already knew the basic options.
So, simplicity came first.
Then came the flags, too long to write... so I also started writing options like -ias which summarizes install-appimage --sandbox... and I forced and promoted the use of bash/zshell/fish completion, if present, in order to make writing easier, and created completion lists full of keywords and options to use with AM.
Sure, the introduction of flags has introduced more complexity, but that does not take away that methods to ease such difficulties are already present, and adding a configuration file for all of them, would only introduce complexity and confusion.
You just need to know how to know a program, to improve it and make it exceptional. And to be honest, I don't even know AM 100% anymore, given the enormity of the code I've written and accumulated over the years, to make it what it is today. Even refactoring and deduplicating popular commands and converting them to functions hasn't helped to make it simpler. And I'm trying not to add more options and flags on top of the ones that already exist. There's too much to control in AM.
That said, I do not think I plan such configurations on the CLI side. The CLI has already been designed to facilitate users as much as possible, through examples and help and error messages, with suggestions following, to direct the user towards the right choices. It is also a way to "educate" users on the use of AM, and why not? Maybe some users will think of taking the GUI issue a little more seriously.
I have always tried to promote AM as an engine to be used in a GUI, in order to facilitate all this, and suppress such complexity. But apparently, the desire to take this commitment seriously is decreasing, for one reason or another... also in me. But that's another story.
Closing as unplanned. Sorry.