┌─────────────────┐ ╔═════════════════╗
│ codechu — ipc │═════>║ your daemon ║
│ client │ JSON ║ handler(req) ║
│ request() │<═════║ → response ║
└─────────────────┘ line ╚═════════════════╝
unix socket · fifo · json-line · pidfile
Local IPC the boring way — Unix sockets, FIFOs, one JSON object per line.
codechu-ipc
Stdlib-only local IPC for Linux daemons and sidecars: Unix domain sockets, named pipes (FIFOs), JSON-line framing, server lifecycle helpers. No third-party dependencies. Python 3.10+.
Linux is the primary target; BSD/macOS are best-effort (anything
POSIX-y with AF_UNIX and mkfifo should work).
Install
pip install codechu-ipc
API at a glance
from codechu_ipc import UnixServer, UnixClient, FifoChannel, pidfile
# --- Server side ------------------------------------------------------
def handler(req: dict) -> dict:
return {"echo": req}
with UnixServer("/run/codechu/myapp/control.sock", handler):
... # serve until the context exits
# --- Client side ------------------------------------------------------
client = UnixClient("/run/codechu/myapp/control.sock")
response = client.request({"cmd": "status"}) # → {"echo": ...}
client.notify({"cmd": "shutdown"}) # fire-and-forget
# --- FIFO -------------------------------------------------------------
ch = FifoChannel("/run/codechu/myapp/events.fifo")
ch.send({"event": "rescan-done"}) # non-blocking
msg = ch.recv() # blocks for next
# --- Lifecycle --------------------------------------------------------
with pidfile("/run/codechu/myapp/daemon.pid"):
serve_forever()
Why JSON-line?
- One object per line. Trivial to parse from any language, any shell pipeline, any log viewer.
- No length prefixes, no schemas. Easy to inspect with
nc -Uorsocatwhile debugging. - Backpressure is the OS's problem. The kernel's socket buffers do the queuing; this library stays a thin wrapper.
If you need binary framing, multiplexing, or RPC semantics, you want gRPC, not this.
UnixServer(path, handler, *, mode=0o600, backlog=16)
- Background accept-loop thread; one worker thread per connection.
- Default socket permissions: owner-only (0o600). Override with
mode=. - Auto-cleans stale socket files from a crashed previous run; refuses
to overwrite a live socket (raises
FileExistsError). - Handler returning
Nonemeans "this was a notification, send no response". Anything else is encoded back as one JSON line. - Handler exceptions are caught and returned to the client as
{"error": "...", "type": "..."}— the server keeps serving. - Context manager:
with UnixServer(...) as srv: ...callsstart()/stop()for you.
UnixClient(path, *, timeout=5.0, retries=3, retry_backoff=0.5)
request(payload)— send a JSON line, read one back.notify(payload)— send a JSON line, close. No response read.- Retries on
ConnectionRefusedError/FileNotFoundError, with exponential backoff (0.5s, 1.0s, 2.0s, ...). Useful for the short window between "daemon is starting" and "daemon is ready".
JsonLineProtocol
The framing helper, exposed so you can build your own transport on top of it.
data = JsonLineProtocol.encode({"hello": "world"}) # → b'{"hello":"world"}\n'
with open("/var/log/myapp.jsonl", "rb") as f:
for obj in JsonLineProtocol.decode_stream(f):
print(obj)
FifoChannel(path, *, mode=0o600)
- Auto-creates the FIFO with
mkfifoif missing. send()opens write-side non-blocking — raisesBrokenPipeErrorif no reader is attached, so you don't deadlock.recv()opens read-side blocking and yields one decoded message.- FIFOs are unidirectional; for request/response use
UnixServer.
pidfile(path)
Context manager that:
- Creates the parent directory.
- Opens the pidfile and acquires an exclusive
flock. - If another process holds the lock, raises
BlockingIOErrorimmediately — perfect for "don't start twice" guards. - Writes the current PID, releases the lock, removes the file on exit (including exceptions).
try:
with pidfile("/run/codechu/myapp/daemon.pid"):
run()
except BlockingIOError:
sys.exit("already running")
Design
- Pure stdlib.
socket,threading,fcntl,os,json— no more. The whole library is five small modules. - Linux-first. AF_UNIX,
mkfifo,flock— all POSIX, but Linux is the platform we run CI on. BSD/macOS work in practice. - No magic. No global registry, no event loop, no decorators. You start the server, you stop the server.
- Crash-safe. Stale socket files are detected on startup; pidfiles are removed on exit; handler exceptions don't kill the server.
Tests
pip install -e ".[dev]"
pytest -q
ruff check src tests
License
MIT — see LICENSE.
Metadata
Release files for codechu-ipc 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| codechu_ipc-0.1.0.tar.gz | 14.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| codechu_ipc-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.7 kB
Release files / codechu_ipc-0.1.0.tar.gz
| Download URL | codechu_ipc-0.1.0.tar.gz |
|---|---|
| Size | 14.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d096574ad8bd4e7aa7f94bb0da730469dce1fceea9d723b798a75aac90f7aafb
|
|
BLAKE2b-256 checksum How to use checksums |
52bd91755225e5eb117af87561056a74c6e6d972bdfafbbce7510f7f46602b0a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 20, 2026.
Transparency logRelease files / codechu_ipc-0.1.0-py3-none-any.whl
| Download URL | codechu_ipc-0.1.0-py3-none-any.whl |
|---|---|
| Size | 12.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
51bf24965f44ece25ea3a3498754e6b7baaf5bfb1918f702fcfb1448677894bd
|
|
BLAKE2b-256 checksum How to use checksums |
7463c079bdf6380fdaff77c355caa6b953249e5cc264a072536cf64fc1215aeb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 20, 2026.
Transparency log