Tools
Instances
{!showingPanel && ( )}{editingId ? 'Edit Instance' : 'Add Instance'}
No instances configured
Add your first qBittorrent instance to get started
Repository: Maciejonos/qbitwebui Branch: master Commit: 1d1e3469ce89 Files: 183 Total size: 1.2 MB Directory structure: gitextract_1rmw6cng/ ├── .dockerignore ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ └── feature_request.md │ └── workflows/ │ ├── docker.yml │ ├── docs.yml │ └── tests.yml ├── .gitignore ├── .npmrc ├── .prettierrc ├── Dockerfile ├── LICENSE ├── README.md ├── __tests__/ │ ├── __mocks__/ │ │ └── bun-sqlite.ts │ ├── api/ │ │ ├── auth.test.ts │ │ ├── crossSeed.test.ts │ │ ├── files.test.ts │ │ ├── instances.test.ts │ │ ├── integrations.test.ts │ │ └── qbittorrent.test.ts │ ├── hooks/ │ │ ├── useInstance.test.tsx │ │ └── usePagination.test.tsx │ ├── reporter.ts │ ├── server/ │ │ ├── crossSeedCache.test.ts │ │ ├── crossSeedMatcher.test.ts │ │ ├── crossSeedScheduler.test.ts │ │ ├── crossSeedWorker.test.ts │ │ ├── fetch.test.ts │ │ ├── logger.test.ts │ │ ├── rateLimit.test.ts │ │ └── url.test.ts │ ├── themes/ │ │ └── themes.test.ts │ └── utils/ │ ├── fileTree.test.ts │ ├── format.test.ts │ ├── pagination.test.ts │ ├── ratioThresholds.test.ts │ └── search.test.ts ├── docs/ │ ├── .vitepress/ │ │ ├── config.ts │ │ └── theme/ │ │ ├── custom.css │ │ └── index.ts │ ├── guide/ │ │ ├── configuration.md │ │ ├── docker.md │ │ ├── features.md │ │ ├── getting-started.md │ │ └── network-agent/ │ │ └── index.md │ └── index.md ├── eslint.config.js ├── index.html ├── net-agent/ │ ├── Dockerfile │ ├── README.md │ ├── go.mod │ └── main.go ├── package.json ├── src/ │ ├── App.tsx │ ├── api/ │ │ ├── auth.ts │ │ ├── crossSeed.ts │ │ ├── files.ts │ │ ├── instances.ts │ │ ├── integrations.ts │ │ ├── netAgent.ts │ │ ├── qbittorrent.ts │ │ └── stats.ts │ ├── components/ │ │ ├── AddTorrentModal.tsx │ │ ├── AuthForm.tsx │ │ ├── CategoryTagManager.tsx │ │ ├── ContextMenu.tsx │ │ ├── CrossSeedManager.tsx │ │ ├── DateSettingsPopup.tsx │ │ ├── FileBrowser.tsx │ │ ├── FilterBar.tsx │ │ ├── Header.tsx │ │ ├── InstanceManager.tsx │ │ ├── Layout.tsx │ │ ├── LogViewer.tsx │ │ ├── NetworkTools.tsx │ │ ├── OrphanManager.tsx │ │ ├── RSSManager.tsx │ │ ├── RatioThresholdPopup.tsx │ │ ├── SearchPanel.tsx │ │ ├── SettingsPanel.tsx │ │ ├── Statistics.tsx │ │ ├── StatusBar.tsx │ │ ├── ThemeManager.tsx │ │ ├── ThemeSwitcher.tsx │ │ ├── TorrentDetailsPanel.tsx │ │ ├── TorrentList.tsx │ │ ├── TorrentRow.tsx │ │ ├── ViewSelector.tsx │ │ ├── columns.ts │ │ ├── settings/ │ │ │ ├── AdvancedTab.tsx │ │ │ ├── BehaviorTab.tsx │ │ │ ├── BitTorrentTab.tsx │ │ │ ├── ConnectionTab.tsx │ │ │ ├── DownloadsTab.tsx │ │ │ ├── RSSTab.tsx │ │ │ ├── SpeedTab.tsx │ │ │ ├── WebUITab.tsx │ │ │ └── index.ts │ │ └── ui/ │ │ ├── Checkbox.tsx │ │ ├── MultiSelect.tsx │ │ ├── Select.tsx │ │ ├── Toggle.tsx │ │ └── index.ts │ ├── contexts/ │ │ ├── InstanceProvider.tsx │ │ ├── PaginationProvider.tsx │ │ ├── ThemeContext.ts │ │ ├── ThemeProvider.tsx │ │ ├── instanceContext.ts │ │ └── paginationContext.ts │ ├── hooks/ │ │ ├── useClickOutside.ts │ │ ├── useCrossSeed.ts │ │ ├── useInstance.ts │ │ ├── usePagination.ts │ │ ├── useRSSManager.ts │ │ ├── useStats.ts │ │ ├── useSyncMaindata.ts │ │ ├── useTheme.ts │ │ ├── useTorrentDetails.ts │ │ ├── useTorrents.ts │ │ ├── useTransferInfo.ts │ │ └── useUpdateCheck.ts │ ├── index.css │ ├── main.tsx │ ├── mobile/ │ │ ├── MobileApp.tsx │ │ ├── MobileCrossSeedManager.tsx │ │ ├── MobileFileBrowser.tsx │ │ ├── MobileInstancePicker.tsx │ │ ├── MobileLogViewer.tsx │ │ ├── MobileNetworkTools.tsx │ │ ├── MobileOrphanManager.tsx │ │ ├── MobileRSSManager.tsx │ │ ├── MobileSearchPanel.tsx │ │ ├── MobileStatistics.tsx │ │ ├── MobileStats.tsx │ │ ├── MobileThemeManager.tsx │ │ ├── MobileThemeSwitcher.tsx │ │ ├── MobileTools.tsx │ │ ├── MobileTorrentDetail.tsx │ │ └── MobileTorrentList.tsx │ ├── server/ │ │ ├── db/ │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── middleware/ │ │ │ └── auth.ts │ │ ├── routes/ │ │ │ ├── auth.ts │ │ │ ├── crossSeed.ts │ │ │ ├── files.ts │ │ │ ├── instances.ts │ │ │ ├── integrations.ts │ │ │ ├── proxy.ts │ │ │ ├── stats.ts │ │ │ └── tools.ts │ │ └── utils/ │ │ ├── crossSeedCache.ts │ │ ├── crossSeedMatcher.ts │ │ ├── crossSeedScheduler.ts │ │ ├── crossSeedWorker.ts │ │ ├── crypto.ts │ │ ├── fetch.ts │ │ ├── logger.ts │ │ ├── qbt.ts │ │ ├── rateLimit.ts │ │ ├── statsRecorder.ts │ │ ├── torznab.ts │ │ └── url.ts │ ├── themes/ │ │ └── index.ts │ ├── types/ │ │ ├── preferences.ts │ │ ├── qbittorrent.ts │ │ ├── rss.ts │ │ ├── torrentDetails.ts │ │ └── views.ts │ └── utils/ │ ├── colorUtils.ts │ ├── customViews.ts │ ├── dateSettings.ts │ ├── fileTree.ts │ ├── format.ts │ ├── markdown.tsx │ ├── pagination.ts │ ├── ratioThresholds.ts │ └── search.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json ├── tsconfig.server.json ├── vite.config.ts └── vitest.config.ts ================================================ FILE CONTENTS ================================================ ================================================ FILE: .dockerignore ================================================ node_modules dist .git *.md docs ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: [Maciejonos] buy_me_a_coffee: maciejonos ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - OS: [e.g. iOS] - Browser [e.g. chrome, safari] - Version [e.g. 22] **Smartphone (please complete the following information):** - Device: [e.g. iPhone6] - OS: [e.g. iOS8.1] - Browser [e.g. stock browser, safari] - Version [e.g. 22] **Additional context** Add any other context about the problem here. ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature request about: Suggest an idea for this project title: '' labels: '' assignees: '' --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Add any other context or screenshots about the feature request here. ================================================ FILE: .github/workflows/docker.yml ================================================ name: Docker on: push: tags: ['v*'] workflow_dispatch: env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} jobs: build: runs-on: ubuntu-latest permissions: contents: read packages: write steps: - uses: actions/checkout@v4 - uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/metadata-action@v5 id: meta with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=raw,value=latest - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - uses: docker/build-push-action@v6 with: context: . push: true platforms: linux/amd64,linux/arm64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} agent: runs-on: ubuntu-latest permissions: contents: read packages: write steps: - uses: actions/checkout@v4 - uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/metadata-action@v5 id: meta with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-agent tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=raw,value=latest - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - uses: docker/build-push-action@v6 with: context: ./net-agent push: true platforms: linux/amd64,linux/arm64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} ================================================ FILE: .github/workflows/docs.yml ================================================ name: Docs on: push: branches: [master] paths: - 'docs/**' - '.github/workflows/docs.yml' workflow_dispatch: permissions: contents: read pages: write id-token: write concurrency: group: pages cancel-in-progress: false jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - run: bun install --frozen-lockfile - run: bun run docs:build - uses: actions/configure-pages@v4 - uses: actions/upload-pages-artifact@v3 with: path: docs/.vitepress/dist deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} needs: build runs-on: ubuntu-latest steps: - uses: actions/deploy-pages@v4 id: deployment ================================================ FILE: .github/workflows/tests.yml ================================================ name: CI on: push: branches: [master] pull_request: branches: [master] jobs: ci: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - run: bun install --frozen-lockfile - run: bun run lint - run: bun run build - run: bun run test env: CI: true agent: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - run: go build -o /dev/null . working-directory: net-agent ================================================ FILE: .gitignore ================================================ # local data node_modules dist *.local *.log CLAUDE.md docker-compose.yml data/ *.env #enforce package manager and runtime package-lock.json yarn.lock pnpm-lock.yaml # dbs *.db *.db-wal *.db-shm # tests coverage/ # docs docs/.vitepress/dist docs/.vitepress/cache ================================================ FILE: .npmrc ================================================ engine-strict=true ================================================ FILE: .prettierrc ================================================ { "useTabs": true, "tabWidth": 2, "semi": false, "singleQuote": true, "trailingComma": "es5", "printWidth": 120 } ================================================ FILE: Dockerfile ================================================ FROM oven/bun:alpine AS builder WORKDIR /app COPY package.json bun.lock ./ RUN bun install --frozen-lockfile COPY . . RUN bun run build FROM oven/bun:alpine WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/src/server ./src/server COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package.json ./ ENV NODE_ENV=production ENV PORT=3000 ENV DATABASE_PATH=/data/qbitwebui.db ENV SALT_PATH=/data/.salt EXPOSE 3000 VOLUME /data CMD ["bun", "run", "src/server/index.ts"] ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2026 Maciej Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================
| |
|
No instances configured
Hardlinks will be created here when file names differ
Delete {selected.size} item{selected.size > 1 ? 's' : ''}? This cannot be undone.
{selected.size <= 5 && (Loading release notes...
) : updateError ? (Failed to load release notes.
) : releaseNotes ? (No release notes available.
)}No instances configured
Add your first qBittorrent instance to get started
Are you sure you want to delete{' '} {deleteConfirm.label}? This action cannot be undone.
View qBittorrent application and peer logs
No instances configured
Add an instance to view logs
No log entries
{tab === 'main' && activeFilterCount < 4 ? 'Try adjusting your filters' : 'Logs will appear here'}
| Timestamp | {tab === 'main' ? (Level | ) : (Status | )}{tab === 'main' ? 'Message' : 'IP Address'} | {tab === 'peers' && (Reason | )}
|---|---|---|---|---|
| {formatTime(entry.timestamp)} | {typeInfo.label} | {entry.message} | ||
| {formatTime(entry.timestamp)} | {entry.blocked ? 'Blocked' : 'Connected'} | {entry.ip} | {entry.reason || '—'} |
Enable net-agent on an instance to run network diagnostics from your qBittorrent host
Setup GuideRun tests from your qBittorrent instance's network
Click Run to fetch IP information
)} {ipInfo.status === 'error' && !ipInfo.data && ({ipInfo.error}
)} {ipInfo.data && (Click Run to show DNS servers
)} {dns.status === 'error' && !dns.data && ({dns.error}
)} {dns.data && (No DNS servers found
)}Click Run to list network interfaces
)} {ifaces.status === 'error' && !ifaces.data && ({ifaces.error}
)} {ifaces.data && (Select a server or use auto-detection, then click Run
)} {speedtest.status === 'loading' && (Running speedtest...
This typically takes 30-60 seconds
{speedtest.error}
)} {speedtest.status === 'success' && speedtest.data && (
{commandResult.data.output || '(no output)'}
{commandResult.data.error && (
Find torrents with missing files or unregistered from trackers
No instances configured
All clear!
No orphaned torrents found
Are you sure you want to delete {selected.size}{' '} torrent{selected.size !== 1 ? 's' : ''}?
No instances available
Are you sure you want to delete{' '} {rss.deleteConfirm.name}? {rss.deleteConfirm.isFolder && ' This will also delete all feeds inside.'}
Are you sure you want to delete{' '} {rss.ruleDeleteConfirm}?
No integrations configured