diff --git a/c3devices/__init__.py b/c3devices/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..8634386a5552c078bc9009b91c51469886159a60
--- /dev/null
+++ b/c3devices/__init__.py
@@ -0,0 +1,10 @@
+from ppadb.device import Device
+from ppadb.client import Client as AdbClient
+from os import makedirs
+
+INVENTORY_PATH = './inventory'
+CACHE_PATH = './apps'
+
+_client = AdbClient()
+makedirs(INVENTORY_PATH, exist_ok=True)
+makedirs(CACHE_PATH, exist_ok=True)
diff --git a/c3devices/__pycache__/__init__.cpython-312.pyc b/c3devices/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f9eca224b983ab97cea5a3dac81adf12e67c4416
Binary files /dev/null and b/c3devices/__pycache__/__init__.cpython-312.pyc differ
diff --git a/c3devices/__pycache__/install.cpython-312.pyc b/c3devices/__pycache__/install.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..40bb414e96938318ae19af24a859ff9cdb8d7b2c
Binary files /dev/null and b/c3devices/__pycache__/install.cpython-312.pyc differ
diff --git a/c3devices/install.py b/c3devices/install.py
new file mode 100644
index 0000000000000000000000000000000000000000..4a10106b022935f550bd4e003a112127948dbc06
--- /dev/null
+++ b/c3devices/install.py
@@ -0,0 +1,36 @@
+from . import _client, Device, CACHE_PATH
+from os.path import isfile
+from bs4 import BeautifulSoup
+import requests
+
+
+def _download_apk(package:str):
+  print("download", package)
+  response = requests.get(f"https://f-droid.org/en/packages/{package}/")
+  soup = BeautifulSoup(response.text, 'html.parser')
+  latest = soup.find(id="latest").find(class_="package-version-download").find("a")["href"]
+  print("downloading", latest, " ",end="")
+  with requests.get(latest, stream=True) as r:
+    r.raise_for_status()
+    with open(f"{CACHE_PATH}/{package}.apk", "wb") as f:
+      for chunk in r.iter_content(chunk_size=8192):
+        f.write(chunk)
+        print(".",end="")
+  print("")
+  print("downloaded", package)
+
+
+def install_packages(packages:list[str]=[], device: Device = None):
+  print(device.get_serial_no())
+  installed = device.list_packages()
+  for package in packages:
+    if not package in installed:
+      print('need install', package)
+      if not (isfile(f'{CACHE_PATH}/{package}.apk')):
+        _download_apk(package)
+      device.install(f'{CACHE_PATH}/{package}.apk')
+
+if __name__ == '__main__':
+  with open('packages.txt') as p:
+    for line in p:
+      print(line)