- Home
- Plugins
- UI Enhancements
- space-lens
space-lens
huakunshen/space-lens
The Space Lens workbench as a DeepSeek Harness panel: the directory the current session is working in, scanned and explored by Space Lens itself.
Install
dsh plugin --profile web add github:huakunshen/space-lensREADME
Space Lens
Fast directory scanning and cleanup candidate utilities, powered by Rust and napi-rs.
Where the engine went (2026-09-14): the Rust engine that lived in
packages/space-lens— scanner, snapshot, cleanup, iCloud eviction — moved to Kuntu askuntu-scan(tagv0.3.0, pinned here atvendors/kuntu). This repo is the product shells: the SwiftUI apps (viaspace-lens-ffi), the npm package, the CLI/TUI, and the standalone iCloud app. Thespace_lens::Rust API is unchanged — the dependency is aliased.
Installation
npm install space-lens
Install the CLI
The Rust CLI is the crate spacelens (scan, candidates, clean, dirty-git,
icloud). Once published to crates.io:
cargo install spacelens # build from source
cargo binstall spacelens # or: prebuilt binary from the GitHub release
brew install HuakunShen/homebrew-tap/spacelens
Until then, install straight from this repository (cargo checks out the vendors/kuntu submodule itself):
cargo install --git https://github.com/HuakunShen/space-lens --locked spacelens
Releasing
Version bumping, publishing (crates.io / npm / Homebrew), tags, and the
packaging gotchas are documented step by step in docs/release.md.
Serve the web workbench
spacelens serve starts an authenticated HTTP host that serves the web UI and
speaks a closed JSON contract (@space-lens/contract): single-use pairing
tickets, bearer sessions, REST reads, and SSE scan events. Cleanup over the
web is trash-only; permanent deletion stays a CLI/TUI concern.
npx spacelens serve # loopback, read-only, current directory
npx spacelens serve --host 0.0.0.0 --allow-cidr 192.168.1.0/24
npx spacelens serve --allow-cleanup # grant trash-based cleanup
API Usage
import { scanDirectory } from 'space-lens'
const tree = scanDirectory({
directories: [process.cwd()],
ignoreHidden: false,
fullPath: false,
respectGitignore: true,
ignoredMode: 'summarize',
})
console.dir(tree, { depth: 3 })
Find cleanup candidates without deleting anything:
import { findCleanupCandidates, planCleanup } from 'space-lens'
const candidates = findCleanupCandidates({
directories: [process.cwd()],
presets: ['node', 'rust', 'gitignored'],
})
const plan = planCleanup({
directories: [process.cwd()],
presets: ['node'],
})
Directory Scanning
scanDirectory is intended for large folders where keeping every file node in memory is too expensive.
With ignoredMode: 'summarize', ignored directories such as target/ or node_modules/ are scanned for total size but returned as collapsed leaf nodes:
{
name: 'target',
path: '/path/to/project/target',
size: 1238249472,
children: [],
ignored: true,
collapsed: true
}
Use ignoredMode: 'exclude' to skip ignored paths entirely.
Cleanup Candidates
Cleanup APIs are dry-run oriented. findCleanupCandidates reports matching paths and sizes, and planCleanup returns a removal plan. The npm package does not execute deletion.
Initial presets:
node: reportsnode_modules.rust: reports Cargotargetdirectories.gitignored: reports paths matched by.gitignore.
Rust CLI
The workspace includes a simple Rust CLI app:
cargo run -p spacelens -- scan ~/Dev --json
cargo run -p spacelens -- candidates ~/Dev --preset node
cargo run -p spacelens -- clean ~/Dev --preset node
clean defaults to dry-run. Add --execute only when you want to remove the planned paths.
iCloud local-copy MVP
The Rust core and CLI also include a macOS-only iCloud inspection/eviction flow. It is separate from the existing deletion cleanup code:
cargo run --release -p spacelens -- icloud --help
cargo run --release -p spacelens -- icloud inspect <absolute-path>
cargo run --release -p spacelens -- icloud plan <disposable-iCloud-test-folder>
cargo run --release -p spacelens -- icloud evict <disposable-iCloud-test-folder>
evict is dry-run by default. Real execution requires --execute and the interactive confirmation phrase. The implementation never falls back to deleting files. Do not use a real Lightroom or Photos folder as the first test target.
Rust eviction uses a bounded worker pool (8 concurrent items by default, capped at 32), so a large plan does not create one task per file or process entries serially. The same bounded execution path is used by the Rust CLI service.
The NAPI package exposes the same native boundary through ICloudSession, with opaque one-shot plan IDs and decimal-string byte counts. The current main TUI does not yet expose these iCloud actions; it still provides the existing scan/cleanup UI.
The published space-lens package supports both the native library and the TUI executable:
import { scanDirectory } from 'space-lens'
npx space-lens ~/Dev --preset rust
space-lens TUI CLI
The space-lens package remains importable as a native library and also exposes the Solid/Uniview TUI as a space-lens executable. It has two modes: scan for a disk usage tree and clean for selecting cleanup candidates and deleting them after confirmation. In Scan mode, d deletes the current file or directory after confirmation, while A deletes all discovered preset candidates at once. Preset candidates are highlighted in red, and scan rows support mouse focus and folder expansion. It runs on Node.js 20 or newer:
yarn tui ~/Dev --preset rust
yarn tui ~/Dev --preset node,gitignored --sort path
npx space-lens ~/Dev --preset rust
Inside the TUI, press tab to switch modes, space to select a cleanup candidate, x to request deletion, and enter to confirm. In Scan mode, use d for the current row or A for all preset candidates. Use Ctrl+C or q to quit.
Benchmark CLI
This repository includes a local CLI for benchmarking the directory scanner and exporting trees:
yarn bench ~/Dev
yarn bench ~/Dev --no-json-size
yarn bench ~/Dev --export-tree tree.json
Options:
--export-tree PATH
--json-size / --no-json-size
--ignore-hidden
--full-path
--respect-gitignore / --no-respect-gitignore
--ignored-mode summarize|exclude
Development
yarn install
yarn workspace space-lens build:debug
yarn workspace @space-lens/cli build
yarn workspace space-lens test
yarn workspace @space-lens/cli test
yarn workspace space-lens typecheck
cargo test --workspace
Useful local commands:
yarn build: build release bindings for the current platform.yarn build:debug: build debug bindings for local testing.yarn tui: run the Solid/Uniview cleanup candidate viewer.yarn test: run Rust workspace tests and AVA tests.yarn typecheck: type-check the TypeScript workspaces.yarn bench: run the benchmark CLI from thespace-lensnpm workspace.
iCloud Free macOS app
The SwiftUI app lives in apps/icloud-free. From the repository root, the convenience recipes are:
just icloud-build # release build and signed local .app bundle
just icloud-open # open the existing bundle
just icloud-build-open # build, then open
just icloud-test # run Swift tests
Use CONFIGURATION=debug just icloud-build for a debug bundle. The app bundle is written to apps/icloud-free/.build/ICloudFree.app and is not installed into /Applications automatically.
Space Lens native macOS prototype
The native Space Lens macOS app lives in apps/space-lens-mac. It keeps a
synthetic demo map for safe UI/performance checks and now supports a read-only
real-folder scan through the separate Rust FFI facade. The scan can be
exported as the portable JSON snapshot. Normal filesystem cleanup uses an
explicit review flow that moves selected real nodes to the macOS Trash, so
they remain recoverable through Finder; it does not permanently delete files.
The MCP adapter is read-only. The macOS app also exposes the Apple-only iCloud Local Copies
capability and its bounded concurrent eviction flow; it never requests
downloads for cloud-only files.
just space-lens-mac-test
just space-lens-mac-build
just space-lens-mac-open
The portable snapshot contract is in packages/space-lens/src/snapshot.rs; the
separate C ABI facade and header are in packages/space-lens-ffi. The FFI
facade exposes read-only filesystem snapshots plus an opaque macOS-only iCloud
plan session. The native app can execute that session only after its explicit
confirmation flow; MCP remains read-only and does not expose the execution API.
Rust MCP adapter
The CLI has an opt-in, read-only MCP stdio adapter. Prebuilt installs (brew,
cargo binstall) carry it out of the box; source builds enable the mcp
feature explicitly:
spacelens mcp # prebuilt binaries
cargo install spacelens --features mcp # from source
cargo run --release -p spacelens --features mcp -- mcp # from a checkout
just space-lens-mcp # from a checkout
Point any MCP client (Claude Desktop, ZCode, Cursor, …) at spacelens mcp
over stdio. It implements the MCP initialize lifecycle and
tools/list/tools/call for filesystem snapshot export, discovery of large
files / developer caches / gitignored paths, cleanup-candidate inspection,
platform capabilities, and read-only iCloud plans. It exposes no delete,
Trash, cloud eviction, or download tool. MCP messages use newline-delimited
JSON-RPC on stdin/stdout; diagnostics must not be written to stdout.
Web UI status
The current main checkout has no apps/web workspace and no web start script. The Svelte Web UI and its standalone/Kunkun hosts live on the separate kunkun-ext branch. Do not switch the current dirty worktree just to run it; use a separate worktree and follow that branch's README instructions.
Related plugins
dsh-web (dsh-task-board)
zhu1090093659/dsh-web
dsh-web (dsh-web-all)
zhu1090093659/dsh-web
dsh-web-ui (dsh-task-board)
zhu1090093659/dsh-web-ui
dsh-web-ui (dsh-web-ui-all)
zhu1090093659/dsh-web-ui