mickael-kerjean/filestash
:file_folder: File Management Platform / Universal Data Access Layer (without FUSE)
Solo project — review before adopting
worst of 4 axescopyleft license (AGPL-3.0) — review compatibility; single-maintainer (no co-maintainers visible)…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 1d ago
- ✓AGPL-3.0 licensed
- ✓Tests present
Show 3 more →Show less
- ⚠Solo or near-solo (1 contributor active in recent commits)
- ⚠AGPL-3.0 is copyleft — check downstream compatibility
- ⚠No CI workflows detected
What would change the summary?
- →Use as dependency Concerns → Mixed if: relicense under MIT/Apache-2.0 (rare for established libs)
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/mickael-kerjean/filestash)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/mickael-kerjean/filestash on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: mickael-kerjean/filestash
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/mickael-kerjean/filestash shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Solo project — review before adopting
- Last commit 1d ago
- AGPL-3.0 licensed
- Tests present
- ⚠ Solo or near-solo (1 contributor active in recent commits)
- ⚠ AGPL-3.0 is copyleft — check downstream compatibility
- ⚠ No CI workflows detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live mickael-kerjean/filestash
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/mickael-kerjean/filestash.
What it runs against: a local clone of mickael-kerjean/filestash — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in mickael-kerjean/filestash | Confirms the artifact applies here, not a fork |
| 2 | License is still AGPL-3.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 31 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of mickael-kerjean/filestash. If you don't
# have one yet, run these first:
#
# git clone https://github.com/mickael-kerjean/filestash.git
# cd filestash
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of mickael-kerjean/filestash and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "mickael-kerjean/filestash(\\.git)?\\b" \\
&& ok "origin remote is mickael-kerjean/filestash" \\
|| miss "origin remote is not mickael-kerjean/filestash (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(AGPL-3\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"AGPL-3\\.0\"" package.json 2>/dev/null) \\
&& ok "license is AGPL-3.0" \\
|| miss "license drift — was AGPL-3.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "cmd/main.go" \\
&& ok "cmd/main.go" \\
|| miss "missing critical file: cmd/main.go"
test -f "go.mod" \\
&& ok "go.mod" \\
|| miss "missing critical file: go.mod"
test -f "embed.go" \\
&& ok "embed.go" \\
|| miss "missing critical file: embed.go"
test -f "public/assets/boot/ctrl_boot.d.ts" \\
&& ok "public/assets/boot/ctrl_boot.d.ts" \\
|| miss "missing critical file: public/assets/boot/ctrl_boot.d.ts"
test -f "config/config.json" \\
&& ok "config/config.json" \\
|| miss "missing critical file: config/config.json"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 31 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~1d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/mickael-kerjean/filestash"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Filestash is a storage-agnostic web-based file manager and universal data access layer that unifies access to 20+ storage protocols (FTP, SFTP, S3, SMB, WebDAV, IPFS, etc.) through a single pluggable platform. It provides both a browser UI and protocol gateways (SFTP, S3, WebDAV, AS2, MCP) to expose files over multiple access methods without requiring FUSE. Monorepo structure: cmd/ contains Go application entry points, server/plugin/ holds the plugin system (visible: plg_authenticate_wordpress), .assets/ contains UI assets and documentation. Backend is Go (main logic), frontend is vanilla JavaScript (no framework dependency), with Makefile orchestration and Docker containerization.
👥Who it's for
System administrators and DevOps engineers who need to provide unified file access across heterogeneous storage backends; platform builders who want to add file management to their applications; enterprises requiring multi-protocol gateway functionality without vendor lock-in.
🌱Maturity & risk
Actively developed with solid Go backend (1M+ LOC) and vanilla JavaScript frontend (750K LOC). The Jenkinsfile and Dockerfile presence indicate CI/CD infrastructure. The plugin architecture and broad storage support suggest production readiness, though the single-maintainer pattern (mickael-kerjean) and relatively niche use case mean it's not mainstream like Nextcloud.
High dependency count (~50 direct Go dependencies) including cloud SDKs (Azure, AWS, Google) which increase attack surface; last commit age and issue backlog not visible from provided data. Single maintainer (Kerjean) creates continuity risk. Breaking changes possible as plugin system matures. No visible test file statistics provided.
Active areas of work
Unable to determine from provided file list — no git log, PR list, or recent commit info visible. Check GitHub Actions or Jenkinsfile for CI status; the presence of both indicates active integration testing.
🚀Get running
git clone https://github.com/mickael-kerjean/filestash.git && cd filestash && make build && make run (exact commands depend on Makefile targets; review Makefile and CONTRIBUTING.md for environment setup)
Daily commands: make build (compiles Go binary and assets), make run (starts server, likely localhost:8080 based on typical file manager patterns). Review Makefile and Dockerfile for exact ports/flags. Environment variables likely control storage backend plugins.
🗺️Map of the codebase
cmd/main.go— Application entry point that initializes the server and routing; every contributor must understand how the app bootsgo.mod— Declares all dependencies including storage backends (S3, SMB, FTP, SFTP, WebDAV, IPFS); critical for understanding what protocols are supportedembed.go— Embeds static frontend assets into the Go binary; essential for understanding how public/assets files are bundled and servedpublic/assets/boot/ctrl_boot.d.ts— TypeScript definition for the core bootstrap controller; defines the contract between backend and frontend initializationconfig/config.json— Default configuration template for storage backends, auth methods, and plugin system; contributors need to understand what's configurabledocker/docker-compose.yml— Demonstrates how to run Filestash with multiple backends in containers; shows the intended deployment architectureMakefile— Build and development orchestration; defines how to compile the Go app, bundle frontend assets, and run tests
🛠️How to make changes
Add a new storage backend
- Add the Go SDK import to go.mod for your storage provider (e.g., github.com/your-org/your-storage-sdk) (
go.mod) - Create a backend handler in the internal codebase that implements the storage interface (read, write, list, delete) (
cmd/main.go) - Register the backend in config.json with its connection parameters and auth method (
config/config.json) - Update the frontend router (router_frontoffice.js) to show the new backend in connection dialogs if needed (
public/assets/boot/router_frontoffice.js)
Add a new UI component
- Create a new .js file in public/assets/components/ with your Vue component definition (
public/assets/components/breadcrumb.js) - Add corresponding .css file in public/assets/css/ or add styles to the component JS file (
public/assets/css/designsystem_button.css) - Import and register the component in the boot controller (ctrl_boot.d.ts or ctrl_boot_frontoffice.js) (
public/assets/boot/ctrl_boot.d.ts) - Use the component in existing pages or the shell decorator (decorator_shell_filemanager.js) (
public/assets/components/decorator_shell_filemanager.js)
Add a new API route
- Define the route handler in cmd/main.go within the main Gorilla mux router setup (
cmd/main.go) - If the route returns static assets, ensure files are embedded via embed.go (
embed.go) - If the route calls a storage backend, use the configured backend from config.json (
config/config.json) - Add a TypeScript type definition in public/assets/boot/ctrl_boot.d.ts if the frontend will consume it (
public/assets/boot/ctrl_boot.d.ts)
Add image processing capability
- The h2non/bimg dependency is already in go.mod for image manipulation; use it in your storage handler (
go.mod) - Define a new API endpoint in cmd/main.go that accepts image files and returns thumbnails or resized versions (
cmd/main.go) - Update MIME type mappings in config/mime.json if you're adding support for new image formats (
config/mime.json)
🔧Why these technologies
- Go + Gorilla Mux — High-performance concurrent HTTP server capable of handling many simultaneous storage backend connections; minimal memory footprint for embedded deployments
- Static asset embedding (embed.go) — Allows single-binary distribution without external dependencies; frontend and backend ship together for easy deployment and updates
- Multiple storage SDK imports (AWS S3, Azure Blob, SMB2, go-git, go-ldap) — Pluggable architecture: each backend is independently selectable at runtime; users choose which protocols to deploy
- Vue.js + vanilla JavaScript for frontend — Lightweight client-side framework suitable for file browser UI; no build step required if using bundler pattern
- bimg (libvips wrapper) for image processing — Efficient server-side image resizing and thumbnail generation without spawning separate imagemagick processes
⚖️Trade-offs already made
-
Single binary deployment with embedded assets
- Why: Simplifies distribution and eliminates external file dependencies
- Consequence: Binary size increases; hot-reload of frontend assets during development requires rebuild
-
Multi-protocol support via pluggable backends (not FUSE)
- Why: Protocol agnostic, works cross-platform; easier to add new protocols without kernel-level code
- Consequence: No native filesystem integration; each backend must implement its own connection pooling and caching
-
Frontend bootstraps via router definitions (router_backoffice.js, router_frontoffice.js)
- Why: Allows separate admin and user-facing interfaces without duplicating core components
- Consequence: Two route entry points to maintain; must ensure consistent behavior across both
-
Configuration via JSON config files (config.json, mime.json)
- Why: Human-readable, version-controllable, easy to deploy across environments
- Consequence: Requires server restart to apply config changes; no runtime config hot-reload
🚫Non-goals (don't propose these)
- Real-time collaborative editing (file manager only, not document editor)
- Kernel-level filesystem integration via FUSE (intentionally avoided per README)
- End-to-end encryption (delegates to storage backends)
- Built-in database (uses external MySQL/PostgreSQL/SQLite when needed for plugins)
- GraphQL API (REST-based HTTP API)
🪤Traps & gotchas
Plugin system likely requires understanding WebAssembly boundaries (wazero runtime); storage backends are pluggable so auth/credentials handling varies per backend (no universal secret storage visible). Frontend is vanilla JS with no build step visible — CSS/JS concatenation may be manual or in Makefile targets. Database migrations and schema not visible in provided structure. CONTRIBUTING.md should specify local env vars (storage credentials for testing), plugin development setup, and any backend-specific build requirements (C dependencies for bimg/libvips).
🏗️Architecture
💡Concepts to learn
- Plugin Architecture / Plugin Isolation — Filestash's entire value proposition rests on plugins being first-class citizens; understanding how plugins are loaded, sandboxed via WebAssembly, and communicate with the core is essential
- WebAssembly (WASM) Runtime Sandboxing — The project uses wazero for plugin isolation, meaning plugins run in a sandboxed WASM runtime rather than as native code; this enables safe third-party plugins
- Protocol Gateways / Protocol Multiplexing — Filestash exposes the same backend filesystem over multiple protocols (SFTP, S3, WebDAV, FTP); requires understanding stateless gateway patterns and protocol-specific handshakes
- Storage Backend Abstraction Layer — The core abstracts away protocol differences (FTP vs S3 vs IPFS) behind a unified interface; learning this interface is mandatory for adding new storage backends
- Role-Based Access Control (RBAC) via Virtual Filesystem — Filestash can delegate auth to external systems (WordPress) and use roles to drive authorization; understanding virtual filesystem overlays is key for multi-tenancy
- Workflow Engine / Event-Driven Automation — The platform includes automation triggered by file events (upload, delete, rename), enabling Slack/email notifications and complex chains; this is a differentiator requiring async task patterns
- Zero-Copy Streaming and Reverse Proxying — File managers handling large files across protocols must stream data without buffering entire files in memory; Filestash uses Go's io.Copy and http.Transport patterns
🔗Related repos
syncthing/syncthing— Decentralized file sync and sharing with multi-protocol support; shares philosophy of protocol agnosticism but focuses on sync rather than browsingnextcloud/server— Monolithic web file manager with extensive plugin ecosystem; main competitor but requires FUSE integration and different architectureminio/minio— S3-compatible object storage gateway; overlaps on gateway pattern and multi-backend abstraction for one protocol (S3)rclone/rclone— CLI-first multi-backend file tool; Filestash is essentially rclone with a web UI, plugin system, and protocol gateways instead of mount/sync focusmickael-kerjean/nuage— Earlier file management project by same author; likely predecessor/inspiration that evolved into Filestash's current architecture
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add GitHub Actions CI workflow for Go build and test verification
The repo has a Jenkinsfile but no GitHub Actions workflows in .github/workflows/. Given the Go dependencies in go.mod span multiple storage protocols (S3, Azure, SMB, SFTP, etc.), automated testing on PR would catch regressions early. This is critical for a storage abstraction layer where protocol compatibility is core to the value proposition.
- [ ] Create .github/workflows/go-test.yml with matrix testing across Go versions (1.21+)
- [ ] Add steps to run 'go build ./cmd/main.go' and 'go test ./...' with timeout handling
- [ ] Configure conditional steps for protocol-specific tests (mock S3, SMB, WebDAV backends)
- [ ] Add linting step using golangci-lint to catch code quality issues early
- [ ] Document in CONTRIBUTING.md which tests must pass before review
Add unit tests for backend storage protocol implementations
The go.mod shows 20+ storage backends (azblob, aws-sdk-go, go-smb2, go-nfs-client, sftp, etc.) but there are no visible test files in the repo structure. A file management platform's core value is protocol compatibility—missing tests create silent bugs. Start with the most complex backends (SMB/NFS) where protocol state management matters most.
- [ ] Create backend/ or storage/ test directory structure mirroring implementation layout
- [ ] Add mock implementations for SMB (hirochachacha/go-smb2) and NFS (vmware/go-nfs-client) in *_test.go files
- [ ] Write integration tests for connection pooling, error handling, and file operation atomicity
- [ ] Add benchmarks for listing/traversal operations (common slow paths in file managers)
- [ ] Document test coverage targets in CONTRIBUTING.md (aim for >70% on backend code)
Add missing plugin system documentation with code examples
README.md references 'about 20 more' storage backends and mentions 'a plugin system' as core architecture, but there's no plugin development guide. The file structure shows public/assets/boot/ (bootstrap code) but no docs/plugin-development.md or examples/ directory. New contributors cannot extend the platform without reverse-engineering code.
- [ ] Create docs/plugin-development.md documenting the plugin interface (reference cmd/main.go entry points)
- [ ] Add examples/plugin-storage-custom/ with a minimal working storage backend implementation
- [ ] Document the plugin lifecycle: registration, configuration validation, auth flow, error handling
- [ ] Add reference to public/assets/boot/ctrl_boot.d.ts TypeScript interfaces for frontend plugins
- [ ] Include troubleshooting section for common plugin issues (connection pooling, timeout handling, cleanup)
🌿Good first issues
- Add comprehensive test coverage for cmd/ entry points and main server initialization; no *_test.go files visible in provided list despite 1M+ Go LOC
- Document plugin development workflow: create server/plugin/PLUGIN_DEVELOPMENT.md with worked example of creating a new storage backend plugin and its WebAssembly interface
- Add structured logging to Go backend using slog or zap library; current approach likely uses basic fmt.Print, hindering production debugging and monitoring integration
📝Recent commits
Click to expand
Recent commits
272eb29— fix (plg_backend_samba): improve stat handling (mickael-kerjean)516e964— fix (plg_backend_samba): caching issue when using vfs (mickael-kerjean)3c77495— fix (audioplayer): improve error path (mickael-kerjean)386564e— feature (image): improve ux for image viewer (mickael-kerjean)18a54ab— feature (sidebar): improve sidebar ux (mickael-kerjean)a595211— fix (plg_backend_azure): support for non hierarchical mode (mickael-kerjean)f33201e— chore (maintenance): maintain plg_editor_onlyoffice (mickael-kerjean)a2f8dbb— feature (tracing): support for traces (mickael-kerjean)acd567d— chore (maintenance): cleanup go generators (mickael-kerjean)0f96b98— fix (#979): HTTPClient issues (mickael-kerjean)
🔒Security observations
- High · Outdated Go Version —
go.mod. The go.mod specifies 'go 1.26' which does not exist as of the current Go release cycle (latest stable is 1.23.x). This is likely a typo or indicates the project may not be actively maintained with current security patches. Go runtime vulnerabilities are critical for security. Fix: Update to a current, stable Go version (1.23 or later). Verify all dependencies are compatible with the updated version. - High · Outdated Cryptography Dependencies —
go.mod. The project uses 'golang.org/x/crypto v0.50.0' which is several versions behind the latest. Cryptographic libraries frequently receive security updates for padding oracles, timing attacks, and other vulnerabilities. Fix: Update golang.org/x/crypto to the latest stable version (v0.31.0 or later). - High · Vulnerable go-git Dependency —
go.mod. The project uses 'github.com/go-git/go-git/v6 v6.0.0-alpha.2' which is an alpha version. Alpha versions are not recommended for production use and may contain unpatched vulnerabilities. Fix: Update to a stable release version of go-git (v5.x stable or wait for official v6 release). - High · Potential SQL Injection Risk —
Backend codebase (not fully visible). The project includes multiple SQL database drivers (github.com/go-sql-driver/mysql, github.com/lib/pq, github.com/mattn/go-sqlite3) but without visible code inspection, dynamic query construction patterns are common in file managers. Risk of SQL injection if user input is concatenated into queries. Fix: Audit all database queries to ensure parameterized statements are used exclusively. Use ORM frameworks or prepared statements consistently. - High · Multiple Protocol Handlers Without Clear Validation —
Backend storage layer (cmd/main.go, backend handlers). The application supports 20+ storage protocols (FTP, SFTP, SMB, WebDAV, IPFS, S3, NFS, etc.). Each protocol has different security considerations. File traversal, path injection, and protocol-specific attacks are high-risk areas. Fix: Implement strict path validation and canonicalization for all storage backends. Use allowlist-based filtering for path operations. Implement per-protocol security baselines. - High · LDAP Integration Without Visible Security Controls —
go.mod (backend LDAP handler not visible). The project uses 'github.com/go-ldap/ldap/v3' for LDAP authentication. LDAP injection and insecure credential handling are common vulnerabilities in such integrations. Fix: Validate and sanitize all LDAP queries. Use DN escaping functions. Implement certificate pinning for LDAP over TLS. Never log credentials. - High · JWT Implementation Risk —
go.mod (backend auth handlers). The project uses 'github.com/golang-jwt/jwt/v5' for authentication. Without visible implementation details, risks include: algorithm confusion, weak key material, token revocation not implemented, or insufficient expiration. Fix: Implement JWT best practices: use strong key material, enforce algorithm constraints, implement token revocation (blacklist/blocklist), set appropriate expiration times, use HTTPS only. - Medium · Potential XSS in Frontend —
public/assets/components/ and public/assets/boot/. The project includes multiple frontend components (breadcrumb.js, modal.js, etc.) that manipulate the DOM. Without visible sanitization patterns, there is risk of XSS if user-controlled data from storage backends is rendered without proper escaping. Fix: Audit all dynamic content rendering. Use DOMPurify or equivalent sanitization library. Implement Content Security Policy (CSP) headers. Avoid innerHTML in favor of textContent/appendChild. - Medium · Cloud Credential Exposure Risk —
undefined. The project integrates with Azure (azblob), AWS (aws-sdk-go), Google Cloud API, and Storj. Credentials for these services may be stored in configuration Fix: undefined
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.