From 814f36942eae2b71a7f9f6a37a9413507c98b1bb Mon Sep 17 00:00:00 2001 From: Robert M1 <50460704+githubrobbi@users.noreply.github.com> Date: Fri, 22 May 2026 10:41:18 -0700 Subject: [PATCH] feat(sponsorship): add Ko-fi donation channel + CITATION.cff + download section - .github/FUNDING.yml: wire Ko-fi (ufffssearch); GitHub Sponsors and Open Collective stubs pre-wired, commented until accounts are live - CITATION.cff: full CFF 1.2.0 spec for "Cite this repository" button; keywords match the 20 planned GitHub Topics - build/update_all_versions.rs: add update_citation() so CITATION.cff version + date-released stay in sync on every just-ship bump - README.md: new "## Download & Install" section leads with pre-built binaries + platform table before cargo-build; add total-downloads badge to header strip Co-Authored-By: Claude Sonnet 4.6 --- .github/FUNDING.yml | 42 ++++++++++++++++++ CITATION.cff | 67 ++++++++++++++++++++++++++++ README.md | 41 +++++++++++++++-- build/update_all_versions.rs | 86 +++++++++++++++++++++++++++++++++++- 4 files changed, 232 insertions(+), 4 deletions(-) create mode 100644 .github/FUNDING.yml create mode 100644 CITATION.cff diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..dcc3b4a43 --- /dev/null +++ b/.github/FUNDING.yml @@ -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 diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 000000000..bebb6a75c --- /dev/null +++ b/CITATION.cff @@ -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" diff --git a/README.md b/README.md index cf0af6702..a014c6b01 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@

CI Release + Total Downloads License: MPL 2.0 Platform: Windows

@@ -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 diff --git a/build/update_all_versions.rs b/build/update_all_versions.rs index 8a98f2769..299fbaf4f 100755 --- a/build/update_all_versions.rs +++ b/build/update_all_versions.rs @@ -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) │ //! └─────────────────────────────────────────────────────────────────┘ //! ``` //! @@ -191,6 +192,7 @@ fn main() -> Result<(), Box> { 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); @@ -200,6 +202,7 @@ fn main() -> Result<(), Box> { update_cargo_toml(¤t_version, &new_version)?; update_readme(&package_name, ¤t_version, &new_version)?; update_docs(¤t_version, &new_version)?; + update_citation(¤t_version, &new_version)?; refresh_cargo_lock()?; println!("✅ All versions updated successfully!"); @@ -1071,3 +1074,84 @@ fn update_docs(current: &str, new: &str) -> Result<(), Box Result<(), Box> { + 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(()) +}