# mr-vaibh/park architecture

> Architecture diagram of the GitHub repository mr-vaibh/park, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-26). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/mr-vaibh/park
- Repository: https://github.com/mr-vaibh/park

## Overview

1. **What this repo is**
   - `park` is a single Go CLI binary that temporarily freezes a process, frees its listening TCP port, and later restores the same process and port.
   - The architecture is centered on one hard boundary: user-space CLI orchestration on top of OS-specific process/socket manipulation.

2. **CLI entrypoint and command surface**
   - `cmd/park/` is the user-facing layer: argument parsing, command dispatch, and terminal output.
   - Main actions are `park <port>`, `resume`, `release`, `list`, plus auxiliary commands like `ui`, `hold`, `sigcont`, and `upgrade`.
   - All commands funnel into shared internal subsystems rather than duplicating OS logic.

3. **Port-to-process discovery**
   - `internal/portfind/` locates the listening process and socket for a given TCP port.
   - On Linux and macOS it uses platform-specific mechanisms to map a port to PID/fd, with parsers for kernel/network data in `parse.go`.
   - This subsystem is the first step in the park flow: it identifies exactly which file descriptor must be closed inside the target process.

4. **Process metadata and safety checks**
   - `internal/procinfo/` gathers command-line, cwd, PID/start-time details, and implements the “should we touch this process?” checks.
   - It enforces repo-level safety constraints such as refusing init-like processes, other users’ processes, and suspicious targets.
   - This package also supports later resume by preserving enough identity information to recognize the original process.

5. **State persistence**
   - `internal/state/` stores parked-process metadata under `~/.park/<pid>.json`.
   - The saved state is the bridge between the two phases: park now, resume later.
   - State is keyed by PID, with additional process identity data captured to reduce the risk of PID reuse issues.

6. **Core injection engine**
   - `internal/ptrace/` is the load-bearing subsystem that actually manipulates the target process and its sockets.
   - The cross-platform interface in `ptrace.go` abstracts “attach, inject, restore, detach.”
   - On Linux x86_64, `ptrace_linux_amd64.go` performs syscall injection to close the listening fd, and later recreate/bind/listen/dup2 it on resume.

7. **Platform split and capability boundaries**
   - Linux support is split by architecture: full implementation on `linux_amd64`, stub/error paths for other Linux arches.
   - macOS has its own path, including an arm64 implementation that uses Mach-based injection and thread control instead of Linux ptrace semantics.
   - This split is important for architecture diagrams: the platform backend is not a detail; it is the core differentiator of behavior and support level.

8. **Park lifecycle data flow**
   - `park <port>`: CLI → port discovery → safety checks → attach/inject close syscall → restore registers/bytes → detach/freeze → persist state.
   - `resume <port|pid>`: CLI → load state → reattach → recreate listener fd and rebind it → restore process state → continue execution.
   - `release` is the same state lookup path but skips re-binding the listener; it simply lets the process run again or terminates it if requested.

9. **macOS-specific listener restoration**
   - The macOS path has extra behavior because listeners may be registered in kqueue-based event loops.
   - On resume it may need to re-register the listener and restore non-blocking mode so async frameworks continue working.
   - This is a platform-specific subflow inside the broader resume pipeline.

10. **Operational model**
   - There is no daemon or background service; all state lives per-user in the filesystem.
   - The tool relies on kernel privileges for attach/detach and on OS socket semantics to truly free the port.
   - The repo is therefore a thin CLI over privileged kernel interactions, not a long-running control plane.

11. **Tests and validation**
   - Unit tests cover parsing, state handling, sockaddr encoding, and related helper logic.
   - A Linux integration test exercises the full end-to-end path: park a live server, bind another process to the freed port, then resume the original server.
   - This mirrors the architecture: most logic is deterministic plumbing, while the critical integration boundary is kernel behavior.

12. **Build and release flow**
   - The project is built and released as a Go binary with GitHub Actions and GoReleaser.
   - The repo also includes install scripting and a docs site, but these are delivery channels rather than runtime subsystems.
   - For an architecture diagram, these belong on the edge: build/release around the binary, not inside the runtime request path.

Main entry points: [`cmd/park/main.go`](https://github.com/mr-vaibh/park/blob/main/cmd/park/main.go) (park CLI), [`internal/ptrace/ptrace.go`](https://github.com/mr-vaibh/park/blob/main/internal/ptrace/ptrace.go) (Ptrace core), [`internal/procinfo/procinfo.go`](https://github.com/mr-vaibh/park/blob/main/internal/procinfo/procinfo.go) (Proc info), [`internal/portfind/portfind.go`](https://github.com/mr-vaibh/park/blob/main/internal/portfind/portfind.go) (Port find)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_cli["CLI"]
  node_cmd_park["park CLI<br/>entrypoint<br/>[main.go]"]
  node_cmd_ui["UI<br/>command<br/>[ui.go]"]
  node_cmd_hold["Hold<br/>command<br/>[hold.go]"]
  node_cmd_sigcont["Sigcont<br/>command<br/>[sigcont.go]"]
  node_cmd_upgrade["Upgrade<br/>command<br/>[upgrade.go]"]
end

subgraph group_core["Core"]
  node_portfind["Port find<br/>discovery<br/>[portfind.go]"]
  node_portparse["Port parse<br/>parser<br/>[parse.go]"]
  node_procinfo["Proc info<br/>safety<br/>[procinfo.go]"]
  node_procparse["Proc parse<br/>parser<br/>[parse.go]"]
  node_state[("State<br/>persistence<br/>[state.go]")]
  node_ptrace["Ptrace core<br/>injector<br/>[ptrace.go]"]
  node_sockaddr["Sockaddr<br/>codec<br/>[sockaddr.go]"]
end

subgraph group_platform["Platform"]
  node_ptrace_linux["Linux amd64<br/>backend"]
  node_ptrace_linux_other{{"Linux other<br/>stub"}}
  node_ptrace_darwin["macOS core<br/>backend<br/>[ptrace_darwin.go]"]
  node_ptrace_darwin_arm64["macOS arm64<br/>backend"]
end

subgraph group_delivery["Delivery"]
  node_ci["CI<br/>workflow<br/>[ci.yml]"]
  node_release["Release<br/>workflow<br/>[release.yml]"]
  node_docs["Docs<br/>site<br/>[index.html]"]
end

node_cmd_park -->|"find port owner"| node_portfind
node_cmd_park -->|"validate target"| node_procinfo
node_cmd_park -->|"park/resume"| node_ptrace
node_cmd_park -->|"persist state"| node_state
node_cmd_ui -->|"drive flows"| node_cmd_park
node_cmd_hold -->|"inspect target"| node_procinfo
node_cmd_sigcont -->|"continue process"| node_ptrace
node_cmd_upgrade -.->|"replace binary"| node_cmd_park
node_portfind -->|"parse kernel data"| node_portparse
node_procinfo -->|"read metadata"| node_procparse
node_cmd_park -.->|"platform lookup"| node_portparse
node_ptrace -->|"encode addr"| node_sockaddr
node_ptrace -->|"linux amd64"| node_ptrace_linux
node_ptrace -->|"linux fallback"| node_ptrace_linux_other
node_ptrace -->|"darwin"| node_ptrace_darwin
node_ptrace_darwin -->|"arm64 impl"| node_ptrace_darwin_arm64
node_state -->|"identity match"| node_procinfo
node_ci -.->|"validate binary"| node_cmd_park
node_release -.->|"ship binary"| node_cmd_park
node_docs -.->|"describe usage"| node_cmd_park

click node_cmd_park "https://github.com/mr-vaibh/park/blob/main/cmd/park/main.go"
click node_cmd_ui "https://github.com/mr-vaibh/park/blob/main/cmd/park/ui.go"
click node_cmd_hold "https://github.com/mr-vaibh/park/blob/main/cmd/park/hold.go"
click node_cmd_sigcont "https://github.com/mr-vaibh/park/blob/main/cmd/park/sigcont.go"
click node_cmd_upgrade "https://github.com/mr-vaibh/park/blob/main/cmd/park/upgrade.go"
click node_portfind "https://github.com/mr-vaibh/park/blob/main/internal/portfind/portfind.go"
click node_portparse "https://github.com/mr-vaibh/park/blob/main/internal/portfind/parse.go"
click node_procinfo "https://github.com/mr-vaibh/park/blob/main/internal/procinfo/procinfo.go"
click node_procparse "https://github.com/mr-vaibh/park/blob/main/internal/procinfo/parse.go"
click node_state "https://github.com/mr-vaibh/park/blob/main/internal/state/state.go"
click node_ptrace "https://github.com/mr-vaibh/park/blob/main/internal/ptrace/ptrace.go"
click node_sockaddr "https://github.com/mr-vaibh/park/blob/main/internal/ptrace/sockaddr.go"
click node_ptrace_linux "https://github.com/mr-vaibh/park/blob/main/internal/ptrace/ptrace_linux_amd64.go"
click node_ptrace_linux_other "https://github.com/mr-vaibh/park/blob/main/internal/ptrace/ptrace_linux_other.go"
click node_ptrace_darwin "https://github.com/mr-vaibh/park/blob/main/internal/ptrace/ptrace_darwin.go"
click node_ptrace_darwin_arm64 "https://github.com/mr-vaibh/park/blob/main/internal/ptrace/ptrace_darwin_arm64.go"
click node_ci "https://github.com/mr-vaibh/park/blob/main/.github/workflows/ci.yml"
click node_release "https://github.com/mr-vaibh/park/blob/main/.github/workflows/release.yml"
click node_docs "https://github.com/mr-vaibh/park/blob/main/docs/index.html"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_cmd_park,node_cmd_ui,node_cmd_hold,node_cmd_sigcont,node_cmd_upgrade toneBlue
class node_portfind,node_portparse,node_procinfo,node_procparse,node_state,node_ptrace,node_sockaddr toneAmber
class node_ptrace_linux,node_ptrace_linux_other,node_ptrace_darwin,node_ptrace_darwin_arm64 toneMint
class node_ci,node_release,node_docs toneRose
```

## Components

### CLI

User-facing command surface and lifecycle commands

- [park CLI](https://github.com/mr-vaibh/park/blob/main/cmd/park/main.go): entrypoint · Command dispatch and terminal UX for park operations · `cmd/park/main.go`
- [UI](https://github.com/mr-vaibh/park/blob/main/cmd/park/ui.go): command · Interactive or status-oriented command surface · `cmd/park/ui.go`
- [Hold](https://github.com/mr-vaibh/park/blob/main/cmd/park/hold.go): command · Auxiliary command for keeping a process parked · `cmd/park/hold.go`
- [Sigcont](https://github.com/mr-vaibh/park/blob/main/cmd/park/sigcont.go): command · Auxiliary command for continuing a process · `cmd/park/sigcont.go`
- [Upgrade](https://github.com/mr-vaibh/park/blob/main/cmd/park/upgrade.go): command · Self-update or upgrade flow for the CLI binary · `cmd/park/upgrade.go`

### Core

Shared discovery, safety, state, and injection subsystems

- [Port find](https://github.com/mr-vaibh/park/blob/main/internal/portfind/portfind.go): discovery · Maps a listening TCP port to the owning process and socket · `internal/portfind/portfind.go`
- [Port parse](https://github.com/mr-vaibh/park/blob/main/internal/portfind/parse.go): parser · Parses OS network and kernel data for port lookup · `internal/portfind/parse.go`
- [Proc info](https://github.com/mr-vaibh/park/blob/main/internal/procinfo/procinfo.go): safety · Collects process identity and enforces target safety checks · `internal/procinfo/procinfo.go`
- [Proc parse](https://github.com/mr-vaibh/park/blob/main/internal/procinfo/parse.go): parser · Parses process metadata used for identity and validation · `internal/procinfo/parse.go`
- [State](https://github.com/mr-vaibh/park/blob/main/internal/state/state.go): persistence · Persists parked-process metadata under the user state directory · `internal/state/state.go`
- [Ptrace core](https://github.com/mr-vaibh/park/blob/main/internal/ptrace/ptrace.go): injector · Attach, inject, restore, and detach abstraction · `internal/ptrace/ptrace.go`
- [Sockaddr](https://github.com/mr-vaibh/park/blob/main/internal/ptrace/sockaddr.go): codec · Socket address encoding and restoration helpers · `internal/ptrace/sockaddr.go`

### Platform

OS and architecture-specific backends

- [Linux amd64](https://github.com/mr-vaibh/park/blob/main/internal/ptrace/ptrace_linux_amd64.go): backend · Syscall injection backend for Linux x86_64 · `internal/ptrace/ptrace_linux_amd64.go`
- [Linux other](https://github.com/mr-vaibh/park/blob/main/internal/ptrace/ptrace_linux_other.go): stub · Unsupported Linux architecture path · `internal/ptrace/ptrace_linux_other.go`
- [macOS core](https://github.com/mr-vaibh/park/blob/main/internal/ptrace/ptrace_darwin.go): backend · macOS injection and thread-control backend · `internal/ptrace/ptrace_darwin.go`
- [macOS arm64](https://github.com/mr-vaibh/park/blob/main/internal/ptrace/ptrace_darwin_arm64.go): backend · Mach-based arm64 implementation for macOS · `internal/ptrace/ptrace_darwin_arm64.go`

### Delivery

Build, release, docs, and install packaging

- [CI](https://github.com/mr-vaibh/park/blob/main/.github/workflows/ci.yml): workflow · Continuous integration and validation pipeline · `.github/workflows/ci.yml`
- [Release](https://github.com/mr-vaibh/park/blob/main/.github/workflows/release.yml): workflow · GitHub Actions and GoReleaser release pipeline · `.github/workflows/release.yml`
- [Docs](https://github.com/mr-vaibh/park/blob/main/docs/index.html): site · Static docs and landing page · `docs/index.html`

## Connections

- park CLI → Port find: find port owner · Park starts by locating the listening process and socket
- park CLI → Proc info: validate target · Checks process identity and safety before touching it
- park CLI → Ptrace core: park/resume · Dispatches to the core injection lifecycle
- park CLI → State: persist state · Stores metadata needed for later resume or release
- UI → park CLI: drive flows · UI sits on the same command and lifecycle surface
- Hold → Proc info: inspect target · Auxiliary control path still depends on process identity
- Sigcont → Ptrace core: continue process · Uses the same process-control boundary to resume execution
- Upgrade → park CLI: replace binary · Upgrade is operationally adjacent to the main CLI
- Port find → Port parse: parse kernel data · Uses OS-specific parsing to map ports to processes
- Proc info → Proc parse: read metadata · Parses command line, cwd, pid, and start-time details
- park CLI → Port parse: platform lookup · Command flow depends on platform port discovery support
- Ptrace core → Sockaddr: encode addr · Restoration paths need socket address reconstruction
- Ptrace core → Linux amd64: linux amd64 · Full Linux x86_64 injection backend
- Ptrace core → Linux other: linux fallback · Unsupported Linux architectures return stubbed behavior
- Ptrace core → macOS core: darwin · macOS backend for attach and restore flows
- macOS core → macOS arm64: arm64 impl · Mach-based implementation on macOS arm64
- State → Proc info: identity match · Saved identity data helps avoid PID reuse mistakes
- CI → park CLI: validate binary · CI exercises command build and test paths
- Release → park CLI: ship binary · Release workflow packages the CLI for distribution
- Docs → park CLI: describe usage · Docs explain the runtime command surface
