prompts/skills/clojure-babashka-fs/SKILL.md
File system operations with babashka.fs. Use when working with file I/O, directory traversal, path manipulation, file copying/moving, temp files, archives (zip/gzip), or file metadata.
npx skillsauth add ramblurr/nix-devenv clojure-babashka-fsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Cross-platform file system utilities for Clojure. Built on java.nio, works in JVM Clojure and babashka (built-in since v0.2.9).
deps.edn:
babashka/fs {:mvn/version "0.5.27"}
Leiningen:
[babashka/fs "0.5.27"]
See https://clojars.org/babashka/fs for the latest version.
Note: Built into babashka, no dependency needed if using bb.
(require '[babashka.fs :as fs])
;; Check file types
(fs/directory? ".") ;; => true
(fs/exists? "project.clj") ;; => true
(fs/regular-file? "README") ;; => true
;; Path manipulation
(str (fs/path "src" "app" "core.clj"))
;; => "src/app/core.clj"
(str (fs/absolutize "."))
;; => "/home/user/project"
;; List directory
(map str (fs/list-dir "src"))
;; => ("src/app" "src/test")
;; Find files
(map str (fs/glob "." "**/*.clj"))
;; => ("src/app/core.clj" "test/app/core_test.clj")
;; Build paths
(fs/path "home" "user" "file.txt") ;; => #object[java.nio.file.Path]
(fs/file "home" "user" "file.txt") ;; => #object[java.io.File]
;; Expand home directory
(fs/expand-home "~/projects")
;; => #object[java.nio.file.Path "/home/user/projects"]
;; Get components
(fs/file-name "/path/to/file.txt") ;; => "file.txt"
(fs/parent "/path/to/file.txt") ;; => #object[Path "/path/to"]
(fs/extension "file.clj") ;; => "clj"
(split-ext "file.tar.gz") ;; => ["file.tar" "gz"]
(strip-ext "file.clj") ;; => "file"
;; Normalize and resolve
(fs/normalize "path/./to/../file") ;; => "path/file"
(fs/absolutize "src") ;; => "/home/user/project/src"
(fs/canonicalize "src") ;; => resolves symlinks + normalizes
(fs/real-path "src") ;; => like canonicalize, requires existence
;; List immediate children
(fs/list-dir "src")
;; => [#object[Path "src/core.clj"] #object[Path "src/util.clj"]]
;; List with glob filter
(fs/list-dir "src" "*.clj")
;; => [#object[Path "src/core.clj"]]
;; Glob search (recursive)
(fs/glob "." "**/*.clj") ;; all .clj files
(fs/glob "." "**{.clj,.cljc}") ;; .clj OR .cljc files
;; Match search (more control)
(fs/match "." "regex:.*\\.clj" {:recursive true})
;; Find files in PATH
(fs/which "java")
;; => #object[Path "/usr/bin/java"]
(fs/exec-paths) ;; all PATH directories as Paths
;; Copy
(fs/copy "src.txt" "dest.txt")
(fs/copy "src.txt" "dest.txt" {:replace-existing true})
(fs/copy-tree "src-dir" "dest-dir") ;; recursive copy
;; Move
(fs/move "old.txt" "new.txt")
(fs/move "old.txt" "new.txt" {:replace-existing true})
;; Delete
(fs/delete "file.txt") ;; throws if not exists
(fs/delete-if-exists "file.txt") ;; safe delete
(fs/delete-tree "dir") ;; recursive delete (rm -rf)
(fs/delete-tree "dir" {:force true}) ;; delete read-only files too
;; Directories
(fs/create-dir "newdir") ;; single dir, parent must exist
(fs/create-dirs "path/to/newdir") ;; like mkdir -p
;; Files
(fs/create-file "empty.txt")
;; Temporary
(fs/create-temp-dir)
(fs/create-temp-dir {:prefix "myapp-"})
(fs/create-temp-file)
(fs/create-temp-file {:prefix "log-" :suffix ".txt"})
;; With auto-cleanup
(fs/with-temp-dir [tmp]
(fs/create-file (fs/path tmp "work.txt"))
;; ... do work ...
) ;; tmp deleted here
;; Read
(fs/read-all-bytes "file.bin") ;; => byte[]
(fs/read-all-lines "file.txt") ;; => ["line1" "line2"]
;; Write
(fs/write-bytes "out.bin" byte-array)
(fs/write-lines "out.txt" ["line1" "line2"])
(fs/write-lines "out.txt" ["more"] {:append true})
;; Update in place
(fs/update-file "config.edn"
#(str/replace % "localhost" "prod.example.com"))
;; Timestamps
(fs/creation-time "file.txt") ;; => FileTime
(fs/last-modified-time "file.txt") ;; => FileTime
(fs/file-time->millis (fs/last-modified-time "file.txt"))
;; Set timestamps
(fs/set-last-modified-time "file.txt" (System/currentTimeMillis))
;; Size
(fs/size "file.txt") ;; => bytes
;; Permissions (Unix/Linux)
(fs/posix-file-permissions "file.sh")
(fs/posix->str (fs/posix-file-permissions "file.sh"))
;; => "rwxr-xr-x"
(fs/set-posix-file-permissions "file.sh" "rwx------")
;; Owner
(str (fs/owner "file.txt")) ;; => "username"
;; Zip
(fs/zip "archive.zip" ["file1.txt" "dir/file2.txt"])
(fs/zip "archive.zip" ["src"] {:root "src"}) ;; elide "src/" in archive
;; Unzip
(fs/unzip "archive.zip") ;; extract to current dir
(fs/unzip "archive.zip" "dest-dir")
(fs/unzip "archive.zip" "dest-dir" {:replace-existing true})
;; Gzip
(fs/gzip "file.txt") ;; creates file.txt.gz
(fs/gzip "file.txt" {:out-file "archive.gz"})
;; Gunzip
(fs/gunzip "file.txt.gz") ;; extracts to current dir
(fs/gunzip "file.txt.gz" "dest-dir")
;; Check
(fs/sym-link? "link") ;; => true/false
;; Create
(fs/create-sym-link "link" "target")
(fs/create-link "hardlink" "existing") ;; hard link
;; Read target
(fs/read-link "link") ;; => Path to target
;; Low-level tree walker
(fs/walk-file-tree "src"
{:pre-visit-dir (fn [dir attrs]
(println "Entering" dir)
:continue)
:visit-file (fn [file attrs]
(println "File:" file)
:continue)})
;; Find modified files
(fs/modified-since "build/last-build-marker"
(fs/glob "src" "**/*.clj"))
;; => seq of files newer than marker
;; Standard user directories
(fs/xdg-config-home) ;; => ~/.config
(fs/xdg-config-home "myapp") ;; => ~/.config/myapp
(fs/xdg-data-home) ;; => ~/.local/share
(fs/xdg-cache-home) ;; => ~/.cache
(fs/xdg-state-home) ;; => ~/.local/state
;; Respects XDG_CONFIG_HOME etc. env vars
;; Use forward slashes on all platforms
(fs/unixify "C:\\Users\\name\\file.txt")
;; => "C:/Users/name/file.txt"
;; Separators
fs/file-separator ;; "/" or "\\" depending on OS
fs/path-separator ;; ":" or ";" for PATH-like strings
;; Platform detection
(fs/windows?) ;; => true on Windows
Empty string means cwd: (fs/list-dir "") is same as (fs/list-dir "."). Most functions treat "" as current directory.
Symlink following: Many functions accept :nofollow-links or :follow-links options. Default behavior varies:
:follow-links truecreation-time is unreliable: Behavior varies by OS and Java version. On Linux it often returns modified time. See API notes.
glob patterns use java.nio syntax:
* matches within directory (not across /)** matches across directories{.clj,.cljc} for alternationPaths vs Files: Functions return java.nio.file.Path objects. Use str to convert to string, or fs/file to convert to java.io.File.
Maps are closed by default in newer glob: Recent versions of fs set {:hidden false} by default unless pattern starts with .
tools
Use when working with Nixbot CI, forge commit statuses, Nix flake checks, nixbot.toml, Nixbot effects, or nixbot-cli - explains how Nixbot runs flake CI and how to inspect builds and logs.
testing
Use this OCP when executing or preparing to execute commands that change a live or important system, service reloads/restarts, package changes, deployments, migrations, firewall/network/access changes, credential rotation, NixOS switch/test/boot/deploy, or incident mitigation. It guides safe operations with a persisted ledger for scope, preflight, baseline, rollback, validation, and evidence.
development
Create new agent skills with proper structure, progressive disclosure, and bundled resources. Use when user wants to create, write, or build a new skill.
documentation
Naming conventions for workflow documents in prompts/. Use when creating plans, PRDs, research reports, idea capture or other workflow documents. Triggers on (1) creating new planning documents, (2) naming PRDs or research reports, (3) questions about document organization in prompts/.