Sailfish OS ‑ No app required

A collection of things you can accomplish with Sailfish OS without the need to install an app. Scripts & configs available here and here (where they might be more up-to-date than here).


Most tips require command line access (via SSH), i.e. you have

  1. enabled Developer mode (and remote connection)
  2. chosen a password

in Settings => Developer tools.

If e.g. your phone is connected to the same WiFi router as your computer and got the IP, then you can

$> ssh defaultuser@

You will be asked to enter your SFOS developer password. However, we strongly recommend to make ssh more secure.

If SSH seems too daunting, developer mode will automatically install the terminal app on your phone and you can do everything there.

You will also need a CLI text edtor. vi is preinstalled, but I like nano more:

$> devel-su pkcon install nano

Limit Charging Current

Lithium-Ion batteries do not like heat. It's a good idea to limit the charging current. An app exists for that: Battery Buddy and it's great, but by now SFOS incorporates most of its functionality - except for limiting the charging current.

My device defaults to 2400mA, but I would lke to reduce it to 1000mA (PC-USB slow charge is 500mA) - which is still fast enough to be usable for me.

The script:

#!/bin/sh dir=/sys/class/power_supply/battery # could also be /sys/class/power_supply/axp20x-battery file1=constant_charge_current_max file2=input_current_limited # maximum current in mA from file, or default value: currmax=1000 # this file is sourced and can override any of the vars above conf=/home/defaultuser/.config/chargecurrent.env [ -r $conf ] && . $conf [ "$currmax" -gt 0 ] && [ "$currmax" -le 2400 ] || exit 1 cd "$dir" || exit 1 printf 'Current value %s:\t' $file1 cat $file1 || exit 1 printf 'Current value %s: \t' $file2 cat $file2 || exit 1 chmod +w $file1 $file2 || exit 1 echo $(($currmax * 1000)) > $file1 && echo 1 > $file2 printf ' New value %s:\t' $file1 cat $file1 printf ' New value %s: \t' $file2 cat $file2

But it needs to be executed after every reboot.

Save this file as /etc/systemd/system/chargecurrent.service:

[Unit] Description=Limit Charging Current After=home.mount [Service] ExecStart=/home/defaultuser/.local/share/git/sfos/battery/ [Install]

and enable the service:

systemctl enable chargecurrent

Remove any icon from app menu and/or customise it

This script will mark a chosen Desktop entry as hidden and give you the opportunity to clone it to your home, and customise it. It will ask for your password (Settings => Developer tools).

#!/bin/bash str="NoDisplay=true" dst="$HOME/.local/share/applications" src="/usr/share/applications" printf "%s\n" "Hide app menu items (.desktop files in $src)" "(and customise them)" cd "$src" || exit 1 PS3=" Choice: " select file in $(for i in *.desktop; do printf "%s " "${i%.*}"; done) do file="$file.desktop" echo "File: $src/$file" read -rp "Do you want to copy it to ~${dst#$HOME}? " x [ "$x" = y ] && cp "$file" "$dst/" grep -qi "^[[:blank:]]*$str[[:space:]]*" "$file" ||\ devel-su sed -i "s/\[[Dd]esktop [Ee]ntry\]/\[Desktop Entry\]\n$str/" "$src/$file" echo "Original menu item is now hidden" [ -r "$dst/$file" ] || continue read -rp "Do you want to edit it in ~${dst#$HOME}? " x [ "$x" = y ] && nano "$dst/$file" # Sth like this is necessary to force lipstick to use the edited version: mv "$dst/$file" "$dst/${file%.desktop}.$(date +%s).desktop" done

select does not appear to exist in Busybox' shell, hence I marked the scribt as bash. I honestly do not remember if bash comes preinstalled; if not: devel-su pkcon install gnu-bash.

Wrapper that will mount a remote location

...via sshfs before starting the app. Or make sure it is mounted. sshfs is in Chum.

#!/bin/bash # $1 mount basedir relative to home,e.g. "Music" # $2 ssh host to look up, also final mountdir # => mountdir=$HOME/$1/$2 # $3 remote directory to mount # the rest will be exec'd after mounting is done me="${0##*/}" #exec > /tmp/$me.log 2>&1 (( $# < 4 )) && { echo "Please provide mountbase, host, remote dir and command to execute"; exit 1; } for var in mountbase host remotedir; do declare "$var"="$1" echo "$var"="$1" shift done mountdir="$HOME/$mountbase/$host" # will be expanded with name of host . ~/.config/bash/notify date text="mounted on $mountdir with" text="$(grep "$text" /proc/self/mountstats)" if [[ "$text" != "" ]] then notify "" "" "" "" "" "~${mountdir#$HOME} already mounted" else # dependency checks for dep in sshfs ssh fusermount; do command -V $dep >/dev/null || exit 1 done hostname='' port='' user='' identityfile='' serveraliveinterval='' identitiesonly='' compression='' while read option value; do option="${option,,}" case "$option" in hostname|port|user|serveraliveinterval|identitiesonly|identityfile|compression) declare "$option"="$value" echo "$option"="$value" ;; esac done <<<"$(ssh -G "$host")" sshfs_options="follow_symlinks,ServerAliveInterval=$serveraliveinterval,reconnect,port=$port,IdentitiesOnly=$identitiesonly,IdentityFile=$identityfile,Compression=$compression" mkdir -p "$mountdir" || exit 1 location="${user}@$hostname:$remotedir" if sshfs -C -o "$sshfs_options" "$location" "$mountdir" then notify "" "" "" "" "" "Mounted $location on ~${mountdir#$HOME}" else notify "" "icon-lock-warning" "" "" "" "Failed: mounting $location" fusermount -u -z "$mountdir" fi fi "$@" grep "mounted on $mountdir with" /proc/self/mountstats && fusermount -u "$mountdir" sleep 10 grep "mounted on $mountdir with" /proc/self/mountstats && fusermount -u -z "$mountdir" exit 0

It will use whatever is configured in ~/.ssh/config for a (named) host, e.g.:

Host myserver
  Port 22222
  User me
  IdentityFile ~/.ssh/some_key

It can be used as a wrapper around apps, but will require modifying the launcher (see previous chapter). Example:

[Desktop Entry] Type=Application X-Nemo-Application-Type=generic # <--- !!! Icon=harbour-unplayer Exec=/home/defaultuser/.local/bin/mountwrapper Music myserver /home/me/music harbour-unplayer %F Name=Unplayer on Server MimeType=audio/flac;audio/x-flac;audio/aac;audio/x-aac;audio/mp4;audio/x-m4a;audio/x-m4b;audio/mpeg;audio/x-mp3;audio/x-mpeg;audio/mp3;application/ogg;audio/ogg;audio /x-ogg;audio/x-vorbis+ogg;audio/vorbis;audio/x-vorbis;audio/x-flac+ogg;audio/x-oggflac;audio/x-ape;audio/x-matroska;audio/x-wav;audio/wav;audio/vnd.wave;audio/x-scpls ;audio/x-mpegurl;application/; [X-Sailjail] Sandboxing=Disabled

Note that you have to change the X-Nemo-Application-Type to generic.

Disable Sailjail for File Managers or similar crucial apps

Disclaimer: it makes sense to have strict per-app permissions. Don't just do this whenever you think it might fix a problem!

But a filemanager is a powerful tool and should be able to see, copy and modify all files where appropriate (Linux file permissions still apply, this is not some sort of root mode).

Example for File Browser from the Jolla store:

  • install the app, but do not start it
  • execute devel-su nano /usr/share/applications/harbour-file-manager.desktop
  • edit the [X-Sailjail] section to look like this:
    [X-Sailjail] #Permissions=Audio;MediaIndexing;RemovableMedia;UserDirs;PublicDir #OrganizationName=harbour-file-browser #ApplicationName=harbour-file-browser Sandboxing=Disabled

    i.e. the old permissions are commented out and Sailjail is disabled.

Now you can start the app and it will see all files & folders.


It seems the PodQast application also requires this, otherwise it forgets all settings after a restart. Do it manually as above or use the Openrepos version.

Notification function

As sourced in a few of my scripts:

notify() { app="$1" icon="$2" summary="$3" text="$4" popup_summary="$5" popup_text="$6" [ "$icon" = "" ] && icon="icon-lock-information" [ "$app" = "" ] && app="${0##*/}" [ "$app" != "${app#-}" ] && app="\\$app" # esacpe leading dash # Why 42? gdbus call --session --dest org.freedesktop.Notifications --object-path /org/freedesktop/Notifications --method org.freedesktop.Notifications.Notify\ "$app" 42 "$icon" "$summary" "$text" "[]" "{'x-nemo-preview-summary':<'$popup_summary'>, 'x-nemo-preview-body':<'$popup_text'>}" 0 }

Usage examples:

  • notify "" "" "" "" "A very short reminder" will display a narrow notification popup across the top for a few seconds
  • notify "" "" "" "" "A very short reminder" "with additional explain" will display a normal notification popup near the top
  • notify "" "" "A reminder" "with more text or not" "A very short reminder" "with additional explain" will display a normal notification popup near the top and a persistent one in the notification area
  • notify "" "" "A reminder" "with more text or not" "A very short reminder" the same with a thin notification popup
  • notify "" "" "A reminder" "with more text or not" notification area only
  • notify "My new app" "icon-lock-warning" "A reminder" "with more text or not" "A very short reminder" the same with a different icon and app name

If you prefer a proper command line utility, install lipstick-qt5-tools which will give you notificationtool.


It's possible that some edits will not survive an OS or app update. In the end, modifying system files would be best achieved with patches for Patchmanager.