Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# UFFS — Sponsor Channels
#
# This file controls the "Sponsor this project" button that GitHub renders
# in the repository sidebar and on the org profile.
#
# Channels are shown in the order listed. Uncomment each line the moment
# the corresponding account is live — the button updates on the next page
# load, no release or deploy needed.
#
# Docs: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/displaying-a-sponsor-button-in-your-repository

# ── GitHub Sponsors ────────────────────────────────────────────────────────
# Primary channel for individual supporters ($5–$50/month).
# Zero platform fees on org-account sponsorships.
# Enroll at: https://github.com/sponsors (requires skyllc-ai org owner login)
# Uncomment once the GitHub Sponsors profile is approved:
# github: skyllc-ai

# ── Open Collective ─────────────────────────────────────────────────────────
# Primary channel for company sponsors who need invoices and receipts.
# Provides automatic invoicing, transparent expense ledger, fiscal hosting.
# Create profile at: https://opencollective.com/create
# Uncomment once the Open Collective profile is live:
# open_collective: uffs

# ── Ko-fi ───────────────────────────────────────────────────────────────────
# Low-friction one-time tips. Takes ~20 min to set up.
# Create at: https://ko-fi.com — use handle "uffs" if available.
# Uncomment once the Ko-fi page is live:
ko_fi: ufffssearch

# ── Patreon ─────────────────────────────────────────────────────────────────
# Not used — Patreon is optimised for creative content, not developer tooling.
# Our audience lives on GitHub; GitHub Sponsors converts better here.

# ── Tidelift ────────────────────────────────────────────────────────────────
# Not used at this stage — Tidelift is for packages published to registries
# (crates.io, npm, PyPI). Revisit when uffs-* crates are published.

# ── Custom ──────────────────────────────────────────────────────────────────
# Reserved for a future dedicated sponsor / enterprise page on skyllc.ai.
# custom: https://skyllc.ai/sponsor
67 changes: 67 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
cff-version: 1.2.0
message: >-
If you use UFFS in research, tooling, or published work, please cite it
using the metadata below. A "Cite this repository" button will appear
in the GitHub sidebar once this file is merged.

# ── Identity ────────────────────────────────────────────────────────────────
title: "UFFS — Ultra Fast File Search"
abstract: >-
UFFS is a benchmark-driven NTFS search engine for Windows, written in Rust.
It bypasses Windows file-enumeration APIs and reads the NTFS Master File
Table (MFT) directly, building a compact persisted index that is held in
memory by a background daemon. Targeted queries are answered in 0–3 ms
daemon-side; the engine has been scale-tested to 100.4 million records.
A single Rust core powers the CLI, TUI, daemon IPC API, and an MCP server
that exposes deterministic local filesystem retrieval to AI agents.
Published benchmarks show UFFS winning 12/12 head-to-head cells against
Everything (voidtools) on documented targeted-query workloads.

# ── Authorship ───────────────────────────────────────────────────────────────
authors:
- name: "Sky, LLC"
alias: skyllc-ai
website: "https://github.com/skyllc-ai"
- given-names: Robert
family-names: Nio
alias: githubrobbi
orcid: "" # add if/when an ORCID is registered

# ── Source & license ────────────────────────────────────────────────────────
repository-code: "https://github.com/skyllc-ai/UltraFastFileSearch"
url: "https://github.com/skyllc-ai/UltraFastFileSearch"
license: MPL-2.0
license-url: "https://github.com/skyllc-ai/UltraFastFileSearch/blob/main/LICENSE"

# ── Version ─────────────────────────────────────────────────────────────────
# Keep this in sync with [workspace.package].version in Cargo.toml.
# The release pipeline (release-plz / just ship) should bump this automatically
# once Pattern 5 in build/update_all_versions.rs is extended to cover CITATION.cff.
version: "0.5.102"
date-released: "2026-05-20"

# ── Classification ───────────────────────────────────────────────────────────
type: software
keywords:
- ntfs
- mft
- file-search
- windows
- rust
- search-engine
- mcp
- model-context-protocol
- cli
- daemon
- forensics
- sysadmin
- developer-tools
- agent-tools
- everything-alternative

# ── Related identifiers ──────────────────────────────────────────────────────
# Uncomment and populate once benchmark data or a companion paper is published.
# references:
# - type: dataset
# title: "UFFS Benchmark Corpus and Raw Results"
# url: "https://github.com/skyllc-ai/UltraFastFileSearch/tree/main/docs/benchmarks"
41 changes: 38 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<p align="center">
<a href="https://github.com/skyllc-ai/UltraFastFileSearch/actions/workflows/pr-fast.yml"><img src="https://img.shields.io/github/actions/workflow/status/skyllc-ai/UltraFastFileSearch/pr-fast.yml?branch=main&label=CI" alt="CI"></a>
<a href="https://github.com/skyllc-ai/UltraFastFileSearch/releases/latest"><img src="https://img.shields.io/github/v/release/skyllc-ai/UltraFastFileSearch?label=release" alt="Release"></a>
<a href="https://github.com/skyllc-ai/UltraFastFileSearch/releases/latest"><img src="https://img.shields.io/github/downloads/skyllc-ai/UltraFastFileSearch/total?label=downloads" alt="Total Downloads"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg" alt="License: MPL 2.0"></a>
<a href="https://github.com/skyllc-ai/UltraFastFileSearch/releases/latest"><img src="https://img.shields.io/badge/platform-Windows-blue.svg" alt="Platform: Windows"></a>
</p>
Expand Down Expand Up @@ -71,13 +72,47 @@ Hot-path context (v0.5.71, 30 rounds, p50):

---

## Quick Start
## Download & Install

> **[⬇ Latest Release — GitHub Releases tab](https://github.com/skyllc-ai/UltraFastFileSearch/releases/latest)**

Each release ships pre-built binaries, a `CHECKSUMS.txt` (SHA256), per-crate SBOMs (CycloneDX), and SLSA build-provenance attestations — no build toolchain needed.

| Platform | Download | Notes |
|---|---|---|
| **Windows x64** | [`uffs-windows-x64.zip`](https://github.com/skyllc-ai/UltraFastFileSearch/releases/latest) | CLI + daemon + MCP + MFT tools. Recommended. |
| **macOS Apple Silicon** | [`uffs-macos-arm64.zip`](https://github.com/skyllc-ai/UltraFastFileSearch/releases/latest) | Offline MFT analysis only. Includes `UFFS.app` bundle. |
| **Linux x64** | [`uffs-linux-x64.zip`](https://github.com/skyllc-ai/UltraFastFileSearch/releases/latest) | Offline MFT analysis only. Includes `install.sh`. |

**Windows quick-install (one command):**
```powershell
# Extract the ZIP anywhere, add the folder to PATH, then:
uffs --version
```

**Verify the download:**
```bash
# Build from source (requires Rust nightly — see rust-toolchain.toml)
# SHA256 checksum
sha256sum -c CHECKSUMS.txt

# SLSA build-provenance attestation (proves the binary came from this exact workflow run)
gh attestation verify uffs-windows-x64.exe --owner skyllc-ai
```

**Build from source** (contributors / nightly development only):
```bash
# Requires Rust nightly — channel is pinned in rust-toolchain.toml
cargo build --release
```

> 📖 **[Full installation guide](docs/user-manual/installation.md)** — PATH setup, daemon autostart, WinGet (coming), Scoop (coming)

---

## Quick Start

# Search all drives (daemon starts automatically)
```bash
# Search all drives (daemon starts automatically on first query)
uffs "*.rs"

# Search a specific drive
Expand Down
86 changes: 85 additions & 1 deletion build/update_all_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
//! │ 3. File Update Phase (with pattern matching) │
//! │ ├── Cargo.toml (workspace version + flexible spacing) │
//! │ ├── README.md (5 pattern types + dependency refs) │
//! │ └── Documentation (version tags + exact matches) │
//! │ ├── Documentation (version tags + exact matches) │
//! │ └── CITATION.cff (version + date-released) │
//! └─────────────────────────────────────────────────────────────────┘
//! ```
//!
Expand Down Expand Up @@ -191,6 +192,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("📝 Would update Cargo.toml...");
println!("📝 Would update README.md...");
println!("📝 Would update documentation files...");
println!("📝 Would update CITATION.cff (version + date-released)...");
println!("🔒 Would refresh Cargo.lock (cargo generate-lockfile --offline)...");
println!("✅ Dry run completed - no files were modified");
println!("📦 {} would be updated to version: {}", package_name, new_version);
Expand All @@ -200,6 +202,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
update_cargo_toml(&current_version, &new_version)?;
update_readme(&package_name, &current_version, &new_version)?;
update_docs(&current_version, &new_version)?;
update_citation(&current_version, &new_version)?;
refresh_cargo_lock()?;

println!("✅ All versions updated successfully!");
Expand Down Expand Up @@ -1071,3 +1074,84 @@ fn update_docs(current: &str, new: &str) -> Result<(), Box<dyn std::error::Error

Ok(())
}

/// # CITATION.cff Version + Date Update
///
/// Keeps `CITATION.cff` in sync with the workspace version on every bump so
/// that the "Cite this repository" button on GitHub always reflects the
/// current release. Two fields are updated:
///
/// - `version: "x.y.z"` — the quoted semver string
/// - `date-released: "YYYY-MM-DD"` — set to today's UTC date
///
/// The file is silently skipped when absent so that a workspace without
/// `CITATION.cff` does not fail the bump pipeline.
fn update_citation(current: &str, new: &str) -> Result<(), Box<dyn std::error::Error>> {
let path = "CITATION.cff";
let Ok(content) = fs::read_to_string(path) else {
println!("ℹ️ CITATION.cff not found, skipping");
return Ok(());
};

let mut updated = content.clone();
let mut changed = false;

// Update version field: `version: "x.y.z"`
let old_version_line = format!("version: \"{}\"", current);
let new_version_line = format!("version: \"{}\"", new);
if updated.contains(&old_version_line) {
updated = updated.replace(&old_version_line, &new_version_line);
changed = true;
}

// Update date-released field to today's UTC date: `date-released: "YYYY-MM-DD"`
// We replace any existing date regardless of its value so the field always
// reflects the actual release day, not a stale copy.
let today = {
use std::time::{SystemTime, UNIX_EPOCH};
let secs = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0);
// Gregorian calendar conversion (no external deps — std-only)
let days_since_epoch = secs / 86_400;
let mut y = 1970u32;
let mut remaining = days_since_epoch as u32;
loop {
let days_in_year = if y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) { 366 } else { 365 };
if remaining < days_in_year { break; }
remaining -= days_in_year;
y += 1;
}
let leap = y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
let month_days = [31u32, if leap { 29 } else { 28 }, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
let mut m = 0usize;
for &md in &month_days {
if remaining < md { break; }
remaining -= md;
m += 1;
}
format!("{:04}-{:02}-{:02}", y, m + 1, remaining + 1)
};

// Replace any `date-released: "YYYY-MM-DD"` line with today's date
if let Some(start) = updated.find("date-released: \"") {
if let Some(end) = updated[start..].find('\n') {
let old_line = updated[start..start + end].to_string();
let new_line = format!("date-released: \"{}\"", today);
if old_line != new_line {
updated = updated.replacen(&old_line, &new_line, 1);
changed = true;
}
}
}

if changed {
fs::write(path, updated)?;
println!("✅ CITATION.cff updated ({} → {}, date-released: {})", current, new, today);
} else {
println!("ℹ️ CITATION.cff — no matching patterns found (version field may already be current)");
}

Ok(())
}
Loading