Python’s posix module exposes the POSIX syscall surface that the os module is built on. import posix (Linux/macOS only; on POSIX systems os re-exports everything from posix transparently). Direct access: posix.stat(path) → os.stat_result; posix.open(path, flags, mode=0o777) → fd int; posix.read(fd, n) → bytes; posix.write(fd, b) → int; posix.close(fd). Process: posix.fork() → 0 in child, child PID in parent; posix.execv(path, args); posix.execve(path, args, env); posix.waitpid(pid, options) → (pid, status); posix.kill(pid, sig). Identity: posix.getpid(), posix.getppid(), posix.getuid(), posix.getgid(), posix.geteuid(), posix.getegid(), posix.getlogin(). Filesystem: posix.getcwd(), posix.chdir(path), posix.listdir(path), posix.mkdir(path, mode), posix.rmdir(path), posix.rename(src, dst), posix.unlink(path), posix.symlink(src, dst), posix.readlink(path). Flags: posix.O_RDONLY, posix.O_WRONLY, posix.O_RDWR, posix.O_CREAT, posix.O_TRUNC, posix.O_NONBLOCK. Prefer os for portability; use posix directly only when you need the raw C-level names in documentation or introspection. Claude Code generates low-level fd pipelines, fork/exec process managers, POSIX syscall wrappers, and fd-level I/O dispatchers.
CLAUDE.md for posix
## posix Stack
- Stdlib: import posix (Linux/macOS; os re-exports all of posix on POSIX systems)
- Open: fd = posix.open(path, posix.O_RDONLY)
- Read: data = posix.read(fd, 4096)
- Write: posix.write(fd, b"data")
- Close: posix.close(fd)
- Fork: pid = posix.fork() # 0=child, >0=parent
- Exec: posix.execv(path, args) # replaces current process
- Stat: result = posix.stat(path) # .st_size .st_mode .st_mtime
- Prefer: use `os` for portable code; use `posix` when C-level names matter
posix Direct POSIX Syscall Pipeline
# app/posixutil.py — fd I/O, fork/exec, stat, working directory ops
from __future__ import annotations
import os
import platform
import signal
import stat as stat_module
from dataclasses import dataclass
_POSIX_AVAILABLE = platform.system() != "Windows"
if _POSIX_AVAILABLE:
import posix
# ─────────────────────────────────────────────────────────────────────────────
# 1. File-descriptor level I/O
# ─────────────────────────────────────────────────────────────────────────────
def open_fd(path: str, flags: int = None, mode: int = 0o666) -> int:
"""
Open a file at the POSIX level, returning a raw file descriptor int.
flags defaults to O_RDONLY.
Example:
fd = open_fd("/etc/hostname")
data = read_fd(fd, 256)
close_fd(fd)
"""
if not _POSIX_AVAILABLE:
raise OSError("posix not available on Windows")
if flags is None:
flags = posix.O_RDONLY
return posix.open(path, flags, mode)
def read_fd(fd: int, n: int = 4096) -> bytes:
"""
Read up to n bytes from a file descriptor.
Example:
data = read_fd(fd, 8192)
"""
if not _POSIX_AVAILABLE:
raise OSError("posix not available on Windows")
return posix.read(fd, n)
def read_fd_all(fd: int, chunk: int = 65536) -> bytes:
"""
Read all bytes from a file descriptor until EOF.
Example:
fd = open_fd("/proc/cpuinfo")
content = read_fd_all(fd)
close_fd(fd)
"""
if not _POSIX_AVAILABLE:
raise OSError("posix not available on Windows")
buf = bytearray()
while True:
chunk_data = posix.read(fd, chunk)
if not chunk_data:
break
buf.extend(chunk_data)
return bytes(buf)
def write_fd(fd: int, data: bytes) -> int:
"""
Write bytes to a file descriptor. Returns bytes written.
Example:
written = write_fd(fd, b"hello\n")
"""
if not _POSIX_AVAILABLE:
raise OSError("posix not available on Windows")
return posix.write(fd, data)
def write_fd_all(fd: int, data: bytes) -> None:
"""
Write all bytes to a file descriptor, retrying on short writes.
Example:
write_fd_all(fd, large_payload)
"""
if not _POSIX_AVAILABLE:
raise OSError("posix not available on Windows")
offset = 0
while offset < len(data):
n = posix.write(fd, data[offset:])
offset += n
def close_fd(fd: int) -> None:
"""Close a file descriptor, ignoring EBADF."""
if not _POSIX_AVAILABLE:
return
try:
posix.close(fd)
except OSError:
pass
def pipe_bytes(data: bytes) -> bytes:
"""
Write data to one end of a pipe, read it back from the other.
Demonstrates posix.pipe() + fork-based data passing.
Example:
result = pipe_bytes(b"hello world")
"""
if not _POSIX_AVAILABLE:
raise OSError("posix not available on Windows")
r_fd, w_fd = posix.pipe()
pid = posix.fork()
if pid == 0:
# Child: write data and exit
posix.close(r_fd)
write_fd_all(w_fd, data)
posix.close(w_fd)
posix._exit(0)
# Parent: read data
posix.close(w_fd)
result = read_fd_all(r_fd)
posix.close(r_fd)
posix.waitpid(pid, 0)
return result
# ─────────────────────────────────────────────────────────────────────────────
# 2. stat / filesystem
# ─────────────────────────────────────────────────────────────────────────────
@dataclass
class StatInfo:
path: str
size: int
mode: int
uid: int
gid: int
mtime: float
inode: int
is_dir: bool
is_file: bool
is_symlink: bool
def mode_str(self) -> str:
return stat_module.filemode(self.mode)
def __str__(self) -> str:
return (f"{self.mode_str()} "
f"uid={self.uid} gid={self.gid} "
f"size={self.size:>10d} "
f"inode={self.inode} "
f"{self.path}")
def stat_path(path: str) -> StatInfo:
"""
Stat a path using posix.stat(). Does not follow symlinks.
Example:
info = stat_path("/etc/hostname")
print(info)
"""
if not _POSIX_AVAILABLE:
raise OSError("posix not available on Windows")
s = posix.stat(path)
return StatInfo(
path=path,
size=s.st_size,
mode=s.st_mode,
uid=s.st_uid,
gid=s.st_gid,
mtime=s.st_mtime,
inode=s.st_ino,
is_dir=stat_module.S_ISDIR(s.st_mode),
is_file=stat_module.S_ISREG(s.st_mode),
is_symlink=stat_module.S_ISLNK(posix.lstat(path).st_mode),
)
def listdir_stat(directory: str) -> list[StatInfo]:
"""
List a directory and stat each entry.
Example:
entries = listdir_stat("/tmp")
for e in sorted(entries, key=lambda e: e.size, reverse=True)[:5]:
print(e)
"""
if not _POSIX_AVAILABLE:
raise OSError("posix not available on Windows")
results = []
for name in posix.listdir(directory):
full = os.path.join(directory, name)
try:
results.append(stat_path(full))
except OSError:
pass
return results
# ─────────────────────────────────────────────────────────────────────────────
# 3. Fork / exec helpers
# ─────────────────────────────────────────────────────────────────────────────
@dataclass
class ProcessResult:
pid: int
exit_code: int
signaled: bool
signal_num: int | None
def fork_and_run(fn, *args) -> ProcessResult:
"""
Fork a child process, call fn(*args) in the child, and wait.
Child exit code is fn's return value (0 if None, 1 on exception).
Example:
result = fork_and_run(lambda: print("hello from child"))
print(result.exit_code)
"""
if not _POSIX_AVAILABLE:
raise OSError("posix not available on Windows")
pid = posix.fork()
if pid == 0:
try:
ret = fn(*args)
posix._exit(0 if ret is None else int(ret))
except Exception:
posix._exit(1)
_, raw_status = posix.waitpid(pid, 0)
return ProcessResult(
pid=pid,
exit_code=os.waitstatus_to_exitcode(raw_status),
signaled=os.WIFSIGNALED(raw_status),
signal_num=os.WTERMSIG(raw_status) if os.WIFSIGNALED(raw_status) else None,
)
def exec_replace(path: str, args: list[str], env: dict[str, str] | None = None) -> None:
"""
Replace the current process with path/args using posix.execve().
Never returns on success.
Example:
exec_replace("/bin/echo", ["echo", "hello"])
"""
if not _POSIX_AVAILABLE:
raise OSError("posix not available on Windows")
if env is None:
posix.execv(path, args)
else:
posix.execve(path, args, env)
def spawn_command(argv: list[str], env: dict[str, str] | None = None) -> ProcessResult:
"""
Fork a child, exec argv[0] with argv, wait for completion.
Example:
result = spawn_command(["ls", "-la", "/tmp"])
print(result.exit_code)
"""
if not _POSIX_AVAILABLE:
raise OSError("posix not available on Windows")
pid = posix.fork()
if pid == 0:
try:
if env is None:
posix.execv(argv[0], argv)
else:
posix.execve(argv[0], argv, env)
except OSError:
posix._exit(127)
_, raw_status = posix.waitpid(pid, 0)
return ProcessResult(
pid=pid,
exit_code=os.waitstatus_to_exitcode(raw_status),
signaled=os.WIFSIGNALED(raw_status),
signal_num=os.WTERMSIG(raw_status) if os.WIFSIGNALED(raw_status) else None,
)
# ─────────────────────────────────────────────────────────────────────────────
# 4. Process identity / environment
# ─────────────────────────────────────────────────────────────────────────────
@dataclass
class ProcessIdentity:
pid: int
ppid: int
uid: int
gid: int
euid: int
egid: int
cwd: str
login: str
def __str__(self) -> str:
return (f"pid={self.pid} ppid={self.ppid} "
f"uid={self.uid} gid={self.gid} "
f"euid={self.euid} egid={self.egid} "
f"login={self.login!r} cwd={self.cwd!r}")
def process_identity() -> ProcessIdentity:
"""
Return the current process's POSIX identity.
Example:
ident = process_identity()
print(ident)
"""
if not _POSIX_AVAILABLE:
raise OSError("posix not available on Windows")
try:
login = posix.getlogin()
except OSError:
login = ""
return ProcessIdentity(
pid=posix.getpid(),
ppid=posix.getppid(),
uid=posix.getuid(),
gid=posix.getgid(),
euid=posix.geteuid(),
egid=posix.getegid(),
cwd=posix.getcwd(),
login=login,
)
# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
print("=== posix demo ===")
if not _POSIX_AVAILABLE:
print(" posix not available on Windows — skipping")
raise SystemExit(0)
# ── identity ───────────────────────────────────────────────────────────────
print("\n--- process_identity ---")
ident = process_identity()
print(f" {ident}")
# ── fd I/O ─────────────────────────────────────────────────────────────────
print("\n--- fd read /etc/hostname ---")
fd = open_fd("/etc/hostname")
hostname = read_fd_all(fd).decode().strip()
close_fd(fd)
print(f" hostname: {hostname!r}")
# ── stat ───────────────────────────────────────────────────────────────────
print("\n--- stat_path ---")
for p in ["/etc/hostname", "/tmp", "/bin/sh"]:
try:
info = stat_path(p)
print(f" {info}")
except OSError as e:
print(f" {p}: {e}")
# ── listdir_stat ───────────────────────────────────────────────────────────
print("\n--- listdir_stat /etc (first 5 by size) ---")
entries = listdir_stat("/etc")
for e in sorted(entries, key=lambda e: e.size, reverse=True)[:5]:
print(f" {e}")
# ── pipe_bytes ─────────────────────────────────────────────────────────────
print("\n--- pipe_bytes ---")
payload = b"hello from parent via posix pipe"
received = pipe_bytes(payload)
print(f" sent: {payload!r}")
print(f" received: {received!r}")
print(f" match: {payload == received}")
# ── spawn_command ──────────────────────────────────────────────────────────
print("\n--- spawn_command ['uname', '-s'] ---")
result = spawn_command(["/usr/bin/uname", "-s"])
print(f" exit_code={result.exit_code} signaled={result.signaled}")
print("\n=== done ===")
For the os alternative — os is the portable stdlib interface that re-exports everything in posix plus Windows equivalents — prefer os in all production code since import os works on every platform and provides the same functions (os.open, os.read, os.write, os.fork, os.execv, os.stat) with identical signatures; use posix directly only when documenting the POSIX C layer, writing introspection tooling (dir(posix) to enumerate available syscalls), or when the explicit POSIX namespacing aids clarity in systems-level documentation. For the subprocess alternative — subprocess.run([...]) and subprocess.Popen wrap fork/exec/waitpid into a higher-level API with stdio capture, timeout enforcement, and communicate() — use subprocess when you need captured output, shell pipelines, or cross-platform process spawning; use posix.fork() + posix.execv() directly when you need fine-grained control over open file descriptors, supplementary groups, process sessions, or pre-exec hooks that subprocess does not expose. The Claude Skills 360 bundle includes posix skill sets covering open_fd()/read_fd()/read_fd_all()/write_fd_all()/close_fd()/pipe_bytes() fd-level I/O, StatInfo with stat_path()/listdir_stat() filesystem inspection, ProcessResult with fork_and_run()/exec_replace()/spawn_command() process management, and ProcessIdentity with process_identity() POSIX identity reporting. Start with the free tier to try POSIX syscall patterns and posix pipeline code generation.