diff --git a/www/data/images/program_img/ffsclient.png b/www/data/images/program_img/ffsclient.png
new file mode 100644
index 0000000..53e199e
Binary files /dev/null and b/www/data/images/program_img/ffsclient.png differ
diff --git a/www/statics/programs/__all.php b/www/statics/programs/__all.php
index afeb35b..b8e4634 100644
--- a/www/statics/programs/__all.php
+++ b/www/statics/programs/__all.php
@@ -752,4 +752,23 @@ return
'download' => 'https://github.com/Mikescher/better-docker-ps/releases',
],
],
+
+
+ [
+ 'name' => 'firefox-sync-client',
+ 'internal_name' => 'ffsclient',
+ 'internal_name_alt' => null,
+ 'category' => 'Commandline',
+ 'stars' => 4,
+ 'ui_language' => 'English',
+ 'prog_language' => 'Go',
+ 'short_description' => 'A cli for firefox-sync (firefox bookmarks, passwords, account, ...)',
+ 'add_date' => '2022-11-11',
+ 'license' => 'Apache-2.0',
+ 'urls' =>
+ [
+ 'github' => 'https://github.com/Mikescher/firefox-sync-client',
+ 'download' => 'https://github.com/Mikescher/firefox-sync-client/releases/latest',
+ ],
+ ],
];
\ No newline at end of file
diff --git a/www/statics/programs/ffsclient_description.md b/www/statics/programs/ffsclient_description.md
new file mode 100644
index 0000000..820206d
--- /dev/null
+++ b/www/statics/programs/ffsclient_description.md
@@ -0,0 +1,345 @@
+ffsclient - firefox-sync-client
+===============================
+
+A commandline-utility to list/view/edit/delete entries in a firefox-sync account.
+Can be used to access bookmarks, passwords or custom data.
+
+
+
+Table of contents
+=================
+* [Installation](#installation)
+* [Usage](#usage)
+* [Examples](#example)
+ * [Get all bookmarks as json](#get-all-bookmarks-as-json)
+ * [Get all bookmarks in netscape format (same as firefox bookmarks.html)](#get-all-bookmarks-in-netscape-format-same-as-firefox-bookmarkshtml)
+ * [Get a single bookmark](#get-a-single-bookmark)
+ * [Create a new bookmark](#create-a-new-bookmark)
+ * [List all passwords](#list-all-passwords)
+ * [List deleted passwords](#list-deleted-passwords)
+ * [Add a new password](#add-a-new-password)
+ * [Delete any record](#delete-any-record)
+ * [Query the server without a session file](#query-the-server-without-a-session-file)
+ * [Create and read unencrypted records](#create-and-read-unencrypted-records)
+* [Delete a password](#manual)
+* [Request Flowchart](#request-flowchart)
+
+
+Installation
+============
+
+The latest binary (windows/linux/macOS/FreeBSD/OpenBSD) can be downloaded from the [github releases page](https://github.com/Mikescher/firefox-sync-client/releases):.
+
+https://github.com/Mikescher/firefox-sync-client/releases/latest
+
+ffsclient does not have any dependencies and can be placed directly in your $PATH (eg /usr/local/bin).
+
+
+
+Alternatively you can use one of the following package manager:
+- [Arch User Repository](https://aur.archlinux.org/packages/ffsclient): `yay -S ffsclient-git` / `yay -S ffsclient-bin`
+- [Homebrew](https://formulae.brew.sh/formula/ffsclient): `brew tap Mikescher/tap && brew install ffsclient`
+- [Chocolatey](https://community.chocolatey.org/packages/ffsclient): `choco install ffsclient`
+
+Usage
+=====
+
+Before the first use you have to authenticate your client and create a session.
+Call `ffsclient {username} {password}` and a session will be created in `~/.config/firefox-sync-client.secret`
+
+After this you can freely use ffsclient (see the full [Manual](#manual) for all commands).
+Common commands are `ffsclient collections` to list all collections in the current account, `ffsclient list {collection}` to list all records in a collection and `ffsclient get {collection} {record-id}` to get a single record.
+
+Almost all commands support different output-formats that can be specified with `--format {fmt}`, available are `text`, `json`, `xml`, `table`, `netscape`. If no format is supplied the command uses a default.
+
+You can get an overview of all commands by invoking `ffsclient --help` and a command-specific help with `ffsclient {command} --help`
+
+For some collections (like `bookmarks`, `passwords`, `forms`, `history`) are specific subcommands available.
+For example you can list your bookmarks with `ffsclient bookmarks list`, this is preferable to the general `ffsclient list {collection}` call, because the bookmark-data in the records gets directly parsed and properly displayed.
+
+Example
+=======
+
+Here I try to show some common usage patterns:
+
+Get all bookmarks as json
+-------------------------
+```
+$ ./ffsclient bookmarks list --format json --output bookmarks.json --ignore-schema-errors
+$ ./ffsclient bookmarks list --format json --output bookmarks.json --ignore-schema-errors --minimized-json
+```
+*`--ignore-schema-errors` skips records that are in the bookmarks collection but do not contain valid data*
+
+Get all bookmarks in netscape format (same as firefox bookmarks.html)
+---------------------------------------------------------------------
+```
+$ ./ffsclient bookmarks list --format netscape
+```
+
+Get a single bookmark
+---------------------
+```
+$ ./ffsclient get bookmarks "{bookmark_id}" --decoded --format json --pretty-print
+```
+The `--pretty-print` flag does format the json in the record payload, the surrounding json (from `--format json`) is pretty-printed by default.
+If you don't want to have the envelope pretty-printed use the `--minimized-json` flag
+
+Create a new bookmark
+---------------------
+```
+$ ./ffsclient bookmarks create "{title}" "{url}"
+$ ./ffsclient bookmarks create "{title}" "{url}" --parent "{parent-record-id}"
+$ ./ffsclient bookmarks create "{title}" "{url}" --parent "{parent-record-id}" --position "{index}"
+```
+By default bookmarks are created at the top-level and at the last position in the parent folder.
+
+List all passwords
+------------------
+```
+$ ./ffsclient passwords list --ignore-schema-errors
+$ ./ffsclient passwords list --show-passwords
+```
+By default passwords are hidden to prevent accidental leaks.
+
+List deleted passwords
+----------------------
+```
+$ ./ffsclient passwords list --only-deleted
+```
+Also useful is the `--include-deleted` flag to show both, deleted and normal entries.
+Also works with other list commands
+
+Add a new password
+------------------
+```
+$ ./ffsclient passwords create "{url}" "{username}" "{password}"
+```
+
+Delete a password
+------------------
+```
+$ ./ffsclient passwords delete "{url}"
+$ ./ffsclient passwords delete "{record-id}"
+```
+
+Delete any record
+------------------
+```
+$ ./ffsclient delete "{record-id}"
+$ ./ffsclient delete "{record-id}" --hard
+```
+*By default the sync protocol needs tombstones. This means deleted records still exist, without their payload and wit a deleted:true flag*
+*If the `--hard` flag is supplied, the record is instead completely deleted from the server*
+
+Query the server without a session file
+---------------------------------------
+```
+$ ./ffsclient collections --auth-login-email "{username}" --auth-login-password "{password}"
+```
+This does not use the normal session file an creates a completely new session for this command only.
+This is genrally **not** recommended to do. Your request will look like a new client to the server, it can happen that you have to allow it via email and it is also much more inefficient.
+If you don't want a session file in your home folder use `--sessionfile` to specify a more secure location
+
+Create and read unencrypted records
+-----------------------------------
+```
+$ ./ffsclient create "{collection}" "{id}" --raw "hello world"
+$ ./ffsclient get "{collection}" "{id}" --raw --format json
+$ ./ffsclient get "{collection}" "{id}" --raw --format text --data-only
+```
+Normally records have an encrypted payload that needs to be decrypted before it can be read (via the `--decrypted` flag in `ffsclient get`).
+But you can also directly write data in the payload field.
+The `--raw` flag in `ffsclient create` skips the normal encryption step and the `--raw` flag in `ffsclient get` skips the decryption.
+This is only recommended for custom collections, you should never write invalid data in one of teh default collections (e.g. `bookmarks`, `passwords`, etc)
+
+Manual
+======
+
+*(copied from v1.2.0)*
+
+*If I forgot to update the README you can always get the current version of the help with `./ffsclient --help`*
+
+```
+firefox-sync-client.
+
+# (Use `ffsclient --help` for more detailed info)
+
+Basic Usage:
+ ffsclient login Login to FF-Sync account, uses ~/.config as default session location
+ [--device-name=]
+ [--device-type=]
+ ffsclient refresh [--force] Refresh the current session token (BID Assertion)
+ ffsclient check-session Verify that the current session is valid
+ ffsclient collections List all available collections
+ [--usage] # Include usage (storage space)
+ ffsclient quota Query the storage quota of the current user
+ ffsclient list Get a all records in a collection (use --format to define the format)
+ (--raw | --decoded | --ids) # Return raw data, decoded payload, or only IDs
+ [--after ] # Return only fields updated after this date
+ [--sort ] # Sort the result by (newest|index|oldest)
+ [--limit ] # Return max elements
+ [--offset ] # Skip the first elements
+ [--pretty-print | --pp] # Pretty-Print json in decoded data / payload (if possible)
+ ffsclient get Get a single record
+ (--raw | --decoded) # Return raw data or decoded payload
+ [--pretty-print | --pp] # Pretty-Print json in decoded data / payload (if possible)
+ [--data-only] # Only return the payload
+ffsclient delete [--hard] Delete the specified record
+ ffsclient delete Delete all the records in a collection
+ ffsclient delete-all --force Delete all (!) records in the server
+ ffsclient create Insert a new record
+ (--raw | --data | --raw-stdin | --data-stdin) # The new data
+ ffsclient update Update an existing record
+ (--raw | --data | --raw-stdin | --data-stdin) # The new data
+ [--create] # Create a new record if the specified record-id does not exist
+ ffsclient meta Get storage metadata
+ ffsclient --help Output specific help for a single subcommand
+
+Usage:
+ ffsclient bookmarks list List bookmarks (use --format to define the format)
+ [--ignore-schema-errors] # Skip records that cannot be decoded into a bookmark schema
+ [--after ] # Return only fields updated after this date
+ [--sort ] # Sort the result by (newest|index|oldest)
+ [--limit ] # Return max elements
+ [--offset ] # Skip the first elements
+ [--include-deleted] # Show deleted entries
+ [--only-deleted] # Show only deleted entries
+ [--type ] # Show only entries with the specified type
+ [--parent ] # Show only entries with the specified parent (by record-id), can be specified multiple times
+ [--linear # Do not output the folder hierachy
+ ffsclient bookmarks delete Delete the specified bookmark
+ ffsclient bookmarks create bookmark Insert a new bookmark
+ [--description ] # Specify the bookmark description
+ [--load-in-sidebar] # If specified the `LoadInSidebar` field is set to true (default is false)
+ [--tag ] # Add a tag to the bookmark, specify multiple times to add multiple tags
+ [--keyword ] # Specify the keyword (to activate the bookmark from the location bar)
+ [--parent ] # Specify the ID of the parent folder (if not specified the entry lives under `unfiled`)
+ [--position=] # The position of the entry in the parent (0 = first, default is last). Can use negative indizes.
+ ffsclient bookmarks create folder Insert a new bookmark-folder
+ [--parent ] # Specify the ID of the parent folder (if not specified the entry lives under `unfiled`)
+ [--position=] # The position of the entry in the parent (0 = first, default is last). Can use negative indizes.
+ ffsclient bookmarks create separator Insert a new bookmark-separator
+ [--parent ] # Specify the ID of the parent folder (if not specified the entry lives under `unfiled`)
+ [--position=] # The position of the entry in the parent (0 = first, default is last). Can use negative indizes.
+ ffsclient bookmarks update Partially update a bookmark
+ [--title ] # Change the bookmark title
+ [--url ] # Change the URL
+ [--description ] # Change the bookmark description
+ [--load-in-sidebar ] # Set the `LoadInSidebar` field
+ [--tag ] # Change the tags, specify multiple times to set multiple tags
+ [--keyword ] # Specify the keyword (to activate the bookmark from the location bar)
+ [--position=] # Change the position of the entry in the parent (0 = first). Can use negative indizes.
+ ffsclient passwords list List passwords
+ [--show-passwords] # Show the actual passwords
+ [--ignore-schema-errors] # Skip records that cannot be decoded into a password schema
+ [--after ] # Return only fields updated after this date
+ [--sort ] # Sort the result by (newest|index|oldest)
+ [--limit ] # Return max elements
+ [--offset ] # Skip the first elements
+ [--include-deleted] # Show deleted entries
+ [--only-deleted] # Show only deleted entries
+ ffsclient passwords delete [--hard] Delete a single password
+ [--is-host | --is-exact-host | --is-id] # Specify that the supplied argument is a host / record-id (otherwise both is possible)
+ ffsclient passwords create Insert a new password
+ [--form-submit-url ] # Specify the submission URL (GET/POST url set by