Repository files navigation

Tortillas

A terminal-based TUI (Text User Interface) torrent client built in Rust 🫓.

🚧 Project Status

Note: This project is currently under active development and is not yet feature-complete. It is by no means ready for use.

🛠️ Roadmap

See our roadmap here.

✅ Currently Supported

  • Parsing and handling Magnet URIs
  • Parsing and handling .torrent files
  • uTP and TCP peer connections
  • Full implementation of the BitTorrent protocol
  • Mainline DHT peer discovery for public and trackerless torrents

🔄 In Development

📈 Future Plans

  • TUI (Text User Interface)

❌ Not Planned

  • WebTorrent connections: Due to the lack of clear documentation and complex, undocumented protocols WebTorrent support is not currently planned.

🧪 Testing

We use Nextest for running tests. To run tests locally, you may need to install Nextest:

# Install Nextest (example using pre-built binaries)# See: https://nexte.st/docs/installation/pre-built-binaries/

The default suite should be deterministic and must not depend on public trackers, public peers, or mutable internet state:

cargo nextest run --workspace

Tests that intentionally exercise public BitTorrent infrastructure are marked #[ignore] and should only be run explicitly:

cargo nextest run --workspace --run-ignored ignored-only

The Arch Linux fixture exercises a trackerless torrent through the public DHT and passes only after downloading real ISO data:

cargo nextest run -p libtortillas --test dht_network --run-ignored ignored-only

Test names use this convention:

subject_when_condition_then_expected_result

Examples:

magnet_uri_when_query_is_missing_then_returns_error
peer_stream_when_handshake_is_valid_then_returns_peer_id

Keep tests focused on one behavior, prefer deterministic fixtures with include_str! or include_bytes!, and avoid public network access unless the test is explicitly ignored.

📦 Installation

Tortillas

Tortillas is the TUI (Text User Interface) application most people will use.

There are plans to publish tortillas to registries such as crates.io and the AUR. However, for now, you can install it from source using cargo:

cargo install --git https://github.com/artrixdotdev/tortillas

This will install tortillas to your local Rust toolchain.

Libtortillas

Libtortillas is the engine behind the TUI. It can also be embedded in other applications that need BitTorrent downloads, seeding, and observable progress.

cargo add --git https://github.com/artrixdotdev/tortillas libtortillas

The live feature is enabled by default and provides views, metrics, event streams, and listener handles. Applications that only need actor-backed commands and direct state queries can remove that projection and publication overhead:

[dependencies]
libtortillas = { git = "https://github.com/artrixdotdev/tortillas", default-features = false }

Runtime Contract

libtortillas is a Tokio-first library. Applications that use it must run engine and torrent operations inside a Tokio runtime.

For the Tortillas TUI, the binary should own a single application runtime, typically through #[tokio::main], and create libtortillas::engine::Engine inside that runtime. UI rendering or terminal input that blocks should run on a dedicated thread or, for bounded work, through Tokio blocking tasks, then send application actions into async engine tasks. Long-lived input loops should use a dedicated thread because spawn_blocking tasks cannot be aborted once they start. The library does not currently support swapping in a different async runtime, HTTP client, clock, listener, or storage executor.

With the default live feature, use listeners for current state and incremental updates, and call Engine and Torrent methods for operations. Do not poll persistence snapshots to drive a display. See the libtortillas::live API documentation and the live example.

🤝 Contributing

We welcome contributions! If you'd like to help improve tortillas, please check out our CONTRIBUTING.md for guidelines and tips.

📊 Analytics

Repobeats Analytics

About

A terminal TUI torrent client.

Resources

Contributing

Stars

28 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Tortillas

A terminal-based TUI (Text User Interface) torrent client built in Rust 🫓.

🚧 Project Status

Note: This project is currently under active development and is not yet feature-complete. It is by no means ready for use.

🛠️ Roadmap

See our roadmap here.

✅ Currently Supported

  • Parsing and handling Magnet URIs
  • Parsing and handling .torrent files
  • uTP and TCP peer connections
  • Full implementation of the BitTorrent protocol
  • Mainline DHT peer discovery for public and trackerless torrents

🔄 In Development

📈 Future Plans

  • TUI (Text User Interface)

❌ Not Planned

  • WebTorrent connections: Due to the lack of clear documentation and complex, undocumented protocols WebTorrent support is not currently planned.

🧪 Testing

We use Nextest for running tests. To run tests locally, you may need to install Nextest:

# Install Nextest (example using pre-built binaries)# See: https://nexte.st/docs/installation/pre-built-binaries/

The default suite should be deterministic and must not depend on public trackers, public peers, or mutable internet state:

cargo nextest run --workspace

Tests that intentionally exercise public BitTorrent infrastructure are marked #[ignore] and should only be run explicitly:

cargo nextest run --workspace --run-ignored ignored-only

The Arch Linux fixture exercises a trackerless torrent through the public DHT and passes only after downloading real ISO data:

cargo nextest run -p libtortillas --test dht_network --run-ignored ignored-only

Test names use this convention:

subject_when_condition_then_expected_result

Examples:

magnet_uri_when_query_is_missing_then_returns_error
peer_stream_when_handshake_is_valid_then_returns_peer_id

Keep tests focused on one behavior, prefer deterministic fixtures with include_str! or include_bytes!, and avoid public network access unless the test is explicitly ignored.

📦 Installation

Tortillas

Tortillas is the TUI (Text User Interface) application most people will use.

There are plans to publish tortillas to registries such as crates.io and the AUR. However, for now, you can install it from source using cargo:

cargo install --git https://github.com/artrixdotdev/tortillas

This will install tortillas to your local Rust toolchain.

Libtortillas

Libtortillas is the engine behind the TUI. It can also be embedded in other applications that need BitTorrent downloads, seeding, and observable progress.

cargo add --git https://github.com/artrixdotdev/tortillas libtortillas

The live feature is enabled by default and provides views, metrics, event streams, and listener handles. Applications that only need actor-backed commands and direct state queries can remove that projection and publication overhead:

[dependencies]
libtortillas = { git = "https://github.com/artrixdotdev/tortillas", default-features = false }

Runtime Contract

libtortillas is a Tokio-first library. Applications that use it must run engine and torrent operations inside a Tokio runtime.

For the Tortillas TUI, the binary should own a single application runtime, typically through #[tokio::main], and create libtortillas::engine::Engine inside that runtime. UI rendering or terminal input that blocks should run on a dedicated thread or, for bounded work, through Tokio blocking tasks, then send application actions into async engine tasks. Long-lived input loops should use a dedicated thread because spawn_blocking tasks cannot be aborted once they start. The library does not currently support swapping in a different async runtime, HTTP client, clock, listener, or storage executor.

With the default live feature, use listeners for current state and incremental updates, and call Engine and Torrent methods for operations. Do not poll persistence snapshots to drive a display. See the libtortillas::live API documentation and the live example.

🤝 Contributing

We welcome contributions! If you'd like to help improve tortillas, please check out our CONTRIBUTING.md for guidelines and tips.

📊 Analytics

Repobeats Analytics

About

A terminal TUI torrent client.

Resources

Contributing

Stars

28 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Tortillas

A terminal-based TUI (Text User Interface) torrent client built in Rust 🫓.

🚧 Project Status

Note: This project is currently under active development and is not yet feature-complete. It is by no means ready for use.

🛠️ Roadmap

See our roadmap here.

✅ Currently Supported

  • Parsing and handling Magnet URIs
  • Parsing and handling .torrent files
  • uTP and TCP peer connections
  • Full implementation of the BitTorrent protocol
  • Mainline DHT peer discovery for public and trackerless torrents

🔄 In Development

📈 Future Plans

  • TUI (Text User Interface)

❌ Not Planned

  • WebTorrent connections: Due to the lack of clear documentation and complex, undocumented protocols WebTorrent support is not currently planned.

🧪 Testing

We use Nextest for running tests. To run tests locally, you may need to install Nextest:

# Install Nextest (example using pre-built binaries)# See: https://nexte.st/docs/installation/pre-built-binaries/

The default suite should be deterministic and must not depend on public trackers, public peers, or mutable internet state:

cargo nextest run --workspace

Tests that intentionally exercise public BitTorrent infrastructure are marked #[ignore] and should only be run explicitly:

cargo nextest run --workspace --run-ignored ignored-only

The Arch Linux fixture exercises a trackerless torrent through the public DHT and passes only after downloading real ISO data:

cargo nextest run -p libtortillas --test dht_network --run-ignored ignored-only

Test names use this convention:

subject_when_condition_then_expected_result

Examples:

magnet_uri_when_query_is_missing_then_returns_error
peer_stream_when_handshake_is_valid_then_returns_peer_id

Keep tests focused on one behavior, prefer deterministic fixtures with include_str! or include_bytes!, and avoid public network access unless the test is explicitly ignored.

📦 Installation

Tortillas

Tortillas is the TUI (Text User Interface) application most people will use.

There are plans to publish tortillas to registries such as crates.io and the AUR. However, for now, you can install it from source using cargo:

cargo install --git https://github.com/artrixdotdev/tortillas

This will install tortillas to your local Rust toolchain.

Libtortillas

Libtortillas is the engine behind the TUI. It can also be embedded in other applications that need BitTorrent downloads, seeding, and observable progress.

cargo add --git https://github.com/artrixdotdev/tortillas libtortillas

The live feature is enabled by default and provides views, metrics, event streams, and listener handles. Applications that only need actor-backed commands and direct state queries can remove that projection and publication overhead:

[dependencies]
libtortillas = { git = "https://github.com/artrixdotdev/tortillas", default-features = false }

Runtime Contract

libtortillas is a Tokio-first library. Applications that use it must run engine and torrent operations inside a Tokio runtime.

For the Tortillas TUI, the binary should own a single application runtime, typically through #[tokio::main], and create libtortillas::engine::Engine inside that runtime. UI rendering or terminal input that blocks should run on a dedicated thread or, for bounded work, through Tokio blocking tasks, then send application actions into async engine tasks. Long-lived input loops should use a dedicated thread because spawn_blocking tasks cannot be aborted once they start. The library does not currently support swapping in a different async runtime, HTTP client, clock, listener, or storage executor.

With the default live feature, use listeners for current state and incremental updates, and call Engine and Torrent methods for operations. Do not poll persistence snapshots to drive a display. See the libtortillas::live API documentation and the live example.

🤝 Contributing

We welcome contributions! If you'd like to help improve tortillas, please check out our CONTRIBUTING.md for guidelines and tips.

📊 Analytics

Repobeats Analytics

About

A terminal TUI torrent client.

Resources

Contributing

Stars

28 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Tortillas

A terminal-based TUI (Text User Interface) torrent client built in Rust 🫓.

🚧 Project Status

Note: This project is currently under active development and is not yet feature-complete. It is by no means ready for use.

🛠️ Roadmap

See our roadmap here.

✅ Currently Supported

  • Parsing and handling Magnet URIs
  • Parsing and handling .torrent files
  • uTP and TCP peer connections
  • Full implementation of the BitTorrent protocol
  • Mainline DHT peer discovery for public and trackerless torrents

🔄 In Development

📈 Future Plans

  • TUI (Text User Interface)

❌ Not Planned

  • WebTorrent connections: Due to the lack of clear documentation and complex, undocumented protocols WebTorrent support is not currently planned.

🧪 Testing

We use Nextest for running tests. To run tests locally, you may need to install Nextest:

# Install Nextest (example using pre-built binaries)# See: https://nexte.st/docs/installation/pre-built-binaries/

The default suite should be deterministic and must not depend on public trackers, public peers, or mutable internet state:

cargo nextest run --workspace

Tests that intentionally exercise public BitTorrent infrastructure are marked #[ignore] and should only be run explicitly:

cargo nextest run --workspace --run-ignored ignored-only

The Arch Linux fixture exercises a trackerless torrent through the public DHT and passes only after downloading real ISO data:

cargo nextest run -p libtortillas --test dht_network --run-ignored ignored-only

Test names use this convention:

subject_when_condition_then_expected_result

Examples:

magnet_uri_when_query_is_missing_then_returns_error
peer_stream_when_handshake_is_valid_then_returns_peer_id

Keep tests focused on one behavior, prefer deterministic fixtures with include_str! or include_bytes!, and avoid public network access unless the test is explicitly ignored.

📦 Installation

Tortillas

Tortillas is the TUI (Text User Interface) application most people will use.

There are plans to publish tortillas to registries such as crates.io and the AUR. However, for now, you can install it from source using cargo:

cargo install --git https://github.com/artrixdotdev/tortillas

This will install tortillas to your local Rust toolchain.

Libtortillas

Libtortillas is the engine behind the TUI. It can also be embedded in other applications that need BitTorrent downloads, seeding, and observable progress.

cargo add --git https://github.com/artrixdotdev/tortillas libtortillas

The live feature is enabled by default and provides views, metrics, event streams, and listener handles. Applications that only need actor-backed commands and direct state queries can remove that projection and publication overhead:

[dependencies]
libtortillas = { git = "https://github.com/artrixdotdev/tortillas", default-features = false }

Runtime Contract

libtortillas is a Tokio-first library. Applications that use it must run engine and torrent operations inside a Tokio runtime.

For the Tortillas TUI, the binary should own a single application runtime, typically through #[tokio::main], and create libtortillas::engine::Engine inside that runtime. UI rendering or terminal input that blocks should run on a dedicated thread or, for bounded work, through Tokio blocking tasks, then send application actions into async engine tasks. Long-lived input loops should use a dedicated thread because spawn_blocking tasks cannot be aborted once they start. The library does not currently support swapping in a different async runtime, HTTP client, clock, listener, or storage executor.

With the default live feature, use listeners for current state and incremental updates, and call Engine and Torrent methods for operations. Do not poll persistence snapshots to drive a display. See the libtortillas::live API documentation and the live example.

🤝 Contributing

We welcome contributions! If you'd like to help improve tortillas, please check out our CONTRIBUTING.md for guidelines and tips.

📊 Analytics

Repobeats Analytics

About

A terminal TUI torrent client.

Resources

Contributing

Stars

28 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Tortillas

A terminal-based TUI (Text User Interface) torrent client built in Rust 🫓.

🚧 Project Status

Note: This project is currently under active development and is not yet feature-complete. It is by no means ready for use.

🛠️ Roadmap

See our roadmap here.

✅ Currently Supported

  • Parsing and handling Magnet URIs
  • Parsing and handling .torrent files
  • uTP and TCP peer connections
  • Full implementation of the BitTorrent protocol
  • Mainline DHT peer discovery for public and trackerless torrents

🔄 In Development

📈 Future Plans

  • TUI (Text User Interface)

❌ Not Planned

  • WebTorrent connections: Due to the lack of clear documentation and complex, undocumented protocols WebTorrent support is not currently planned.

🧪 Testing

We use Nextest for running tests. To run tests locally, you may need to install Nextest:

# Install Nextest (example using pre-built binaries)# See: https://nexte.st/docs/installation/pre-built-binaries/

The default suite should be deterministic and must not depend on public trackers, public peers, or mutable internet state:

cargo nextest run --workspace

Tests that intentionally exercise public BitTorrent infrastructure are marked #[ignore] and should only be run explicitly:

cargo nextest run --workspace --run-ignored ignored-only

The Arch Linux fixture exercises a trackerless torrent through the public DHT and passes only after downloading real ISO data:

cargo nextest run -p libtortillas --test dht_network --run-ignored ignored-only

Test names use this convention:

subject_when_condition_then_expected_result

Examples:

magnet_uri_when_query_is_missing_then_returns_error
peer_stream_when_handshake_is_valid_then_returns_peer_id

Keep tests focused on one behavior, prefer deterministic fixtures with include_str! or include_bytes!, and avoid public network access unless the test is explicitly ignored.

📦 Installation

Tortillas

Tortillas is the TUI (Text User Interface) application most people will use.

There are plans to publish tortillas to registries such as crates.io and the AUR. However, for now, you can install it from source using cargo:

cargo install --git https://github.com/artrixdotdev/tortillas

This will install tortillas to your local Rust toolchain.

Libtortillas

Libtortillas is the engine behind the TUI. It can also be embedded in other applications that need BitTorrent downloads, seeding, and observable progress.

cargo add --git https://github.com/artrixdotdev/tortillas libtortillas

The live feature is enabled by default and provides views, metrics, event streams, and listener handles. Applications that only need actor-backed commands and direct state queries can remove that projection and publication overhead:

[dependencies]
libtortillas = { git = "https://github.com/artrixdotdev/tortillas", default-features = false }

Runtime Contract

libtortillas is a Tokio-first library. Applications that use it must run engine and torrent operations inside a Tokio runtime.

For the Tortillas TUI, the binary should own a single application runtime, typically through #[tokio::main], and create libtortillas::engine::Engine inside that runtime. UI rendering or terminal input that blocks should run on a dedicated thread or, for bounded work, through Tokio blocking tasks, then send application actions into async engine tasks. Long-lived input loops should use a dedicated thread because spawn_blocking tasks cannot be aborted once they start. The library does not currently support swapping in a different async runtime, HTTP client, clock, listener, or storage executor.

With the default live feature, use listeners for current state and incremental updates, and call Engine and Torrent methods for operations. Do not poll persistence snapshots to drive a display. See the libtortillas::live API documentation and the live example.

🤝 Contributing

We welcome contributions! If you'd like to help improve tortillas, please check out our CONTRIBUTING.md for guidelines and tips.

📊 Analytics

Repobeats Analytics

About

A terminal TUI torrent client.

Resources

Contributing

Stars

28 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Tortillas

A terminal-based TUI (Text User Interface) torrent client built in Rust 🫓.

🚧 Project Status

Note: This project is currently under active development and is not yet feature-complete. It is by no means ready for use.

🛠️ Roadmap

See our roadmap here.

✅ Currently Supported

  • Parsing and handling Magnet URIs
  • Parsing and handling .torrent files
  • uTP and TCP peer connections
  • Full implementation of the BitTorrent protocol
  • Mainline DHT peer discovery for public and trackerless torrents

🔄 In Development

📈 Future Plans

  • TUI (Text User Interface)

❌ Not Planned

  • WebTorrent connections: Due to the lack of clear documentation and complex, undocumented protocols WebTorrent support is not currently planned.

🧪 Testing

We use Nextest for running tests. To run tests locally, you may need to install Nextest:

# Install Nextest (example using pre-built binaries)# See: https://nexte.st/docs/installation/pre-built-binaries/

The default suite should be deterministic and must not depend on public trackers, public peers, or mutable internet state:

cargo nextest run --workspace

Tests that intentionally exercise public BitTorrent infrastructure are marked #[ignore] and should only be run explicitly:

cargo nextest run --workspace --run-ignored ignored-only

The Arch Linux fixture exercises a trackerless torrent through the public DHT and passes only after downloading real ISO data:

cargo nextest run -p libtortillas --test dht_network --run-ignored ignored-only

Test names use this convention:

subject_when_condition_then_expected_result

Examples:

magnet_uri_when_query_is_missing_then_returns_error
peer_stream_when_handshake_is_valid_then_returns_peer_id

Keep tests focused on one behavior, prefer deterministic fixtures with include_str! or include_bytes!, and avoid public network access unless the test is explicitly ignored.

📦 Installation

Tortillas

Tortillas is the TUI (Text User Interface) application most people will use.

There are plans to publish tortillas to registries such as crates.io and the AUR. However, for now, you can install it from source using cargo:

cargo install --git https://github.com/artrixdotdev/tortillas

This will install tortillas to your local Rust toolchain.

Libtortillas

Libtortillas is the engine behind the TUI. It can also be embedded in other applications that need BitTorrent downloads, seeding, and observable progress.

cargo add --git https://github.com/artrixdotdev/tortillas libtortillas

The live feature is enabled by default and provides views, metrics, event streams, and listener handles. Applications that only need actor-backed commands and direct state queries can remove that projection and publication overhead:

[dependencies]
libtortillas = { git = "https://github.com/artrixdotdev/tortillas", default-features = false }

Runtime Contract

libtortillas is a Tokio-first library. Applications that use it must run engine and torrent operations inside a Tokio runtime.

For the Tortillas TUI, the binary should own a single application runtime, typically through #[tokio::main], and create libtortillas::engine::Engine inside that runtime. UI rendering or terminal input that blocks should run on a dedicated thread or, for bounded work, through Tokio blocking tasks, then send application actions into async engine tasks. Long-lived input loops should use a dedicated thread because spawn_blocking tasks cannot be aborted once they start. The library does not currently support swapping in a different async runtime, HTTP client, clock, listener, or storage executor.

With the default live feature, use listeners for current state and incremental updates, and call Engine and Torrent methods for operations. Do not poll persistence snapshots to drive a display. See the libtortillas::live API documentation and the live example.

🤝 Contributing

We welcome contributions! If you'd like to help improve tortillas, please check out our CONTRIBUTING.md for guidelines and tips.

📊 Analytics

Repobeats Analytics

About

A terminal TUI torrent client.

Resources

Contributing

Stars

28 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Tortillas

A terminal-based TUI (Text User Interface) torrent client built in Rust 🫓.

🚧 Project Status

Note: This project is currently under active development and is not yet feature-complete. It is by no means ready for use.

🛠️ Roadmap

See our roadmap here.

✅ Currently Supported

  • Parsing and handling Magnet URIs
  • Parsing and handling .torrent files
  • uTP and TCP peer connections
  • Full implementation of the BitTorrent protocol
  • Mainline DHT peer discovery for public and trackerless torrents

🔄 In Development

📈 Future Plans

  • TUI (Text User Interface)

❌ Not Planned

  • WebTorrent connections: Due to the lack of clear documentation and complex, undocumented protocols WebTorrent support is not currently planned.

🧪 Testing

We use Nextest for running tests. To run tests locally, you may need to install Nextest:

# Install Nextest (example using pre-built binaries)# See: https://nexte.st/docs/installation/pre-built-binaries/

The default suite should be deterministic and must not depend on public trackers, public peers, or mutable internet state:

cargo nextest run --workspace

Tests that intentionally exercise public BitTorrent infrastructure are marked #[ignore] and should only be run explicitly:

cargo nextest run --workspace --run-ignored ignored-only

The Arch Linux fixture exercises a trackerless torrent through the public DHT and passes only after downloading real ISO data:

cargo nextest run -p libtortillas --test dht_network --run-ignored ignored-only

Test names use this convention:

subject_when_condition_then_expected_result

Examples:

magnet_uri_when_query_is_missing_then_returns_error
peer_stream_when_handshake_is_valid_then_returns_peer_id

Keep tests focused on one behavior, prefer deterministic fixtures with include_str! or include_bytes!, and avoid public network access unless the test is explicitly ignored.

📦 Installation

Tortillas

Tortillas is the TUI (Text User Interface) application most people will use.

There are plans to publish tortillas to registries such as crates.io and the AUR. However, for now, you can install it from source using cargo:

cargo install --git https://github.com/artrixdotdev/tortillas

This will install tortillas to your local Rust toolchain.

Libtortillas

Libtortillas is the engine behind the TUI. It can also be embedded in other applications that need BitTorrent downloads, seeding, and observable progress.

cargo add --git https://github.com/artrixdotdev/tortillas libtortillas

The live feature is enabled by default and provides views, metrics, event streams, and listener handles. Applications that only need actor-backed commands and direct state queries can remove that projection and publication overhead:

[dependencies]
libtortillas = { git = "https://github.com/artrixdotdev/tortillas", default-features = false }

Runtime Contract

libtortillas is a Tokio-first library. Applications that use it must run engine and torrent operations inside a Tokio runtime.

For the Tortillas TUI, the binary should own a single application runtime, typically through #[tokio::main], and create libtortillas::engine::Engine inside that runtime. UI rendering or terminal input that blocks should run on a dedicated thread or, for bounded work, through Tokio blocking tasks, then send application actions into async engine tasks. Long-lived input loops should use a dedicated thread because spawn_blocking tasks cannot be aborted once they start. The library does not currently support swapping in a different async runtime, HTTP client, clock, listener, or storage executor.

With the default live feature, use listeners for current state and incremental updates, and call Engine and Torrent methods for operations. Do not poll persistence snapshots to drive a display. See the libtortillas::live API documentation and the live example.

🤝 Contributing

We welcome contributions! If you'd like to help improve tortillas, please check out our CONTRIBUTING.md for guidelines and tips.

📊 Analytics

Repobeats Analytics

About

A terminal TUI torrent client.

Resources

Contributing

Stars

28 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Tortillas

A terminal-based TUI (Text User Interface) torrent client built in Rust 🫓.

🚧 Project Status

Note: This project is currently under active development and is not yet feature-complete. It is by no means ready for use.

🛠️ Roadmap

See our roadmap here.

✅ Currently Supported

  • Parsing and handling Magnet URIs
  • Parsing and handling .torrent files
  • uTP and TCP peer connections
  • Full implementation of the BitTorrent protocol
  • Mainline DHT peer discovery for public and trackerless torrents

🔄 In Development

📈 Future Plans

  • TUI (Text User Interface)

❌ Not Planned

  • WebTorrent connections: Due to the lack of clear documentation and complex, undocumented protocols WebTorrent support is not currently planned.

🧪 Testing

We use Nextest for running tests. To run tests locally, you may need to install Nextest:

# Install Nextest (example using pre-built binaries)# See: https://nexte.st/docs/installation/pre-built-binaries/

The default suite should be deterministic and must not depend on public trackers, public peers, or mutable internet state:

cargo nextest run --workspace

Tests that intentionally exercise public BitTorrent infrastructure are marked #[ignore] and should only be run explicitly:

cargo nextest run --workspace --run-ignored ignored-only

The Arch Linux fixture exercises a trackerless torrent through the public DHT and passes only after downloading real ISO data:

cargo nextest run -p libtortillas --test dht_network --run-ignored ignored-only

Test names use this convention:

subject_when_condition_then_expected_result

Examples:

magnet_uri_when_query_is_missing_then_returns_error
peer_stream_when_handshake_is_valid_then_returns_peer_id

Keep tests focused on one behavior, prefer deterministic fixtures with include_str! or include_bytes!, and avoid public network access unless the test is explicitly ignored.

📦 Installation

Tortillas

Tortillas is the TUI (Text User Interface) application most people will use.

There are plans to publish tortillas to registries such as crates.io and the AUR. However, for now, you can install it from source using cargo:

cargo install --git https://github.com/artrixdotdev/tortillas

This will install tortillas to your local Rust toolchain.

Libtortillas

Libtortillas is the engine behind the TUI. It can also be embedded in other applications that need BitTorrent downloads, seeding, and observable progress.

cargo add --git https://github.com/artrixdotdev/tortillas libtortillas

The live feature is enabled by default and provides views, metrics, event streams, and listener handles. Applications that only need actor-backed commands and direct state queries can remove that projection and publication overhead:

[dependencies]
libtortillas = { git = "https://github.com/artrixdotdev/tortillas", default-features = false }

Runtime Contract

libtortillas is a Tokio-first library. Applications that use it must run engine and torrent operations inside a Tokio runtime.

For the Tortillas TUI, the binary should own a single application runtime, typically through #[tokio::main], and create libtortillas::engine::Engine inside that runtime. UI rendering or terminal input that blocks should run on a dedicated thread or, for bounded work, through Tokio blocking tasks, then send application actions into async engine tasks. Long-lived input loops should use a dedicated thread because spawn_blocking tasks cannot be aborted once they start. The library does not currently support swapping in a different async runtime, HTTP client, clock, listener, or storage executor.

With the default live feature, use listeners for current state and incremental updates, and call Engine and Torrent methods for operations. Do not poll persistence snapshots to drive a display. See the libtortillas::live API documentation and the live example.

🤝 Contributing

We welcome contributions! If you'd like to help improve tortillas, please check out our CONTRIBUTING.md for guidelines and tips.

📊 Analytics

Repobeats Analytics

About

A terminal TUI torrent client.

Resources

Contributing

Stars

28 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages