Find which process is using or locking a file, folder, or port on Windows, Linux, and macOS.
Rust
4
65 commits
updated Sep 27, 2026
Open File Lock Handle (oflh) finds processes using a file or directory on
Windows, Linux, and macOS. It is a command-line tool with an interactive
terminal UI (TUI) for investigating locked files, open file handles, and mapped
files. It also finds TCP listening ports and bound UDP sockets, shows their
processes, and links them to file usage in your project. Start with a path to see which processes reference it and what they have open.
oflh ./build # Find processes using files in a directory
oflh ./build/plugin.dll # Investigate a file or DLL in use
oflh . # Inspect the current directory
oflh --port 3000 # Find the process using a local port
Install · Quick start · Keyboard shortcuts · Platform support · User guide
Demo with sample processes and paths. Watch the terminal recording.
An open file is not necessarily locked. oflh separates file usage from lock
evidence and does not directly unlock files. Stopping a process may release its
resources; it can also interrupt work in that application.
Use it alongside lsof, fuser, or Task Manager when you want to start with a
path and investigate interactively, without knowing a process name or PID.
Written in Rust, oflh uses native OS interfaces. See platform behavior
for discovery coverage and lock-detection limits.
On macOS or Linux:
brew install karimz1/tap/oflh
To update:
brew update
brew upgrade oflh
Download the executable for your operating system and CPU from the latest release:
| Platform | x86-64 (Intel / AMD) | ARM64 |
|---|---|---|
| Linux | oflh-linux-amd64 | oflh-linux-arm64 |
| macOS | oflh-darwin-amd64 | oflh-darwin-arm64 (Apple Silicon) |
| Windows | oflh-windows-amd64.exe | oflh-windows-arm64.exe |
Open a terminal in the download folder. On Linux or macOS, rename the downloaded
file to oflh, then make it executable and run it against the folder you want to inspect:
chmod +x ./oflh
./oflh "/path/to/project"
On Windows, rename the downloaded file to oflh.exe and run it in PowerShell:
.\oflh.exe "C:\projects\example"
You can run it this way without changing PATH. To use the shorter oflh command
from any folder, put the executable in a directory listed in your PATH environment
variable. Otherwise, keep using its full path or ./oflh (.\oflh.exe in PowerShell)
from the download folder.
Releases include checksums.txt for SHA-256 verification.
Install Rust with rustup. The repository pins its toolchain. From a checkout:
cargo build --release --locked --bin oflh
./target/release/oflh .
On Windows:
cargo build --release --locked --bin oflh
.\target\release\oflh.exe .
Run oflh [PATH] in an interactive terminal. With no path, it inspects the current
directory. A directory target includes its descendants.
oflh
oflh "/path/with spaces"
oflh --help
oflh --version
Windows PowerShell example:
oflh "C:\projects\example\build\plugin.dll"
oflh and select a process in Processes (1)./ to search and Enter to finish typing. For example, dll finds a fragment; micro*dll matches chunks in order.Enter on a process to inspect its file usages, or 2 to open Locked files.k requests termination and x requests force kill; both require confirmation.r to rescan and check whether the file is still in use.Use ? for help. See the user guide for search syntax,
process actions, and the
full keyboard reference.
Open Ports (3) to inspect local TCP listeners and bound UDP sockets. Search
with / for a port number, process name, protocol, or address. Results update
as you type: 50 matches 5040; port:5040 matches only that port. Press s
to switch between ALL PORTS and THIS PATH, which shows ports belonging to
processes observed using the target file or directory.
oflh --ports # All visible local port bindings
oflh --port 3000 # Exact local port, TCP or UDP
oflh --ports ./project # Ports of processes using this project
The Processes table shows a port binding count, and the side panel previews
ports for the selected process. From Processes, press Enter, then p to inspect
its ports. In Ports, Enter opens port details directly. Within details, p opens
ports and f opens file usages. Esc returns to the view you came from: opening details
from Ports returns directly to Ports, with your search preserved.
Without an explicit path, inspecting a port owner or switching from Ports to
Processes/Locked files scans that process’s working directory (or its executable
directory if unavailable). An explicit path scopes Ports to that folder and keeps
the file-inspection folder fixed. Press s to switch to all ports.
Normal termination and force kill use the same confirmation and identity checks as file inspection. Unknown owners cannot be terminated. A bound port does not prove that it is reachable over the network.
See port search and scope for examples and platform limitations.
| Key | Action |
|---|---|
1 / 2 / 3 | Processes / Locked files / Ports |
s in Ports | Switch all ports / this path |
p / f in details | Inspect ports / file usages |
↑ / ↓ | Move through results |
/ | Search |
Enter | Finish search editing / open process details |
r / a | Refresh / toggle five-second auto-refresh |
Space | Select or deselect a process |
k / x | Request termination / force kill |
Tab | Switch focus between results and ancestry tree |
? | Show help and scan limitations |
Esc | Clear search, cancel, or go back |
q / Ctrl+C | Quit (while typing a search, use Ctrl+C) |
Process actions use the selection, or the current process if nothing is selected. Selections survive filtering; confirmation lists hidden selections too, and Cancel is the default. When the ancestry tree has focus, actions apply only to the highlighted ancestor. See process actions before stopping a parent application.
Binaries are available for Linux, macOS, and Windows on x86-64 and ARM64. The interface is shared, but file discovery and lock detection depend on the OS.
| Platform | File usage discovery | Lock evidence |
|---|---|---|
| Linux | Open descriptors, working directories, executables, mapped files, deleted-but-open files via /proc | Held FLOCK, POSIX, and OFD locks |
| macOS | Vnode descriptors, working directories, executables, mapped files via libproc | POSIX byte-range conflicts; flock-only locks may be missed |
| Windows | Restart Manager resource users, modules and executables via Toolhelp | Read, write, or delete sharing conflicts; reported owners are unverified |
On Windows, a sharing conflict does not prove which reported process caused it. Discovery does not cover working directories, directory handles, or deleted files, and byte-range locks are not enumerated.
Results are a snapshot limited by permissions, process exits, and concurrent file
activity. When the footer says “Results may be incomplete,” press ? for
details. See platform support and limitations for the
full detection scope, termination behavior, and metric definitions.
It can help you find and stop a process using the file. It does not remove locks directly or bypass OS permissions. Close the application normally first when possible; force killing can lose unsaved work.
File usage and file locks are different. A process can have an open descriptor or mapped file without holding a detectable lock. The Locked files view requires additional evidence, and each platform has detection limits.
Permissions and platform coverage limit what can be inspected. Elevated
privileges may improve visibility, but cannot guarantee complete results. On
Linux, inspecting another container may require running oflh inside its mount
namespace. Check ? for scan warnings and the platform reference.
File inspection requires an interactive terminal; oflh currently has no JSON
or non-interactive scan output. --help and --version work without a TTY.
Run cargo xtask check for formatting, Clippy, and workspace tests. CI covers
native Linux, macOS, and Windows on x86-64 and ARM64.
oflh is in beta. Report a bug
with the version, operating system, and steps to reproduce it.
Licensed under MIT. Support development.
65 commits
Rust
100.0%
Find which process is using or locking a file, folder, or port on Windows, Linux, and macOS.
Rust
4
65 commits
updated Sep 27, 2026
Open File Lock Handle (oflh) finds processes using a file or directory on
Windows, Linux, and macOS. It is a command-line tool with an interactive
terminal UI (TUI) for investigating locked files, open file handles, and mapped
files. It also finds TCP listening ports and bound UDP sockets, shows their
processes, and links them to file usage in your project. Start with a path to see which processes reference it and what they have open.
oflh ./build # Find processes using files in a directory
oflh ./build/plugin.dll # Investigate a file or DLL in use
oflh . # Inspect the current directory
oflh --port 3000 # Find the process using a local port
Install · Quick start · Keyboard shortcuts · Platform support · User guide
Demo with sample processes and paths. Watch the terminal recording.
An open file is not necessarily locked. oflh separates file usage from lock
evidence and does not directly unlock files. Stopping a process may release its
resources; it can also interrupt work in that application.
Use it alongside lsof, fuser, or Task Manager when you want to start with a
path and investigate interactively, without knowing a process name or PID.
Written in Rust, oflh uses native OS interfaces. See platform behavior
for discovery coverage and lock-detection limits.
On macOS or Linux:
brew install karimz1/tap/oflh
To update:
brew update
brew upgrade oflh
Download the executable for your operating system and CPU from the latest release:
| Platform | x86-64 (Intel / AMD) | ARM64 |
|---|---|---|
| Linux | oflh-linux-amd64 | oflh-linux-arm64 |
| macOS | oflh-darwin-amd64 | oflh-darwin-arm64 (Apple Silicon) |
| Windows | oflh-windows-amd64.exe | oflh-windows-arm64.exe |
Open a terminal in the download folder. On Linux or macOS, rename the downloaded
file to oflh, then make it executable and run it against the folder you want to inspect:
chmod +x ./oflh
./oflh "/path/to/project"
On Windows, rename the downloaded file to oflh.exe and run it in PowerShell:
.\oflh.exe "C:\projects\example"
You can run it this way without changing PATH. To use the shorter oflh command
from any folder, put the executable in a directory listed in your PATH environment
variable. Otherwise, keep using its full path or ./oflh (.\oflh.exe in PowerShell)
from the download folder.
Releases include checksums.txt for SHA-256 verification.
Install Rust with rustup. The repository pins its toolchain. From a checkout:
cargo build --release --locked --bin oflh
./target/release/oflh .
On Windows:
cargo build --release --locked --bin oflh
.\target\release\oflh.exe .
Run oflh [PATH] in an interactive terminal. With no path, it inspects the current
directory. A directory target includes its descendants.
oflh
oflh "/path/with spaces"
oflh --help
oflh --version
Windows PowerShell example:
oflh "C:\projects\example\build\plugin.dll"
oflh and select a process in Processes (1)./ to search and Enter to finish typing. For example, dll finds a fragment; micro*dll matches chunks in order.Enter on a process to inspect its file usages, or 2 to open Locked files.k requests termination and x requests force kill; both require confirmation.r to rescan and check whether the file is still in use.Use ? for help. See the user guide for search syntax,
process actions, and the
full keyboard reference.
Open Ports (3) to inspect local TCP listeners and bound UDP sockets. Search
with / for a port number, process name, protocol, or address. Results update
as you type: 50 matches 5040; port:5040 matches only that port. Press s
to switch between ALL PORTS and THIS PATH, which shows ports belonging to
processes observed using the target file or directory.
oflh --ports # All visible local port bindings
oflh --port 3000 # Exact local port, TCP or UDP
oflh --ports ./project # Ports of processes using this project
The Processes table shows a port binding count, and the side panel previews
ports for the selected process. From Processes, press Enter, then p to inspect
its ports. In Ports, Enter opens port details directly. Within details, p opens
ports and f opens file usages. Esc returns to the view you came from: opening details
from Ports returns directly to Ports, with your search preserved.
Without an explicit path, inspecting a port owner or switching from Ports to
Processes/Locked files scans that process’s working directory (or its executable
directory if unavailable). An explicit path scopes Ports to that folder and keeps
the file-inspection folder fixed. Press s to switch to all ports.
Normal termination and force kill use the same confirmation and identity checks as file inspection. Unknown owners cannot be terminated. A bound port does not prove that it is reachable over the network.
See port search and scope for examples and platform limitations.
| Key | Action |
|---|---|
1 / 2 / 3 | Processes / Locked files / Ports |
s in Ports | Switch all ports / this path |
p / f in details | Inspect ports / file usages |
↑ / ↓ | Move through results |
/ | Search |
Enter | Finish search editing / open process details |
r / a | Refresh / toggle five-second auto-refresh |
Space | Select or deselect a process |
k / x | Request termination / force kill |
Tab | Switch focus between results and ancestry tree |
? | Show help and scan limitations |
Esc | Clear search, cancel, or go back |
q / Ctrl+C | Quit (while typing a search, use Ctrl+C) |
Process actions use the selection, or the current process if nothing is selected. Selections survive filtering; confirmation lists hidden selections too, and Cancel is the default. When the ancestry tree has focus, actions apply only to the highlighted ancestor. See process actions before stopping a parent application.
Binaries are available for Linux, macOS, and Windows on x86-64 and ARM64. The interface is shared, but file discovery and lock detection depend on the OS.
| Platform | File usage discovery | Lock evidence |
|---|---|---|
| Linux | Open descriptors, working directories, executables, mapped files, deleted-but-open files via /proc | Held FLOCK, POSIX, and OFD locks |
| macOS | Vnode descriptors, working directories, executables, mapped files via libproc | POSIX byte-range conflicts; flock-only locks may be missed |
| Windows | Restart Manager resource users, modules and executables via Toolhelp | Read, write, or delete sharing conflicts; reported owners are unverified |
On Windows, a sharing conflict does not prove which reported process caused it. Discovery does not cover working directories, directory handles, or deleted files, and byte-range locks are not enumerated.
Results are a snapshot limited by permissions, process exits, and concurrent file
activity. When the footer says “Results may be incomplete,” press ? for
details. See platform support and limitations for the
full detection scope, termination behavior, and metric definitions.
It can help you find and stop a process using the file. It does not remove locks directly or bypass OS permissions. Close the application normally first when possible; force killing can lose unsaved work.
File usage and file locks are different. A process can have an open descriptor or mapped file without holding a detectable lock. The Locked files view requires additional evidence, and each platform has detection limits.
Permissions and platform coverage limit what can be inspected. Elevated
privileges may improve visibility, but cannot guarantee complete results. On
Linux, inspecting another container may require running oflh inside its mount
namespace. Check ? for scan warnings and the platform reference.
File inspection requires an interactive terminal; oflh currently has no JSON
or non-interactive scan output. --help and --version work without a TTY.
Run cargo xtask check for formatting, Clippy, and workspace tests. CI covers
native Linux, macOS, and Windows on x86-64 and ARM64.
oflh is in beta. Report a bug
with the version, operating system, and steps to reproduce it.
Licensed under MIT. Support development.
65 commits
Rust
100.0%