{"id":31632760,"url":"https://github.com/riki-pedia/ft-to-inv","last_synced_at":"2026-01-03T23:13:56.754Z","repository":{"id":305980020,"uuid":"1024584643","full_name":"riki-pedia/ft-to-inv","owner":"riki-pedia","description":"Converts FreeTube data to Invidious JSON","archived":false,"fork":false,"pushed_at":"2025-10-06T00:32:59.000Z","size":960,"stargazers_count":2,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-10-06T02:21:08.821Z","etag":null,"topics":["cli","convert","converter","fortheloveofcode","freetube","ft","hackathon","invidious","iv","youtube","yt"],"latest_commit_sha":null,"homepage":"https://dev.riki-pedia.org/projects/ft-to-inv.html","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/riki-pedia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-23T00:10:19.000Z","updated_at":"2025-10-04T21:28:27.000Z","dependencies_parsed_at":"2025-08-11T06:22:54.105Z","dependency_job_id":"e14b4810-1843-419b-858d-6cf9fd7ecadc","html_url":"https://github.com/riki-pedia/ft-to-inv","commit_stats":null,"previous_names":["riki-pedia/ft-to-invidious-exporter","riki-pedia/ft-to-inv"],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/riki-pedia/ft-to-inv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riki-pedia%2Fft-to-inv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riki-pedia%2Fft-to-inv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riki-pedia%2Fft-to-inv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riki-pedia%2Fft-to-inv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/riki-pedia","download_url":"https://codeload.github.com/riki-pedia/ft-to-inv/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riki-pedia%2Fft-to-inv/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278548819,"owners_count":26004976,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-06T02:00:05.630Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","convert","converter","fortheloveofcode","freetube","ft","hackathon","invidious","iv","youtube","yt"],"created_at":"2025-10-06T23:04:30.891Z","updated_at":"2026-01-03T23:13:56.743Z","avatar_url":"https://github.com/riki-pedia.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ft-to-inv\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/riki-pedia/ft-to-inv/actions/workflows/ci.yml\"\u003e\n    \u003cimg alt='CI status' src=\"https://github.com/riki-pedia/ft-to-inv/actions/workflows/ci.yml/badge.svg?branch=master\" /\u003e\n  \u003c/a\u003e\n  \u003cimg alt=\"NPM Downloads\" src=\"https://img.shields.io/npm/d18m/ft-to-inv\"\u003e\n  \u003cimg alt=\"Version\" src=\"https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Friki-pedia%2Fft-to-inv%2Frefs%2Fheads%2Fmaster%2Fpackage.json\u0026query=version\u0026label=version\"\u003e\n  \u003cimg alt=\"GitHub last commit\" src=\"https://img.shields.io/github/last-commit/riki-pedia/ft-to-inv\"\u003e\n  \u003cimg alt=\"NPM Last Update\" src=\"https://img.shields.io/npm/last-update/ft-to-inv\"\u003e\n  \u003cbr/\u003e\n  \nTakes FreeTube data and exports it to invidious-import.json, where it can be optionally imported to Invidious via the API. You can also schedule runs via the --cron flag, see below.\n## Demo\n\u003cimg alt=\"demo of the tool\" src=\"https://raw.githubusercontent.com/riki-pedia/ft-to-inv/refs/heads/master/assets/demo.gif\" width=\"600\"/\u003e\n\n## Why?\n\"FreeTube is great for local use, but it doesn’t sync across devices. Invidious does. This tool bridges the gap so your history, subscriptions, and playlists stay consistent.\" - albert einstein i think \n### Warnings: \n- wsl isnt supported right now, if you want to run on windows, use cmd, powershell, or windows terminal. Wsl has issues with keytar and system keychains.\n- also its ur fault if my tool eats your files or something like that. you should back them up next time instead of blaming my hungry tool or me.\n- and i dont have a mac so pls report any macos issues if you have one (tested on windows 11 and ubuntu noble)\n\u003c!-- this is extremely unprofessional but it shows what the code looks like --\u003e\n## Installation\n```\n# npm\nnpm i -g ft-to-inv \n\n# yarn\nyarn global add ft-to-inv \n\n# pnpm\npnpm add -g ft-to-inv\n```\n### Or Import (still in testing)\nESM:\n```\nimport main from \"ft-to-inv\";\n// overrides here\nawait main({\n  token: \"abc123\",\n // etc...\n  })\n```\nCommonJS:\n```\nconst main = require(\"ft-to-inv\");\n// overrides here\nawait main({\n  token: \"abc123\",\n // etc...\n  })\n```\n## Quick Start\nAfter installing, run the package to begin syncing\n```\nft-to-inv # its really that simple!\n```\n## Highlights\n- Automatically detects your FreeTube data directory\n- Supported anywhere you can run Node.js (Windows, Linux, MacOS)\n- Optionally contacts the Invidious API to sync your data\n- Can be scheduled to run on a cron schedule\n- Supports environment variables, CLI args, and a config file\n- Dry run mode to check for errors without making changes\n- Retries with exponential backoff\n- Encrypted token storage\n- some other stuff install it to find out\n### Why should I give you my Invidious token?\nYour Invidious token is only used to authenticate with the Invidious API. It is optional to use the API, you can run in no-sync mode to generate the invidious-import.json file without contacting the API. If you do give me the token, it's encrypted at rest using your system keychain via the keytar package. The encryption is done using a passphrase that you provide, which is stored securely in your system keychain. The passphrase is only used to encrypt and decrypt the token. The default passphrase is \"ilikewaffles\" + 8 random hex characters. If you want to change the passphrase, you can delete it from your keychain and the tool will prompt you again.\n### Config \nThere's a config file that you can use to further change the program. The config is read after environment variables and CLI arguments, here's the order:\n`cli args \u003e environment variables \u003e config`.\nThe config is a simple jsonc file, here's an excerpt:\n```\n{\n  \"token\":\"abc123\",\n  // make sure to include the protocol (http or https) and no trailing slash\n  \"instance\":\"http://localhost:3000\",\n  \"verbose\": true,\n  \"dont_shorten_paths\": false\n}\n```\nIf you need help with any of the config options, there's comments in the config file, and there's a help menu. If there's anything else, please open an issue on the repo.\n#### Usage with args\n```\nnpx ft-to-inv -t abc123 -i localhost:3000 \n```\n### Environment Variables\nThis tool also supports using environment variables to control the config! Every variable has only a few possible aliases. Here's an example for `token`.\n```\nFT_TO_INV_TOKEN\nFT_TO_INV_CONFIG_TOKEN\nTOKEN\n```\nMost other flags have those 3 prefixes.\nHere's the full list of config options:\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand table of args\u003c/summary\u003e\n\n  ### CLI Arguments\n| Argument | Aliases | Explanation | Usage |\n| ------- | -------- | ------- | ----- |\n| --token| -t | Your Invidious SID token. This is required unless using no-sync or dry-run. You can get it by going to your instance \u003e Settings/Preferences \u003e Manage Tokens. | -t abc123 |\n|--instance| -i | Your Invidious instance. Required unless you have no-sync or dry-run enabled. | -i https://invidious.example.com |\n|--freetube-dir| -dir, -cd, -f| Path to the FreeTube data directory. Defaults to a certain path based on which OS you have. On Windows, it's yourUser\\AppData\\Roaming\\FreeTube. On Linux, it's yourUsersHome/.config/FreeTube/. On MacOS, it defaults to you/Library/Application Support/FreeTube/. If it's not there you need to specify where it is with this flag.| -dir ./ |\n| --export-dir | -e | Where export files should be saved. The default is wherever the command is being run from (./). Exports 2 files, 3 if there are playlists, *invidious-import.json,* *import.old.json*, and *playlist-import.json*. *invidious-import.json* is for you to import into invidious (if there's no API), *import.old.json* is a copy of *invidious-import.json* used for tracking diffs, and *playlist-import.json* is used for importing playlists specifically into Invidious as there's no API endpoint. | -e .\\ |\n| --verbose | -v | Enables more verbose logging (WIP!). Useful for debugging or seeing how it works| -v |\n| --dry-run | none | Dry Run mode is useful for checking if you have correct files. It only reads the FreeTube files, checks what it would sync, then exits | --dry-run |\n| --quiet | -q | Enables less verbose logging, suppresses all non-error messages. | -q |\n| --no-sync | none | No-sync mode generates an *invidious-import.json* file but does not contact the Invidious API. Useful for cases where the API is disabled or where you don't feel comfortable pasting your Invidious token. | --no-sync |\n| --dont-shorten-paths | none | Disables path shortening, by default your export and FreeTube data directories are replaced with *\\\u003cExportDir\\\u003e* and *\\\u003cFreeTubeDir\\\u003e*| --dont-shorten-paths | \n| --dont-run-first-time-setup | -drs, --dont-run-setup| Skip the first time setup prompts and get straight to syncing. Useful for automated runs. | -drs |\n| --run-first-time-setup | -fts, --first-time-setup | Runs the first time setup even if all the files are detected. Useful if there are malformed or corrupt entries, or something changed. | -fts |\n| --insecure | --http | Tells the script to run in HTTP mode, rather than HTTPS. This is automatically set based on the protocol entered in --instance | --insecure |\n| --cron-schedule | --cron, -cron | Allows you to schedule a run on a cron schedule. If not used with an = or quotes, it checks the next 4-5 args | --cron 0 * * * * |\n| --config | -c | Path to the config file. | -c config.example.jsonc\n| --help | -h, -?, /? | Displays a help message that is only slightly better than this README | -h | \n| --logs | -l | Specifies whether to log console output to a file. The only name for this is ft-to-inv-(time).log | -l |\n\u003c/details\u003e\n\n## Contributing\nThis repo follows the standard approach to contributing, just make a fork of the repo and submit a PR. \n## License\n\u003ca href=\"https://github.com/riki-pedia/ft-to-inv/blob/master/LICENSE\"\u003e MIT \u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Friki-pedia%2Fft-to-inv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Friki-pedia%2Fft-to-inv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Friki-pedia%2Fft-to-inv/lists"}