I run a LineageOS device with MicroG, but since the default messaging app is not able to be disabled I need to remove it everytime I flash an update file. This is becoming more and more tedious as more apps I need to remove on update increase.

How do you write a script that removes these apps whenever you flash so the removal changes persists? Something like addon.d but that is for backing up apps.

Edit : Both answers are correct, the one I posted and the one by Death Mask Salesman. I accepted the one by Death Mask Salesman because it is relevant to the question, however the one I posted solved my problem.

  • I'm a bit late to the party, but addon.d scripts aren't only for backup purposes. Assuming that the app you wish to remove be, say, AudioFX, you could write one such script that executes rm -rf on /system/priv-app/AudioFX. This would remove AudioFX each time you flash an OTA. – Grimoire Oct 4 '18 at 16:26
  • Thanks, Kuo! I've fixed formatting and gave it a thumbs-up. Will cleanup comments now. Consider taking a look at Adebar nevertheless, you'll find some other interesting aspects with it (like the device documentation or the backup scripts it generates). – Izzy Oct 4 '18 at 20:09
  • @DeathMaskSalesman How would you write something like that? I tried a few options but I just can't get it right, I eventually gave up and manually remove them instead. – Ojii Oct 5 '18 at 6:03
  • @Izzy I will take a look at it more! In all honesty, when I first looked at it, it overwhelms me,. – Ojii Oct 5 '18 at 6:05
  • @KuoChongYii I'll write an answer in due time. – Grimoire Oct 5 '18 at 8:59

As an alternative to the other answer, I bring a more definitive approach, based on addon.d and targeted at system apps deletion.

Remember that, unlike the pm based method, which can be reversed at will, apps deleted with this approach can only be reobtained by commenting out the appropriate lines in the debloater script and reapplying the OTA update.


Any shell script in the /system/addon.d directory is executed right after an OTA update has been applied. The order of execution depends on the integer at the beginning of a file's name, since scripts are evaluated in increasing order.

The code

The removal of a system app is simply a matter of issuing rm -rf on the app's parent directory. We can thus write a script so that these removals are carried out seamlessly after each update.

If, for example, we want to remove the stock Email app, our script will look like


rm -rf "/system/app/Email"

Here, the #!/sbin/sh is a mandatory line that instructs TWRP about which program will evaluate the script. Do not remove it.

rm -rf is a command used to forcibly remove whatever follows it in a recursive fashion. Thus, rm -rf "/system/app/Email" removes the /system/app/Email directory and everything inside it, thereby deleting the Email app altogether.

To add more apps to the list, simply append more rm -rf statements as per the example, replacing /system/app/Email with the path of the app you want to remove.


Once you're done writing the script, you'll need to copy it to /system/addon.d. In order to be executed, its name should begin with an integer, followed by a hyphen. For the sake of this answer, I'll call it 99-debloat.sh, which makes it be evaluated after the other addon scripts.

After that, you'll likely need to change the script's permissions and ownership. To change the permissions, use

chmod 755 /system/addon.d/99-debloat.sh

To alter the ownership, use

chown 0.0 /system/addon.d/99-debloat.sh

A full example

The method described in this answer is the one I myself use; I'll add my personal 99-debloat.sh script here for reference.



rm -rf $app/Calendar
rm -rf $app/Email
rm -rf $app/FM2
rm -rf $app/PicoTts
rm -rf $app/Stk
rm -rf $priv_app/FlipFlap
rm -rf $priv_app/Gallery2
rm -rf $priv_app/Snap
rm -rf $priv_app/WeatherProvider
| improve this answer | |
  • 1
    That is so simple. I thought that addon.d only takes a specific code format not regular shell script. This is useful. Thank you for your help! – Ojii Oct 5 '18 at 10:17
  • @KuoChongYii Both addon and init scripts are shell ones; just take care for the interpreter to be /sbin/sh and not something like /system/bin/sh. – Grimoire Oct 5 '18 at 10:19
  • What is the difference between both? is sh binary in system a different build from a sh binary in sbin? – Ojii Oct 5 '18 at 10:21
  • @KuoChongYii When booted into TWRP, the /sbin/sh is the one provided by TWRP itself: addon scripts use that because it's guaranteed to be always available, while the other sh might not exist if /system is empty. /system/bin/sh is the sh binary provided by Android; unlike what I mistakenly said above, that sh is the one used in init.d scripts because the /sbin/sh one isn't available when Android boots. – Grimoire Oct 5 '18 at 10:28
  • Ah, I understand. – Ojii Oct 5 '18 at 10:30

I tried pm disable <app>, pm hide <app>, and pm block <app> – but all of them spew out error messages. But when I tried pm disable-user <app> it works! And the changes persists after reflashing, so that's great! I don't need to write a script after all!

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.