https://github.com/anantadwi13/explorer
https://github.com/anantadwi13/explorer
ai-generated claude-code file-browser file-explorer vibe-coding
Last synced: about 1 month ago
JSON representation
- Host: GitHub
- URL: https://github.com/anantadwi13/explorer
- Owner: anantadwi13
- License: mit
- Created: 2026-05-03T12:14:45.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-05-03T15:28:02.000Z (about 1 month ago)
- Last Synced: 2026-05-03T17:27:30.638Z (about 1 month ago)
- Topics: ai-generated, claude-code, file-browser, file-explorer, vibe-coding
- Language: TypeScript
- Homepage:
- Size: 963 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# explorer
[](go.mod)
[](LICENSE)
> ⚠ **Playground / personal use only.** This is a hobby project, not a
> hardened service. There is no authentication, no rate limiting, and no
> security audit. Anyone who can reach the port can read every file
> under the served directory. Run it on your own machine bound to
> loopback (the default), or on a trusted LAN — never expose it to the
> public internet, behind a tunnel, or on a shared host.
A single-binary local directory browser — point it at a folder, open the URL, read everything in place from your phone on the same Wi-Fi.
## Why explorer?
Sometimes you just want to read the markdown notes, text files, and images on your laptop from the couch — on a phone, in a browser, without copying anything anywhere. `explorer` is a single static Go binary that serves a chosen directory over HTTP as a read-only browser, with markdown rendering, inline images, and deep-linkable URLs. No accounts, no writes, no cloud.
## Install
### Download the binary (fastest)
Bare binary, no extract step. Replace `` with the latest release version from the [Releases page](https://github.com/anantadwi13/explorer/releases) (e.g. `v0.2.0`).
```bash
# linux/amd64
curl -L -o explorer https://github.com/anantadwi13/explorer/releases/download//explorer__linux_amd64 && chmod +x explorer && ./explorer ./
# linux/arm64
curl -L -o explorer https://github.com/anantadwi13/explorer/releases/download//explorer__linux_arm64 && chmod +x explorer && ./explorer ./
# darwin/amd64 (Intel Macs)
curl -L -o explorer https://github.com/anantadwi13/explorer/releases/download//explorer__darwin_amd64 && chmod +x explorer && ./explorer ./
# darwin/arm64 (Apple Silicon)
curl -L -o explorer https://github.com/anantadwi13/explorer/releases/download//explorer__darwin_arm64 && chmod +x explorer && ./explorer ./
```
Windows (PowerShell):
```powershell
Invoke-WebRequest -Uri https://github.com/anantadwi13/explorer/releases/download//explorer__windows_amd64.exe -OutFile explorer.exe
.\explorer.exe .
```
### Download the archive (with LICENSE + README)
Same binary inside, plus `LICENSE` and `README.md` at the same directory level. The unix archive preserves the executable bit, so no `chmod` is needed after extracting.
```bash
# linux/amd64
curl -L -o explorer.tar.gz https://github.com/anantadwi13/explorer/releases/download//explorer__linux_amd64.tar.gz && tar -xzf explorer.tar.gz && ./explorer ./
# linux/arm64
curl -L -o explorer.tar.gz https://github.com/anantadwi13/explorer/releases/download//explorer__linux_arm64.tar.gz && tar -xzf explorer.tar.gz && ./explorer ./
# darwin/amd64
curl -L -o explorer.tar.gz https://github.com/anantadwi13/explorer/releases/download//explorer__darwin_amd64.tar.gz && tar -xzf explorer.tar.gz && ./explorer ./
# darwin/arm64
curl -L -o explorer.tar.gz https://github.com/anantadwi13/explorer/releases/download//explorer__darwin_arm64.tar.gz && tar -xzf explorer.tar.gz && ./explorer ./
```
Windows (PowerShell):
```powershell
Invoke-WebRequest -Uri https://github.com/anantadwi13/explorer/releases/download//explorer__windows_amd64.zip -OutFile explorer.zip
Expand-Archive .\explorer.zip -DestinationPath .
.\explorer.exe .
```
### Verify the download
Each release ships a single `checksums.txt` covering both bare binaries and archives. `--ignore-missing` lets the verify step succeed for whichever subset you actually downloaded.
```bash
# linux
sha256sum --ignore-missing -c checksums.txt
# macOS
shasum -a 256 --ignore-missing -c checksums.txt
```
After running the binary, confirm what you have with `./explorer --version` — it prints the embedded tag, short commit, and build date in ` (commit , built )` form.
**macOS Gatekeeper:** the first launch may show *"cannot be opened because the developer cannot be verified"* — these binaries are not signed/notarised. Clear the quarantine attribute once with:
```bash
xattr -d com.apple.quarantine ./explorer
```
This applies to both the bare binary and the binary extracted from the archive.
**Windows SmartScreen:** the first launch may show *"Windows protected your PC"*. Click **More info → Run anyway**. Same caveat applies to both shapes — the binaries are not Authenticode-signed.
### With Go (recommended for users with a Go toolchain)
Requires Go 1.24+.
```bash
go install github.com/anantadwi13/explorer/cmd/explorer@latest
```
This drops an `explorer` binary in `$GOBIN` (or `$GOPATH/bin` — make sure it is on your `PATH`). Once tagged releases exist, pin a version with `@v0.2.0` instead of `@latest`.
To try it without installing:
```bash
go run github.com/anantadwi13/explorer/cmd/explorer@latest
```
### From source (for contributors)
Requires Go 1.24+ and Node 18+.
```bash
git clone https://github.com/anantadwi13/explorer.git
cd explorer
make build # builds the SPA, embeds it, produces ./explorer
./explorer
```
### Docker / Docker Compose
```bash
docker compose up --build
```
Then open `http://localhost:8080`. The `docker-compose.yml` bind-mounts the current directory into `/data` (read-only) and runs:
```
explorer /data --host 0.0.0.0 --port 8080
```
**`--host 0.0.0.0` is mandatory inside the container.** With the default `127.0.0.1`, the server listens only on the container's loopback interface and Docker's port mapping cannot reach it.
## Quick start
```bash
# Serve the current directory on the default loopback port
explorer .
# Serve /home/alice/docs on port 9000
explorer /home/alice/docs --port 9000
# Expose on all interfaces (LAN-accessible — read the warning below)
explorer . --host 0.0.0.0
```
When `--host` is not a loopback address, the startup banner prints a warning:
**Output:**
```
explorer (playground build — no auth, no audit; do not expose publicly)
explorer serving /home/alice/docs
→ http://0.0.0.0:8080
⚠ host is not loopback — anyone on this network can read these files.
```
## Configuration
| Flag | Default | Description |
|------|---------|-------------|
| `--port` | `8080` | TCP port to listen on |
| `--host` | `127.0.0.1` | Address to bind to |
| `--version`, `-v` | — | Print ` (commit , built )` and exit |
## Features
- Serves any local directory over HTTP as a read-only browser
- Embedded React SPA: markdown rendering (GFM), syntax-highlighted text viewer for 35+ languages (Go, TypeScript, Python, Kotlin, Swift, Rust, JSON, TOML, and more), inline images, download button for everything else
- Mobile-first responsive layout; desktop shows a persistent tree sidebar
- Deep-linkable URLs for every folder and file
- Light / dark / system theme toggle
- Single static binary — no runtime dependencies
## Security model
`explorer` is designed for trusted, local use:
- **Read-only.** No write, update, or delete endpoints exist. The binary never modifies the served tree.
- **Loopback by default.** `--host` defaults to `127.0.0.1`, so out of the box only your own machine can reach it.
- **Path-traversal containment.** Every path-accepting endpoint resolves the request relative to the served root, rejects `..` and absolute paths, and follows symlinks only if the resolved target stays inside the root. Symlinks pointing outside the root are silently dropped from listings and return `400 outside_root` when accessed directly.
- **No authentication.** There is no login, no token, no per-file ACL.
Because there is no authentication, **`--host 0.0.0.0` exposes every file under the served root to anyone who can reach your machine on the network.** Only do this on a network you trust. Do not expose `explorer` to the public internet.
## Development
Two-process dev workflow: Go server on `:8080` + Vite dev server on `:5173` proxying API/raw paths to the Go server.
```bash
make dev-server # builds and runs the Go binary against ./testdata
make dev-web # starts the Vite dev server on :5173 (run alongside dev-server)
make test # go test ./cmd/... ./internal/...
make web-commit # rebuild the embedded SPA and stage internal/server/ui/dist/
make clean # remove ./explorer and internal/server/ui/dist
```
`internal/server/ui/dist/` is committed to source control so module-proxy installs (`go install`, `go run`) ship a working SPA. **Run `make web-commit` whenever you change anything under `web/src/`** so the embedded build stays in sync.
## Out-of-scope (v1)
These are intentionally deferred:
- File watcher / live reload
- Search across files
- ~~Syntax highlighting for code~~ ✓ shipped — Go, TypeScript, Python, Kotlin, Swift, Rust, and 35+ more languages plus JSON/TOML/GraphQL/Protobuf; see `web/src/components/syntax/grammars.ts` for the full list
- README auto-render in folder listings
- Tree pagination per folder
- Authentication / multi-user
- Write / update / delete
- PDF, Office, video, audio preview
## Troubleshooting
**"connection refused" on port 8080 in Docker**
Make sure the `command` in `docker-compose.yml` includes `--host 0.0.0.0`. The default loopback bind is not reachable through Docker's port mapping.
**`GET /` returns a plain-text 404 (`404 page not found`) after a local build**
The embedded SPA is empty. Run `make build` (not just `go build`) to build the frontend and embed it. If you got the binary via `go install ...@latest` and still see this, the published `internal/server/ui/dist/` is empty — please open an issue, this should not happen.
**Symlink file is missing from listing**
Symlinks whose targets resolve outside the served root are silently omitted from directory listings and return a `400 outside_root` error when accessed directly — this is intentional path-traversal containment.
## Contributing
Issues and pull requests are welcome.
- Run `make test` before submitting a PR.
- If your PR touches `web/src/`, run `make web-commit` and include the regenerated `internal/server/ui/dist/` in the same commit. The embedded SPA is shipped via the Go module proxy, so a stale `dist/` means `go install` users get an outdated frontend against an updated API.
## License
[MIT](LICENSE) © anantadwi13