Bumps the python-deps group with 5 updates in the / directory: | Package | From | To | | --- | --- | --- | | [authlib](https://github.com/authlib/authlib) | `1.6.9` | `1.7.0` | | [seleniumbase](https://github.com/seleniumbase/SeleniumBase) | `4.47.9` | `4.48.2` | | [basedpyright](https://github.com/detachhead/basedpyright) | `1.39.0` | `1.39.3` | | [prek](https://github.com/j178/prek) | `0.3.8` | `0.3.10` | | [ruff](https://github.com/astral-sh/ruff) | `0.15.10` | `0.15.11` | Updates `authlib` from 1.6.9 to 1.7.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/authlib/authlib/releases">authlib's releases</a>.</em></p> <blockquote> <h2>v1.7.0</h2> <h2>What's Changed</h2> <ul> <li>Authorization and token endpoints request empty scope parameter management by <a href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/847">authlib/authlib#847</a></li> <li>Support from Python 3.10 to 3.14 by <a href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/850">authlib/authlib#850</a></li> <li>Allow composition of AuthorizationServerMetadata by <a href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/853">authlib/authlib#853</a></li> <li>Make require_oauth parenthesis optional by <a href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/855">authlib/authlib#855</a></li> <li>Fix <code>expires_at</code> behavior when its value is 0 by <a href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/854">authlib/authlib#854</a></li> <li>Migration to joserfc by <a href="https://github.com/lepture"><code>@lepture</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/852">authlib/authlib#852</a></li> <li>RP-initiated logout by <a href="https://github.com/frohrlich"><code>@frohrlich</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/849">authlib/authlib#849</a></li> <li>Fix <code>get_jwt_config</code> by <a href="https://github.com/lepture"><code>@lepture</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/858">authlib/authlib#858</a></li> <li>chore(ci): Update PyPy version from 3.10 to 3.11 by <a href="https://github.com/cclauss"><code>@cclauss</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/863">authlib/authlib#863</a></li> <li>fix: remove "none" from default authlib.jose.jwt algorithms by <a href="https://github.com/lepture"><code>@lepture</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/860">authlib/authlib#860</a></li> <li>fix: normalize resolve_client_public_key method by <a href="https://github.com/lepture"><code>@lepture</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/861">authlib/authlib#861</a></li> <li>Implement rfc9700 PKCE downgrade countermeasure by <a href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/864">authlib/authlib#864</a></li> <li>Use correct syntax for tox.requires in tox.ini by <a href="https://github.com/alex-ball"><code>@alex-ball</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/868">authlib/authlib#868</a></li> <li>Set client session User-Agent when fetching server metadata and JWKs by <a href="https://github.com/alex-ball"><code>@alex-ball</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/867">authlib/authlib#867</a></li> <li>fix: use the real application object for Flask by <a href="https://github.com/nblock"><code>@nblock</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/869">authlib/authlib#869</a></li> <li>Accept the issuer URL as a valid audience by <a href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/865">authlib/authlib#865</a></li> <li>Don't nest InvalidTokenError extra attribute by <a href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/872">authlib/authlib#872</a></li> <li>Documentation overhaul by <a href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/875">authlib/authlib#875</a></li> <li>Update README.md docs.authlib.org/en/latest => docs.authlib.org/en/stable by <a href="https://github.com/guillett"><code>@guillett</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/876">authlib/authlib#876</a></li> <li>Merge release/1.6 branch by <a href="https://github.com/lepture"><code>@lepture</code></a> in <a href="https://redirect.github.com/authlib/authlib/pull/877">authlib/authlib#877</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/frohrlich"><code>@frohrlich</code></a> made their first contribution in <a href="https://redirect.github.com/authlib/authlib/pull/849">authlib/authlib#849</a></li> <li><a href="https://github.com/cclauss"><code>@cclauss</code></a> made their first contribution in <a href="https://redirect.github.com/authlib/authlib/pull/863">authlib/authlib#863</a></li> <li><a href="https://github.com/alex-ball"><code>@alex-ball</code></a> made their first contribution in <a href="https://redirect.github.com/authlib/authlib/pull/868">authlib/authlib#868</a></li> <li><a href="https://github.com/nblock"><code>@nblock</code></a> made their first contribution in <a href="https://redirect.github.com/authlib/authlib/pull/869">authlib/authlib#869</a></li> <li><a href="https://github.com/guillett"><code>@guillett</code></a> made their first contribution in <a href="https://redirect.github.com/authlib/authlib/pull/876">authlib/authlib#876</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/authlib/authlib/compare/v1.6.10...v1.7.0">https://github.com/authlib/authlib/compare/v1.6.10...v1.7.0</a></p> <h2>v1.6.11</h2> <p><strong>Full Changelog</strong>: <a href="https://github.com/authlib/authlib/compare/v1.6.10...v1.6.11">https://github.com/authlib/authlib/compare/v1.6.10...v1.6.11</a></p> <ul> <li>Fix CSRF issue with starlette client</li> </ul> <h2>v1.6.10</h2> <p><strong>Full Changelog</strong>: <a href="https://github.com/authlib/authlib/compare/v1.6.9...v1.6.10">https://github.com/authlib/authlib/compare/v1.6.9...v1.6.10</a></p> <ul> <li>Fix redirecting to unvalidated <code>redirect_uri</code> on <code>UnsupportedResponseTypeError</code>.</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/authlib/authlib/commit/5d2e603ec5f10bd2c4bf20e2495c076370d65b74"><code>5d2e603</code></a> chore: release 1.7.0</li> <li><a href="https://github.com/authlib/authlib/commit/767f08bb80ad6635beb7b54ad98ee9494b84bc26"><code>767f08b</code></a> fix: CSRF issue with starlette client</li> <li><a href="https://github.com/authlib/authlib/commit/e9aaef33933717e1bb5cf77a2cc1ceeb4c948620"><code>e9aaef3</code></a> Merge pull request <a href="https://redirect.github.com/authlib/authlib/issues/877">#877</a> from authlib/merge/1.6</li> <li><a href="https://github.com/authlib/authlib/commit/3c8ec9a8895ce3f7c588a9c3bf8e48cdf0c5b2c3"><code>3c8ec9a</code></a> Merge branch 'main' into merge/1.6</li> <li><a href="https://github.com/authlib/authlib/commit/ef09aebbba4439dedb22bd15777d1b3458b6f0ab"><code>ef09aeb</code></a> chore: release 1.6.10</li> <li><a href="https://github.com/authlib/authlib/commit/3be08468201a7766a93012ce149ea12822cab096"><code>3be0846</code></a> fix: redirecting to unvalidated redirect_uri on UnsupportedResponseTypeError</li> <li><a href="https://github.com/authlib/authlib/commit/4cf6f9792c56a5d598d1525af6384380cdccc4ec"><code>4cf6f97</code></a> Merge pull request <a href="https://redirect.github.com/authlib/authlib/issues/876">#876</a> from guillett/patch-1</li> <li><a href="https://github.com/authlib/authlib/commit/23f67b440ca4e2283139b6a57b3c979dbb3c4a50"><code>23f67b4</code></a> Update README.md docs.authlib.org/en/latest => docs.authlib.org/en/stable</li> <li><a href="https://github.com/authlib/authlib/commit/10401635d06f59aa282d3367b38dba73574a9127"><code>1040163</code></a> chore: prek autoupdate</li> <li><a href="https://github.com/authlib/authlib/commit/491209fb393c829cb38aebecd614f612191286b2"><code>491209f</code></a> Merge pull request <a href="https://redirect.github.com/authlib/authlib/issues/875">#875</a> from azmeuk/doc</li> <li>Additional commits viewable in <a href="https://github.com/authlib/authlib/compare/v1.6.9...v1.7.0">compare view</a></li> </ul> </details> <br /> Updates `seleniumbase` from 4.47.9 to 4.48.2 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/seleniumbase/SeleniumBase/releases">seleniumbase's releases</a>.</em></p> <blockquote> <h2>Fix unzip in powershell</h2> <ul> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/2bc7763221c6a0726010caf49476a2f5e87413d7">Fix unzip in powershell for paths that contain spaces</a></li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/b0518dc2bbd3bf28f659a310cec12ef6e07cb4f9">Refresh Python dependencies</a></li> </ul> <h2>What's Changed</h2> <ul> <li>Fix unzip in powershell by <a href="https://github.com/mdmintz"><code>@mdmintz</code></a> in <a href="https://redirect.github.com/seleniumbase/SeleniumBase/pull/4330">seleniumbase/SeleniumBase#4330</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/seleniumbase/SeleniumBase/compare/v4.48.1...v4.48.2">https://github.com/seleniumbase/SeleniumBase/compare/v4.48.1...v4.48.2</a></p> <h2>4.48.1 - Browser config updates</h2> <h2>Browser config updates</h2> <ul> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/bfb94e2fbdceea6e34f9f56297ee44eac9045c25">Update default config for Chrome and Edge</a></li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/77ea8fcb8c7bc355aa3b9e1a225b5545a90e4431">Refresh Python dependencies</a></li> </ul> <h2>What's Changed</h2> <ul> <li>Browser config updates by <a href="https://github.com/mdmintz"><code>@mdmintz</code></a> in <a href="https://redirect.github.com/seleniumbase/SeleniumBase/pull/4323">seleniumbase/SeleniumBase#4323</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/seleniumbase/SeleniumBase/compare/v4.48.0...v4.48.1">https://github.com/seleniumbase/SeleniumBase/compare/v4.48.0...v4.48.1</a></p> <h2>4.48.0 - Selenium and CDP updates</h2> <h2>Selenium and CDP updates</h2> <ul> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/8123a0e674f507629264b178afa4ba9585776056">Update CDP Mode</a> --> <code>solve_captcha()</code> now supports "Friendly Captcha" --> <code>nest-asyncio</code> is patched from within to avoid deprecation warnings on Python 3.14</li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/657c7231e62ab19deef514ac002995211b7ab814">Refresh Python dependencies</a> --> Includes a <code>selenium</code> upgrade</li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/9cc818b48e0cea0718421eff2dbb6ca8f924aed2">Add an example that bypasses "Friendly Captcha"</a></li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/afef6b86e848cdd699f03fe2fa4078c9893ff10d">Add Stealthy Playwright examples for BrowserScan</a></li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/184f079229055b845c514596ef08e284995e9823">Warn when await is missing from async method calls</a></li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/7abc5e4f0f746bf979730a514fc2854ddb5f10fd">Support "Friendly Captcha" solving in async mode</a></li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/7d0f56963af0baf69b09c1975b6b0c95b2e6855f">Add async example of solving "Friendly Captcha"</a></li> </ul> <h2>What's Changed</h2> <ul> <li>Selenium and CDP updates by <a href="https://github.com/mdmintz"><code>@mdmintz</code></a> in <a href="https://redirect.github.com/seleniumbase/SeleniumBase/pull/4319">seleniumbase/SeleniumBase#4319</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/seleniumbase/SeleniumBase/compare/v4.47.9...v4.48.0">https://github.com/seleniumbase/SeleniumBase/compare/v4.47.9...v4.48.0</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/a9605aea13b4498a8b60065a23201dae80413316"><code>a9605ae</code></a> Merge pull request <a href="https://redirect.github.com/seleniumbase/SeleniumBase/issues/4330">#4330</a> from seleniumbase/fix-unzip-in-powershell</li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/3a38776ea74d463b4f605753962137401d1ce847"><code>3a38776</code></a> Version 4.48.2</li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/b0518dc2bbd3bf28f659a310cec12ef6e07cb4f9"><code>b0518dc</code></a> Refresh Python dependencies</li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/2bc7763221c6a0726010caf49476a2f5e87413d7"><code>2bc7763</code></a> Fix unzip in powershell for paths that contain spaces</li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/a0aceea5080a14342fdf90919383f407d314f618"><code>a0aceea</code></a> Merge pull request <a href="https://redirect.github.com/seleniumbase/SeleniumBase/issues/4323">#4323</a> from seleniumbase/browser-config-updates</li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/9dc951b431e0faab1c586e70adf9ba92a26ad721"><code>9dc951b</code></a> Version 4.48.1</li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/77ea8fcb8c7bc355aa3b9e1a225b5545a90e4431"><code>77ea8fc</code></a> Refresh Python dependencies</li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/bfb94e2fbdceea6e34f9f56297ee44eac9045c25"><code>bfb94e2</code></a> Update default config for Chrome and Edge</li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/a381c354bb1cbef92466d75cadfccd7b2f8a6cb1"><code>a381c35</code></a> Update documentation in migration examples</li> <li><a href="https://github.com/seleniumbase/SeleniumBase/commit/377c3d218e5e688ddbb04aae9ebd71685e6725bf"><code>377c3d2</code></a> Merge pull request <a href="https://redirect.github.com/seleniumbase/SeleniumBase/issues/4319">#4319</a> from seleniumbase/selenium-and-cdp-updates</li> <li>Additional commits viewable in <a href="https://github.com/seleniumbase/SeleniumBase/compare/v4.47.9...v4.48.2">compare view</a></li> </ul> </details> <br /> Updates `basedpyright` from 1.39.0 to 1.39.3 <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/DetachHead/basedpyright/commit/5f6672701c5b6a739563894256418845239be2a2"><code>5f66727</code></a> 1.39.3</li> <li><a href="https://github.com/DetachHead/basedpyright/commit/d8741dfc88be16e11c66cceff78e6e2634ddf49b"><code>d8741df</code></a> hopefully fix docs deployment job</li> <li><a href="https://github.com/DetachHead/basedpyright/commit/ceb200c192bb53629b4c62fdc082ec27b108f316"><code>ceb200c</code></a> 1.39.2</li> <li><a href="https://github.com/DetachHead/basedpyright/commit/eb7a92cacd2697acb4e36e2f3147333588c88fa7"><code>eb7a92c</code></a> try to fix browser-basedpyright being published with nothing in it</li> <li><a href="https://github.com/DetachHead/basedpyright/commit/dec5306e9aabbce3f9b1b9ec283981d92dd43d80"><code>dec5306</code></a> update package-lock.json</li> <li><a href="https://github.com/DetachHead/basedpyright/commit/6db43de5dda601e3cd83998c669c4ecbbfde26f6"><code>6db43de</code></a> 1.39.1</li> <li><a href="https://github.com/DetachHead/basedpyright/commit/335e48619fa223fe3be0b6560d746a10934509c8"><code>335e486</code></a> fix failing tests from merge</li> <li><a href="https://github.com/DetachHead/basedpyright/commit/bbe71b686e84ebbff7699d35dab3376d411bb99d"><code>bbe71b6</code></a> delete newly added github action from upstream that we don't use</li> <li><a href="https://github.com/DetachHead/basedpyright/commit/8f2261891e8ceb278963e84658ebaf054b88e559"><code>8f22618</code></a> update prettierignore</li> <li><a href="https://github.com/DetachHead/basedpyright/commit/ff1f5a4af835b14927545c8890b303f48553acac"><code>ff1f5a4</code></a> fix compile errors from merge</li> <li>Additional commits viewable in <a href="https://github.com/detachhead/basedpyright/compare/v1.39.0...v1.39.3">compare view</a></li> </ul> </details> <br /> Updates `prek` from 0.3.8 to 0.3.10 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/j178/prek/releases">prek's releases</a>.</em></p> <blockquote> <h2>0.3.10</h2> <h2>Release Notes</h2> <p>Released on 2026-04-21.</p> <h3>Enhancements</h3> <ul> <li>Disallow rev for non-remote repos in schema (<a href="https://redirect.github.com/j178/prek/pull/1964">#1964</a>)</li> <li>Hide up-to-date output in non-verbose mode (<a href="https://redirect.github.com/j178/prek/pull/1942">#1942</a>)</li> <li>Improve merge conflict marker detection (<a href="https://redirect.github.com/j178/prek/pull/1937">#1937</a>)</li> <li>Keep finished hooks visible (<a href="https://redirect.github.com/j178/prek/pull/1967">#1967</a>)</li> <li>Preserve frozen comment spacing in auto-update (<a href="https://redirect.github.com/j178/prek/pull/1945">#1945</a>)</li> <li>Reimplement <code>@j178/prek</code> npm package (<a href="https://redirect.github.com/j178/prek/pull/1973">#1973</a>)</li> </ul> <h3>Bug fixes</h3> <ul> <li>Prefer stable Rust toolchains (<a href="https://redirect.github.com/j178/prek/pull/1974">#1974</a>)</li> </ul> <h3>Documentation</h3> <ul> <li>Add <code>SKILL.md</code> for prek (<a href="https://redirect.github.com/j178/prek/pull/1950">#1950</a>)</li> <li>Document <code>gh skill install j178/prek prek</code> to install prek skill for agents (<a href="https://redirect.github.com/j178/prek/pull/1951">#1951</a>)</li> <li>Improve compatibility and migration docs (<a href="https://redirect.github.com/j178/prek/pull/1940">#1940</a>)</li> </ul> <h3>Other changes</h3> <ul> <li>Sync latest identify tags (<a href="https://redirect.github.com/j178/prek/pull/1947">#1947</a>)</li> </ul> <h3>Contributors</h3> <ul> <li><a href="https://github.com/github-actions"><code>@github-actions</code></a></li> <li><a href="https://github.com/renovate"><code>@renovate</code></a></li> <li><a href="https://github.com/j178"><code>@j178</code></a></li> </ul> <h2>Install prek 0.3.10</h2> <h3>Install prebuilt binaries via shell script</h3> <pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf https://github.com/j178/prek/releases/download/v0.3.10/prek-installer.sh | sh </code></pre> <h3>Install prebuilt binaries via powershell script</h3> <pre lang="sh"><code>powershell -ExecutionPolicy Bypass -c "irm https://github.com/j178/prek/releases/download/v0.3.10/prek-installer.ps1 | iex" </code></pre> <h3>Install prebuilt binaries via Homebrew</h3> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/j178/prek/blob/master/CHANGELOG.md">prek's changelog</a>.</em></p> <blockquote> <h2>0.3.10</h2> <p>Released on 2026-04-21.</p> <h3>Enhancements</h3> <ul> <li>Disallow rev for non-remote repos in schema (<a href="https://redirect.github.com/j178/prek/pull/1964">#1964</a>)</li> <li>Hide up-to-date output in non-verbose mode (<a href="https://redirect.github.com/j178/prek/pull/1942">#1942</a>)</li> <li>Improve merge conflict marker detection (<a href="https://redirect.github.com/j178/prek/pull/1937">#1937</a>)</li> <li>Keep finished hooks visible (<a href="https://redirect.github.com/j178/prek/pull/1967">#1967</a>)</li> <li>Preserve frozen comment spacing in auto-update (<a href="https://redirect.github.com/j178/prek/pull/1945">#1945</a>)</li> <li>Reimplement <code>@j178/prek</code> npm package (<a href="https://redirect.github.com/j178/prek/pull/1973">#1973</a>)</li> </ul> <h3>Bug fixes</h3> <ul> <li>Prefer stable Rust toolchains (<a href="https://redirect.github.com/j178/prek/pull/1974">#1974</a>)</li> </ul> <h3>Documentation</h3> <ul> <li>Add <code>SKILL.md</code> for prek (<a href="https://redirect.github.com/j178/prek/pull/1950">#1950</a>)</li> <li>Document <code>gh skill install j178/prek prek</code> to install prek skill for agents (<a href="https://redirect.github.com/j178/prek/pull/1951">#1951</a>)</li> <li>Improve compatibility and migration docs (<a href="https://redirect.github.com/j178/prek/pull/1940">#1940</a>)</li> </ul> <h3>Other changes</h3> <ul> <li>Sync latest identify tags (<a href="https://redirect.github.com/j178/prek/pull/1947">#1947</a>)</li> </ul> <h3>Contributors</h3> <ul> <li><a href="https://github.com/github-actions"><code>@github-actions</code></a></li> <li><a href="https://github.com/renovate"><code>@renovate</code></a></li> <li><a href="https://github.com/j178"><code>@j178</code></a></li> </ul> <h2>0.3.9</h2> <p>Released on 2026-04-13.</p> <h3>Highlight</h3> <p><code>prek auto-update</code> is now stricter about pinned revisions and more useful in CI. It now keeps <code>rev</code> and <code># frozen:</code> comments in sync, can detect <a href="https://docs.zizmor.sh/audits/#impostor-commit">impostor commits</a> when validating pinned SHAs, and lets you use <code>prek auto-update --check</code> to fail on both available updates and frozen-ref mismatches without rewriting the config.</p> <p>Examples:</p> <pre lang="console"><code>$ prek auto-update # updates revs and repairs stale `# frozen:` comments </tr></table> </code></pre> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/j178/prek/commit/1981c51f599ed9db4a428eae13e4a8baf0cb0427"><code>1981c51</code></a> Bump version to 0.3.10</li> <li><a href="https://github.com/j178/prek/commit/ba745f6f407d43e70d2155c7929004a7701ca7e8"><code>ba745f6</code></a> Prefer stable Rust toolchains (<a href="https://redirect.github.com/j178/prek/issues/1974">#1974</a>)</li> <li><a href="https://github.com/j178/prek/commit/b6c591dbbc4d9917e62b4b6c1dd65419cffeb464"><code>b6c591d</code></a> Reimplement <code>@j178/prek</code> npm package (<a href="https://redirect.github.com/j178/prek/issues/1973">#1973</a>)</li> <li><a href="https://github.com/j178/prek/commit/fba1c85b1f2ce244e4b491ccaa0edffbdee01348"><code>fba1c85</code></a> Keep finished hooks visible (<a href="https://redirect.github.com/j178/prek/issues/1967">#1967</a>)</li> <li><a href="https://github.com/j178/prek/commit/bce57a3415d688a9b9d893018348570b381023e3"><code>bce57a3</code></a> Disallow rev for non-remote repos in schema (<a href="https://redirect.github.com/j178/prek/issues/1964">#1964</a>)</li> <li><a href="https://github.com/j178/prek/commit/afac10cf3ae355f6e2948c62ec25c54536bea40d"><code>afac10c</code></a> Split <code>auto_update.rs</code> into modules (<a href="https://redirect.github.com/j178/prek/issues/1962">#1962</a>)</li> <li><a href="https://github.com/j178/prek/commit/c3b9f115dabff92fde388c5edb091a10c00fb18f"><code>c3b9f11</code></a> Update GitHub Actions (major) (<a href="https://redirect.github.com/j178/prek/issues/1961">#1961</a>)</li> <li><a href="https://github.com/j178/prek/commit/6ca0443ecca17e8bc6df972740f445dd9795b4bd"><code>6ca0443</code></a> Update Rust crate annotate-snippets to v0.12.15 (<a href="https://redirect.github.com/j178/prek/issues/1955">#1955</a>)</li> <li><a href="https://github.com/j178/prek/commit/776277e104a751634711821c10f871a95b5bcd70"><code>776277e</code></a> Update Rust crate tokio to v1.51.1 (<a href="https://redirect.github.com/j178/prek/issues/1957">#1957</a>)</li> <li><a href="https://github.com/j178/prek/commit/c2b445a722db49f6b0dfeee763c19944bc77e757"><code>c2b445a</code></a> Update Rust crate toml_edit to v0.25.11 (<a href="https://redirect.github.com/j178/prek/issues/1958">#1958</a>)</li> <li>Additional commits viewable in <a href="https://github.com/j178/prek/compare/v0.3.8...v0.3.10">compare view</a></li> </ul> </details> <br /> Updates `pytest` from 9.0.2 to 9.0.3 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/pytest-dev/pytest/releases">pytest's releases</a>.</em></p> <blockquote> <h2>9.0.3</h2> <h1>pytest 9.0.3 (2026-04-07)</h1> <h2>Bug fixes</h2> <ul> <li> <p><a href="https://redirect.github.com/pytest-dev/pytest/issues/12444">#12444</a>: Fixed <code>pytest.approx</code> which now correctly takes into account <code>~collections.abc.Mapping</code> keys order to compare them.</p> </li> <li> <p><a href="https://redirect.github.com/pytest-dev/pytest/issues/13634">#13634</a>: Blocking a <code>conftest.py</code> file using the <code>-p no:</code> option is now explicitly disallowed.</p> <p>Previously this resulted in an internal assertion failure during plugin loading.</p> <p>Pytest now raises a clear <code>UsageError</code> explaining that conftest files are not plugins and cannot be disabled via <code>-p</code>.</p> </li> <li> <p><a href="https://redirect.github.com/pytest-dev/pytest/issues/13734">#13734</a>: Fixed crash when a test raises an exceptiongroup with <code>__tracebackhide__ = True</code>.</p> </li> <li> <p><a href="https://redirect.github.com/pytest-dev/pytest/issues/14195">#14195</a>: Fixed an issue where non-string messages passed to <!-- raw HTML omitted -->unittest.TestCase.subTest()<!-- raw HTML omitted --> were not printed.</p> </li> <li> <p><a href="https://redirect.github.com/pytest-dev/pytest/issues/14343">#14343</a>: Fixed use of insecure temporary directory (CVE-2025-71176).</p> </li> </ul> <h2>Improved documentation</h2> <ul> <li><a href="https://redirect.github.com/pytest-dev/pytest/issues/13388">#13388</a>: Clarified documentation for <code>-p</code> vs <code>PYTEST_PLUGINS</code> plugin loading and fixed an incorrect <code>-p</code> example.</li> <li><a href="https://redirect.github.com/pytest-dev/pytest/issues/13731">#13731</a>: Clarified that capture fixtures (e.g. <code>capsys</code> and <code>capfd</code>) take precedence over the <code>-s</code> / <code>--capture=no</code> command-line options in <code>Accessing captured output from a test function <accessing-captured-output></code>.</li> <li><a href="https://redirect.github.com/pytest-dev/pytest/issues/14088">#14088</a>: Clarified that the default <code>pytest_collection</code> hook sets <code>session.items</code> before it calls <code>pytest_collection_finish</code>, not after.</li> <li><a href="https://redirect.github.com/pytest-dev/pytest/issues/14255">#14255</a>: TOML integer log levels must be quoted: Updating reference documentation.</li> </ul> <h2>Contributor-facing changes</h2> <ul> <li> <p><a href="https://redirect.github.com/pytest-dev/pytest/issues/12689">#12689</a>: The test reports are now published to Codecov from GitHub Actions. The test statistics is visible <a href="https://app.codecov.io/gh/pytest-dev/pytest/tests">on the web interface</a>.</p> <p>-- by <code>aleguy02</code></p> </li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/pytest-dev/pytest/commit/a7d58d7a21b78581e636bbbdea13c66ad1657c1e"><code>a7d58d7</code></a> Prepare release version 9.0.3</li> <li><a href="https://github.com/pytest-dev/pytest/commit/089d98199c253d8f89a040243bc4f2aa6cd5ab22"><code>089d981</code></a> Merge pull request <a href="https://redirect.github.com/pytest-dev/pytest/issues/14366">#14366</a> from bluetech/revert-14193-backport</li> <li><a href="https://github.com/pytest-dev/pytest/commit/8127eaf4ab7f6b2fdd0dc1b38343ec97aeef05ac"><code>8127eaf</code></a> Revert "Fix: assertrepr_compare respects dict insertion order (<a href="https://redirect.github.com/pytest-dev/pytest/issues/14050">#14050</a>) (<a href="https://redirect.github.com/pytest-dev/pytest/issues/14193">#14193</a>)"</li> <li><a href="https://github.com/pytest-dev/pytest/commit/99a7e6029e7a6e8d53e5df114b1346e035370241"><code>99a7e60</code></a> Merge pull request <a href="https://redirect.github.com/pytest-dev/pytest/issues/14363">#14363</a> from pytest-dev/patchback/backports/9.0.x/95d8423bd...</li> <li><a href="https://github.com/pytest-dev/pytest/commit/ddee02a578da30dd43aedc39c1c1f1aaadfcee95"><code>ddee02a</code></a> Merge pull request <a href="https://redirect.github.com/pytest-dev/pytest/issues/14343">#14343</a> from bluetech/cve-2025-71176-simple</li> <li><a href="https://github.com/pytest-dev/pytest/commit/74eac6916fee34726cb194f16c516e96fbd29619"><code>74eac69</code></a> doc: Update training info (<a href="https://redirect.github.com/pytest-dev/pytest/issues/14298">#14298</a>) (<a href="https://redirect.github.com/pytest-dev/pytest/issues/14301">#14301</a>)</li> <li><a href="https://github.com/pytest-dev/pytest/commit/f92dee777cfdb77d1c43633d02766ddf1f07c869"><code>f92dee7</code></a> Merge pull request <a href="https://redirect.github.com/pytest-dev/pytest/issues/14267">#14267</a> from pytest-dev/patchback/backports/9.0.x/d6fa26c62...</li> <li><a href="https://github.com/pytest-dev/pytest/commit/7ee58acc8777c31ac6cf388d01addf5a414a7439"><code>7ee58ac</code></a> Merge pull request <a href="https://redirect.github.com/pytest-dev/pytest/issues/12378">#12378</a> from Pierre-Sassoulas/fix-implicit-str-concat-and-d...</li> <li><a href="https://github.com/pytest-dev/pytest/commit/37da870d37e3a2f5177cae075c7b9ae279432bf8"><code>37da870</code></a> Merge pull request <a href="https://redirect.github.com/pytest-dev/pytest/issues/14259">#14259</a> from mitre88/patch-4 (<a href="https://redirect.github.com/pytest-dev/pytest/issues/14268">#14268</a>)</li> <li><a href="https://github.com/pytest-dev/pytest/commit/c34bfa3b7acb65b594707c714f1d8461b0304eed"><code>c34bfa3</code></a> Add explanation for string context diffs (<a href="https://redirect.github.com/pytest-dev/pytest/issues/14257">#14257</a>) (<a href="https://redirect.github.com/pytest-dev/pytest/issues/14266">#14266</a>)</li> <li>Additional commits viewable in <a href="https://github.com/pytest-dev/pytest/compare/9.0.2...9.0.3">compare view</a></li> </ul> </details> <br /> Updates `ruff` from 0.15.10 to 0.15.11 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/astral-sh/ruff/releases">ruff's releases</a>.</em></p> <blockquote> <h2>0.15.11</h2> <h2>Release Notes</h2> <p>Released on 2026-04-16.</p> <h3>Preview features</h3> <ul> <li>[<code>ruff</code>] Ignore <code>RUF029</code> when function is decorated with <code>asynccontextmanager</code> (<a href="https://redirect.github.com/astral-sh/ruff/pull/24642">#24642</a>)</li> <li>[<code>airflow</code>] Implement <code>airflow-xcom-pull-in-template-string</code> (<code>AIR201</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/23583">#23583</a>)</li> <li>[<code>flake8-bandit</code>] Fix <code>S103</code> false positives and negatives in mask analysis (<a href="https://redirect.github.com/astral-sh/ruff/pull/24424">#24424</a>)</li> </ul> <h3>Bug fixes</h3> <ul> <li>[<code>flake8-async</code>] Omit overridden methods for <code>ASYNC109</code> (<a href="https://redirect.github.com/astral-sh/ruff/pull/24648">#24648</a>)</li> </ul> <h3>Documentation</h3> <ul> <li>[<code>flake8-async</code>] Add override mention to <code>ASYNC109</code> docs (<a href="https://redirect.github.com/astral-sh/ruff/pull/24666">#24666</a>)</li> <li>Update Neovim config examples to use <code>vim.lsp.config</code> (<a href="https://redirect.github.com/astral-sh/ruff/pull/24577">#24577</a>)</li> </ul> <h3>Contributors</h3> <ul> <li><a href="https://github.com/augustelalande"><code>@augustelalande</code></a></li> <li><a href="https://github.com/anishgirianish"><code>@anishgirianish</code></a></li> <li><a href="https://github.com/benberryallwood"><code>@benberryallwood</code></a></li> <li><a href="https://github.com/charliermarsh"><code>@charliermarsh</code></a></li> <li><a href="https://github.com/Dev-iL"><code>@Dev-iL</code></a></li> </ul> <h2>Install ruff 0.15.11</h2> <h3>Install prebuilt binaries via shell script</h3> <pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-installer.sh | sh </code></pre> <h3>Install prebuilt binaries via powershell script</h3> <pre lang="sh"><code>powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-installer.ps1 | iex" </code></pre> <h2>Download ruff 0.15.11</h2> <table> <thead> <tr> <th>File</th> <th>Platform</th> <th>Checksum</th> </tr> </thead> <tbody> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-aarch64-apple-darwin.tar.gz">ruff-aarch64-apple-darwin.tar.gz</a></td> <td>Apple Silicon macOS</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-aarch64-apple-darwin.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-x86_64-apple-darwin.tar.gz">ruff-x86_64-apple-darwin.tar.gz</a></td> <td>Intel macOS</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-x86_64-apple-darwin.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-aarch64-pc-windows-msvc.zip">ruff-aarch64-pc-windows-msvc.zip</a></td> <td>ARM64 Windows</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-aarch64-pc-windows-msvc.zip.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-i686-pc-windows-msvc.zip">ruff-i686-pc-windows-msvc.zip</a></td> <td>x86 Windows</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-i686-pc-windows-msvc.zip.sha256">checksum</a></td> </tr> </tbody> </table> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's changelog</a>.</em></p> <blockquote> <h2>0.15.11</h2> <p>Released on 2026-04-16.</p> <h3>Preview features</h3> <ul> <li>[<code>ruff</code>] Ignore <code>RUF029</code> when function is decorated with <code>asynccontextmanager</code> (<a href="https://redirect.github.com/astral-sh/ruff/pull/24642">#24642</a>)</li> <li>[<code>airflow</code>] Implement <code>airflow-xcom-pull-in-template-string</code> (<code>AIR201</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/23583">#23583</a>)</li> <li>[<code>flake8-bandit</code>] Fix <code>S103</code> false positives and negatives in mask analysis (<a href="https://redirect.github.com/astral-sh/ruff/pull/24424">#24424</a>)</li> </ul> <h3>Bug fixes</h3> <ul> <li>[<code>flake8-async</code>] Omit overridden methods for <code>ASYNC109</code> (<a href="https://redirect.github.com/astral-sh/ruff/pull/24648">#24648</a>)</li> </ul> <h3>Documentation</h3> <ul> <li>[<code>flake8-async</code>] Add override mention to <code>ASYNC109</code> docs (<a href="https://redirect.github.com/astral-sh/ruff/pull/24666">#24666</a>)</li> <li>Update Neovim config examples to use <code>vim.lsp.config</code> (<a href="https://redirect.github.com/astral-sh/ruff/pull/24577">#24577</a>)</li> </ul> <h3>Contributors</h3> <ul> <li><a href="https://github.com/augustelalande"><code>@augustelalande</code></a></li> <li><a href="https://github.com/anishgirianish"><code>@anishgirianish</code></a></li> <li><a href="https://github.com/benberryallwood"><code>@benberryallwood</code></a></li> <li><a href="https://github.com/charliermarsh"><code>@charliermarsh</code></a></li> <li><a href="https://github.com/Dev-iL"><code>@Dev-iL</code></a></li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/astral-sh/ruff/commit/53554b1cfe837f2eb992a81794480699478f1116"><code>53554b1</code></a> Bump 0.15.11 (<a href="https://redirect.github.com/astral-sh/ruff/issues/24678">#24678</a>)</li> <li><a href="https://github.com/astral-sh/ruff/commit/08c56c83cffbb1025cbf5bdede6c6d8be591cf47"><code>08c56c8</code></a> Factor out the <code>mdtest</code> crate (<a href="https://redirect.github.com/astral-sh/ruff/issues/24616">#24616</a>)</li> <li><a href="https://github.com/astral-sh/ruff/commit/725fbb736d2a999971449b61190b914abd26102a"><code>725fbb7</code></a> [ty] Use partially qualified names when reporting diagnostics regarding bad c...</li> <li><a href="https://github.com/astral-sh/ruff/commit/ddd6a30ff5fa27694dc1c50d0749885a1519d0a7"><code>ddd6a30</code></a> [ty] Do not suggest argument completion when at value of keyword argument (<a href="https://redirect.github.com/astral-sh/ruff/issues/2">#2</a>...</li> <li><a href="https://github.com/astral-sh/ruff/commit/9282e61d482a36da08d66bb8271afeef50b3bc45"><code>9282e61</code></a> Disallow <a href="https://github.com/disjoint"><code>@disjoint</code></a>_base on TypedDicts and Protocols (<a href="https://redirect.github.com/astral-sh/ruff/issues/24671">#24671</a>)</li> <li><a href="https://github.com/astral-sh/ruff/commit/e9986d8e3008eefe2e387312c4dc8b9c60f6f362"><code>e9986d8</code></a> [ty] Reject using properties with <code>Never</code> setters or deleters (<a href="https://redirect.github.com/astral-sh/ruff/issues/24510">#24510</a>)</li> <li><a href="https://github.com/astral-sh/ruff/commit/9cf212ff82f7b66b4a275ad6a9b1564aee1fa4a8"><code>9cf212f</code></a> [ty] Normalize property setter and deleter wrappers (<a href="https://redirect.github.com/astral-sh/ruff/issues/24509">#24509</a>)</li> <li><a href="https://github.com/astral-sh/ruff/commit/12a1589de4d7120cf99441ee4c14871bdc20968d"><code>12a1589</code></a> Add override mention to ASYNC109 docs (<a href="https://redirect.github.com/astral-sh/ruff/issues/24666">#24666</a>)</li> <li><a href="https://github.com/astral-sh/ruff/commit/dccb03d010f4442ed60624f8d2ba932706abaabb"><code>dccb03d</code></a> [ty] Avoid panicking on overloaded <code>Callable</code> type context (<a href="https://redirect.github.com/astral-sh/ruff/issues/24661">#24661</a>)</li> <li><a href="https://github.com/astral-sh/ruff/commit/61f9a0a5763fb068cd2f26c0ee9d63a277fb26c2"><code>61f9a0a</code></a> [ty] Sync vendored typeshed stubs (<a href="https://redirect.github.com/astral-sh/ruff/issues/24646">#24646</a>)</li> <li>Additional commits viewable in <a href="https://github.com/astral-sh/ruff/compare/0.15.10...0.15.11">compare view</a></li> </ul> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
📚 Shelfmark: Book Search & Request Tool
Shelfmark is a self-hosted web interface for searching and requesting books and audiobooks across multiple sources. Bring your own sources, metadata providers, and download clients to build a single hub for your digital library. Supports multiple users with a built-in request system, so you can share your instance with others and let them browse and request books on their own.
Works great alongside the following library tools, with support for automatic imports:
✨ Features
- One-Stop Interface - A clean, modern UI to search, browse, and download from multiple configured sources in one place
- Multiple Sources - Configurable web, torrent, usenet, and IRC source support
- Audiobook Support - Full audiobook search and download with dedicated processing
- Flexible Search - Search metadata providers (Hardcover, Open Library, Google Books) for rich book and audiobook discovery, or query configured sources directly
- Multi-User & Requests - Share your instance with others, let users browse and request books, and manage approvals with configurable notifications
- Authentication - Built-in login, OIDC single sign-on, proxy auth, and Calibre-Web database support
- Real-Time Progress - Unified download queue with live status updates across all sources
- Network Flexibility - Configurable proxy support, DNS settings, and optional Cloudflare handling for protected sources
🖼️ Screenshots
🚀 Quick Start
Prerequisites
- Docker & Docker Compose
Installation
-
Download the docker-compose file:
curl -O https://raw.githubusercontent.com/calibrain/shelfmark/main/compose/docker-compose.yml -
Start the service:
docker compose up -d -
Open
http://localhost:8084
Open the web interface, then configure the sources and settings you want to use.
Volume Setup
volumes:
- /your/config/path:/config # Config, database, and artwork cache directory
- /your/download/path:/books # Downloaded books
- /client/path:/client/path # Optional: For Torrent/Usenet downloads, match your client directory exactly.
Tip
: Point the download volume to your CWA or Grimmory ingest folder for automatic import.
Note
: CIFS shares require
nobrlmount option to avoid database lock errors.
Non-root container mode
- Start the container as
1000:1000with Dockeruser: "1000:1000"ordocker run --user 1000:1000. - For Kubernetes, set
runAsUser: 1000,runAsGroup: 1000, andrunAsNonRoot: truetogether. PUID/PGIDkeep the default root startup flow.- Mounted paths must already be writable by
1000:1000. USING_TOR=truerequires root startup.
⚙️ Configuration
Search Modes
Direct
- Queries configured sources directly
Universal (recommended)
- Search via metadata providers (Hardcover, Open Library, Google Books) for richer results
- Aggregates releases from multiple configured sources
- Full audiobook support
Environment Variables
Environment variables work for initial setup and Docker deployments. They serve as defaults that can be overridden in the web interface.
| Variable | Description | Default |
|---|---|---|
FLASK_PORT |
Web interface port | 8084 |
INGEST_DIR |
Book download directory | /books |
TZ |
Container timezone | UTC |
PUID / PGID |
Runtime user/group for the default root-startup flow (also supports legacy UID/GID) |
1000 / 1000 |
SEARCH_MODE |
direct or universal |
universal |
USING_TOR |
Enable Tor routing (requires root startup) | false |
See the full Environment Variables Reference for all available options.
Some of the additional options available in Settings:
- Prowlarr - Configure indexers and download clients to download books and audiobooks
- Additional audiobook sources - Configure additional sources for audiobook discovery
- IRC - Add details for IRC book sources and download directly from the UI
- Library Link - Add a link to your Calibre-Web or Grimmory instance in the UI header
- File processing - Customiseable download paths, file renaming and directory creation with template-based renaming
- Network Settings - Custom proxy support (SOCKS5 + HTTP/S) and configurable DNS
- Format & Language - Filter downloads by preferred formats, languages and sorting order
- Metadata Providers - Configure API keys for Hardcover, Open Library, etc.
🐳 Docker Variants
Standard
docker compose up -d
The full-featured image with all network capabilities included.
Tor Routing
Optional Tor support for network privacy:
curl -O https://raw.githubusercontent.com/calibrain/shelfmark/main/compose/docker-compose.tor.yml
docker compose -f docker-compose.tor.yml up -d
Notes:
- Requires root startup
- Requires
NET_ADMINandNET_RAWcapabilities - Timezone is auto-detected from Tor exit node
- Custom DNS/proxy settings are ignored when Tor is active
Lite
A lighter image without the built-in browser automation. Ideal for:
- External services - Already running FlareSolverr or similar for other applications
- Alternative sources - Using Prowlarr, IRC, or other configured sources
- Audiobooks - Using Shelfmark primarily for audiobooks
curl -O https://raw.githubusercontent.com/calibrain/shelfmark/main/compose/docker-compose.lite.yml
docker compose -f docker-compose.lite.yml up -d
If you need browser-based access with the Lite image, configure an external resolver in Settings.
🔐 Authentication
Authentication is optional but recommended for shared or exposed instances. Multiple authentication methods are available in Settings:
1. Single Username/Password
2. Proxy (Forward) Authentication
Proxy auth trusts headers set by your reverse proxy (e.g. X-Auth-User). Ensure Shelfmark is not directly exposed, and configure your proxy to strip/overwrite these headers for all inbound requests.
3. OIDC (OpenID Connect)
Integrate with your identity provider (Authelia, Authentik, Keycloak, etc.) for single sign-on. Supports PKCE flow, auto-discovery, group-based admin mapping, and auto-provisioning of new users.
4. Calibre-Web Database
If you're running Calibre-Web, you can reuse its user database by mounting it:
volumes:
- /path/to/calibre-web/app.db:/auth/app.db:ro
Multi-User Support
With any authentication method enabled, Shelfmark supports multi-user management with admin/user roles. Users can have per-user settings for download destinations, email recipients, and notification preferences. Non-admin users only see their own downloads and can submit book requests for admin review. Admins can configure request policies per source to control whether users can download directly, must submit a request, or are blocked entirely.
Project Scope
Shelfmark is a manual search and download tool, the entry point to your book library, not a library manager. It finds books, downloads them, and sends them to a configured destination. That's the full scope.
Shelfmark intentionally does not:
- Track or manage your library - it doesn't know or care what you already own
- Integrate with library software - what happens after delivery is up to your library tool
- Monitor authors, series, or new releases - there is no background automation
- Queue future downloads - if a book isn't available now, Shelfmark won't watch for it
These are non-goals, not missing features.
Contributing
Shelfmark's core feature set is complete. Development focuses on stability, bug fixes, quality-of-life improvements, and refining the search experience. Contributions in these areas are welcome, please file issues or submit pull requests on GitHub.
Feature requests that fall outside the project scope (library integration, automation, collection management) will be closed. If you're unsure whether something fits, open a discussion first.
Health Monitoring
The application exposes a health endpoint at /api/health (no authentication required). Add a health check to your compose:
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:8084/api/health"]
interval: 30s
timeout: 30s
retries: 3
Logging
Logs are available via:
docker logs <container-name>/var/log/shelfmark/inside the container (whenENABLE_LOGGING=true)
Log level is configurable via Settings or LOG_LEVEL environment variable.
Development
# Quality checks
make checks # Run ALL static analysis (frontend + Python)
make python-checks # Run Ruff, BasedPyright, and Vulture
make install-python-dev # Sync Python runtime + dev tools with uv
# Frontend development
make install # Install dependencies
make dev # Start Vite dev server (localhost:5173)
make build # Production build
make frontend-typecheck # TypeScript checks
# Backend (Docker)
make up # Start backend via docker-compose.dev.yml
make down # Stop services
make refresh # Rebuild and restart
make restart # Restart container
The frontend dev server proxies to the backend on port 8084.
License
MIT License - see LICENSE for details.
⚠️ Disclaimer
Shelfmark is a search interface that displays results from external metadata providers and sources. It does not host, store, or distribute any content. The developers are not responsible for how the tool is used or what is accessed through it.
Users are solely responsible for:
- Ensuring they have the legal right to download any material they access
- Complying with copyright laws and intellectual property rights in their jurisdiction
- Understanding and accepting the terms of any sources they configure
Use of this tool is entirely at your own risk.
Support
For issues or questions, please file an issue on GitHub.



