Full Code of pranshuparmar/witr for AI

main e81f0fbf75a0 cached
925 files
11.7 MB
3.1M tokens
103001 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (12,477K chars total). Download the full file to get everything.
Repository: pranshuparmar/witr
Branch: main
Commit: e81f0fbf75a0
Files: 925
Total size: 11.7 MB

Directory structure:
gitextract_4kvh9lo7/

├── .agent/
│   └── workflows/
│       └── validate-pr-check.md
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   └── feature_request.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── e2e-tests.yml
│       ├── pr-check.yml
│       ├── release.yml
│       └── update-docs.yml
├── .gitignore
├── .goreleaser.yml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── cmd/
│   └── witr/
│       ├── main.go
│       └── unsupported.go
├── docs/
│   └── cli/
│       ├── witr.1
│       └── witr.md
├── flake.nix
├── go.mod
├── go.sum
├── install.ps1
├── install.sh
├── internal/
│   ├── app/
│   │   └── app.go
│   ├── launchd/
│   │   └── plist.go
│   ├── output/
│   │   ├── children.go
│   │   ├── colors.go
│   │   ├── docker.go
│   │   ├── docker_test.go
│   │   ├── envonly.go
│   │   ├── json.go
│   │   ├── printer.go
│   │   ├── safe_writer.go
│   │   ├── sanitize.go
│   │   ├── sanitize_test.go
│   │   ├── short.go
│   │   ├── standard.go
│   │   └── tree.go
│   ├── pipeline/
│   │   └── analyze.go
│   ├── proc/
│   │   ├── ancestry.go
│   │   ├── boot_darwin.go
│   │   ├── boot_freebsd.go
│   │   ├── boot_linux.go
│   │   ├── boot_windows.go
│   │   ├── capabilities_linux.go
│   │   ├── children_unix.go
│   │   ├── children_windows.go
│   │   ├── cmdline_darwin.go
│   │   ├── cmdline_freebsd.go
│   │   ├── cmdline_linux.go
│   │   ├── cmdline_windows.go
│   │   ├── command.go
│   │   ├── command_test.go
│   │   ├── container.go
│   │   ├── container_detect.go
│   │   ├── container_test.go
│   │   ├── docker_proxy.go
│   │   ├── extended_darwin.go
│   │   ├── extended_darwin_test.go
│   │   ├── extended_freebsd.go
│   │   ├── extended_linux.go
│   │   ├── extended_windows.go
│   │   ├── fd_darwin.go
│   │   ├── fd_freebsd.go
│   │   ├── fd_linux.go
│   │   ├── filecontext_darwin.go
│   │   ├── filecontext_freebsd.go
│   │   ├── filecontext_linux.go
│   │   ├── filecontext_windows.go
│   │   ├── git.go
│   │   ├── libproc_darwin_cgo.go
│   │   ├── libproc_darwin_stub.go
│   │   ├── libproc_darwin_test.go
│   │   ├── net_darwin.go
│   │   ├── net_freebsd.go
│   │   ├── net_linux.go
│   │   ├── net_linux_test.go
│   │   ├── net_windows.go
│   │   ├── peb_windows.go
│   │   ├── process_darwin.go
│   │   ├── process_darwin_test.go
│   │   ├── process_freebsd.go
│   │   ├── process_linux.go
│   │   ├── process_list_darwin.go
│   │   ├── process_list_freebsd.go
│   │   ├── process_list_linux.go
│   │   ├── process_list_windows.go
│   │   ├── process_windows.go
│   │   ├── psenv_unix.go
│   │   ├── resource_darwin.go
│   │   ├── resource_freebsd.go
│   │   ├── resource_linux.go
│   │   ├── resource_windows.go
│   │   ├── socketstate_darwin.go
│   │   ├── socketstate_freebsd.go
│   │   ├── socketstate_linux.go
│   │   ├── socketstate_windows.go
│   │   ├── sort.go
│   │   ├── systemd_linux.go
│   │   ├── systemd_stub.go
│   │   ├── user_darwin.go
│   │   ├── user_freebsd.go
│   │   ├── user_linux.go
│   │   └── user_windows.go
│   ├── source/
│   │   ├── bsdrc_darwin.go
│   │   ├── bsdrc_freebsd.go
│   │   ├── bsdrc_linux.go
│   │   ├── bsdrc_windows.go
│   │   ├── container.go
│   │   ├── cron.go
│   │   ├── detect.go
│   │   ├── detect_test.go
│   │   ├── init.go
│   │   ├── launchd_darwin.go
│   │   ├── launchd_freebsd.go
│   │   ├── launchd_linux.go
│   │   ├── launchd_windows.go
│   │   ├── network.go
│   │   ├── service_other.go
│   │   ├── service_windows.go
│   │   ├── shell.go
│   │   ├── ssh.go
│   │   ├── supervisor.go
│   │   ├── systemd_darwin.go
│   │   ├── systemd_freebsd.go
│   │   ├── systemd_linux.go
│   │   └── systemd_windows.go
│   ├── target/
│   │   ├── file_darwin.go
│   │   ├── file_freebsd.go
│   │   ├── file_linux.go
│   │   ├── file_windows.go
│   │   ├── name_darwin.go
│   │   ├── name_freebsd.go
│   │   ├── name_linux.go
│   │   ├── name_windows.go
│   │   ├── port_darwin.go
│   │   ├── port_freebsd.go
│   │   ├── port_linux.go
│   │   ├── port_windows.go
│   │   ├── resolve.go
│   │   └── resolve_test.go
│   ├── tools/
│   │   └── docgen/
│   │       └── main.go
│   ├── tui/
│   │   ├── actions.go
│   │   ├── actions_windows.go
│   │   ├── data.go
│   │   ├── helpers.go
│   │   ├── model.go
│   │   ├── mouse.go
│   │   ├── update.go
│   │   └── view.go
│   └── version/
│       ├── VERSION
│       └── version.go
├── pkg/
│   └── model/
│       ├── docker.go
│       ├── filecontext.go
│       ├── net.go
│       ├── process.go
│       ├── resource.go
│       ├── result.go
│       ├── socket.go
│       ├── source.go
│       └── target.go
└── vendor/
    ├── github.com/
    │   ├── atotto/
    │   │   └── clipboard/
    │   │       ├── .travis.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── clipboard.go
    │   │       ├── clipboard_darwin.go
    │   │       ├── clipboard_plan9.go
    │   │       ├── clipboard_unix.go
    │   │       └── clipboard_windows.go
    │   ├── aymanbagabas/
    │   │   └── go-osc52/
    │   │       └── v2/
    │   │           ├── LICENSE
    │   │           ├── README.md
    │   │           └── osc52.go
    │   ├── charmbracelet/
    │   │   ├── bubbles/
    │   │   │   ├── LICENSE
    │   │   │   ├── cursor/
    │   │   │   │   └── cursor.go
    │   │   │   ├── help/
    │   │   │   │   └── help.go
    │   │   │   ├── key/
    │   │   │   │   └── key.go
    │   │   │   ├── runeutil/
    │   │   │   │   └── runeutil.go
    │   │   │   ├── table/
    │   │   │   │   └── table.go
    │   │   │   ├── textinput/
    │   │   │   │   └── textinput.go
    │   │   │   └── viewport/
    │   │   │       ├── keymap.go
    │   │   │       └── viewport.go
    │   │   ├── bubbletea/
    │   │   │   ├── .gitattributes
    │   │   │   ├── .gitignore
    │   │   │   ├── .golangci.yml
    │   │   │   ├── .goreleaser.yml
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── Taskfile.yaml
    │   │   │   ├── commands.go
    │   │   │   ├── exec.go
    │   │   │   ├── focus.go
    │   │   │   ├── inputreader_other.go
    │   │   │   ├── inputreader_windows.go
    │   │   │   ├── key.go
    │   │   │   ├── key_other.go
    │   │   │   ├── key_sequences.go
    │   │   │   ├── key_windows.go
    │   │   │   ├── logging.go
    │   │   │   ├── mouse.go
    │   │   │   ├── nil_renderer.go
    │   │   │   ├── options.go
    │   │   │   ├── renderer.go
    │   │   │   ├── screen.go
    │   │   │   ├── signals_unix.go
    │   │   │   ├── signals_windows.go
    │   │   │   ├── standard_renderer.go
    │   │   │   ├── tea.go
    │   │   │   ├── tea_init.go
    │   │   │   ├── tty.go
    │   │   │   ├── tty_unix.go
    │   │   │   └── tty_windows.go
    │   │   ├── colorprofile/
    │   │   │   ├── .golangci.yml
    │   │   │   ├── .goreleaser.yml
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── doc.go
    │   │   │   ├── env.go
    │   │   │   ├── env_other.go
    │   │   │   ├── env_windows.go
    │   │   │   ├── profile.go
    │   │   │   └── writer.go
    │   │   ├── lipgloss/
    │   │   │   ├── .gitignore
    │   │   │   ├── .golangci.yml
    │   │   │   ├── .goreleaser.yml
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── Taskfile.yaml
    │   │   │   ├── align.go
    │   │   │   ├── ansi_unix.go
    │   │   │   ├── ansi_windows.go
    │   │   │   ├── borders.go
    │   │   │   ├── color.go
    │   │   │   ├── get.go
    │   │   │   ├── join.go
    │   │   │   ├── position.go
    │   │   │   ├── ranges.go
    │   │   │   ├── renderer.go
    │   │   │   ├── runes.go
    │   │   │   ├── set.go
    │   │   │   ├── size.go
    │   │   │   ├── style.go
    │   │   │   ├── unset.go
    │   │   │   └── whitespace.go
    │   │   └── x/
    │   │       ├── ansi/
    │   │       │   ├── LICENSE
    │   │       │   ├── ansi.go
    │   │       │   ├── ascii.go
    │   │       │   ├── background.go
    │   │       │   ├── c0.go
    │   │       │   ├── c1.go
    │   │       │   ├── charset.go
    │   │       │   ├── clipboard.go
    │   │       │   ├── color.go
    │   │       │   ├── ctrl.go
    │   │       │   ├── cursor.go
    │   │       │   ├── cwd.go
    │   │       │   ├── doc.go
    │   │       │   ├── finalterm.go
    │   │       │   ├── focus.go
    │   │       │   ├── graphics.go
    │   │       │   ├── hyperlink.go
    │   │       │   ├── inband.go
    │   │       │   ├── iterm2.go
    │   │       │   ├── keypad.go
    │   │       │   ├── kitty.go
    │   │       │   ├── method.go
    │   │       │   ├── mode.go
    │   │       │   ├── mode_deprecated.go
    │   │       │   ├── modes.go
    │   │       │   ├── mouse.go
    │   │       │   ├── notification.go
    │   │       │   ├── palette.go
    │   │       │   ├── parser/
    │   │       │   │   ├── const.go
    │   │       │   │   ├── seq.go
    │   │       │   │   └── transition_table.go
    │   │       │   ├── parser.go
    │   │       │   ├── parser_decode.go
    │   │       │   ├── parser_handler.go
    │   │       │   ├── parser_sync.go
    │   │       │   ├── passthrough.go
    │   │       │   ├── paste.go
    │   │       │   ├── progress.go
    │   │       │   ├── reset.go
    │   │       │   ├── screen.go
    │   │       │   ├── sgr.go
    │   │       │   ├── status.go
    │   │       │   ├── style.go
    │   │       │   ├── termcap.go
    │   │       │   ├── title.go
    │   │       │   ├── truncate.go
    │   │       │   ├── urxvt.go
    │   │       │   ├── util.go
    │   │       │   ├── width.go
    │   │       │   ├── winop.go
    │   │       │   ├── wrap.go
    │   │       │   └── xterm.go
    │   │       ├── cellbuf/
    │   │       │   ├── LICENSE
    │   │       │   ├── buffer.go
    │   │       │   ├── cell.go
    │   │       │   ├── errors.go
    │   │       │   ├── geom.go
    │   │       │   ├── hardscroll.go
    │   │       │   ├── hashmap.go
    │   │       │   ├── link.go
    │   │       │   ├── pen.go
    │   │       │   ├── screen.go
    │   │       │   ├── sequence.go
    │   │       │   ├── style.go
    │   │       │   ├── tabstop.go
    │   │       │   ├── utils.go
    │   │       │   ├── wrap.go
    │   │       │   └── writer.go
    │   │       └── term/
    │   │           ├── LICENSE
    │   │           ├── term.go
    │   │           ├── term_other.go
    │   │           ├── term_plan9.go
    │   │           ├── term_unix.go
    │   │           ├── term_unix_bsd.go
    │   │           ├── term_unix_other.go
    │   │           ├── term_windows.go
    │   │           ├── terminal.go
    │   │           └── util.go
    │   ├── clipperhouse/
    │   │   ├── displaywidth/
    │   │   │   ├── .gitignore
    │   │   │   ├── AGENTS.md
    │   │   │   ├── CHANGELOG.md
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── gen.go
    │   │   │   ├── graphemes.go
    │   │   │   ├── trie.go
    │   │   │   └── width.go
    │   │   ├── stringish/
    │   │   │   ├── .gitignore
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   └── interface.go
    │   │   └── uax29/
    │   │       └── v2/
    │   │           ├── LICENSE
    │   │           └── graphemes/
    │   │               ├── README.md
    │   │               ├── iterator.go
    │   │               ├── reader.go
    │   │               ├── splitfunc.go
    │   │               └── trie.go
    │   ├── cpuguy83/
    │   │   └── go-md2man/
    │   │       └── v2/
    │   │           ├── LICENSE.md
    │   │           └── md2man/
    │   │               ├── debug.go
    │   │               ├── md2man.go
    │   │               └── roff.go
    │   ├── erikgeiser/
    │   │   └── coninput/
    │   │       ├── .gitignore
    │   │       ├── .golangci.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── keycodes.go
    │   │       ├── mode.go
    │   │       ├── read.go
    │   │       └── records.go
    │   ├── inconshreveable/
    │   │   └── mousetrap/
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── trap_others.go
    │   │       └── trap_windows.go
    │   ├── mattn/
    │   │   ├── go-isatty/
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── doc.go
    │   │   │   ├── go.test.sh
    │   │   │   ├── isatty_bsd.go
    │   │   │   ├── isatty_others.go
    │   │   │   ├── isatty_plan9.go
    │   │   │   ├── isatty_solaris.go
    │   │   │   ├── isatty_tcgets.go
    │   │   │   └── isatty_windows.go
    │   │   ├── go-localereader/
    │   │   │   ├── README.md
    │   │   │   ├── localereader.go
    │   │   │   ├── localereader_unix.go
    │   │   │   └── localereader_windows.go
    │   │   └── go-runewidth/
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── benchstat.txt
    │   │       ├── new.txt
    │   │       ├── old.txt
    │   │       ├── runewidth.go
    │   │       ├── runewidth_appengine.go
    │   │       ├── runewidth_js.go
    │   │       ├── runewidth_posix.go
    │   │       ├── runewidth_table.go
    │   │       └── runewidth_windows.go
    │   ├── muesli/
    │   │   ├── ansi/
    │   │   │   ├── .gitignore
    │   │   │   ├── .golangci.yml
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── ansi.go
    │   │   │   ├── buffer.go
    │   │   │   ├── compressor/
    │   │   │   │   └── writer.go
    │   │   │   └── writer.go
    │   │   ├── cancelreader/
    │   │   │   ├── .gitignore
    │   │   │   ├── .golangci-soft.yml
    │   │   │   ├── .golangci.yml
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── cancelreader.go
    │   │   │   ├── cancelreader_bsd.go
    │   │   │   ├── cancelreader_default.go
    │   │   │   ├── cancelreader_linux.go
    │   │   │   ├── cancelreader_select.go
    │   │   │   ├── cancelreader_unix.go
    │   │   │   └── cancelreader_windows.go
    │   │   ├── reflow/
    │   │   │   ├── LICENSE
    │   │   │   ├── ansi/
    │   │   │   │   ├── ansi.go
    │   │   │   │   ├── buffer.go
    │   │   │   │   └── writer.go
    │   │   │   └── wrap/
    │   │   │       └── wrap.go
    │   │   └── termenv/
    │   │       ├── .gitignore
    │   │       ├── .golangci-soft.yml
    │   │       ├── .golangci.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── ansi_compat.md
    │   │       ├── ansicolors.go
    │   │       ├── color.go
    │   │       ├── constants_linux.go
    │   │       ├── constants_solaris.go
    │   │       ├── constants_unix.go
    │   │       ├── constants_zos.go
    │   │       ├── copy.go
    │   │       ├── hyperlink.go
    │   │       ├── notification.go
    │   │       ├── output.go
    │   │       ├── profile.go
    │   │       ├── screen.go
    │   │       ├── style.go
    │   │       ├── templatehelper.go
    │   │       ├── termenv.go
    │   │       ├── termenv_other.go
    │   │       ├── termenv_posix.go
    │   │       ├── termenv_solaris.go
    │   │       ├── termenv_unix.go
    │   │       └── termenv_windows.go
    │   ├── rivo/
    │   │   └── uniseg/
    │   │       ├── LICENSE.txt
    │   │       ├── README.md
    │   │       ├── doc.go
    │   │       ├── eastasianwidth.go
    │   │       ├── emojipresentation.go
    │   │       ├── gen_breaktest.go
    │   │       ├── gen_properties.go
    │   │       ├── grapheme.go
    │   │       ├── graphemeproperties.go
    │   │       ├── graphemerules.go
    │   │       ├── line.go
    │   │       ├── lineproperties.go
    │   │       ├── linerules.go
    │   │       ├── properties.go
    │   │       ├── sentence.go
    │   │       ├── sentenceproperties.go
    │   │       ├── sentencerules.go
    │   │       ├── step.go
    │   │       ├── width.go
    │   │       ├── word.go
    │   │       ├── wordproperties.go
    │   │       └── wordrules.go
    │   ├── russross/
    │   │   └── blackfriday/
    │   │       └── v2/
    │   │           ├── .gitignore
    │   │           ├── .travis.yml
    │   │           ├── LICENSE.txt
    │   │           ├── README.md
    │   │           ├── block.go
    │   │           ├── doc.go
    │   │           ├── entities.go
    │   │           ├── esc.go
    │   │           ├── html.go
    │   │           ├── inline.go
    │   │           ├── markdown.go
    │   │           ├── node.go
    │   │           └── smartypants.go
    │   ├── spf13/
    │   │   ├── cobra/
    │   │   │   ├── .gitignore
    │   │   │   ├── .golangci.yml
    │   │   │   ├── .mailmap
    │   │   │   ├── CONDUCT.md
    │   │   │   ├── CONTRIBUTING.md
    │   │   │   ├── LICENSE.txt
    │   │   │   ├── MAINTAINERS
    │   │   │   ├── Makefile
    │   │   │   ├── README.md
    │   │   │   ├── SECURITY.md
    │   │   │   ├── active_help.go
    │   │   │   ├── args.go
    │   │   │   ├── bash_completions.go
    │   │   │   ├── bash_completionsV2.go
    │   │   │   ├── cobra.go
    │   │   │   ├── command.go
    │   │   │   ├── command_notwin.go
    │   │   │   ├── command_win.go
    │   │   │   ├── completions.go
    │   │   │   ├── doc/
    │   │   │   │   ├── man_docs.go
    │   │   │   │   ├── md_docs.go
    │   │   │   │   ├── rest_docs.go
    │   │   │   │   ├── util.go
    │   │   │   │   └── yaml_docs.go
    │   │   │   ├── fish_completions.go
    │   │   │   ├── flag_groups.go
    │   │   │   ├── powershell_completions.go
    │   │   │   ├── shell_completions.go
    │   │   │   └── zsh_completions.go
    │   │   └── pflag/
    │   │       ├── .editorconfig
    │   │       ├── .gitignore
    │   │       ├── .golangci.yaml
    │   │       ├── .travis.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── bool.go
    │   │       ├── bool_func.go
    │   │       ├── bool_slice.go
    │   │       ├── bytes.go
    │   │       ├── count.go
    │   │       ├── duration.go
    │   │       ├── duration_slice.go
    │   │       ├── errors.go
    │   │       ├── flag.go
    │   │       ├── float32.go
    │   │       ├── float32_slice.go
    │   │       ├── float64.go
    │   │       ├── float64_slice.go
    │   │       ├── func.go
    │   │       ├── golangflag.go
    │   │       ├── int.go
    │   │       ├── int16.go
    │   │       ├── int32.go
    │   │       ├── int32_slice.go
    │   │       ├── int64.go
    │   │       ├── int64_slice.go
    │   │       ├── int8.go
    │   │       ├── int_slice.go
    │   │       ├── ip.go
    │   │       ├── ip_slice.go
    │   │       ├── ipmask.go
    │   │       ├── ipnet.go
    │   │       ├── ipnet_slice.go
    │   │       ├── string.go
    │   │       ├── string_array.go
    │   │       ├── string_slice.go
    │   │       ├── string_to_int.go
    │   │       ├── string_to_int64.go
    │   │       ├── string_to_string.go
    │   │       ├── text.go
    │   │       ├── time.go
    │   │       ├── uint.go
    │   │       ├── uint16.go
    │   │       ├── uint32.go
    │   │       ├── uint64.go
    │   │       ├── uint8.go
    │   │       └── uint_slice.go
    │   └── xo/
    │       └── terminfo/
    │           ├── .gitignore
    │           ├── LICENSE
    │           ├── README.md
    │           ├── caps.go
    │           ├── capvals.go
    │           ├── color.go
    │           ├── dec.go
    │           ├── load.go
    │           ├── param.go
    │           ├── stack.go
    │           └── terminfo.go
    ├── go.yaml.in/
    │   └── yaml/
    │       └── v3/
    │           ├── LICENSE
    │           ├── NOTICE
    │           ├── README.md
    │           ├── apic.go
    │           ├── decode.go
    │           ├── emitterc.go
    │           ├── encode.go
    │           ├── parserc.go
    │           ├── readerc.go
    │           ├── resolve.go
    │           ├── scannerc.go
    │           ├── sorter.go
    │           ├── writerc.go
    │           ├── yaml.go
    │           ├── yamlh.go
    │           └── yamlprivateh.go
    ├── golang.org/
    │   └── x/
    │       ├── sys/
    │       │   ├── LICENSE
    │       │   ├── PATENTS
    │       │   ├── unix/
    │       │   │   ├── .gitignore
    │       │   │   ├── README.md
    │       │   │   ├── affinity_linux.go
    │       │   │   ├── aliases.go
    │       │   │   ├── asm_aix_ppc64.s
    │       │   │   ├── asm_bsd_386.s
    │       │   │   ├── asm_bsd_amd64.s
    │       │   │   ├── asm_bsd_arm.s
    │       │   │   ├── asm_bsd_arm64.s
    │       │   │   ├── asm_bsd_ppc64.s
    │       │   │   ├── asm_bsd_riscv64.s
    │       │   │   ├── asm_linux_386.s
    │       │   │   ├── asm_linux_amd64.s
    │       │   │   ├── asm_linux_arm.s
    │       │   │   ├── asm_linux_arm64.s
    │       │   │   ├── asm_linux_loong64.s
    │       │   │   ├── asm_linux_mips64x.s
    │       │   │   ├── asm_linux_mipsx.s
    │       │   │   ├── asm_linux_ppc64x.s
    │       │   │   ├── asm_linux_riscv64.s
    │       │   │   ├── asm_linux_s390x.s
    │       │   │   ├── asm_openbsd_mips64.s
    │       │   │   ├── asm_solaris_amd64.s
    │       │   │   ├── asm_zos_s390x.s
    │       │   │   ├── auxv.go
    │       │   │   ├── auxv_unsupported.go
    │       │   │   ├── bluetooth_linux.go
    │       │   │   ├── bpxsvc_zos.go
    │       │   │   ├── bpxsvc_zos.s
    │       │   │   ├── cap_freebsd.go
    │       │   │   ├── constants.go
    │       │   │   ├── dev_aix_ppc.go
    │       │   │   ├── dev_aix_ppc64.go
    │       │   │   ├── dev_darwin.go
    │       │   │   ├── dev_dragonfly.go
    │       │   │   ├── dev_freebsd.go
    │       │   │   ├── dev_linux.go
    │       │   │   ├── dev_netbsd.go
    │       │   │   ├── dev_openbsd.go
    │       │   │   ├── dev_zos.go
    │       │   │   ├── dirent.go
    │       │   │   ├── endian_big.go
    │       │   │   ├── endian_little.go
    │       │   │   ├── env_unix.go
    │       │   │   ├── fcntl.go
    │       │   │   ├── fcntl_darwin.go
    │       │   │   ├── fcntl_linux_32bit.go
    │       │   │   ├── fdset.go
    │       │   │   ├── gccgo.go
    │       │   │   ├── gccgo_c.c
    │       │   │   ├── gccgo_linux_amd64.go
    │       │   │   ├── ifreq_linux.go
    │       │   │   ├── ioctl_linux.go
    │       │   │   ├── ioctl_signed.go
    │       │   │   ├── ioctl_unsigned.go
    │       │   │   ├── ioctl_zos.go
    │       │   │   ├── mkall.sh
    │       │   │   ├── mkerrors.sh
    │       │   │   ├── mmap_nomremap.go
    │       │   │   ├── mremap.go
    │       │   │   ├── pagesize_unix.go
    │       │   │   ├── pledge_openbsd.go
    │       │   │   ├── ptrace_darwin.go
    │       │   │   ├── ptrace_ios.go
    │       │   │   ├── race.go
    │       │   │   ├── race0.go
    │       │   │   ├── readdirent_getdents.go
    │       │   │   ├── readdirent_getdirentries.go
    │       │   │   ├── sockcmsg_dragonfly.go
    │       │   │   ├── sockcmsg_linux.go
    │       │   │   ├── sockcmsg_unix.go
    │       │   │   ├── sockcmsg_unix_other.go
    │       │   │   ├── sockcmsg_zos.go
    │       │   │   ├── symaddr_zos_s390x.s
    │       │   │   ├── syscall.go
    │       │   │   ├── syscall_aix.go
    │       │   │   ├── syscall_aix_ppc.go
    │       │   │   ├── syscall_aix_ppc64.go
    │       │   │   ├── syscall_bsd.go
    │       │   │   ├── syscall_darwin.go
    │       │   │   ├── syscall_darwin_amd64.go
    │       │   │   ├── syscall_darwin_arm64.go
    │       │   │   ├── syscall_darwin_libSystem.go
    │       │   │   ├── syscall_dragonfly.go
    │       │   │   ├── syscall_dragonfly_amd64.go
    │       │   │   ├── syscall_freebsd.go
    │       │   │   ├── syscall_freebsd_386.go
    │       │   │   ├── syscall_freebsd_amd64.go
    │       │   │   ├── syscall_freebsd_arm.go
    │       │   │   ├── syscall_freebsd_arm64.go
    │       │   │   ├── syscall_freebsd_riscv64.go
    │       │   │   ├── syscall_hurd.go
    │       │   │   ├── syscall_hurd_386.go
    │       │   │   ├── syscall_illumos.go
    │       │   │   ├── syscall_linux.go
    │       │   │   ├── syscall_linux_386.go
    │       │   │   ├── syscall_linux_alarm.go
    │       │   │   ├── syscall_linux_amd64.go
    │       │   │   ├── syscall_linux_amd64_gc.go
    │       │   │   ├── syscall_linux_arm.go
    │       │   │   ├── syscall_linux_arm64.go
    │       │   │   ├── syscall_linux_gc.go
    │       │   │   ├── syscall_linux_gc_386.go
    │       │   │   ├── syscall_linux_gc_arm.go
    │       │   │   ├── syscall_linux_gccgo_386.go
    │       │   │   ├── syscall_linux_gccgo_arm.go
    │       │   │   ├── syscall_linux_loong64.go
    │       │   │   ├── syscall_linux_mips64x.go
    │       │   │   ├── syscall_linux_mipsx.go
    │       │   │   ├── syscall_linux_ppc.go
    │       │   │   ├── syscall_linux_ppc64x.go
    │       │   │   ├── syscall_linux_riscv64.go
    │       │   │   ├── syscall_linux_s390x.go
    │       │   │   ├── syscall_linux_sparc64.go
    │       │   │   ├── syscall_netbsd.go
    │       │   │   ├── syscall_netbsd_386.go
    │       │   │   ├── syscall_netbsd_amd64.go
    │       │   │   ├── syscall_netbsd_arm.go
    │       │   │   ├── syscall_netbsd_arm64.go
    │       │   │   ├── syscall_openbsd.go
    │       │   │   ├── syscall_openbsd_386.go
    │       │   │   ├── syscall_openbsd_amd64.go
    │       │   │   ├── syscall_openbsd_arm.go
    │       │   │   ├── syscall_openbsd_arm64.go
    │       │   │   ├── syscall_openbsd_libc.go
    │       │   │   ├── syscall_openbsd_mips64.go
    │       │   │   ├── syscall_openbsd_ppc64.go
    │       │   │   ├── syscall_openbsd_riscv64.go
    │       │   │   ├── syscall_solaris.go
    │       │   │   ├── syscall_solaris_amd64.go
    │       │   │   ├── syscall_unix.go
    │       │   │   ├── syscall_unix_gc.go
    │       │   │   ├── syscall_unix_gc_ppc64x.go
    │       │   │   ├── syscall_zos_s390x.go
    │       │   │   ├── sysvshm_linux.go
    │       │   │   ├── sysvshm_unix.go
    │       │   │   ├── sysvshm_unix_other.go
    │       │   │   ├── timestruct.go
    │       │   │   ├── unveil_openbsd.go
    │       │   │   ├── vgetrandom_linux.go
    │       │   │   ├── vgetrandom_unsupported.go
    │       │   │   ├── xattr_bsd.go
    │       │   │   ├── zerrors_aix_ppc.go
    │       │   │   ├── zerrors_aix_ppc64.go
    │       │   │   ├── zerrors_darwin_amd64.go
    │       │   │   ├── zerrors_darwin_arm64.go
    │       │   │   ├── zerrors_dragonfly_amd64.go
    │       │   │   ├── zerrors_freebsd_386.go
    │       │   │   ├── zerrors_freebsd_amd64.go
    │       │   │   ├── zerrors_freebsd_arm.go
    │       │   │   ├── zerrors_freebsd_arm64.go
    │       │   │   ├── zerrors_freebsd_riscv64.go
    │       │   │   ├── zerrors_linux.go
    │       │   │   ├── zerrors_linux_386.go
    │       │   │   ├── zerrors_linux_amd64.go
    │       │   │   ├── zerrors_linux_arm.go
    │       │   │   ├── zerrors_linux_arm64.go
    │       │   │   ├── zerrors_linux_loong64.go
    │       │   │   ├── zerrors_linux_mips.go
    │       │   │   ├── zerrors_linux_mips64.go
    │       │   │   ├── zerrors_linux_mips64le.go
    │       │   │   ├── zerrors_linux_mipsle.go
    │       │   │   ├── zerrors_linux_ppc.go
    │       │   │   ├── zerrors_linux_ppc64.go
    │       │   │   ├── zerrors_linux_ppc64le.go
    │       │   │   ├── zerrors_linux_riscv64.go
    │       │   │   ├── zerrors_linux_s390x.go
    │       │   │   ├── zerrors_linux_sparc64.go
    │       │   │   ├── zerrors_netbsd_386.go
    │       │   │   ├── zerrors_netbsd_amd64.go
    │       │   │   ├── zerrors_netbsd_arm.go
    │       │   │   ├── zerrors_netbsd_arm64.go
    │       │   │   ├── zerrors_openbsd_386.go
    │       │   │   ├── zerrors_openbsd_amd64.go
    │       │   │   ├── zerrors_openbsd_arm.go
    │       │   │   ├── zerrors_openbsd_arm64.go
    │       │   │   ├── zerrors_openbsd_mips64.go
    │       │   │   ├── zerrors_openbsd_ppc64.go
    │       │   │   ├── zerrors_openbsd_riscv64.go
    │       │   │   ├── zerrors_solaris_amd64.go
    │       │   │   ├── zerrors_zos_s390x.go
    │       │   │   ├── zptrace_armnn_linux.go
    │       │   │   ├── zptrace_linux_arm64.go
    │       │   │   ├── zptrace_mipsnn_linux.go
    │       │   │   ├── zptrace_mipsnnle_linux.go
    │       │   │   ├── zptrace_x86_linux.go
    │       │   │   ├── zsymaddr_zos_s390x.s
    │       │   │   ├── zsyscall_aix_ppc.go
    │       │   │   ├── zsyscall_aix_ppc64.go
    │       │   │   ├── zsyscall_aix_ppc64_gc.go
    │       │   │   ├── zsyscall_aix_ppc64_gccgo.go
    │       │   │   ├── zsyscall_darwin_amd64.go
    │       │   │   ├── zsyscall_darwin_amd64.s
    │       │   │   ├── zsyscall_darwin_arm64.go
    │       │   │   ├── zsyscall_darwin_arm64.s
    │       │   │   ├── zsyscall_dragonfly_amd64.go
    │       │   │   ├── zsyscall_freebsd_386.go
    │       │   │   ├── zsyscall_freebsd_amd64.go
    │       │   │   ├── zsyscall_freebsd_arm.go
    │       │   │   ├── zsyscall_freebsd_arm64.go
    │       │   │   ├── zsyscall_freebsd_riscv64.go
    │       │   │   ├── zsyscall_illumos_amd64.go
    │       │   │   ├── zsyscall_linux.go
    │       │   │   ├── zsyscall_linux_386.go
    │       │   │   ├── zsyscall_linux_amd64.go
    │       │   │   ├── zsyscall_linux_arm.go
    │       │   │   ├── zsyscall_linux_arm64.go
    │       │   │   ├── zsyscall_linux_loong64.go
    │       │   │   ├── zsyscall_linux_mips.go
    │       │   │   ├── zsyscall_linux_mips64.go
    │       │   │   ├── zsyscall_linux_mips64le.go
    │       │   │   ├── zsyscall_linux_mipsle.go
    │       │   │   ├── zsyscall_linux_ppc.go
    │       │   │   ├── zsyscall_linux_ppc64.go
    │       │   │   ├── zsyscall_linux_ppc64le.go
    │       │   │   ├── zsyscall_linux_riscv64.go
    │       │   │   ├── zsyscall_linux_s390x.go
    │       │   │   ├── zsyscall_linux_sparc64.go
    │       │   │   ├── zsyscall_netbsd_386.go
    │       │   │   ├── zsyscall_netbsd_amd64.go
    │       │   │   ├── zsyscall_netbsd_arm.go
    │       │   │   ├── zsyscall_netbsd_arm64.go
    │       │   │   ├── zsyscall_openbsd_386.go
    │       │   │   ├── zsyscall_openbsd_386.s
    │       │   │   ├── zsyscall_openbsd_amd64.go
    │       │   │   ├── zsyscall_openbsd_amd64.s
    │       │   │   ├── zsyscall_openbsd_arm.go
    │       │   │   ├── zsyscall_openbsd_arm.s
    │       │   │   ├── zsyscall_openbsd_arm64.go
    │       │   │   ├── zsyscall_openbsd_arm64.s
    │       │   │   ├── zsyscall_openbsd_mips64.go
    │       │   │   ├── zsyscall_openbsd_mips64.s
    │       │   │   ├── zsyscall_openbsd_ppc64.go
    │       │   │   ├── zsyscall_openbsd_ppc64.s
    │       │   │   ├── zsyscall_openbsd_riscv64.go
    │       │   │   ├── zsyscall_openbsd_riscv64.s
    │       │   │   ├── zsyscall_solaris_amd64.go
    │       │   │   ├── zsyscall_zos_s390x.go
    │       │   │   ├── zsysctl_openbsd_386.go
    │       │   │   ├── zsysctl_openbsd_amd64.go
    │       │   │   ├── zsysctl_openbsd_arm.go
    │       │   │   ├── zsysctl_openbsd_arm64.go
    │       │   │   ├── zsysctl_openbsd_mips64.go
    │       │   │   ├── zsysctl_openbsd_ppc64.go
    │       │   │   ├── zsysctl_openbsd_riscv64.go
    │       │   │   ├── zsysnum_darwin_amd64.go
    │       │   │   ├── zsysnum_darwin_arm64.go
    │       │   │   ├── zsysnum_dragonfly_amd64.go
    │       │   │   ├── zsysnum_freebsd_386.go
    │       │   │   ├── zsysnum_freebsd_amd64.go
    │       │   │   ├── zsysnum_freebsd_arm.go
    │       │   │   ├── zsysnum_freebsd_arm64.go
    │       │   │   ├── zsysnum_freebsd_riscv64.go
    │       │   │   ├── zsysnum_linux_386.go
    │       │   │   ├── zsysnum_linux_amd64.go
    │       │   │   ├── zsysnum_linux_arm.go
    │       │   │   ├── zsysnum_linux_arm64.go
    │       │   │   ├── zsysnum_linux_loong64.go
    │       │   │   ├── zsysnum_linux_mips.go
    │       │   │   ├── zsysnum_linux_mips64.go
    │       │   │   ├── zsysnum_linux_mips64le.go
    │       │   │   ├── zsysnum_linux_mipsle.go
    │       │   │   ├── zsysnum_linux_ppc.go
    │       │   │   ├── zsysnum_linux_ppc64.go
    │       │   │   ├── zsysnum_linux_ppc64le.go
    │       │   │   ├── zsysnum_linux_riscv64.go
    │       │   │   ├── zsysnum_linux_s390x.go
    │       │   │   ├── zsysnum_linux_sparc64.go
    │       │   │   ├── zsysnum_netbsd_386.go
    │       │   │   ├── zsysnum_netbsd_amd64.go
    │       │   │   ├── zsysnum_netbsd_arm.go
    │       │   │   ├── zsysnum_netbsd_arm64.go
    │       │   │   ├── zsysnum_openbsd_386.go
    │       │   │   ├── zsysnum_openbsd_amd64.go
    │       │   │   ├── zsysnum_openbsd_arm.go
    │       │   │   ├── zsysnum_openbsd_arm64.go
    │       │   │   ├── zsysnum_openbsd_mips64.go
    │       │   │   ├── zsysnum_openbsd_ppc64.go
    │       │   │   ├── zsysnum_openbsd_riscv64.go
    │       │   │   ├── zsysnum_zos_s390x.go
    │       │   │   ├── ztypes_aix_ppc.go
    │       │   │   ├── ztypes_aix_ppc64.go
    │       │   │   ├── ztypes_darwin_amd64.go
    │       │   │   ├── ztypes_darwin_arm64.go
    │       │   │   ├── ztypes_dragonfly_amd64.go
    │       │   │   ├── ztypes_freebsd_386.go
    │       │   │   ├── ztypes_freebsd_amd64.go
    │       │   │   ├── ztypes_freebsd_arm.go
    │       │   │   ├── ztypes_freebsd_arm64.go
    │       │   │   ├── ztypes_freebsd_riscv64.go
    │       │   │   ├── ztypes_linux.go
    │       │   │   ├── ztypes_linux_386.go
    │       │   │   ├── ztypes_linux_amd64.go
    │       │   │   ├── ztypes_linux_arm.go
    │       │   │   ├── ztypes_linux_arm64.go
    │       │   │   ├── ztypes_linux_loong64.go
    │       │   │   ├── ztypes_linux_mips.go
    │       │   │   ├── ztypes_linux_mips64.go
    │       │   │   ├── ztypes_linux_mips64le.go
    │       │   │   ├── ztypes_linux_mipsle.go
    │       │   │   ├── ztypes_linux_ppc.go
    │       │   │   ├── ztypes_linux_ppc64.go
    │       │   │   ├── ztypes_linux_ppc64le.go
    │       │   │   ├── ztypes_linux_riscv64.go
    │       │   │   ├── ztypes_linux_s390x.go
    │       │   │   ├── ztypes_linux_sparc64.go
    │       │   │   ├── ztypes_netbsd_386.go
    │       │   │   ├── ztypes_netbsd_amd64.go
    │       │   │   ├── ztypes_netbsd_arm.go
    │       │   │   ├── ztypes_netbsd_arm64.go
    │       │   │   ├── ztypes_openbsd_386.go
    │       │   │   ├── ztypes_openbsd_amd64.go
    │       │   │   ├── ztypes_openbsd_arm.go
    │       │   │   ├── ztypes_openbsd_arm64.go
    │       │   │   ├── ztypes_openbsd_mips64.go
    │       │   │   ├── ztypes_openbsd_ppc64.go
    │       │   │   ├── ztypes_openbsd_riscv64.go
    │       │   │   ├── ztypes_solaris_amd64.go
    │       │   │   └── ztypes_zos_s390x.go
    │       │   └── windows/
    │       │       ├── aliases.go
    │       │       ├── dll_windows.go
    │       │       ├── env_windows.go
    │       │       ├── eventlog.go
    │       │       ├── exec_windows.go
    │       │       ├── memory_windows.go
    │       │       ├── mkerrors.bash
    │       │       ├── mkknownfolderids.bash
    │       │       ├── mksyscall.go
    │       │       ├── race.go
    │       │       ├── race0.go
    │       │       ├── security_windows.go
    │       │       ├── service.go
    │       │       ├── setupapi_windows.go
    │       │       ├── str.go
    │       │       ├── syscall.go
    │       │       ├── syscall_windows.go
    │       │       ├── types_windows.go
    │       │       ├── types_windows_386.go
    │       │       ├── types_windows_amd64.go
    │       │       ├── types_windows_arm.go
    │       │       ├── types_windows_arm64.go
    │       │       ├── zerrors_windows.go
    │       │       ├── zknownfolderids_windows.go
    │       │       └── zsyscall_windows.go
    │       └── text/
    │           ├── LICENSE
    │           ├── PATENTS
    │           └── transform/
    │               └── transform.go
    └── modules.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .agent/workflows/validate-pr-check.md
================================================
---
description: How to validate the PR check workflow locally
---

# Validate PR Check Locally

You can validate the PR check workflow in two ways: manually running the commands or using `act` to simulate GitHub Actions.

## Option 1: Manual Validation (Fastest)

Run the following commands in your terminal to mimic the workflow steps:

1. **Validate Code**
   ```bash
   # Check formatting
   test -z $(gofmt -l .)
   
   # Run static analysis
   go vet ./...
   
   # Run tests
   go test -v ./...
   ```

2. **Verify Builds (Cross-compilation)**
   ```bash
   # Linux
   GOOS=linux GOARCH=amd64 go build -v ./cmd/witr
   GOOS=linux GOARCH=arm64 go build -v ./cmd/witr
   
   # macOS
   GOOS=darwin GOARCH=amd64 go build -v ./cmd/witr
   GOOS=darwin GOARCH=arm64 go build -v ./cmd/witr
   ```

## Option 2: Using `act` (Docker required)

If you have [act](https://github.com/nektos/act) installed, you can run the workflow in a container:

```bash
# Run the specific job
act -j validate
act -j build

# Or run the whole workflow for a pull_request event
act pull_request
```


================================================
FILE: .github/FUNDING.yml
================================================
github: pranshuparmar


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: Bug report
description: Create a report to help us improve
title: "[Bug]: "
labels: ["bug"]
body:
  - type: markdown
    attributes:
      value: |
        Thanks for taking the time to fill out this bug report!
  - type: textarea
    id: description
    attributes:
      label: Describe the bug
      description: A clear and concise description of what the bug is.
      placeholder: I was doing X and Y happened...
    validations:
      required: true
  - type: textarea
    id: reproduce
    attributes:
      label: To Reproduce
      description: Steps to reproduce the behavior.
      placeholder: |
        1. Run '...'
        2. See error
  - type: input
    id: os
    attributes:
      label: OS
      description: e.g. macOS, Ubuntu
      placeholder: macOS 14.0
    validations:
      required: true
  - type: input
    id: version
    attributes:
      label: Version
      description: e.g. v0.1.0
      placeholder: v0.1.0
  - type: input
    id: arch
    attributes:
      label: Architecture
      description: e.g. amd64, arm64
      placeholder: amd64
  - type: textarea
    id: context
    attributes:
      label: Additional context
      description: Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: Feature request
title: "[Feature]: "
description: Suggest an idea for this project
labels: ["enhancement"]
body:
  - type: markdown
    attributes:
      value: |
        Thank you for taking the time to suggest a feature!
  - type: textarea
    id: problem
    attributes:
      label: Is your feature request related to a problem?
      description: A clear and concise description of what the problem is. Ex. I'm currently unable to [...]
      placeholder: I wish I could...
    validations:
      required: true
  - type: textarea
    id: solution
    attributes:
      label: Describe the solution you'd like
      description: A clear and concise description of what you want to happen.
      placeholder: It would be great if...
  - type: textarea
    id: context
    attributes:
      label: Additional context
      description: Add any other context or screenshots about the feature request here.


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================

## Description

Briefly describe what this PR does. Mention existing issue number, if applicable.

## Type of change

Check all that apply:

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (may affect existing functionality)
- [ ] This change requires a documentation update

## Checklist

- [ ] I have formatted my code using `go fmt ./...`
- [ ] I have opened this PR against the `staging` branch
- [ ] I have performed a self-review of my own code
- [ ] I have added helpful comments where needed
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] New and existing unit tests pass locally with my changes

## Thank you for your contribution! 🎉

We’re excited to review your pull request. Please fill out the details above to help us understand your changes. Don’t worry if you can’t check every box, just do your best!


================================================
FILE: .github/dependabot.yml
================================================
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file

version: 2
updates:
  - package-ecosystem: "gomod"
    directory: "/"
    schedule:
      interval: "weekly"
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    groups:
      actions:
        patterns:
          - "*"


================================================
FILE: .github/workflows/e2e-tests.yml
================================================
name: E2E Tests

on:
  pull_request:
    branches: [ "main" ]

permissions: read-all

jobs:
  build-and-test:
    name: "Build & Test"
    runs-on: ${{ matrix.runner }}
    strategy:
      matrix:
        include:
          - os: linux
            arch: amd64
            runner: ubuntu-latest
          - os: darwin
            arch: amd64
            runner: macos-15
          - os: windows
            arch: amd64
            runner: windows-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version: '1.25'

      - name: Build ${{ matrix.os }}/${{ matrix.arch }}
        shell: bash
        run: |
          GOOS=${{ matrix.os }} GOARCH=${{ matrix.arch }} go build -o witr-${{ matrix.os }}-${{ matrix.arch }} ./cmd/witr
          chmod +x witr-${{ matrix.os }}-${{ matrix.arch }}

      - name: Verify Version
        shell: bash
        run: ./witr-${{ matrix.os }}-${{ matrix.arch }} --version

      - name: Verify Help
        shell: bash
        run: ./witr-${{ matrix.os }}-${{ matrix.arch }} --help

  test-freebsd:
    name: "Test: FreeBSD"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Run on FreeBSD
        uses: vmactions/freebsd-vm@v1
        with:
          usesh: true
          prepare: pkg install -y go
          run: |
            go build -o witr-freebsd-amd64 ./cmd/witr
            chmod +x witr-freebsd-amd64
            ./witr-freebsd-amd64 --version
            ./witr-freebsd-amd64 --help


================================================
FILE: .github/workflows/pr-check.yml
================================================
name: PR Check

on:
  pull_request:
    types: [opened, synchronize, reopened, edited]
  push:
    branches:
      - main
      - staging

permissions: read-all

jobs:

  semantic-pull-request:
    name: "Compliance: Check PR Title"
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    steps:
      - name: Check PR title
        uses: amannn/action-semantic-pull-request@v6
        id: lint_pr_title
        continue-on-error: true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Warn on failure
        if: steps.lint_pr_title.outcome == 'failure'
        run: echo "::warning::PR title does not follow semantic commit convention"

  lint:
    name: "Code Quality: Lint"
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version: '1.25'

      - name: Verify formatting
        run: |
          if [ -n "$(find . -name "*.go" -not -path "./vendor/*" | xargs gofmt -l)" ]; then
            echo "Go code is not formatted:"
            find . -name "*.go" -not -path "./vendor/*" | xargs gofmt -d
            exit 1
          fi

  vet:
    name: "Code Quality: Vet"
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version: '1.25'

      - name: Run go vet
        run: go vet ./...

  test:
    name: "Tests: Unit"
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version: '1.25'

      - name: Run tests
        run: go test -v ./...


================================================
FILE: .github/workflows/release.yml
================================================
# .github/workflows/release.yml
name: Release

on:
  push:
    tags:
      - 'v*'

permissions:
  contents: write

concurrency:
  group: release-${{ github.ref }}
  cancel-in-progress: true

env:
  GO_VERSION: '1.25'
  PROJECT_NAME: witr

jobs:
  release:

    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version: ${{ env.GO_VERSION }}

      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@v7
        with:
          version: latest
          args: release --clean
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GORELEASER_CURRENT_TAG: ${{ github.ref_name }}


================================================
FILE: .github/workflows/update-docs.yml
================================================
name: Update Documentation
on:
  push:
    branches:
      - main
  workflow_dispatch:



permissions:
  contents: write




concurrency:
  group: ${{github.workflow}}-${{ github.ref }}
  cancel-in-progress: true

env:
  GO_VERSION: '1.25'
  PROJECT_NAME: witr

jobs:
  update-docs:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version: ${{ env.GO_VERSION }}

      - name: Create man.1 documentation
        run: |
          go run internal/tools/docgen/main.go -out ./docs/cli -format man

      - name: Create markdown documentation
        run: |
          go run internal/tools/docgen/main.go -out ./docs/cli -format markdown

      - name: Commit and push documentation
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"

          git add docs/cli

          if git diff --cached --quiet; then
            echo "No changes to commit"
            exit 0
          fi

          git commit -m "docs: update CLI documentation"

      - name: Push documentation
        run: |
          git push origin ${{ github.ref }}





================================================
FILE: .gitignore
================================================
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Code coverage profiles and other test artifacts
*.out
coverage.*
*.coverprofile
profile.cov

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
go.work
go.work.sum

# env file
.env

# Editor/IDE
.idea/
.vscode/

# Nix
result

# Binary files
/witr

# Ignore build artifacts
dist/
pkg-dist/


================================================
FILE: .goreleaser.yml
================================================
version: 2

project_name: witr

builds:
  - id: witr
    main: ./cmd/witr
    binary: witr
    goos:
      - linux
      - darwin
      - freebsd
      - windows
    goarch:
      - amd64
      - arm64
    env:
      - CGO_ENABLED=0
    ldflags:
      - -s -w
      - -X github.com/pranshuparmar/witr/internal/version.Version=v{{ .Version }}
      - -X github.com/pranshuparmar/witr/internal/version.Commit={{ .Commit }}
      - -X github.com/pranshuparmar/witr/internal/version.BuildDate={{ .Date }}

archives:
  - id: binaries
    formats:
      - binary
    format_overrides:
      - goos: windows
        formats: [ 'zip' ]
    ids:
      - witr
    name_template: "witr-{{ .Os }}-{{ .Arch }}"

checksum:
  name_template: SHA256SUMS
  algorithm: sha256

nfpms:
  - id: witr
    package_name: witr
    file_name_template: "witr-{{ .Version }}-{{ .Os }}-{{ .Arch }}"
    formats:
      - apk
      - deb
      - rpm
    maintainer: Pranshu Parmar <pranshu.parmar@gmail.com>
    description: witr explains why a process or port is running by tracing its ancestry.
    homepage: https://github.com/pranshuparmar/witr
    license: Apache-2.0
    contents:
      - src: docs/cli/witr.1
        dst: /usr/share/man/man1/witr.1
        file_info:
          mode: 0644

changelog:
  sort: asc
  use: github-native

release:
  extra_files:
    - glob: docs/cli/witr.1



================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or
  advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
  address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior,  harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to witr

First off, thank you for considering contributing to **witr**! It's people like you that make the open-source community such an amazing place to learn, inspire, and create.

All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. 🎉

> If you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:
> - Star the project
> - Tweet about it
> - Refer this project in your project's readme
> - Mention the project at local meetups and tell your friends/colleagues

## Table of Contents

- [Code of Conduct](#code-of-conduct)
- [I Have a Question](#i-have-a-question)
- [I Want To Contribute](#i-want-to-contribute)
  - [Reporting Bugs](#reporting-bugs)
  - [Suggesting Enhancements](#suggesting-enhancements)
  - [Your First Code Contribution](#your-first-code-contribution)
  - [Improving Documentation](#improving-documentation)
- [Styleguides](#styleguides)
  - [Commit Messages](#commit-messages)
- [Join The Project Team](#join-the-project-team)

## Building from source

When you need to verify a change locally, compile the CLI with Go 1.25+
so that the embedded version data stays accurate:

```bash
git clone https://github.com/pranshuparmar/witr.git
cd witr
go build -o witr ./cmd/witr
./witr --help  # quick smoke test
```

- The `-ldflags` block injects commit/date metadata for `witr --version`.
- The resulting `witr` binary lands in the repo root.

## Code Style
## Code of Conduct

This project and everyone participating in it is governed by the [witr Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to .

## I Have a Question

> If you want to ask a question, we assume that you have read the available [Documentation](README.md).

Before you ask a question, it is best to search for existing [Issues](https://github.com/pranshuparmar/witr/issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first.

If you then still feel the need to ask a question and need clarification, we recommend the following:

- Open an [Issue](https://github.com/pranshuparmar/witr/issues/new).
- Provide as much context as you can about what you're running into.
- Provide project and platform versions (witr version, OS, Shell, target service (if possible) etc.), depending on what seems relevant.

We will then answer as soon as possible.

## I Want To Contribute

> ### Legal Notice
> When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license.

### Suggesting Enhancements

This section guides you through submitting an enhancement suggestion for **witr**, including completely new features and minor improvements to existing functionality. Following these steps helps maintainers and the community understand your suggestion and find related suggestions.

#### Before Submitting an Enhancement

- Make sure that you are using the latest version.
- Read the [documentation](README.md) carefully and find out if the functionality is already covered, maybe by an individual configuration.
- Search [Issues](https://github.com/pranshuparmar/witr/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a edge case, might be better to create a separate extension/library.

#### How Do I Submit a Good Enhancement Suggestion?

Enhancement suggestions are tracked as [GitHub issues](https://github.com/pranshuparmar/witr/issues).

- Open an [Issue](https://github.com/pranshuparmar/witr/issues/new).
- Use a **clear and descriptive title** for the issue to identify the suggestion.
- Provide a **step-by-step description of the suggested enhancement** in as many details as possible.
- **Describe the current behavior** and explain which behavior you expected to see instead and why. At this point you can also tell which alternatives do not work for you.
- **Explain why this enhancement would be useful** to most **witr** users. You may also want to point out the other projects that solved it better and which could serve as inspiration.

### Your First Code Contribution

#### Setup

1. Fork the repository.
2. Clone your fork: `git clone https://github.com/YOUR_USERNAME/witr.git`
3. Create a feature branch: `git checkout -b feature/your-feature-name`
4. Install dependencies: `go mod download`

#### Development

- Follow the existing code style.
- Use `gofmt` to format your code.
- Write unit tests for new functionality.
- Ensure all tests pass: `go test ./...`

#### Pull Request Process

1. **Squash your commits**: We prefer a clean history. Please squash your commits into a single logical commit before submitting.
2. **Rebase on `staging`**: Ensure your branch is up to date with the `staging` branch.
3. **Open a PR**: Open a PR against the `staging` branch, not `main`.
4. **Use the Template**: Fill out the PR template completely.
5. **Review**: Wait for a maintainer to review your PR. Address any feedback promptly.
6. **Merge**: Once approved, a maintainer will merge your PR. We **strictly use Squash and Merge** to keep the `main` history clean.

### Improving Documentation

Documentation improvements are always welcome! If you find a typo or want to clarify a section, feel free to open a PR.

## Styleguides

### Commit Messages

We follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification.

Format: `<type>(<scope>): <description>`

Types:
- `feat`: A new feature
- `fix`: A bug fix
- `docs`: Documentation only changes
- `style`: Changes that do not affect the meaning of the code (white-space, formatting, etc)
- `refactor`: A code change that neither fixes a bug nor adds a feature
- `perf`: A code change that improves performance
- `test`: Adding missing tests or correcting existing tests
- `build`: Changes that affect the build system or external dependencies
- `ci`: Changes to our CI configuration files and scripts
- `chore`: Other changes that don't modify src or test files

## License

By contributing, you agree that your contributions will be licensed under the Apache License 2.0.


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   Copyright 2025 Pranshu Parmar

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: Makefile
================================================
.PHONY: build test lint docs man clean

BINARY := witr
CMD    := ./cmd/witr

build:
	CGO_ENABLED=0 go build -o $(BINARY) $(CMD)

test:
	go test ./...

test-race:
	go test -race ./...

lint:
	gofmt -l .
	go vet ./...

docs: man markdown

man:
	go run ./internal/tools/docgen -format man -out docs/cli

markdown:
	go run ./internal/tools/docgen -format markdown -out docs/cli

clean:
	rm -f $(BINARY)


================================================
FILE: README.md
================================================
<div align="center">

# witr

### Why is this running?
*with* [**Interactive TUI Mode**](#3-interactive-mode-tui) ✨

[![Go Version](https://img.shields.io/github/go-mod/go-version/pranshuparmar/witr?style=flat-square)](https://github.com/pranshuparmar/witr/blob/main/go.mod) [![Go Report Card](https://goreportcard.com/badge/github.com/pranshuparmar/witr?style=flat-square)](https://goreportcard.com/report/github.com/pranshuparmar/witr) [![Release](https://img.shields.io/github/actions/workflow/status/pranshuparmar/witr/release.yml?style=flat-square)](https://github.com/pranshuparmar/witr/actions/workflows/release.yml) [![Platforms](https://img.shields.io/badge/platforms-linux%20%7C%20macos%20%7C%20windows%20%7C%20freebsd-blue?style=flat-square)](#6-platform-support) <br>
[![Latest Release](https://img.shields.io/github/v/release/pranshuparmar/witr?label=Latest%20Release&style=flat-square)](https://github.com/pranshuparmar/witr/releases/latest) [![Package Managers](https://img.shields.io/badge/Package%20Managers-brew%20|%20conda%20|%20aur%20|%20winget%20|%20npm%20|%20ports%20|%20...%20-blue?style=flat-square)](https://repology.org/project/witr/versions)

📖 Read the [story](https://medium.com/@pranshu.parmar/witr-why-is-this-running-a9a97cbedd18) behind witr

<img width="1232" height="693" alt="witr_banner" src="https://github.com/user-attachments/assets/e9c19ef0-1391-4a5f-a015-f4003d3697a9" />

</div>

---

<div align="center">

[**Purpose**](#1-purpose) • [**Installation**](#2-installation) • ✨ [**TUI**](#3-interactive-mode-tui) • [**Flags**](#4-flags--options) • [**Examples**](#5-example-outputs) • [**Platforms**](#6-platform-support)
<br>
[**Goals**](#7-goals) • [**Core Concept**](#8-core-concept) • [**Output Behavior**](#9-output-behavior) • [**Success Criteria**](#10-success-criteria) • [**Sponsors**](#11-sponsors)

</div>

---

## 1. Purpose

**witr** exists to answer a single question:

> **Why is this running?**

When something is running on a system, whether it is a process, a service, or something bound to a port, there is always a cause. That cause is often indirect, non-obvious, or spread across multiple layers such as supervisors, containers, services, or shells.

Existing tools (`ps`, `top`, `lsof`, `ss`, `systemctl`, `docker ps`) expose state and metadata. They show _what_ is running, but leave the user to infer _why_ by manually correlating outputs across tools.

**witr** makes that causality explicit.

It explains **where a running thing came from**, **how it was started**, and **what chain of systems is responsible for it existing right now**, in a single, human-readable output or an **interactive TUI dashboard**.

---

## 2. Installation

witr is distributed as a single static binary for Linux, macOS, FreeBSD, and Windows.

witr is also independently packaged and maintained across multiple operating systems and ecosystems. An up-to-date overview of packaging status is available on [Repology](https://repology.org/project/witr/versions). Please note that community packages may lag GitHub releases due to independent review and validation.

> [!TIP]
> If you use a package manager (Homebrew, Conda, Winget, etc.), we recommend installing via that for easier updates. Otherwise, the install script is the quickest way to get started.

---

### 2.1 Quick Install

#### Unix (Linux, macOS & FreeBSD)

```bash
curl -fsSL https://raw.githubusercontent.com/pranshuparmar/witr/main/install.sh | bash
```

<details>
<summary>Script Details</summary>

The script will:
- Detect your operating system (`linux`, `darwin` or `freebsd`)
- Detect your CPU architecture (`amd64` or `arm64`)
- Download the latest released binary and man page
- Install it to `/usr/local/bin/witr`
- Install the man page to `/usr/local/share/man/man1/witr.1`
- Pass INSTALL_PREFIX to override default install path

</details>

#### Windows (PowerShell)

```powershell
irm https://raw.githubusercontent.com/pranshuparmar/witr/main/install.ps1 | iex
```

<details>
<summary>Script Details</summary>

The script will:
- Download the latest release (zip) and verify checksum.
- Extract `witr.exe` to `%LocalAppData%\witr\bin`.
- Add the bin directory to your User `PATH`.

</details>

---

### 2.2 Package Managers

<details>
<summary><strong>Homebrew (macOS & Linux)</strong> <a href="https://formulae.brew.sh/formula/witr"><img src="https://img.shields.io/homebrew/v/witr?style=flat-square" alt="Homebrew"></a></summary>
<br>


You can install **witr** using [Homebrew](https://brew.sh/) on macOS or Linux:

```bash
brew install witr
```
</details>

<details>
<summary><strong>Conda (macOS, Linux & Windows)</strong> <a href="https://anaconda.org/conda-forge/witr"><img src="https://img.shields.io/conda/vn/conda-forge/witr?style=flat-square" alt="Conda"></a></summary>
<br>


You can install **witr** using [conda](https://docs.conda.io/en/latest/), [mamba](https://mamba.readthedocs.io/en/latest/), or [pixi](https://pixi.prefix.dev/latest/) on macOS, Linux, and Windows:

```bash
conda install -c conda-forge witr
# alternatively using mamba
mamba install -c conda-forge witr
# alternatively using pixi
pixi global install witr
```
</details>

<details>
<summary><strong>Arch Linux (AUR)</strong> <a href="https://aur.archlinux.org/packages/witr-bin"><img src="https://img.shields.io/aur/version/witr-bin?style=flat-square" alt="AUR"></a></summary>
<br>


On Arch Linux and derivatives, install from the [AUR package](https://aur.archlinux.org/packages/witr-bin):

```bash
yay -S witr-bin
# alternatively using paru
paru -S witr-bin
# or use your preferred AUR helper
```
</details>

<details>
<summary><strong>Winget (Windows)</strong> <a href="https://winstall.app/apps/PranshuParmar.witr"><img src="https://img.shields.io/winget/v/PranshuParmar.witr?style=flat-square" alt="Winget"></a></summary>
<br>


You can install **witr** via [winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/):

```powershell
winget install -e --id PranshuParmar.witr
```
</details>

<details>
<summary><strong>NPM (Cross-platform)</strong> <a href="https://www.npmjs.com/package/@pranshuparmar/witr"><img src="https://img.shields.io/npm/v/@pranshuparmar/witr?label=npm&color=blue&style=flat-square" alt="NPM"></a></summary>
<br>

You can install **witr** using [npm](https://www.npmjs.com/package/@pranshuparmar/witr):

```bash
npm install -g @pranshuparmar/witr
```
</details>

<details>
<summary><strong>FreeBSD Ports</strong> <a href="https://www.freshports.org/sysutils/witr/"><img src="https://repology.org/badge/version-for-repo/freebsd/witr.svg?style=flat-square" alt="FreeBSD Port"></a></summary>
<br>


You can install **witr** on FreeBSD from the [FreshPorts port](https://www.freshports.org/sysutils/witr/):

```bash
pkg install witr
# or
pkg install sysutils/witr
```

Or build from Ports:

```bash
cd /usr/ports/sysutils/witr/
make install clean
```
</details>

<details>
<summary><strong>Chocolatey (Windows)</strong> <a href="https://community.chocolatey.org/packages/witr"><img src="https://img.shields.io/chocolatey/v/witr?style=flat-square" alt="Chocolatey"></a></summary>

<br>


You can install **witr** using [Chocolatey](https://community.chocolatey.org):

```powershell
choco install witr
```
</details>

<details>
<summary><strong>Scoop (Windows)</strong> <a href="https://scoop.sh/#/apps?q=witr"><img src="https://img.shields.io/scoop/v/witr?bucket=main&style=flat-square" alt="Scoop"></a></summary>
<br>


You can install **witr** using [Scoop](https://scoop.sh):

```powershell
scoop install main/witr
```
</details>

<details>
<summary><strong>AOSC OS</strong> <a href="https://packages.aosc.io/packages/witr"><img src="https://repology.org/badge/version-for-repo/aosc/witr.svg?style=flat-square" alt="AOSC OS"></a></summary>
<br>


You can install **witr** from the [AOSC OS repository](https://packages.aosc.io/packages/witr):

```bash
oma install witr
```
</details>

<details>
<summary><strong>GNU Guix</strong> <a href="https://packages.guix.gnu.org/packages/witr/"><img src="https://repology.org/badge/version-for-repo/gnuguix/witr.svg?style=flat-square" alt="GNU Guix"></a></summary>
<br>


You can install **witr** from the [GNU Guix repository](https://packages.guix.gnu.org/packages/witr/):

```bash
guix install witr
```
</details>

<details>
<summary><strong>Uniget (Linux)</strong> <a href="https://github.com/uniget-org/tools/tree/main/tools/witr"><img src="https://img.shields.io/badge/dynamic/yaml?url=https%3A%2F%2Fraw.githubusercontent.com%2Funiget-org%2Ftools%2Fmain%2Ftools%2Fwitr%2Fmanifest.yaml&query=%24.version&label=uniget&style=flat-square&color=blue" alt="Uniget"></a></summary>
<br>

You can install **witr** using [uniget](https://uniget.dev/):

```bash
uniget install witr
```
</details>

<details>
<summary><strong>Aqua (macOS, Linux & Windows)</strong> <a href="https://github.com/aquaproj/aqua-registry/blob/main/pkgs/pranshuparmar/witr"><img src="https://img.shields.io/badge/dynamic/yaml?url=https%3A%2F%2Fraw.githubusercontent.com%2Faquaproj%2Faqua-registry%2Fmain%2Fpkgs%2Fpranshuparmar%2Fwitr%2Fpkg.yaml&query=%24.packages%5B0%5D.name&label=aqua&style=flat-square&color=blue" alt="Aqua"></a></summary>
<br>

You can install **witr** using [aqua](https://aquaproj.github.io/):

```bash
# Add package
aqua g -i pranshuparmar/witr

# Install package
aqua i pranshuparmar/witr
```
</details>

<details>
<summary><strong>Brioche (Linux)</strong> <a href="https://github.com/brioche-dev/brioche-packages/tree/main/packages/witr"><img src="https://img.shields.io/static/v1?label=brioche&message=v0.3.0&color=blue&style=flat-square" alt="Brioche"></a></summary>
<br>

You can install **witr** using [brioche](https://brioche.dev/):

```bash
brioche install -r witr
```
</details>

<details>
<summary><strong>Prebuilt Packages (deb, rpm, apk)</strong></summary>
<br>

**witr** provides native packages for major Linux distributions. You can download the latest `.deb`, `.rpm`, or `.apk` package from the [GitHub releases page](https://github.com/pranshuparmar/witr/releases/latest).

- Generic download command using `curl`:
  ```bash
  # Replace <package name with the actual package that you need>
  curl -LO https://github.com/pranshuparmar/witr/releases/latest/download/<package-name>
  ```

- **Debian/Ubuntu (.deb):**
  ```bash
  sudo dpkg -i ./witr-*.deb
  # Or, using apt for dependency resolution:
  sudo apt install ./witr-*.deb
  ```
- **Fedora/RHEL/CentOS (.rpm):**
  ```bash
  sudo rpm -i ./witr-*.rpm
  ```
- **Alpine Linux (.apk):**
  ```bash
  sudo apk add --allow-untrusted ./witr-*.apk
  ```
</details>

---

### 2.3 Source & Manual Installation

<details>
<summary><strong>Go (cross-platform)</strong></summary>
<br>

You can install the latest version directly from source:

```bash
go install github.com/pranshuparmar/witr/cmd/witr@latest
```

This will place the `witr` binary in your `$GOPATH/bin` or `$HOME/go/bin` directory. Make sure this directory is in your `PATH`.
</details>

<details>
<summary><strong>Manual Installation</strong></summary>
<br>

If you prefer manual installation, follow these simple steps for your platform:

**Unix (Linux, macOS, FreeBSD)**

```bash
# 1. Determine OS and Architecture
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
[ "$ARCH" = "x86_64" ] && ARCH="amd64"
[ "$ARCH" = "aarch64" ] && ARCH="arm64"

# 2. Download the binary
curl -fsSL "https://github.com/pranshuparmar/witr/releases/latest/download/witr-${OS}-${ARCH}" -o witr

# 3. Verify checksum (Optional)
curl -fsSL "https://github.com/pranshuparmar/witr/releases/latest/download/SHA256SUMS" -o SHA256SUMS
grep "witr-${OS}-${ARCH}" SHA256SUMS | (sha256sum -c - 2>/dev/null || shasum -a 256 -c - 2>/dev/null)
rm SHA256SUMS

# 4. Rename and install
chmod +x witr
sudo mkdir -p /usr/local/bin
sudo mv witr /usr/local/bin/witr

# 5. Install man page (Optional)
sudo mkdir -p /usr/local/share/man/man1
sudo curl -fsSL https://github.com/pranshuparmar/witr/releases/latest/download/witr.1 -o /usr/local/share/man/man1/witr.1
```

**Windows (PowerShell)**

```powershell
# 1. Determine Architecture
if ($env:PROCESSOR_ARCHITECTURE -eq "AMD64") {
    $ZipName = "witr-windows-amd64.zip"
} elseif ($env:PROCESSOR_ARCHITECTURE -eq "ARM64") {
    $ZipName = "witr-windows-arm64.zip"
} else {
    Write-Error "Unsupported architecture: $($env:PROCESSOR_ARCHITECTURE)"
    exit 1
}

# 2. Download the zip
Invoke-WebRequest -Uri "https://github.com/pranshuparmar/witr/releases/latest/download/$ZipName" -OutFile "witr.zip"
# 3. Extract the binary
Expand-Archive -Path "witr.zip" -DestinationPath "." -Force

# 4. Verify checksum (Optional)
Invoke-WebRequest -Uri "https://github.com/pranshuparmar/witr/releases/latest/download/SHA256SUMS" -OutFile "SHA256SUMS"
$hash = Get-FileHash -Algorithm SHA256 .\witr.zip
$expected = Select-String -Path .\SHA256SUMS -Pattern $ZipName
if ($expected -and $hash.Hash.ToLower() -eq $expected.Line.Split(' ')[0]) { Write-Host "Checksum OK" } else { Write-Host "Checksum Mismatch" }

# 5. Install to local bin directory
$InstallDir = "$env:LocalAppData\witr\bin"
New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
Move-Item .\witr.exe $InstallDir\witr.exe -Force

# 6. Add to User Path (Persistent)
$UserPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($UserPath -notlike "*$InstallDir*") {
    [Environment]::SetEnvironmentVariable("Path", "$UserPath;$InstallDir", "User")
    $env:Path += ";$InstallDir"
    Write-Host "Added to Path. You may need to restart PowerShell."
}

# 7. Cleanup
Remove-Item witr.zip
Remove-Item SHA256SUMS
```
</details>

---

### 2.4 Run Without Installation

<details>
<summary><strong>Nix Flake</strong></summary>
<br>

If you use Nix, you can build **witr** from source and run without installation:

```bash
nix run github:pranshuparmar/witr -- --help
```

</details>

<details>
<summary><strong>Pixi</strong></summary>
<br>

If you use [pixi](https://pixi.prefix.dev/latest/), you can run without installation on Linux or macOS:

```bash
pixi exec witr --help
```
</details>

---

### 2.5 Other Operations

<details>
<summary><strong>Verify Installation</strong></summary>
<br>

```bash
witr --version
man witr
```
</details>

<details>
<summary><strong>Shell Completions</strong></summary>
<br>

`witr` supports tab completion for all flags. To enable it, add the appropriate line to your shell configuration:

**Bash**
```bash
echo 'eval "$(witr completion bash)"' >> ~/.bashrc
source ~/.bashrc
```

**Zsh**
```zsh
echo 'eval "$(witr completion zsh)"' >> ~/.zshrc
source ~/.zshrc
```

**Fish**
```fish
witr completion fish | source
# To make it permanent:
witr completion fish > ~/.config/fish/completions/witr.fish
```

**PowerShell**
```powershell
witr completion powershell | Out-String | Invoke-Expression
# To make it permanent, add the above line to your $PROFILE
```
</details>

<details>
<summary><strong>Uninstallation</strong></summary>
<br>

If you installed via a package manager (Homebrew, Conda, etc.), please use the respective uninstall command (e.g., `brew uninstall witr`).

To completely remove script/manual installation of **witr**:

**Unix (Linux, macOS, FreeBSD)**

```bash
sudo rm -f /usr/local/bin/witr
sudo rm -f /usr/local/share/man/man1/witr.1
```

**Windows**

```powershell
Remove-Item -Recurse -Force "$env:LocalAppData\witr"
```
</details>

---
 
## 3. Interactive Mode (TUI)

Running `witr` without any arguments or with the `-i` flag launches the **Interactive Mode (TUI)**. This provides a real-time, terminal-based dashboard for exploring processes and ports.

### Key Features:
- **Live Process List**: Real-time view of all running processes with sorting and filtering.
- **Port View**: Explore open ports and immediately see which processes are holding them.
- **Process Details**: Deep-dive into a specific process to see its full ancestry tree, child processes, environment variables, working directory, and more.
- **Process Actions**: Send signals (Kill, Terminate, Pause, Resume) or Renice processes directly from the UI.
- **Mouse Support**: Navigate, sort columns, and click rows using your mouse.

---

## 4. Flags & Options

```
      --env              show environment variables for the process
  -x, --exact            use exact name matching (no substring search)
  -f, --file strings     file path(s) to find process for (repeatable)
  -h, --help             help for witr
  -i, --interactive      interactive mode (TUI)
      --json             show result as JSON
      --no-color         disable colorized output
  -p, --pid strings      pid(s) to look up (repeatable)
  -o, --port strings     port(s) to look up (repeatable)
  -s, --short            show only ancestry
  -t, --tree             show only ancestry as a tree
      --verbose          show extended process information
  -v, --version          version for witr
      --warnings         show only warnings
```

Positional arguments (without flags) are treated as process or service names. Multiple names can be passed. By default, name matching uses substring matching (fuzzy search). Use `--exact` to match only processes with the exact name.

All target flags (`--pid`, `--port`, `--file`) are repeatable and can be mixed with each other and with positional name arguments. When multiple targets are provided, results are shown sequentially with labeled dividers. All output modes (standard, short, tree, JSON, env, warnings, verbose) work with multiple inputs.

The TUI is launched if no arguments or relevant flags (`--pid`, `--port`, `--file`) are provided, or if the `--interactive` flag is explicitly used.

---

## 5. Example Outputs

### 5.1 Name Based Query

```bash
witr node
```

```
Target      : node

Process     : node (pid 14233)
User        : pm2
Command     : node index.js
Started     : 2 days ago (Mon 2025-02-02 11:42:10 +05:30)
Restarts    : 1

Why It Exists :
  systemd (pid 1) → pm2 (pid 5034) → node (pid 14233)

Source      : pm2

Working Dir : /opt/apps/expense-manager
Git Repo    : expense-manager (main)
Listening   : 127.0.0.1:5001
```

---

### 5.2 Short Output

```bash
witr --port 5000 --short
```

```
systemd (pid 1) → PM2 v5.3.1: God (pid 1481580) → python (pid 1482060)
```

---

### 5.3 Tree Output

```bash
witr --pid 143895 --tree
```

```
systemd (pid 1)
  └─ init-systemd(Ub (pid 2)
    └─ SessionLeader (pid 143858)
      └─ Relay(143860) (pid 143859)
        └─ bash (pid 143860)
          └─ sh (pid 143886)
            └─ node (pid 143895)
              ├─ node (pid 143930)
              ├─ node (pid 144189)
              └─ node (pid 144234)
```

Note: _Tree view includes child processes (up to 10) and highlights the target process._

---

### 5.4 Multiple Matches

```bash
witr ng
```

```
Multiple matching processes found:

[1] nginx (pid 2311)
    nginx -g daemon off;
[2] nginx (pid 24891)
    nginx -g daemon off;
[3] ngrok (pid 14233)
    ngrok http 5000

Re-run with:
  witr --pid <pid>
```

To avoid substring matching and only find processes with an exact name, use the `--exact` flag:

```bash
witr nginx -x
```

---

### 5.5 File Based Query

```bash
witr --file /var/lib/dpkg/lock
```

Explains the process holding a file open.

---

### 5.6 Multiple Inputs

```bash
witr nginx --port 5432 --pid 1234
```

```
----- [name: nginx] -----
Target      : nginx
Process     : nginx (pid 2311)
...

----- [port: 5432] -----
Target      : postgres
Process     : postgres (pid 891)
...

----- [pid: 1234] -----
Target      : node
Process     : node (pid 1234)
...
```

All target flags are repeatable and can be mixed. Results appear in the order you typed them. All output modes (`--short`, `--tree`, `--json`, `--env`, `--warnings`, `--verbose`) work with multiple inputs.

---

## 6. Platform Support

- **Linux** (x86_64, arm64) - Full feature support (`/proc`).
- **macOS** (x86_64, arm64) - Uses `ps`, `lsof`, `sysctl`, `pgrep`.
- **Windows** (x86_64, arm64) - Uses `Get-CimInstance`, `tasklist`, `netstat`.
- **FreeBSD** (x86_64, arm64) - Uses `procstat`, `ps`, `lsof`.

---

### 5.1 Feature Compatibility Matrix

| Feature | Linux | macOS | Windows | FreeBSD | Notes |
|---------|:-----:|:-----:|:-------:|:-------:|-------|
| **Process Selection** |
| By Name | ✅ | ✅ | ✅ | ✅ | |
| By PID | ✅ | ✅ | ✅ | ✅ | |
| By Port | ✅ | ✅ | ✅ | ✅ | |
| By File | ✅ | ✅ | ❌ | ✅ | |
| Multiple/mixed inputs | ✅ | ✅ | ✅ | ✅ | Repeatable flags, mixed types. |
| Exact Match | ✅ | ✅ | ✅ | ✅ | |
| Full command line | ✅ | ✅ | ✅ | ✅ | |
| Process start time | ✅ | ✅ | ✅ | ✅ | |
| Working directory | ✅ | ✅ | ✅ | ✅ | |
| Environment variables | ✅ | ⚠️ | ❌ | ✅ | macOS: Partial support due to SIP restrictions. |
| **Network** |
| Listening ports | ✅ | ✅ | ✅ | ✅ | |
| Bind addresses | ✅ | ✅ | ✅ | ✅ | |
| Port → PID resolution | ✅ | ✅ | ✅ | ✅ | |
| **Service Detection** |
| Service Manager | ✅ | ✅ | ✅ | ✅ | Linux: systemd, macOS: launchd, Windows: Services, FreeBSD: rc.d |
| Service Description | ✅ | ✅ | ✅ | ✅ | Linux: `Description`, macOS: `Comment`, Windows: `Display Name`, FreeBSD: `rc` header |
| Configuration Source | ✅ | ✅ | ✅ | ✅ | Linux: Unit File, macOS: Plist, Windows: Registry Key, FreeBSD: Rc Script |
| Supervisor | ✅ | ✅ | ✅ | ✅ | |
| Containers | ✅ | ✅ | ✅ | ✅ | Docker (plus Compose mappings), Podman, K8s (Kubepods), Containerd. Colima on macOS/Linux. Jails on FreeBSD. |
| SSH session detection | ✅ | ✅ | ✅ | ✅ | Detects remote IP and terminal. |
| tmux/screen detection | ✅ | ✅ | ❌ | ✅ | Shows session name in source. |
| Schedule detection | ✅ | ✅ | ❌ | ❌ | Linux: systemd timers, macOS: launchd intervals/calendar. |
| Snap/Flatpak detection | ✅ | ❌ | ❌ | ❌ | |
| **Health & Diagnostics** |
| CPU usage detection | ✅ | ✅ | ✅ | ✅ | |
| Memory usage detection | ✅ | ✅ | ✅ | ✅ | |
| Health status detection | ✅ | ✅ | ✅ | ✅ | |
| Open Files / Handles | ✅ | ✅ | ⚠️ | ✅ | Windows: count only. |
| Deleted binary detection | ✅ | ✅ | ✅ | ✅ | Warns if executable is missing. |
| Capability warnings | ✅ | ❌ | ❌ | ❌ | Warns about dangerous capabilities on non-root processes. |
| **Context** |
| Git repo/branch detection | ✅ | ✅ | ✅ | ✅ | |
| **Interactive Mode (TUI)** |
| Process Dashboard | ✅ | ✅ | ✅ | ✅ | |
| Port Dashboard | ✅ | ✅ | ✅ | ✅ | |
| Process Details | ✅ | ✅ | ✅ | ✅ | |
| Process Actions | ✅ | ✅ | ❌ | ✅ | |

**Legend:** ✅ Full support | ⚠️ Partial/limited support | ❌ Not available

---

### 5.2 Permissions Note

#### Linux/FreeBSD

witr inspects system directories which may require elevated permissions.

If you are not seeing the expected information, try running witr with sudo:

```bash
sudo witr [your arguments]
```

#### macOS

On macOS, witr uses `ps`, `lsof`, and `launchctl` to gather process information. Some operations may require elevated permissions:

```bash
sudo witr [your arguments]
```

Note: Due to macOS System Integrity Protection (SIP), some system process details may not be accessible even with sudo.

#### Windows

On Windows, witr uses `Get-CimInstance`, `tasklist`, and `netstat`. To see details for processes owned by other users or system services, you must run the terminal as **Administrator**.

```powershell
# Run in Administrator PowerShell
.\witr.exe [your arguments]
```

---

## 7. Goals

### Primary goals

- Explain **why a process exists**, not just that it exists
- Reduce time‑to‑understanding during debugging and outages
- Work with zero configuration
- Be safe, read‑only, and non‑destructive
- Prefer clarity over completeness

### Non‑goals

- Not a monitoring tool
- Not a performance profiler
- Not a replacement for systemd/docker tooling
- Not a remediation or auto‑fix tool

---

## 8. Core Concept

witr treats **everything as a process question**.

Ports, services, containers, and commands all eventually map to **PIDs**. Once a PID is identified, witr builds a causal chain explaining _why that PID exists_.

At its core, witr answers:

1. What is running?
2. How did it start?
3. What is keeping it running?
4. What context does it belong to?

---

## 9. Output Behavior

### 9.1 Output Principles

- Single screen by default (best effort)
- Deterministic ordering
- Narrative-style explanation
- Best-effort detection with explicit uncertainty

---

### 9.2 Exit Codes

witr returns meaningful exit codes for use in scripts, CI pipelines, and monitoring:

| Code | Meaning |
|------|---------|
| 0 | Clean: process found, no warnings |
| 1 | Warnings: process found but has one or more warnings |
| 2 | Not found: no matching process or service |
| 3 | Permission denied: insufficient privileges |
| 4 | Invalid input: bad arguments or ambiguous match |

#### Example Usage:

```bash
witr nginx --short
case $? in
  0) echo "All clear" ;;
  1) echo "Warnings detected" ;;
  2) echo "Process not running" ;;
  3) echo "Need elevated privileges" ;;
  4) echo "Invalid input or ambiguous match" ;;
esac
```

---

### 9.3 Standard Output Sections

#### Target

What the user asked about.

#### Process

Executable, PID, user, command, start time and restart count.

#### Why It Exists

A causal ancestry chain showing how the process came to exist.
This is the core value of witr.

#### Source

The primary system responsible for starting or supervising the process (best effort).

Examples:

- systemd unit with schedule info for timer-triggered services (Linux)
- launchd service with schedule/trigger details (macOS)
- SSH session (with remote IP and terminal)
- docker container
- pm2
- cron
- interactive shell (detects tmux/screen sessions)
- Snap/Flatpak sandbox (Linux)

Only **one primary source** is selected.

#### Context (best effort)

- Working directory
- Git repository name and branch
- Container name / image (docker, podman, kubernetes, colima, containerd)
- Public vs private bind

#### Warnings

Non‑blocking observations such as:

- Process is running as root
- Dangerous Linux capabilities on non-root processes (CAP_SYS_ADMIN, etc.)
- Process is listening on a public interface (0.0.0.0 / ::)
- Restarted multiple times (warning only if above threshold)
- Process is using high memory (>1GB RSS)
- Process has been running for over 90 days
- Deleted binary, library injection indicators (LD_PRELOAD, DYLD_*)

---

## 10. Success Criteria

witr is successful if:

- A user can answer "why is this running?" within seconds
- It reduces reliance on multiple tools
- Output is understandable under stress
- Users trust it during incidents

---

## 11. Sponsors

Special thanks to the people supporting **witr** ❤️

<p>
  <a href="https://github.com/timcolson" title="Tim Colson">
    <img src="https://images.weserv.nl/?url=github.com/timcolson.png&mask=circle&w=80&h=80" width="80">
  </a>
</p>


================================================
FILE: SECURITY.md
================================================
# Security Policy

## Supported Versions

We currently support the following versions of **witr** with security updates:

| OS | Supported |
| ------- | --------- |
| macOS   | :white_check_mark: |
| Linux   | :white_check_mark: |
| Windows | :x: |

See our [Feature Compatibility Matrix](README.md#91-feature-compatibility-matrix) for more details.

## Reporting a Vulnerability

We take the security of **witr** seriously. If you believe you have found a security vulnerability, please report it to us responsibly.

**How to report:**

Use the "Report a vulnerability" button in the repository’s [Security](https://github.com/pranshuparmar/witr/security) tab on GitHub to submit your report privately. Only maintainers and the reporter will see the submission.

**What to include in your report:**

- A description of the vulnerability.
- Steps to reproduce the issue (including any sample code or configuration).
- Potential impact of the vulnerability.
- Any suggested mitigations or fixes.

## Our Response Process

1. **Acknowledgment**: We will acknowledge receipt of your report within 48 hours.
2. **Investigation**: We will investigate the report and determine the severity and impact.
3. **Fix**: If a vulnerability is confirmed, we will work on a fix and release a new version as soon as possible.
4. **Disclosure**: We will coordinate the disclosure of the vulnerability with you to ensure that users have time to update.

## Attribution

This security policy is based on standard open-source practices.


================================================
FILE: cmd/witr/main.go
================================================
//go:build linux || darwin || freebsd || windows

//go:generate go run ../../internal/tools/docgen -format man -out ../../docs/cli
//go:generate go run ../../internal/tools/docgen -format markdown -out ../../docs/cli

package main

import (
	"github.com/pranshuparmar/witr/internal/app"
	"github.com/pranshuparmar/witr/internal/version"
)

// Override version at build time with ldflags:
//   go build -ldflags "-X github.com/pranshuparmar/witr/internal/version.Version=v0.3.0 -X github.com/pranshuparmar/witr/internal/version.Commit=$(git rev-parse --short HEAD) -X 'github.com/pranshuparmar/witr/internal/version.BuildDate=$(date +%Y-%m-%d)'" -o witr ./cmd/witr

func main() {
	app.SetVersion(version.Version, version.Commit, version.BuildDate)
	app.Execute()
}


================================================
FILE: cmd/witr/unsupported.go
================================================
//go:build !linux && !darwin && !freebsd && !windows

package main

import (
	"fmt"
	"os"
)

func main() {
	fmt.Fprintln(
		os.Stderr,
		"witr is only supported on Linux, macOS, Windows, and FreeBSD.\n\nIf you are seeing this message, you are attempting to build or run witr on an unsupported platform.\n\nPlease use Linux, macOS, Windows, or FreeBSD to build and run witr.",
	)
	os.Exit(1)
}


================================================
FILE: docs/cli/witr.1
================================================
.nh
.TH "WITR" "1" "Mar 2026" "" ""

.SH NAME
witr - Why is this running?


.SH SYNOPSIS
\fBwitr [process name...] [flags]\fP


.SH DESCRIPTION
witr explains why a process or port is running by tracing its ancestry.


.SH OPTIONS
\fB--env\fP[=false]
	show environment variables for the process

.PP
\fB-x\fP, \fB--exact\fP[=false]
	use exact name matching (no substring search)

.PP
\fB-f\fP, \fB--file\fP=[]
	file path(s) to find process for (repeatable)

.PP
\fB-h\fP, \fB--help\fP[=false]
	help for witr

.PP
\fB-i\fP, \fB--interactive\fP[=false]
	interactive mode (TUI)

.PP
\fB--json\fP[=false]
	show result as JSON

.PP
\fB--no-color\fP[=false]
	disable colorized output

.PP
\fB-p\fP, \fB--pid\fP=[]
	pid(s) to look up (repeatable)

.PP
\fB-o\fP, \fB--port\fP=[]
	port(s) to look up (repeatable)

.PP
\fB-s\fP, \fB--short\fP[=false]
	show only ancestry

.PP
\fB-t\fP, \fB--tree\fP[=false]
	show only ancestry as a tree

.PP
\fB--verbose\fP[=false]
	show extended process information

.PP
\fB--warnings\fP[=false]
	show only warnings


.SH EXAMPLE
.EX

  # Inspect a running process by name
  witr nginx

  # Look up a process by PID
  witr --pid 1234

  # Find the process listening on a specific port
  witr --port 5432

  # Find the process holding a lock on a file
  witr --file /var/lib/dpkg/lock

  # Inspect a process by name with exact matching (no fuzzy search)
  witr bun --exact

  # Show the full process ancestry (who started whom)
  witr postgres --tree

  # Show only warnings (suspicious env, arguments, parents)
  witr docker --warnings

  # Display only environment variables of the process
  witr node --env

  # Short, single-line output (useful for scripts)
  witr sshd --short

  # Disable colorized output (CI or piping)
  witr redis --no-color

  # Output machine-readable JSON
  witr chrome --json

  # Show extended process information (memory, I/O, file descriptors)
  witr mysql --verbose

  # Combine flags: inspect port, show environment variables, output JSON
  witr --port 8080 --env --json

  # Multiple inputs
  witr nginx node
  witr --port 8080 --port 3000
  witr --pid 1234 --pid 5678

  # Mixed inputs
  witr nginx --pid 1234 --port 8080

.EE


================================================
FILE: docs/cli/witr.md
================================================
## witr

Why is this running?

### Synopsis

witr explains why a process or port is running by tracing its ancestry.

```
witr [process name...] [flags]
```

### Examples

```

  # Inspect a running process by name
  witr nginx

  # Look up a process by PID
  witr --pid 1234

  # Find the process listening on a specific port
  witr --port 5432

  # Find the process holding a lock on a file
  witr --file /var/lib/dpkg/lock

  # Inspect a process by name with exact matching (no fuzzy search)
  witr bun --exact

  # Show the full process ancestry (who started whom)
  witr postgres --tree

  # Show only warnings (suspicious env, arguments, parents)
  witr docker --warnings

  # Display only environment variables of the process
  witr node --env

  # Short, single-line output (useful for scripts)
  witr sshd --short

  # Disable colorized output (CI or piping)
  witr redis --no-color

  # Output machine-readable JSON
  witr chrome --json

  # Show extended process information (memory, I/O, file descriptors)
  witr mysql --verbose

  # Combine flags: inspect port, show environment variables, output JSON
  witr --port 8080 --env --json

  # Multiple inputs
  witr nginx node
  witr --port 8080 --port 3000
  witr --pid 1234 --pid 5678

  # Mixed inputs
  witr nginx --pid 1234 --port 8080

```

### Options

```
      --env            show environment variables for the process
  -x, --exact          use exact name matching (no substring search)
  -f, --file strings   file path(s) to find process for (repeatable)
  -h, --help           help for witr
  -i, --interactive    interactive mode (TUI)
      --json           show result as JSON
      --no-color       disable colorized output
  -p, --pid strings    pid(s) to look up (repeatable)
  -o, --port strings   port(s) to look up (repeatable)
  -s, --short          show only ancestry
  -t, --tree           show only ancestry as a tree
      --verbose        show extended process information
      --warnings       show only warnings
```



================================================
FILE: flake.nix
================================================
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
  };
  outputs =
    {
      self,
      nixpkgs,
    }:
    let
      inherit (nixpkgs) lib;
    in
    {
      packages = lib.genAttrs [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ] (
        system:
        let
          pkgs = nixpkgs.legacyPackages.${system};
          version = if self ? rev then "git-${builtins.substring 0 7 self.rev}" else "dirty";
          commit = self.rev or "dirty";
          buildDate = pkgs.lib.concatStringsSep "-" [
            (builtins.substring 0 4 self.lastModifiedDate)
            (builtins.substring 4 2 self.lastModifiedDate)
            (builtins.substring 6 2 self.lastModifiedDate)
          ];
        in
        {
          default = pkgs.buildGoModule {
            pname = "witr";
            inherit version;
            src = lib.cleanSourceWith {
              src = ./.;
              filter =
                path: _:
                let
                  pathRelative = lib.removePrefix (toString ./.) (toString path);
                in
                builtins.any (p: lib.hasPrefix p pathRelative) [
                  "/go.mod"
                  "/internal"
                  "/pkg"
                  "/cmd"
                  "/doc"
                  "/vendor"
                ];
            };

            vendorHash = null;
            ldflags = [
              "-X github.com/pranshuparmar/witr/internal/version.Version=v${version}"
              "-X github.com/pranshuparmar/witr/internal/version.Commit=${commit}"
              "-X github.com/pranshuparmar/witr/internal/version.BuildDate=${buildDate}"
            ];

            nativeBuildInputs = [ pkgs.installShellFiles ];
            postInstall = ''
              installManPage ./doc/witr.*
            '';

            meta = {
              description = "Why is this running?";
              homepage = "https://github.com/pranshuparmar/witr";
              license = lib.licenses.asl20;
            };
          };
        }
      );

      formatter = lib.genAttrs [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ] (
        system: nixpkgs.legacyPackages.${system}.nixpkgs-fmt
      );

      apps = lib.genAttrs [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ] (system: {
        default = {
          type = "app";
          program = "${self.packages.${system}.default}/bin/witr";
        };
      });
    };
}


================================================
FILE: go.mod
================================================
module github.com/pranshuparmar/witr

go 1.25

require (
	github.com/charmbracelet/bubbles v1.0.0
	github.com/charmbracelet/bubbletea v1.3.10
	github.com/charmbracelet/lipgloss v1.1.0
	github.com/muesli/reflow v0.3.1-0.20230316100924-83f637991171
	github.com/spf13/cobra v1.10.2
)

require (
	github.com/atotto/clipboard v0.1.4 // indirect
	github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
	github.com/charmbracelet/colorprofile v0.4.1 // indirect
	github.com/charmbracelet/x/ansi v0.11.6 // indirect
	github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
	github.com/charmbracelet/x/term v0.2.2 // indirect
	github.com/clipperhouse/displaywidth v0.9.0 // indirect
	github.com/clipperhouse/stringish v0.1.1 // indirect
	github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
	github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
	github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
	github.com/inconshreveable/mousetrap v1.1.0 // indirect
	github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
	github.com/mattn/go-isatty v0.0.20 // indirect
	github.com/mattn/go-localereader v0.0.1 // indirect
	github.com/mattn/go-runewidth v0.0.19 // indirect
	github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
	github.com/muesli/cancelreader v0.2.2 // indirect
	github.com/muesli/termenv v0.16.0 // indirect
	github.com/rivo/uniseg v0.4.7 // indirect
	github.com/russross/blackfriday/v2 v2.1.0 // indirect
	github.com/spf13/pflag v1.0.10 // indirect
	github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
	go.yaml.in/yaml/v3 v3.0.4 // indirect
	golang.org/x/sys v0.38.0 // indirect
	golang.org/x/text v0.3.8 // indirect
)


================================================
FILE: go.sum
================================================
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY=
github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E=
github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc=
github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E=
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk=
github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk=
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8=
github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI=
github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q=
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ=
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA=
github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA=
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U=
github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/reflow v0.3.1-0.20230316100924-83f637991171 h1:twNwyBIUfWPxvaSS8yMYkJLlGO62pp09YhLND+MojXo=
github.com/muesli/reflow v0.3.1-0.20230316100924-83f637991171/go.mod h1:mEMWZ0nzoGlTCHkXp5ljOWhHi1tjvtDGh7wuT1Thhsk=
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=


================================================
FILE: install.ps1
================================================
$ErrorActionPreference = "Stop"

$Repo = "pranshuparmar/witr"
$InstallDir = Join-Path $env:LOCALAPPDATA "witr\bin"
$UserPath = [Environment]::GetEnvironmentVariable("Path", "User")

Write-Host "Installing witr..."

# 1. Get Latest Tag
Write-Host "Fetching latest version..."
$LatestUrl = "https://api.github.com/repos/$Repo/releases/latest"
try {
    $LatestJson = Invoke-RestMethod -Uri $LatestUrl
    $LatestTag = $LatestJson.tag_name
} catch {
    Write-Error "Failed to fetch latest release version. check internet connection."
    exit 1
}
Write-Host "Detected latest version: $LatestTag"

# 2. Setup Paths
if ($env:PROCESSOR_ARCHITECTURE -eq "AMD64") {
    $ZipName = "witr-windows-amd64.zip"
} elseif ($env:PROCESSOR_ARCHITECTURE -eq "ARM64") {
    $ZipName = "witr-windows-arm64.zip"
} else {
    Write-Error "Unsupported architecture: $($env:PROCESSOR_ARCHITECTURE)"
    exit 1
}
Write-Host "Detected Architecture: $($env:PROCESSOR_ARCHITECTURE)"
$DownloadUrl = "https://github.com/$Repo/releases/download/$LatestTag/$ZipName"
$ChecksumUrl = "https://github.com/$Repo/releases/download/$LatestTag/SHA256SUMS"
$TempDir = [System.IO.Path]::GetTempPath()
$ZipPath = Join-Path $TempDir $ZipName
$ChecksumPath = Join-Path $TempDir "SHA256SUMS"

# 3. Download
Write-Host "Downloading $DownloadUrl..."
Invoke-WebRequest -Uri $DownloadUrl -OutFile $ZipPath
Invoke-WebRequest -Uri $ChecksumUrl -OutFile $ChecksumPath

# 4. Verify Checksum
Write-Host "Verifying checksum..."
$Hash = Get-FileHash -Algorithm SHA256 $ZipPath
$ExpectedLine = Select-String -Path $ChecksumPath -Pattern $ZipName
if (-not $ExpectedLine) {
    Write-Error "Checksum verification failed: could not find $ZipName in SHA256SUMS"
    Remove-Item $ZipPath, $ChecksumPath -ErrorAction SilentlyContinue
    exit 1
}
$ExpectedHash = $ExpectedLine.Line.Split(' ')[0].Trim()

if ($Hash.Hash.ToLower() -ne $ExpectedHash.ToLower()) {
    Write-Error "Checksum mismatch!`nExpected: $ExpectedHash`nActual:   $($Hash.Hash)"
    Remove-Item $ZipPath, $ChecksumPath -ErrorAction SilentlyContinue
    exit 1
}
Write-Host "Checksum verified."

# 5. Extract/Install
if (-not (Test-Path $InstallDir)) {
    New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
}

Write-Host "Extracting to $InstallDir..."
Expand-Archive -Path $ZipPath -DestinationPath $InstallDir -Force

# Cleanup downloads
Remove-Item $ZipPath, $ChecksumPath -ErrorAction SilentlyContinue

# 6. Update PATH
if ($UserPath -notlike "*$InstallDir*") {
    Write-Host "Adding $InstallDir to User Path..."
    $NewPath = "$UserPath;$InstallDir" 
    [Environment]::SetEnvironmentVariable("Path", $NewPath, "User")
    $env:Path += ";$InstallDir"
    Write-Host "Path updated. You may need to restart your shell."
} else {
    Write-Host "Install directory already in Path."
}

Write-Host "`nwitr ($LatestTag) installed successfully!"
Write-Host "Try running: witr --help"


================================================
FILE: install.sh
================================================
#!/usr/bin/env bash
# Installs the latest release of witr from GitHub
# Repo: https://github.com/pranshuparmar/witr

set -euo pipefail

REPO="pranshuparmar/witr"

# Standard configurable install prefix (override to avoid sudo):
#   INSTALL_PREFIX="$HOME/.local" ./install.sh
INSTALL_PREFIX="${INSTALL_PREFIX:=/usr/local}"

INSTALL_PATH="$INSTALL_PREFIX/bin/witr"
MAN_PATH="$INSTALL_PREFIX/share/man/man1/witr.1"

# Detect OS
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$OS" in
    linux)
        OS=linux
        ;;
    darwin)
        OS=darwin
        ;;
    freebsd)
        OS=freebsd
        ;;
    *)
        echo "Unsupported OS: $OS" >&2
        exit 1
        ;;
esac


# Detect Architecture
ARCH=$(uname -m)
case "$ARCH" in
    x86_64|amd64)
        ARCH=amd64
        ;;
    aarch64|arm64)
        ARCH=arm64
        ;;
    *)
        echo "Unsupported architecture: $ARCH" >&2
        exit 1
        ;;
esac

# Ensure required tools exist
for cmd in curl install; do
  if ! command -v "$cmd" >/dev/null 2>&1; then
    echo "Missing required command: $cmd"
    exit 1
  fi
done

# Get latest release tag from GitHub API
LATEST=$(curl -fsSL "https://api.github.com/repos/$REPO/releases/latest" | grep '"tag_name"' | cut -d '"' -f4)
if [[ -z "$LATEST" ]]; then
    echo "Could not determine latest release tag." >&2
    exit 1
fi

# Construct download URL
URL="https://github.com/$REPO/releases/download/$LATEST/witr-$OS-$ARCH"
TMP=$(mktemp)
MANURL="https://github.com/$REPO/releases/download/$LATEST/witr.1"
MAN_TMP=$(mktemp)

# Cleanup on exit
cleanup() {
    rm -f "${TMP:-}" "${MAN_TMP:-}"
}
trap cleanup EXIT

# Download release
curl -fL "$URL" -o "$TMP"
curl -fL "$MANURL" -o "$MAN_TMP"

INSTALL_BIN_DIR=$(dirname "$INSTALL_PATH")
INSTALL_MAN_DIR=$(dirname "$MAN_PATH")

# Decide whether we need sudo (based on whether we can write to the target dirs)
need_sudo=0
if ! mkdir -p "$INSTALL_BIN_DIR" 2>/dev/null; then need_sudo=1; fi
if ! mkdir -p "$INSTALL_MAN_DIR" 2>/dev/null; then need_sudo=1; fi
if [[ "$need_sudo" == "0" ]]; then
    [[ -w "$INSTALL_BIN_DIR" ]] || need_sudo=1
    [[ -w "$INSTALL_MAN_DIR" ]] || need_sudo=1
fi

SUDO=()
if [[ "$need_sudo" == "1" ]]; then
    # checking for sudo because alpine using doas and people like me started to use run0
    if command -v sudo >/dev/null 2>&1; then
        # echo "sudo is available"
        SUDO=(sudo)
    elif command -v doas >/dev/null 2>&1; then
        # echo "doas is available"
        SUDO=(doas)
    elif command -v run0 >/dev/null 2>&1; then
        # echo "run0 is available"
        SUDO=(run0)
    fi

fi

# Install
${SUDO[@]+"${SUDO[@]}"} install -m 755 "$TMP" "$INSTALL_PATH"

# Install man page
${SUDO[@]+"${SUDO[@]}"} mkdir -p "$INSTALL_MAN_DIR"
${SUDO[@]+"${SUDO[@]}"} install -m 644 "$MAN_TMP" "$MAN_PATH"
echo "witr installed successfully to $INSTALL_PATH (version: $LATEST, os: $OS, arch: $ARCH)"
echo "Man page installed to $MAN_PATH"


================================================
FILE: internal/app/app.go
================================================
//go:build linux || darwin || freebsd || windows

package app

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"

	"github.com/pranshuparmar/witr/internal/output"
	"github.com/pranshuparmar/witr/internal/pipeline"
	procpkg "github.com/pranshuparmar/witr/internal/proc"
	"github.com/pranshuparmar/witr/internal/source"
	"github.com/pranshuparmar/witr/internal/target"
	"github.com/pranshuparmar/witr/internal/tui"
	"github.com/pranshuparmar/witr/pkg/model"
	"github.com/spf13/cobra"
)

var (
	version   = "v0.0.0-dev"
	commit    = "unknown"
	buildDate = "unknown"
)

var rootCmd = &cobra.Command{
	Use:   "witr [process name...]",
	Short: "Why is this running?",
	Long:  "witr explains why a process or port is running by tracing its ancestry.",
	Args:  cobra.ArbitraryArgs,
	CompletionOptions: cobra.CompletionOptions{
		HiddenDefaultCmd:  false,
		DisableDefaultCmd: false,
		DisableNoDescFlag: false,
	},
	Example: _genExamples(),
	RunE:    runApp,
}

func _genExamples() string {

	return `
  # Inspect a running process by name
  witr nginx

  # Look up a process by PID
  witr --pid 1234

  # Find the process listening on a specific port
  witr --port 5432

  # Find the process holding a lock on a file
  witr --file /var/lib/dpkg/lock

  # Inspect a process by name with exact matching (no fuzzy search)
  witr bun --exact

  # Show the full process ancestry (who started whom)
  witr postgres --tree

  # Show only warnings (suspicious env, arguments, parents)
  witr docker --warnings

  # Display only environment variables of the process
  witr node --env

  # Short, single-line output (useful for scripts)
  witr sshd --short

  # Disable colorized output (CI or piping)
  witr redis --no-color

  # Output machine-readable JSON
  witr chrome --json

  # Show extended process information (memory, I/O, file descriptors)
  witr mysql --verbose

  # Combine flags: inspect port, show environment variables, output JSON
  witr --port 8080 --env --json

  # Multiple inputs
  witr nginx node
  witr --port 8080 --port 3000
  witr --pid 1234 --pid 5678

  # Mixed inputs
  witr nginx --pid 1234 --port 8080
`
}

// Exit codes
const (
	ExitOK            = 0
	ExitWarnings      = 1
	ExitInternalError = 1
	ExitNotFound      = 2
	ExitPermission    = 3
	ExitInvalidInput  = 4
)

// exitCodeError wraps an error with a specific exit code.
type exitCodeError struct {
	code int
	err  error
}

func (e *exitCodeError) Error() string { return e.err.Error() }
func (e *exitCodeError) Unwrap() error { return e.err }

func withExitCode(code int, err error) error {
	return &exitCodeError{code: code, err: err}
}

func Execute() {
	err := rootCmd.Execute()
	if err == nil {
		return
	}

	var ece *exitCodeError
	if errors.As(err, &ece) {
		os.Exit(ece.code)
	}
	os.Exit(1)
}

func init() {
	rootCmd.InitDefaultCompletionCmd()
	rootCmd.Version = version
	rootCmd.SetVersionTemplate(fmt.Sprintf("witr {{.Version}} (commit %s, built %s)\n", commit, buildDate))
	rootCmd.SetErr(output.NewSafeTerminalWriter(os.Stderr))

	rootCmd.Flags().StringSliceP("pid", "p", nil, "pid(s) to look up (repeatable)")
	rootCmd.Flags().StringSliceP("port", "o", nil, "port(s) to look up (repeatable)")
	rootCmd.Flags().StringSliceP("file", "f", nil, "file path(s) to find process for (repeatable)")
	rootCmd.Flags().BoolP("short", "s", false, "show only ancestry")
	rootCmd.Flags().BoolP("tree", "t", false, "show only ancestry as a tree")
	rootCmd.Flags().Bool("json", false, "show result as JSON")
	rootCmd.Flags().Bool("warnings", false, "show only warnings")
	rootCmd.Flags().Bool("no-color", false, "disable colorized output")
	rootCmd.Flags().Bool("env", false, "show environment variables for the process")
	rootCmd.Flags().Bool("verbose", false, "show extended process information")
	rootCmd.Flags().BoolP("exact", "x", false, "use exact name matching (no substring search)")
	rootCmd.Flags().BoolP("interactive", "i", false, "interactive mode (TUI)")

}

// appFlags holds all parsed CLI flags for convenience.
type appFlags struct {
	short   bool
	tree    bool
	json    bool
	warn    bool
	noColor bool
	verbose bool
	exact   bool
	env     bool
}

func runApp(cmd *cobra.Command, args []string) error {
	interactiveFlag, _ := cmd.Flags().GetBool("interactive")
	if interactiveFlag {
		return runInteractive()
	}

	envFlag, _ := cmd.Flags().GetBool("env")
	pidFlags, _ := cmd.Flags().GetStringSlice("pid")
	portFlags, _ := cmd.Flags().GetStringSlice("port")
	fileFlags, _ := cmd.Flags().GetStringSlice("file")

	// Default to interactive mode if no arguments or relevant flags are provided
	if !envFlag && len(pidFlags) == 0 && len(portFlags) == 0 && len(fileFlags) == 0 && len(args) == 0 {
		return runInteractive()
	}

	flags := appFlags{
		env:     envFlag,
		exact:   boolFlag(cmd, "exact"),
		short:   boolFlag(cmd, "short"),
		tree:    boolFlag(cmd, "tree"),
		json:    boolFlag(cmd, "json"),
		warn:    boolFlag(cmd, "warnings"),
		noColor: boolFlag(cmd, "no-color"),
		verbose: boolFlag(cmd, "verbose"),
	}

	// Collect all targets preserving command-line order
	targets := collectTargetsInOrder(os.Args[1:], args)

	if len(targets) == 0 {
		return withExitCode(ExitInvalidInput, fmt.Errorf("must specify --pid, --port, --file, or a process name"))
	}

	outw := cmd.OutOrStdout()
	outp := output.NewPrinter(outw)
	multiMode := len(targets) > 1
	colorEnabled := !flags.noColor

	// For JSON multi-output, collect all JSON strings and wrap in array
	var jsonResults []string
	highestExit := ExitOK

	for i, t := range targets {
		if multiMode && !flags.json {
			printDivider(outp, t, colorEnabled, i > 0)
		}

		exitCode := processTarget(cmd, outw, outp, t, flags, multiMode, &jsonResults)
		if exitCode > highestExit {
			highestExit = exitCode
		}
	}

	// Emit JSON array for multi-target
	if flags.json && multiMode {
		indented := make([]string, len(jsonResults))
		for i, r := range jsonResults {
			lines := strings.Split(r, "\n")
			for j := range lines {
				if j > 0 {
					lines[j] = "  " + lines[j]
				}
			}
			indented[i] = "  " + strings.Join(lines, "\n")
		}
		fmt.Fprintf(outw, "[\n%s\n]\n", strings.Join(indented, ",\n"))
	}

	if highestExit > ExitOK {
		cmd.SilenceErrors = true
		return withExitCode(highestExit, fmt.Errorf("completed with exit code %d", highestExit))
	}
	return nil
}

func boolFlag(cmd *cobra.Command, name string) bool {
	v, _ := cmd.Flags().GetBool(name)
	return v
}

// collectTargetsInOrder walks the raw command-line arguments to build a target
// list that preserves the order the user typed them in.
func collectTargetsInOrder(rawArgs []string, positionalArgs []string) []model.Target {
	var targets []model.Target
	positionalIdx := 0

	// Map flag names to target types
	flagType := map[string]model.TargetType{
		"-p": model.TargetPID, "--pid": model.TargetPID,
		"-o": model.TargetPort, "--port": model.TargetPort,
		"-f": model.TargetFile, "--file": model.TargetFile,
	}

	// Track which positional args we've placed so we can insert them in order
	// between flag-based targets
	i := 0
	for i < len(rawArgs) {
		arg := rawArgs[i]

		// Check for --flag=value form
		if strings.HasPrefix(arg, "--") {
			if eqIdx := strings.Index(arg, "="); eqIdx >= 0 {
				flagName := arg[:eqIdx]
				flagVal := arg[eqIdx+1:]
				if tt, ok := flagType[flagName]; ok {
					for _, v := range strings.Split(flagVal, ",") {
						v = strings.TrimSpace(v)
						if v != "" {
							targets = append(targets, model.Target{Type: tt, Value: v})
						}
					}
				}
				i++
				continue
			}
		}

		// Check for -f value or --flag value form
		if tt, ok := flagType[arg]; ok {
			if i+1 < len(rawArgs) {
				i++
				for _, v := range strings.Split(rawArgs[i], ",") {
					v = strings.TrimSpace(v)
					if v != "" {
						targets = append(targets, model.Target{Type: tt, Value: v})
					}
				}
			}
			i++
			continue
		}

		// Skip known boolean flags and their short forms
		if strings.HasPrefix(arg, "-") {
			i++
			continue
		}

		// Positional argument — use it as a name target
		if positionalIdx < len(positionalArgs) {
			targets = append(targets, model.Target{Type: model.TargetName, Value: positionalArgs[positionalIdx]})
			positionalIdx++
		}
		i++
	}

	// Append any remaining positional args that weren't matched
	for positionalIdx < len(positionalArgs) {
		targets = append(targets, model.Target{Type: model.TargetName, Value: positionalArgs[positionalIdx]})
		positionalIdx++
	}

	return targets
}

// targetLabel returns a human-readable label for the divider.
func targetLabel(t model.Target) string {
	switch t.Type {
	case model.TargetPID:
		return fmt.Sprintf("pid: %s", t.Value)
	case model.TargetPort:
		return fmt.Sprintf("port: %s", t.Value)
	case model.TargetFile:
		return fmt.Sprintf("file: %s", t.Value)
	default:
		return fmt.Sprintf("name: %s", t.Value)
	}
}

func printDivider(outp output.Printer, t model.Target, colorEnabled bool, needsNewline bool) {
	label := targetLabel(t)
	if needsNewline {
		outp.Println()
	}
	if colorEnabled {
		outp.Printf("%s----- [%s] -----%s\n", output.ColorCyan, label, output.ColorReset)
	} else {
		outp.Printf("----- [%s] -----\n", label)
	}
}

// jsonErrorEntry returns a JSON string representing a failed target lookup.
func jsonErrorEntry(t model.Target, errMsg string) string {
	type errorEntry struct {
		Target model.Target
		Error  string
	}
	data, _ := json.MarshalIndent(errorEntry{Error: errMsg, Target: t}, "", "  ")
	return string(data)
}

// processTarget handles resolving and rendering a single target.
// Returns the exit code for this target.
func processTarget(cmd *cobra.Command, outw io.Writer, outp output.Printer, t model.Target, flags appFlags, multiMode bool, jsonResults *[]string) int {
	colorEnabled := !flags.noColor

	if flags.env {
		return processEnvTarget(outw, outp, t, flags, multiMode, jsonResults)
	}

	pids, err := target.Resolve(t, flags.exact)
	if err == nil && len(pids) == 0 {
		err = fmt.Errorf("no matching process found")
	}
	if err != nil {
		return handleResolveError(cmd, outw, outp, t, err, flags, multiMode, jsonResults)
	}

	if len(pids) > 1 {
		if multiMode && flags.json {
			*jsonResults = append(*jsonResults, jsonErrorEntry(t, fmt.Sprintf("multiple processes matched (%d results)", len(pids))))
		} else {
			hint := "witr --pid <pid>"
			if flags.env {
				hint = "witr --pid <pid> --env"
			}
			printMultiMatch(outp, pids, colorEnabled, hint)
		}
		return ExitInvalidInput
	}

	pid := pids[0]

	var systemdService string
	if t.Type == model.TargetPort && pid == 1 && source.IsSystemdRunning() {
		if portNum, err := strconv.Atoi(t.Value); err == nil {
			if svc, err := procpkg.ResolveSystemdService(portNum); err == nil && svc != "" {
				systemdService = svc
			}
		}
	}

	res, err := pipeline.AnalyzePID(pipeline.AnalyzeConfig{
		PID:     pid,
		Verbose: flags.verbose,
		Tree:    flags.tree,
		Target:  t,
	})

	if err != nil {
		if multiMode {
			if flags.json {
				*jsonResults = append(*jsonResults, jsonErrorEntry(t, err.Error()))
			} else {
				outp.Printf("Error: %v\n", err)
			}
			return classifyError(err)
		}
		errStr := err.Error()
		errorMsg := fmt.Sprintf("%s\n\nNo matching process or service found. Please check your query or try a different name/port/PID.\nFor usage and options, run: witr --help", errStr)
		cmd.PrintErrln(errorMsg)
		return classifyError(err)
	}

	if systemdService != "" {
		res.ResolvedTarget = strings.TrimSuffix(systemdService, ".service")
	}

	if t.Type == model.TargetPort {
		portNum := 0
		fmt.Sscanf(t.Value, "%d", &portNum)
		if portNum > 0 {
			res.SocketInfo = procpkg.GetSocketStateForPort(portNum)
			source.EnrichSocketInfo(res.SocketInfo)
		}
	}

	renderResult(outw, res, flags, multiMode, jsonResults)

	if len(res.Warnings) > 0 {
		return ExitWarnings
	}
	return ExitOK
}

// processEnvTarget handles the --env flag for a single target.
func processEnvTarget(outw io.Writer, outp output.Printer, t model.Target, flags appFlags, multiMode bool, jsonResults *[]string) int {
	colorEnabled := !flags.noColor

	pids, err := target.Resolve(t, flags.exact)
	if err != nil {
		if multiMode {
			if flags.json {
				*jsonResults = append(*jsonResults, jsonErrorEntry(t, err.Error()))
			} else {
				outp.Printf("Error: %v\n", err)
			}
			return classifyError(err)
		}
		outp.Printf("error: %v\n", err)
		return classifyError(err)
	}
	if len(pids) == 0 {
		if multiMode && flags.json {
			*jsonResults = append(*jsonResults, jsonErrorEntry(t, "no matching process found"))
			return ExitNotFound
		}
		outp.Println("No matching process found.")
		return ExitNotFound
	}
	if len(pids) > 1 {
		printMultiMatch(outp, pids, colorEnabled, "witr --pid <pid> --env")
		return ExitInvalidInput
	}

	pid := pids[0]
	procInfo, err := procpkg.ReadProcess(pid)
	if err != nil {
		outp.Printf("error: %v\n", err)
		return ExitInternalError
	}

	resEnv := model.Result{
		Process:  procInfo,
		Ancestry: []model.Process{procInfo},
	}

	if flags.json {
		jsonStr, err := output.ToEnvJSON(resEnv)
		if err != nil {
			outp.Printf("failed to generate json output: %v\n", err)
			return ExitInternalError
		}
		if multiMode {
			*jsonResults = append(*jsonResults, jsonStr)
		} else {
			fmt.Fprintln(outw, jsonStr)
		}
	} else {
		output.RenderEnvOnly(outw, resEnv, colorEnabled)
	}
	return ExitOK
}

// handleResolveError handles target resolution errors, including Docker fallback.
func handleResolveError(cmd *cobra.Command, outw io.Writer, outp output.Printer, t model.Target, err error, flags appFlags, multiMode bool, jsonResults *[]string) int {
	errStr := err.Error()
	colorEnabled := !flags.noColor

	if strings.Contains(errStr, "socket found but owning process not detected") {
		if t.Type == model.TargetPort {
			if portNum, convErr := strconv.Atoi(t.Value); convErr == nil {
				if match := procpkg.ResolveContainerByPort(portNum); match != nil {
					if flags.json {
						jsonStr, jsonErr := output.DockerFallbackToJSON(t.Value, match)
						if jsonErr != nil {
							outp.Printf("failed to generate json output: %v\n", jsonErr)
							return ExitInternalError
						}
						if multiMode {
							*jsonResults = append(*jsonResults, jsonStr)
						} else {
							fmt.Fprintln(outw, jsonStr)
						}
					} else if flags.short {
						output.RenderDockerFallbackShort(outw, t.Value, match, colorEnabled)
					} else {
						output.RenderDockerFallback(outw, t.Value, match, colorEnabled)
					}
					return ExitOK
				}
			}
		}
		if multiMode {
			if flags.json {
				*jsonResults = append(*jsonResults, jsonErrorEntry(t, "socket found but owning process not detected (try sudo)"))
			} else {
				outp.Printf("Error: socket found but owning process not detected (try sudo)\n")
			}
			return ExitPermission
		}
		errorMsg := fmt.Sprintf("%s\n\nA socket was found for the port, but the owning process could not be detected.\nThis may be due to insufficient permissions. Try running with sudo:\n  sudo %s", errStr, strings.Join(os.Args, " "))
		cmd.PrintErrln(errorMsg)
		return ExitPermission
	}

	if multiMode {
		if flags.json {
			*jsonResults = append(*jsonResults, jsonErrorEntry(t, errStr))
		} else {
			outp.Printf("Error: %v\n", err)
		}
		return classifyError(err)
	}
	errorMsg := fmt.Sprintf("%s\n\nNo matching process or service found. Please check your query or try a different name/port/PID.\nFor usage and options, run: witr --help", errStr)
	cmd.PrintErrln(errorMsg)
	return classifyError(err)
}

// renderResult renders a single result in the appropriate output mode.
func renderResult(outw io.Writer, res model.Result, flags appFlags, multiMode bool, jsonResults *[]string) {
	colorEnabled := !flags.noColor

	if flags.json {
		var jsonStr string
		var err error

		if flags.short {
			jsonStr, err = output.ToShortJSON(res)
		} else if flags.tree {
			jsonStr, err = output.ToTreeJSON(res)
		} else if flags.warn {
			jsonStr, err = output.ToWarningsJSON(res)
		} else {
			jsonStr, err = output.ToJSON(res)
		}

		if err != nil {
			fmt.Fprintf(outw, "failed to generate json output: %v\n", err)
			return
		}
		if multiMode {
			*jsonResults = append(*jsonResults, jsonStr)
		} else {
			fmt.Fprintln(outw, jsonStr)
		}
	} else if flags.warn {
		output.RenderWarnings(outw, res, colorEnabled)
	} else if flags.tree {
		output.PrintTree(outw, res.Ancestry, res.Children, colorEnabled)
	} else if flags.short {
		output.RenderShort(outw, res, colorEnabled)
	} else {
		output.RenderStandard(outw, res, colorEnabled, flags.verbose)
	}
}

func Root() *cobra.Command { return rootCmd }

func runInteractive() error {
	v := version
	if v == "v0.0.0-dev" {
		v = ""
	}
	return tui.Start(v)
}

func printMultiMatch(outp output.Printer, pids []int, colorEnabled bool, hint string) {
	outp.Print("Multiple matching processes found:\n\n")
	for i, pid := range pids {
		proc, err := procpkg.ReadProcess(pid)
		var command, cmdline string
		if err != nil {
			command = "unknown"
			cmdline = procpkg.GetCmdline(pid)
		} else {
			command = proc.Command
			cmdline = proc.Cmdline
		}
		if colorEnabled {
			outp.Printf("[%d] %s%s%s (%spid %d%s)\n    %s\n",
				i+1, output.ColorGreen, command, output.ColorReset,
				output.ColorDim, pid, output.ColorReset,
				cmdline)
		} else {
			outp.Printf("[%d] %s (pid %d)\n    %s\n", i+1, command, pid, cmdline)
		}
	}
	outp.Println("\nRe-run with:")
	outp.Printf("  %s\n", hint)
}

// classifyError maps common error strings to exit codes.
func classifyError(err error) int {
	msg := strings.ToLower(err.Error())
	switch {
	case strings.Contains(msg, "permission denied") ||
		strings.Contains(msg, "operation not permitted") ||
		strings.Contains(msg, "insufficient permissions"):
		return ExitPermission
	case strings.Contains(msg, "no matching") ||
		strings.Contains(msg, "no running process") ||
		strings.Contains(msg, "not found") ||
		strings.Contains(msg, "no process"):
		return ExitNotFound
	case strings.Contains(msg, "invalid") ||
		strings.Contains(msg, "must specify"):
		return ExitInvalidInput
	default:
		return ExitInternalError
	}
}

func SetVersion(v string, c string, bd string) {
	version = v
	commit = c
	buildDate = bd

	rootCmd.Version = version
	rootCmd.SetVersionTemplate(fmt.Sprintf("witr {{.Version}} (commit %s, built %s)\n", commit, buildDate))
	rootCmd.SilenceUsage = true
}


================================================
FILE: internal/launchd/plist.go
================================================
//go:build darwin

package launchd

import (
	"bytes"
	"encoding/xml"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
)

// LaunchdInfo contains parsed information about a launchd service
type LaunchdInfo struct {
	Label     string
	Comment   string
	PlistPath string
	Domain    string // user, system, or gui/<uid>

	// Triggers
	RunAtLoad             bool
	KeepAlive             bool
	StartInterval         int    // seconds
	StartCalendarInterval string // human-readable schedule
	WatchPaths            []string
	QueueDirectories      []string

	// Program info
	Program          string
	ProgramArguments []string
}

// plistDict represents a plist dictionary for XML parsing
type plistDict struct {
	Keys   []string
	Values []plistValue
}

type plistValue struct {
	String  string
	Integer int
	Bool    *bool
	Array   []string
	Dict    *plistDict
}

// plist search paths in order of precedence
var plistSearchPaths = []string{
	"~/Library/LaunchAgents",
	"/Library/LaunchAgents",
	"/Library/LaunchDaemons",
	"/System/Library/LaunchAgents",
	"/System/Library/LaunchDaemons",
}

// GetServiceLabel uses launchctl blame to get the service label for a PID
func GetServiceLabel(pid int) (string, string, error) {
	// launchctl blame <pid> returns the service that started the process
	out, err := exec.Command("launchctl", "blame", strconv.Itoa(pid)).Output()
	if err != nil {
		return "", "", fmt.Errorf("launchctl blame failed: %w", err)
	}

	// Output format varies:
	// - "system/com.apple.example" or "gui/501/com.example.app" (real service)
	// - "speculative", "non-ipc demand", "launch job demand", "ipc (mach)" (blame reasons)
	line := strings.TrimSpace(string(out))
	if line == "" {
		return "", "", fmt.Errorf("no service label found for pid %d", pid)
	}

	// Check if this is a real service path (contains "/" and starts with domain)
	if !strings.Contains(line, "/") {
		// This is a blame reason, not a service label
		// Try to find the service by querying launchctl list
		label, domain := findServiceByPID(pid)
		if label != "" {
			return label, domain, nil
		}
		return "", "", fmt.Errorf("process not managed by a named launchd service: %s", line)
	}

	// Parse domain and label from service path
	parts := strings.SplitN(line, "/", 2)
	if len(parts) < 2 {
		return line, "", nil
	}

	domain := parts[0]
	label := parts[1]

	// Handle gui/501/label format
	if domain == "gui" {
		subParts := strings.SplitN(label, "/", 2)
		if len(subParts) == 2 {
			domain = "gui/" + subParts[0]
			label = subParts[1]
		}
	}

	return label, domain, nil
}

// findServiceByPID queries launchctl list to find a service matching the given PID
func findServiceByPID(pid int) (string, string) {
	// launchctl list shows: PID Status Label
	out, err := exec.Command("launchctl", "list").Output()
	if err != nil {
		return "", ""
	}

	pidStr := strconv.Itoa(pid)
	for line := range strings.Lines(string(out)) {
		fields := strings.Fields(line)
		if len(fields) >= 3 && fields[0] == pidStr {
			label := fields[2]
			// Determine domain based on label prefix
			domain := "user"
			if strings.HasPrefix(label, "com.apple.") {
				domain = "system"
			}
			return label, domain
		}
	}

	return "", ""
}

// FindPlistPath searches for the plist file for a given service label
func FindPlistPath(label string) string {
	homeDir, _ := os.UserHomeDir()

	for _, searchPath := range plistSearchPaths {
		path := searchPath
		if strings.HasPrefix(path, "~") {
			path = filepath.Join(homeDir, path[1:])
		}

		plistPath := filepath.Join(path, label+".plist")
		if _, err := os.Stat(plistPath); err == nil {
			return plistPath
		}
	}

	return ""
}

// ParsePlist reads and parses a launchd plist file
func ParsePlist(path string) (*LaunchdInfo, error) {
	// Use plutil to convert to XML (handles binary plists)
	out, err := exec.Command("plutil", "-convert", "xml1", "-o", "-", path).Output()
	if err != nil {
		return nil, fmt.Errorf("failed to convert plist: %w", err)
	}

	info := &LaunchdInfo{
		PlistPath: path,
	}

	// Parse the XML plist
	if err := parsePlistXML(out, info); err != nil {
		return nil, err
	}

	return info, nil
}

// parsePlistXML parses XML plist data into LaunchdInfo
func parsePlistXML(data []byte, info *LaunchdInfo) error {
	decoder := xml.NewDecoder(bytes.NewReader(data))

	var currentKey string
	var dictDepth int // Track dict nesting depth (1 = root dict)

	for {
		token, err := decoder.Token()
		if err != nil {
			break
		}

		switch t := token.(type) {
		case xml.StartElement:
			switch t.Name.Local {
			case "dict":
				dictDepth++
				if dictDepth == 2 && currentKey == "StartCalendarInterval" {
					cal := parseCalendarDict(decoder)
					info.StartCalendarInterval = formatCalendarInterval(cal)
					currentKey = ""
					continue
				}
				// Skip other nested dicts by clearing currentKey
				if dictDepth > 1 {
					currentKey = ""
				}
			case "key":
				// Only capture keys at root dict level
				if dictDepth == 1 {
					var key string
					decoder.DecodeElement(&key, &t)
					currentKey = key
				}
			case "string":
				if dictDepth == 1 && currentKey != "" {
					var val string
					decoder.DecodeElement(&val, &t)
					handleStringValue(info, currentKey, val)
					currentKey = ""
				}
			case "integer":
				if dictDepth == 1 && currentKey != "" {
					var val string
					decoder.DecodeElement(&val, &t)
					if i, err := strconv.Atoi(val); err == nil {
						handleIntValue(info, currentKey, i)
					}
					currentKey = ""
				}
			case "true":
				if dictDepth == 1 && currentKey != "" {
					handleBoolValue(info, currentKey, true)
					currentKey = ""
				}
			case "false":
				if dictDepth == 1 && currentKey != "" {
					handleBoolValue(info, currentKey, false)
					currentKey = ""
				}
			case "array":
				if dictDepth == 1 && currentKey == "StartCalendarInterval" {
					intervals := parseCalendarArray(decoder)
					info.StartCalendarInterval = intervals
					currentKey = ""
				} else if dictDepth == 1 && currentKey != "" {
					arr := parseArray(decoder)
					handleArrayValue(info, currentKey, arr)
					currentKey = ""
				}
			}
		case xml.EndElement:
			if t.Name.Local == "dict" {
				dictDepth--
			}
		}
	}

	return nil
}

func parseArray(decoder *xml.Decoder) []string {
	var result []string
	depth := 1

	for depth > 0 {
		token, err := decoder.Token()
		if err != nil {
			break
		}

		switch t := token.(type) {
		case xml.StartElement:
			if t.Name.Local == "array" {
				depth++
			} else if t.Name.Local == "string" {
				var val string
				decoder.DecodeElement(&val, &t)
				result = append(result, val)
			}
		case xml.EndElement:
			if t.Name.Local == "array" {
				depth--
			}
		}
	}

	return result
}

// parseCalendarDict parses a single StartCalendarInterval dict into key-value pairs.
func parseCalendarDict(decoder *xml.Decoder) map[string]int {
	result := make(map[string]int)
	var currentKey string

	for {
		token, err := decoder.Token()
		if err != nil {
			break
		}
		switch t := token.(type) {
		case xml.StartElement:
			switch t.Name.Local {
			case "key":
				var key string
				decoder.DecodeElement(&key, &t)
				currentKey = key
			case "integer":
				var val string
				decoder.DecodeElement(&val, &t)
				if currentKey != "" {
					if i, err := strconv.Atoi(val); err == nil {
						result[currentKey] = i
					}
					currentKey = ""
				}
			}
		case xml.EndElement:
			if t.Name.Local == "dict" {
				return result
			}
		}
	}
	return result
}

// parseCalendarArray parses an array of StartCalendarInterval dicts.
func parseCalendarArray(decoder *xml.Decoder) string {
	var intervals []string
	depth := 1

	for depth > 0 {
		token, err := decoder.Token()
		if err != nil {
			break
		}
		switch t := token.(type) {
		case xml.StartElement:
			if t.Name.Local == "array" {
				depth++
			} else if t.Name.Local == "dict" {
				cal := parseCalendarDict(decoder)
				if s := formatCalendarInterval(cal); s != "" {
					intervals = append(intervals, s)
				}
			}
		case xml.EndElement:
			if t.Name.Local == "array" {
				depth--
			}
		}
	}

	if len(intervals) == 0 {
		return ""
	}
	return strings.Join(intervals, "; ")
}

// formatCalendarInterval converts a calendar dict into a human-readable string.
// Keys: Month, Day, Weekday (0=Sun), Hour, Minute
func formatCalendarInterval(cal map[string]int) string {
	if len(cal) == 0 {
		return ""
	}

	weekdays := []string{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}

	var parts []string
	if w, ok := cal["Weekday"]; ok && w >= 0 && w < len(weekdays) {
		parts = append(parts, weekdays[w])
	}
	if m, ok := cal["Month"]; ok {
		parts = append(parts, fmt.Sprintf("month %d", m))
	}
	if d, ok := cal["Day"]; ok {
		parts = append(parts, fmt.Sprintf("day %d", d))
	}

	h, hasHour := cal["Hour"]
	min, hasMin := cal["Minute"]
	switch {
	case hasHour && hasMin:
		parts = append(parts, fmt.Sprintf("at %02d:%02d", h, min))
	case hasHour:
		parts = append(parts, fmt.Sprintf("at %02d:00", h))
	case hasMin:
		parts = append(parts, fmt.Sprintf("at *:%02d", min))
	}

	if len(parts) == 0 {
		return ""
	}
	return strings.Join(parts, " ")
}

func handleStringValue(info *LaunchdInfo, key, val string) {
	switch key {
	case "Label":
		info.Label = val
	case "Comment":
		info.Comment = val
	case "Program":
		info.Program = val
	}
}

func handleIntValue(info *LaunchdInfo, key string, val int) {
	switch key {
	case "StartInterval":
		info.StartInterval = val
	}
}

func handleBoolValue(info *LaunchdInfo, key string, val bool) {
	switch key {
	case "RunAtLoad":
		info.RunAtLoad = val
	case "KeepAlive":
		info.KeepAlive = val
	}
}

func handleArrayValue(info *LaunchdInfo, key string, val []string) {
	switch key {
	case "ProgramArguments":
		info.ProgramArguments = val
	case "WatchPaths":
		info.WatchPaths = val
	case "QueueDirectories":
		info.QueueDirectories = val
	}
}

// GetLaunchdInfo retrieves full launchd information for a process
func GetLaunchdInfo(pid int) (*LaunchdInfo, error) {
	label, domain, err := GetServiceLabel(pid)
	if err != nil {
		return nil, err
	}

	plistPath := FindPlistPath(label)
	if plistPath == "" {
		// Return basic info even if we can't find the plist
		return &LaunchdInfo{
			Label:  label,
			Domain: domain,
		}, nil
	}

	info, err := ParsePlist(plistPath)
	if err != nil {
		// Return basic info on parse error
		return &LaunchdInfo{
			Label:     label,
			Domain:    domain,
			PlistPath: plistPath,
		}, nil
	}

	info.Domain = domain
	return info, nil
}

// FormatTriggers returns a human-readable description of what triggers the service
func (info *LaunchdInfo) FormatTriggers() []string {
	var triggers []string

	if info.RunAtLoad {
		triggers = append(triggers, "RunAtLoad (starts at login/boot)")
	}

	if info.StartInterval > 0 {
		triggers = append(triggers, fmt.Sprintf("StartInterval (every %s)", formatDuration(info.StartInterval)))
	}

	if info.StartCalendarInterval != "" {
		triggers = append(triggers, fmt.Sprintf("StartCalendarInterval (%s)", info.StartCalendarInterval))
	}

	if len(info.WatchPaths) > 0 {
		for _, p := range info.WatchPaths {
			triggers = append(triggers, fmt.Sprintf("WatchPaths: %s", p))
		}
	}

	if len(info.QueueDirectories) > 0 {
		for _, p := range info.QueueDirectories {
			triggers = append(triggers, fmt.Sprintf("QueueDirectories: %s", p))
		}
	}

	return triggers
}

func formatDuration(seconds int) string {
	if seconds < 60 {
		return fmt.Sprintf("%ds", seconds)
	}
	if seconds < 3600 {
		return fmt.Sprintf("%dm", seconds/60)
	}
	if seconds < 86400 {
		return fmt.Sprintf("%dh", seconds/3600)
	}
	return fmt.Sprintf("%dd", seconds/86400)
}

// DomainDescription returns a human-readable description of the domain
func (info *LaunchdInfo) DomainDescription() string {
	switch {
	case info.Domain == "system":
		return "Launch Daemon"
	case strings.HasPrefix(info.Domain, "gui/"):
		return "Launch Agent"
	case info.Domain == "user":
		return "Launch Agent"
	default:
		return "launchd service"
	}
}


================================================
FILE: internal/output/children.go
================================================
package output

import (
	"io"

	"github.com/pranshuparmar/witr/pkg/model"
)

func PrintChildren(w io.Writer, root model.Process, children []model.Process, colorEnabled bool) {
	p := NewPrinter(w)

	rootName := root.Command
	if rootName == "" && root.Cmdline != "" {
		rootName = root.Cmdline
	}
	if rootName == "" {
		rootName = "unknown"
	}

	if colorEnabled {
		p.Printf("%sChildren%s of %s (%spid %d%s):\n", ColorGreen, ColorReset, rootName, ColorDim, root.PID, ColorReset)
	} else {
		p.Printf("Children of %s (pid %d):\n", rootName, root.PID)
	}

	if len(children) == 0 {
		if colorEnabled {
			p.Printf("%sNo child processes found.%s\n", ColorGreen, ColorReset)
		} else {
			p.Println("No child processes found.")
		}
		return
	}

	limit := 10
	count := len(children)
	for i, child := range children {
		if i >= limit {
			remaining := count - limit
			if colorEnabled {
				p.Printf("  %s└─ %s... and %d more\n", ColorMagenta, ColorReset, remaining)
			} else {
				p.Printf("  └─ ... and %d more\n", remaining)
			}
			break
		}

		connector := "├─ "
		isLast := (i == count-1) || (i == limit-1 && count <= limit)
		if isLast {
			connector = "└─ "
		}

		childName := child.Command
		if childName == "" && child.Cmdline != "" {
			childName = child.Cmdline
		}
		if childName == "" {
			childName = "unknown"
		}

		if colorEnabled {
			p.Printf("  %s%s%s%s (%spid %d%s)\n", ColorMagenta, connector, ColorReset, childName, ColorDim, child.PID, ColorReset)
		} else {
			p.Printf("  %s%s (pid %d)\n", connector, childName, child.PID)
		}
	}
}


================================================
FILE: internal/output/colors.go
================================================
package output

var (
	ColorReset     = ansiString("\033[0m")
	ColorRed       = ansiString("\033[31m")
	ColorGreen     = ansiString("\033[32m")
	ColorBlue      = ansiString("\033[34m")
	ColorCyan      = ansiString("\033[36m")
	ColorMagenta   = ansiString("\033[35m")
	ColorDim       = ansiString("\033[2m")
	ColorDimYellow = ansiString("\033[2;33m")
)


================================================
FILE: internal/output/docker.go
================================================
package output

import (
	"encoding/json"
	"fmt"
	"io"

	"github.com/pranshuparmar/witr/pkg/model"
)

// dockerSourceLabel builds the source label from a DockerPortMatch.
func dockerSourceLabel(match *model.DockerPortMatch) string {
	if match.ComposeProject != "" && match.ComposeService != "" {
		return fmt.Sprintf("docker-compose: %s/%s", match.ComposeProject, match.ComposeService)
	}
	return "docker"
}

// RenderDockerFallback renders Docker container info when /proc scanning fails
// but a container was identified via Docker CLI.
func RenderDockerFallback(w io.Writer, portValue string, match *model.DockerPortMatch, colorEnabled bool) {
	out := NewPrinter(w)

	name := SanitizeTerminal(match.Name)
	image := SanitizeTerminal(match.Image)
	ports := SanitizeTerminal(match.Ports)

	// Target
	if colorEnabled {
		out.Printf("%sTarget%s      : port %s\n\n", ColorBlue, ColorReset, portValue)
	} else {
		out.Printf("Target      : port %s\n\n", portValue)
	}

	// Container
	if colorEnabled {
		out.Printf("%sContainer%s   : %s%s%s\n", ColorBlue, ColorReset, ColorGreen, ansiString(name), ColorReset)
	} else {
		out.Printf("Container   : %s\n", name)
	}

	// Image
	if colorEnabled {
		out.Printf("%sImage%s       : %s\n", ColorBlue, ColorReset, ansiString(image))
	} else {
		out.Printf("Image       : %s\n", image)
	}

	// Ports
	if ports != "" {
		if colorEnabled {
			out.Printf("%sPorts%s       : %s\n", ColorBlue, ColorReset, ansiString(ports))
		} else {
			out.Printf("Ports       : %s\n", ports)
		}
	}

	// Why It Exists
	if colorEnabled {
		out.Printf("\n%sWhy It Exists%s :\n  ", ColorMagenta, ColorReset)
		out.Print("Docker Desktop (process not visible in current namespace)\n\n")
	} else {
		out.Printf("\nWhy It Exists :\n  ")
		out.Print("Docker Desktop (process not visible in current namespace)\n\n")
	}

	// Source
	sourceLabel := dockerSourceLabel(match)
	if colorEnabled {
		out.Printf("%sSource%s      : %s\n", ColorCyan, ColorReset, sourceLabel)
	} else {
		out.Printf("Source      : %s\n", sourceLabel)
	}

	// Note
	if colorEnabled {
		out.Printf("\n%sNote%s        : The owning process is not visible in this environment.\n", ColorDimYellow, ColorReset)
		out.Printf("              This is common when Docker Desktop runs in a separate namespace\n")
		out.Printf("              (e.g., WSL2 distro, macOS VM).\n")
	} else {
		out.Printf("\nNote        : The owning process is not visible in this environment.\n")
		out.Printf("              This is common when Docker Desktop runs in a separate namespace\n")
		out.Printf("              (e.g., WSL2 distro, macOS VM).\n")
	}
}

// RenderDockerFallbackShort renders a single-line summary for --short mode.
func RenderDockerFallbackShort(w io.Writer, portValue string, match *model.DockerPortMatch, colorEnabled bool) {
	out := NewPrinter(w)
	name := SanitizeTerminal(match.Name)
	image := SanitizeTerminal(match.Image)

	if colorEnabled {
		out.Printf("port %s → %s%s%s (%s) [%s]\n", portValue, ColorGreen, ansiString(name), ColorReset, ansiString(image), dockerSourceLabel(match))
	} else {
		out.Printf("port %s → %s (%s) [%s]\n", portValue, name, image, dockerSourceLabel(match))
	}
}

// DockerFallbackToJSON returns JSON output for a Docker fallback match.
func DockerFallbackToJSON(portValue string, match *model.DockerPortMatch) (string, error) {
	type dockerResult struct {
		Target         string
		ContainerID    string
		ContainerName  string
		Image          string
		Ports          string `json:",omitempty"`
		ComposeProject string `json:",omitempty"`
		ComposeService string `json:",omitempty"`
		Source         string
		Note           string
	}

	res := dockerResult{
		Target:         "port " + portValue,
		ContainerID:    match.ID,
		ContainerName:  match.Name,
		Image:          match.Image,
		Ports:          match.Ports,
		ComposeProject: match.ComposeProject,
		ComposeService: match.ComposeService,
		Source:         dockerSourceLabel(match),
		Note:           "The owning process is not visible in this environment. This is common when Docker Desktop runs in a separate namespace (e.g., WSL2 distro, macOS VM).",
	}

	data, err := json.MarshalIndent(res, "", "  ")
	if err != nil {
		return "", err
	}
	return string(data), nil
}


================================================
FILE: internal/output/docker_test.go
================================================
package output

import (
	"bytes"
	"encoding/json"
	"strings"
	"testing"

	"github.com/pranshuparmar/witr/pkg/model"
)

func TestRenderDockerFallback(t *testing.T) {
	match := &model.DockerPortMatch{
		ID:    "abc123",
		Name:  "my-container",
		Image: "nginx:latest",
		Ports: "0.0.0.0:8080->80/tcp",
	}

	var buf bytes.Buffer
	RenderDockerFallback(&buf, "8080", match, false)
	out := buf.String()

	expected := []string{
		"Target      : port 8080",
		"Container   : my-container",
		"Image       : nginx:latest",
		"Ports       : 0.0.0.0:8080->80/tcp",
		"Why It Exists",
		"Docker Desktop",
		"Source      : docker",
		"Note",
	}

	for _, want := range expected {
		if !strings.Contains(out, want) {
			t.Errorf("RenderDockerFallback output missing %q\nGot:\n%s", want, out)
		}
	}
}

func TestRenderDockerFallbackWithCompose(t *testing.T) {
	match := &model.DockerPortMatch{
		ID:             "abc123",
		Name:           "myapp-db-1",
		Image:          "postgres:16",
		Ports:          "0.0.0.0:5432->5432/tcp",
		ComposeProject: "myapp",
		ComposeService: "db",
	}

	var buf bytes.Buffer
	RenderDockerFallback(&buf, "5432", match, false)
	out := buf.String()

	if !strings.Contains(out, "docker-compose: myapp/db") {
		t.Errorf("expected compose source label, got:\n%s", out)
	}
}

func TestRenderDockerFallbackShort(t *testing.T) {
	match := &model.DockerPortMatch{
		ID:    "abc123",
		Name:  "my-container",
		Image: "nginx:latest",
		Ports: "0.0.0.0:8080->80/tcp",
	}

	var buf bytes.Buffer
	RenderDockerFallbackShort(&buf, "8080", match, false)
	out := buf.String()

	if !strings.Contains(out, "my-container") {
		t.Errorf("short output missing container name, got: %s", out)
	}
	if !strings.Contains(out, "nginx:latest") {
		t.Errorf("short output missing image, got: %s", out)
	}
	if !strings.Contains(out, "[docker]") {
		t.Errorf("short output missing source, got: %s", out)
	}
	// Should be a single line
	if strings.Count(out, "\n") != 1 {
		t.Errorf("short output should be single line, got: %s", out)
	}
}

func TestDockerFallbackToJSON(t *testing.T) {
	match := &model.DockerPortMatch{
		ID:             "abc123",
		Name:           "sql-proxy",
		Image:          "gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.13.0",
		Ports:          "127.0.0.1:5432->5432/tcp",
		ComposeProject: "",
		ComposeService: "",
	}

	jsonStr, err := DockerFallbackToJSON("5432", match)
	if err != nil {
		t.Fatalf("DockerFallbackToJSON() error: %v", err)
	}

	var result map[string]interface{}
	if err := json.Unmarshal([]byte(jsonStr), &result); err != nil {
		t.Fatalf("invalid JSON output: %v", err)
	}

	if result["Target"] != "port 5432" {
		t.Errorf("Target = %v, want %q", result["Target"], "port 5432")
	}
	if result["ContainerName"] != "sql-proxy" {
		t.Errorf("ContainerName = %v, want %q", result["ContainerName"], "sql-proxy")
	}
	if result["Source"] != "docker" {
		t.Errorf("Source = %v, want %q", result["Source"], "docker")
	}
}

func TestDockerFallbackToJSONCompose(t *testing.T) {
	match := &model.DockerPortMatch{
		ID:             "def456",
		Name:           "myapp-db-1",
		Image:          "postgres:16",
		Ports:          "0.0.0.0:5432->5432/tcp",
		ComposeProject: "myapp",
		ComposeService: "db",
	}

	jsonStr, err := DockerFallbackToJSON("5432", match)
	if err != nil {
		t.Fatalf("DockerFallbackToJSON() error: %v", err)
	}

	var result map[string]interface{}
	if err := json.Unmarshal([]byte(jsonStr), &result); err != nil {
		t.Fatalf("invalid JSON output: %v", err)
	}

	if result["Source"] != "docker-compose: myapp/db" {
		t.Errorf("Source = %v, want %q", result["Source"], "docker-compose: myapp/db")
	}
}

func TestRenderDockerFallbackSanitizesOutput(t *testing.T) {
	// Simulate a malicious container name with ANSI escape sequence
	match := &model.DockerPortMatch{
		ID:    "abc123",
		Name:  "evil\x1b[31mcontainer",
		Image: "evil\x1b[0mimage",
		Ports: "0.0.0.0:80->80/tcp",
	}

	var buf bytes.Buffer
	RenderDockerFallback(&buf, "80", match, false)
	out := buf.String()

	if strings.Contains(out, "\x1b") {
		t.Errorf("output contains raw ANSI escape sequences, sanitization failed:\n%s", out)
	}
}


================================================
FILE: internal/output/envonly.go
================================================
package output

import (
	"io"

	"github.com/pranshuparmar/witr/pkg/model"
)

// RenderEnvOnly prints only the command and environment variables for a process
func RenderEnvOnly(w io.Writer, r model.Result, colorEnabled bool) {
	p := NewPrinter(w)

	colorResetEnv := ansiString("")
	colorBlueEnv := ansiString("")
	colorRedEnv := ansiString("")
	colorGreenEnv := ansiString("")
	colorDimEnv := ansiString("")
	if colorEnabled {
		colorResetEnv = ColorReset
		colorBlueEnv = ColorBlue
		colorRedEnv = ColorRed
		colorGreenEnv = ColorGreen
		colorDimEnv = ColorDim
	}

	procName := r.Process.Command
	if len(r.Ancestry) > 0 {
		procName = r.Ancestry[len(r.Ancestry)-1].Command
	}

	if colorEnabled {
		p.Printf("%sProcess%s     : %s%s%s (%spid %d%s)\n", colorBlueEnv, colorResetEnv, colorGreenEnv, procName, colorResetEnv, colorDimEnv, r.Process.PID, colorResetEnv)
	} else {
		p.Printf("Process     : %s (pid %d)\n", procName, r.Process.PID)
	}

	p.Printf("%sCommand%s     : %s\n", colorGreenEnv, colorResetEnv, r.Process.Cmdline)
	if len(r.Process.Env) > 0 {
		p.Printf("%sEnvironment%s :\n", colorBlueEnv, colorResetEnv)
		for _, env := range r.Process.Env {
			p.Printf("  %s\n", env)
		}
	} else {
		p.Printf("%sEnvironment%s : %sNo environment variables found.%s\n", colorBlueEnv, colorResetEnv, colorRedEnv, colorResetEnv)
	}
}


================================================
FILE: internal/output/json.go
================================================
package output

import (
	"encoding/json"

	"github.com/pranshuparmar/witr/pkg/model"
)

func ToJSON(r model.Result) (string, error) {
	data, err := json.MarshalIndent(r, "", "  ")
	if err != nil {
		return "", err
	}
	return string(data), nil
}

type shortProcess struct {
	PID     int
	Command string
}

func ToShortJSON(r model.Result) (string, error) {
	ancestry := make([]shortProcess, len(r.Ancestry))
	for i, p := range r.Ancestry {
		ancestry[i] = shortProcess{PID: p.PID, Command: p.Command}
	}
	data, err := json.MarshalIndent(ancestry, "", "  ")
	if err != nil {
		return "", err
	}
	return string(data), nil
}

func ToTreeJSON(r model.Result) (string, error) {
	type treeResult struct {
		Ancestry []shortProcess
		Children []shortProcess `json:",omitempty"`
	}

	res := treeResult{
		Ancestry: make([]shortProcess, len(r.Ancestry)),
	}

	for i, p := range r.Ancestry {
		res.Ancestry[i] = shortProcess{PID: p.PID, Command: p.Command}
	}

	if len(r.Children) > 0 {
		res.Children = make([]shortProcess, len(r.Children))
		for i, p := range r.Children {
			res.Children[i] = shortProcess{PID: p.PID, Command: p.Command}
		}
	}

	data, err := json.MarshalIndent(res, "", "  ")
	if err != nil {
		return "", err
	}
	return string(data), nil
}

func ToWarningsJSON(r model.Result) (string, error) {
	type warningResult struct {
		PID      int
		Process  string
		Command  string
		Warnings []string
	}

	procName := "unknown"
	if len(r.Ancestry) > 0 {
		procName = r.Ancestry[len(r.Ancestry)-1].Command
	} else if r.Process.Command != "" {
		procName = r.Process.Command
	}

	cmdLine := r.Process.Cmdline
	if cmdLine == "" {
		cmdLine = r.Process.Command
	}

	warnings := r.Warnings
	if warnings == nil {
		warnings = []string{}
	}

	res := warningResult{
		PID:      r.Process.PID,
		Process:  procName,
		Command:  cmdLine,
		Warnings: warnings,
	}

	data, err := json.MarshalIndent(res, "", "  ")
	if err != nil {
		return "", err
	}
	return string(data), nil
}

func ToEnvJSON(r model.Result) (string, error) {
	type envResult struct {
		PID     int
		Process string
		Command string
		Env     []string
	}

	procName := "unknown"
	if len(r.Ancestry) > 0 {
		procName = r.Ancestry[len(r.Ancestry)-1].Command
	} else if r.Process.Command != "" {
		procName = r.Process.Command
	}

	res := envResult{
		PID:     r.Process.PID,
		Process: procName,
		Command: r.Process.Cmdline,
		Env:     r.Process.Env,
	}

	data, err := json.MarshalIndent(res, "", "  ")
	if err != nil {
		return "", err
	}
	return string(data), nil
}


================================================
FILE: internal/output/printer.go
================================================
package output

import (
	"fmt"
	"io"
)

type ansiString string

// Printer writes terminal-safe output to an io.Writer
// sanitizing any string-like arguments (string, []byte, error, fmt.Stringer)
type Printer struct {
	w io.Writer
}

func NewPrinter(w io.Writer) Printer {
	return Printer{w: w}
}

func (p Printer) Printf(format string, args ...any) {
	fmt.Fprintf(p.w, format, sanitizePrintArgs(args)...)
}

func (p Printer) Print(args ...any) {
	fmt.Fprint(p.w, sanitizePrintArgs(args)...)
}

func (p Printer) Println(args ...any) {
	fmt.Fprintln(p.w, sanitizePrintArgs(args)...)
}

func sanitizePrintArgs(args []any) []any {
	if len(args) == 0 {
		return nil
	}
	out := make([]any, len(args))
	for i, a := range args {
		switch v := a.(type) {
		case ansiString: // our own ansiString type is allowed to render as-is
			out[i] = string(v)
		case string:
			out[i] = SanitizeTerminal(v)
		case []byte:
			out[i] = SanitizeTerminal(string(v))
		case error:
			out[i] = SanitizeTerminal(v.Error())
		case fmt.Stringer:
			out[i] = SanitizeTerminal(v.String())
		default:
			out[i] = a
		}
	}
	return out
}


================================================
FILE: internal/output/safe_writer.go
================================================
package output

import "io"

// SafeTerminalWriter sanitizes all bytes written to it so the output is safe to
// display in an interactive terminal, it should be used to print anything that
// we don't control (like processes' args, env vars, ...)
type SafeTerminalWriter struct {
	W io.Writer
}

func (w SafeTerminalWriter) Write(p []byte) (int, error) {
	if len(p) == 0 {
		return 0, nil
	}
	_, err := io.WriteString(w.W, SanitizeTerminal(string(p)))
	if err != nil {
		return 0, err
	}
	return len(p), nil
}

func NewSafeTerminalWriter(w io.Writer) io.Writer {
	return SafeTerminalWriter{W: w}
}


================================================
FILE: internal/output/sanitize.go
================================================
package output

import (
	"strings"
	"unicode"
	"unicode/utf8"
)

const hexDigits = "0123456789abcdef"

// SanitizeTerminal makes a string safe to print to an interactive terminal
// by just replacing control characters with visible escape sequences (e.g. "\x1b")
// Examples:
//   - "hi\x1b[31mred" -> "hi\x1b[31mred" (ESC becomes visible)
//   - "nul:\x00"      -> "nul:\x00"
//   - "bad:\xff"      -> "bad:\xff" (invalid UTF-8 byte)
//   - "a\tb\nc"        -> "a\tb\nc" (tabs/newlines are untouched)
func SanitizeTerminal(s string) string {
	idx := 0
	// fast path: scan until we find a control rune / invalid UTF-8 byte
	for idx < len(s) {
		r, size := utf8.DecodeRuneInString(s[idx:])
		if r == utf8.RuneError && size == 1 {
			break
		}
		if r == '\n' || r == '\t' {
			idx += size
			continue
		}
		if unicode.IsControl(r) {
			break
		}
		idx += size
	}
	if idx == len(s) {
		return s
	}

	var b strings.Builder
	b.Grow(len(s) + 8)
	b.WriteString(s[:idx])

	// slow path: walk the remainder and rewrite any control bytes/runes
	for idx < len(s) {
		r, size := utf8.DecodeRuneInString(s[idx:])
		if r == utf8.RuneError && size == 1 {
			// preserve invalid bytes without letting them act as controls just in case
			appendEscapedByte(&b, s[idx])
			idx++
			continue
		}

		if r == '\n' || r == '\t' {
			b.WriteRune(r)
			idx += size
			continue
		}

		if unicode.IsControl(r) {
			appendEscapedRune(&b, r)
			idx += size
			continue
		}
		b.WriteString(s[idx : idx+size])
		idx += size
	}

	return b.String()
}

func appendEscapedByte(b *strings.Builder, bt byte) {
	b.WriteString(`\\x`)
	b.WriteByte(hexDigits[bt>>4])
	b.WriteByte(hexDigits[bt&0x0f])
}

// while this looks extremely bad, it just outputs this:
//   - r = 0x1b     -> "\x1b"
//   - r = 0x2028   -> "\u2028"
//   - r = 0x1f600  -> "\U0001f600"
func appendEscapedRune(b *strings.Builder, r rune) {
	// 0xFF: "\xHH" (simple byte escape)
	if r <= 0xFF {
		appendEscapedByte(b, byte(r))
		return
	}

	// <= 0xFFFF: "\uHHHH" (BMP escape)
	if r <= 0xFFFF {
		b.WriteString(`\\u`)
		b.WriteByte(hexDigits[(r>>12)&0x0f])
		b.WriteByte(hexDigits[(r>>8)&0x0f])
		b.WriteByte(hexDigits[(r>>4)&0x0f])
		b.WriteByte(hexDigits[r&0x0f])
		return
	}

	// otherwise: "\UHHHHHHHH" (full 32-bit escape)
	b.WriteString(`\\U`)
	b.WriteByte(hexDigits[(r>>28)&0x0f])
	b.WriteByte(hexDigits[(r>>24)&0x0f])
	b.WriteByte(hexDigits[(r>>20)&0x0f])
	b.WriteByte(hexDigits[(r>>16)&0x0f])
	b.WriteByte(hexDigits[(r>>12)&0x0f])
	b.WriteByte(hexDigits[(r>>8)&0x0f])
	b.WriteByte(hexDigits[(r>>4)&0x0f])
	b.WriteByte(hexDigits[r&0x0f])
}


================================================
FILE: internal/output/sanitize_test.go
================================================
package output

import (
	"fmt"
	"strings"
	"testing"
	"unicode"
)

func FuzzAppendEscapedRune(f *testing.F) {
	f.Add(uint32(0x00))
	f.Add(uint32(0x1b))
	f.Add(uint32(0x7f))
	f.Add(uint32(0x80))
	f.Add(uint32(0xff))
	f.Add(uint32(0x100))
	f.Add(uint32(0x20ac))
	f.Add(uint32(0xffff))
	f.Add(uint32(0x10000))
	f.Add(uint32(0x10ffff))

	f.Fuzz(func(t *testing.T, raw uint32) {
		// keep this within the valid Unicode scalar range
		r := rune(raw % (unicode.MaxRune + 1))

		var b strings.Builder
		appendEscapedRune(&b, r)
		got := b.String()

		var want string
		switch {
		case r <= 0xFF:
			want = fmt.Sprintf(`\\x%02x`, r)
		case r <= 0xFFFF:
			want = fmt.Sprintf(`\\u%04x`, r)
		default:
			want = fmt.Sprintf(`\\U%08x`, r)
		}

		if got != want {
			t.Fatalf("appendEscapedRune(%#x) = %q, want %q", r, got, want)
		}

		// output must be visible ascii
		for i := 0; i < len(got); i++ {
			if got[i] >= 0x80 {
				t.Fatalf("appendEscapedRune(%#x) produced non-ASCII byte 0x%02x in %q", r, got[i], got)
			}
		}
	})
}


================================================
FILE: internal/output/short.go
================================================
package output

import (
	"io"

	"github.com/pranshuparmar/witr/pkg/model"
)

func RenderShort(w io.Writer, r model.Result, colorEnabled bool) {
	p := NewPrinter(w)

	for i, proc := range r.Ancestry {
		if i > 0 {
			if colorEnabled {
				p.Printf("%s → %s", ColorMagenta, ColorReset)
			} else {
				p.Print(" → ")
			}
		}

		if colorEnabled {
			nameColor := ansiString("")
			if i == len(r.Ancestry)-1 {
				nameColor = ColorGreen
			}
			p.Printf("%s%s%s (%spid %d%s)", nameColor, proc.Command, ColorReset, ColorDim, proc.PID, ColorReset)
		} else {
			p.Printf("%s (pid %d)", proc.Command, proc.PID)
		}
	}
	p.Println()
}


================================================
FILE: internal/output/standard.go
================================================
package output

import (
	"fmt"
	"io"
	"net"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/pranshuparmar/witr/pkg/model"
)

// Maximum number of items to display in any list before truncating
const MaxDisplayItems = 10

var detailLabels = map[string]string{
	"type":      "              Type",
	"plist":     "              Plist",
	"triggers":  "              Trigger",
	"keepalive": "              KeepAlive",
}

func formatDetailLabel(key string) string {
	if label, ok := detailLabels[key]; ok {
		return label
	}
	return "              " + key
}

func RenderWarnings(w io.Writer, r model.Result, colorEnabled bool) {
	out := NewPrinter(w)

	proc := r.Process
	if len(r.Ancestry) > 0 {
		proc = r.Ancestry[len(r.Ancestry)-1]
	}

	proc.Command = SanitizeTerminal(proc.Command)

	if colorEnabled {
		out.Printf("%sProcess%s     : %s%s%s (%spid %d%s)\n", ColorBlue, ColorReset, ColorGreen, proc.Command, ColorReset, ColorDim, proc.PID, ColorReset)
		if proc.Cmdline != "" {
			out.Printf("%sCommand%s     : %s\n", ColorBlue, ColorReset, proc.Cmdline)
		} else {
			out.Printf("%sCommand%s     : %s\n", ColorBlue, ColorReset, proc.Command)
		}
	} else {
		out.Printf("Process     : %s (pid %d)\n", proc.Command, proc.PID)
		if proc.Cmdline != "" {
			out.Printf("Command     : %s\n", proc.Cmdline)
		} else {
			out.Printf("Command     : %s\n", proc.Command)
		}
	}

	if len(r.Warnings) == 0 {
		if colorEnabled {
			out.Printf("%sWarnings%s    : %sNo warnings.%s\n", ColorRed, ColorReset, ColorGreen, ColorReset)
		} else {
			out.Println("Warnings    : No warnings.")
		}
		return
	}

	if colorEnabled {
		out.Printf("%sWarnings%s    :\n", ColorRed, ColorReset)
		for _, w := range r.Warnings {
			out.Printf("  • %s\n", SanitizeTerminal(w))
		}
	} else {
		out.Println("Warnings    :")
		for _, w := range r.Warnings {
			out.Printf("  • %s\n", SanitizeTerminal(w))
		}
	}
}

func RenderStandard(w io.Writer, r model.Result, colorEnabled bool, verbose bool) {
	out := NewPrinter(w)
	if len(r.Ancestry) == 0 {
		out.Println("No process information available.")
		return
	}

	target := SanitizeTerminal(r.Ancestry[len(r.Ancestry)-1].Command)
	if colorEnabled {
		out.Printf("%sTarget%s      : %s\n\n", ColorBlue, ColorReset, target)
	} else {
		out.Printf("Target      : %s\n\n", target)
	}

	var proc = r.Ancestry[len(r.Ancestry)-1]
	proc.Command = SanitizeTerminal(proc.Command)
	proc.Cmdline = SanitizeTerminal(proc.Cmdline)
	proc.User = SanitizeTerminal(proc.User)
	proc.Container = SanitizeTerminal(proc.Container)
	proc.Service = SanitizeTerminal(proc.Service)
	proc.WorkingDir = SanitizeTerminal(proc.WorkingDir)
	proc.GitRepo = SanitizeTerminal(proc.GitRepo)
	proc.GitBranch = SanitizeTerminal(proc.GitBranch)
	if colorEnabled {
		out.Printf("%sProcess%s     : %s%s%s (%spid %d%s)", ColorBlue, ColorReset, ColorGreen, proc.Command, ColorReset, ColorDim, proc.PID, ColorReset)
	} else {
		out.Printf("Process     : %s (pid %d)", proc.Command, proc.PID)
	}
	// Health status
	if proc.Health != "" && proc.Health != "healthy" {
		health := SanitizeTerminal(proc.Health)
		healthColor := ColorRed
		if colorEnabled {
			out.Printf(" %s[%s]%s", healthColor, health, ColorReset)
		} else {
			out.Printf(" [%s]", health)
		}
	}
	// Forked status: only display if forked
	if proc.Forked == "forked" {
		forkColor := ColorDimYellow
		if colorEnabled {
			out.Printf(" %s{forked}%s", forkColor, ColorReset)
		} else {
			out.Printf(" {forked}")
		}
	}
	out.Println("")
	if proc.User != "" && proc.User != "unknown" {
		if colorEnabled {
			out.Printf("%sUser%s        : %s\n", ColorBlue, ColorReset, proc.User)
		} else {
			out.Printf("User        : %s\n", proc.User)
		}
	}

	// Container
	if proc.Container != "" {
		if colorEnabled {
			out.Printf("%sContainer%s   : %s\n", ColorBlue, ColorReset, proc.Container)
		} else {
			out.Printf("Container   : %s\n", proc.Container)
		}
	}
	// Service
	if proc.Service != "" {
		if colorEnabled {
			out.Printf("%sService%s     : %s\n", ColorBlue, ColorReset, proc.Service)
		} else {
			out.Printf("Service     : %s\n", proc.Service)
		}
	}

	if proc.Cmdline != "" {
		if colorEnabled {
			out.Printf("%sCommand%s     : %s\n", ColorBlue, ColorReset, proc.Cmdline)
		} else {
			out.Printf("Command     : %s\n", proc.Cmdline)
		}
	} else {
		if colorEnabled {
			out.Printf("%sCommand%s     : %s\n", ColorBlue, ColorReset, proc.Command)
		} else {
			out.Printf("Command     : %s\n", proc.Command)
		}
	}
	// Format as: 2 days ago (Mon 2025-02-02 11:42:10 +0530)
	startedAt := proc.StartedAt
	now := time.Now()
	dur := now.Sub(startedAt)
	var rel string
	switch {
	case dur.Hours() >= 48:
		days := int(dur.Hours()) / 24
		rel = fmt.Sprintf("%d days ago", days)
	case dur.Hours() >= 24:
		rel = "1 day ago"
	case dur.Hours() >= 2:
		hours := int(dur.Hours())
		rel = fmt.Sprintf("%d hours ago", hours)
	case dur.Minutes() >= 60:
		rel = "1 hour ago"
	default:
		mins := int(dur.Minutes())
		if mins > 0 {
			rel = fmt.Sprintf("%d min ago", mins)
		} else {
			rel = "just now"
		}
	}
	dtStr := startedAt.Format("Mon 2006-01-02 15:04:05 -07:00")
	if colorEnabled {
		out.Printf("%sStarted%s     : %s (%s)\n", ColorMagenta, ColorReset, rel, dtStr)
	} else {
		out.Printf("Started     : %s (%s)\n", rel, dtStr)
	}

	if schedule, ok := r.Source.Details["schedule"]; ok {
		if colorEnabled {
			out.Printf("%sSchedule%s    : %s\n", ColorMagenta, ColorReset, schedule)
		} else {
			out.Printf("Schedule    : %s\n", schedule)
		}
	}

	// Why It Exists (short chain)
	if colorEnabled {
		out.Printf("\n%sWhy It Exists%s :\n  ", ColorMagenta, ColorReset)
		for i, p := range r.Ancestry {
			name := p.Command
			if name == "" && p.Cmdline != "" {
				name = p.Cmdline
			}
			name = SanitizeTerminal(name)

			nameColor := ansiString("")
			if i == len(r.Ancestry)-1 {
				nameColor = ColorGreen
			}
			out.Printf("%s%s%s (%spid %d%s)", nameColor, name, ColorReset, ColorDim, p.PID, ColorReset)
			if i < len(r.Ancestry)-1 {
				out.Printf(" %s\u2192%s ", ColorMagenta, ColorReset)
			}
		}
		out.Print("\n\n")
	} else {
		out.Printf("\nWhy It Exists :\n  ")
		for i, p := range r.Ancestry {
			name := p.Command
			if name == "" && p.Cmdline != "" {
				name = p.Cmdline
			}
			name = SanitizeTerminal(name)
			out.Printf("%s (pid %d)", name, p.PID)
			if i < len(r.Ancestry)-1 {
				out.Printf(" \u2192 ")
			}
		}
		out.Print("\n\n")
	}

	// Source
	sourceLabel := string(r.Source.Type)
	sourceName := SanitizeTerminal(r.Source.Name)
	if colorEnabled {
		if r.Source.Name != "" && r.Source.Name != sourceLabel {
			out.Printf("%sSource%s      : %s (%s)\n", ColorCyan, ColorReset, sourceName, sourceLabel)
		} else {
			out.Printf("%sSource%s      : %s\n", ColorCyan, ColorReset, sourceLabel)
		}
	} else {
		if r.Source.Name != "" && r.Source.Name != sourceLabel {
			out.Printf("Source      : %s (%s)\n", sourceName, sourceLabel)
		} else {
			out.Printf("Source      : %s\n", sourceLabel)
		}
	}

	// Description
	if r.Source.Description != "" {
		if colorEnabled {
			out.Printf("%sDescription%s : %s\n", ColorCyan, ColorReset, SanitizeTerminal(r.Source.Description))
		} else {
			out.Printf("Description : %s\n", SanitizeTerminal(r.Source.Description))
		}
	}

	// Unit File / Config Source
	if r.Source.UnitFile != "" {
		label := "Unit File"
		switch r.Source.Type {
		case model.SourceLaunchd:
			label = "Plist File"
		case model.SourceWindowsService:
			label = "Registry Key"
		case model.SourceBsdRc:
			label = "Rc Script"
		}

		var pad string
		if len(label) < 12 {
			pad = strings.Repeat(" ", 12-len(label))
		} else {
			pad = " "
		}

		if colorEnabled {
			out.Printf("%s%s%s%s: %s\n", ColorCyan, label, ColorReset, pad, r.Source.UnitFile)
		} else {
			out.Printf("%s%s: %s\n", label, pad, r.Source.UnitFile)
		}
	}

	// Source details (launchd triggers, plist path, etc.)
	if len(r.Source.Details) > 0 {
		// Display in consistent order
		detailKeys := []string{"type", "plist", "triggers", "keepalive"}
		for _, key := range detailKeys {
			if val, ok := r.Source.Details[key]; ok {
				label := formatDetailLabel(key)
				if colorEnabled {
					out.Printf("%s%s%s : %s\n", ColorDim, label, ColorReset, SanitizeTerminal(val))
				} else {
					out.Printf("%s : %s\n", label, SanitizeTerminal(val))
				}
			}
		}
	}

	// Context group
	if colorEnabled {
		if proc.WorkingDir != "" && proc.WorkingDir != "unknown" {
			out.Printf("\n%sWorking Dir%s : %s\n", ColorCyan, ColorReset, proc.WorkingDir)
		}
		if proc.GitRepo != "" {
			if proc.GitBranch != "" {
				out.Printf("%sGit Repo%s    : %s (%s)\n", ColorCyan, ColorReset, proc.GitRepo, proc.GitBranch)
			} else {
				out.Printf("%sGit Repo%s    : %s\n", ColorCyan, ColorReset, proc.GitRepo)
			}
		}
	} else {
		if proc.WorkingDir != "" && proc.WorkingDir != "unknown" {
			out.Printf("\nWorking Dir : %s\n", proc.WorkingDir)
		}
		if proc.GitRepo != "" {
			if proc.GitBranch != "" {
				out.Printf("Git Repo    : %s (%s)\n", proc.GitRepo, proc.GitBranch)
			} else {
				out.Printf("Git Repo    : %s\n", proc.GitRepo)
			}
		}
	}

	// Listening section (address:port)
	if len(proc.ListeningPorts) > 0 && len(proc.BindAddresses) == len(proc.ListeningPorts) {
		count := len(proc.ListeningPorts)
		displayed := 0
		for i := range proc.ListeningPorts {
			if displayed >= MaxDisplayItems {
				remaining := count - displayed
				out.Printf("              ... and %d more\n", remaining)
				break
			}
			addr := proc.BindAddresses[i]
			port := proc.ListeningPorts[i]
			if addr != "" && port > 0 {
				hostPort := net.JoinHostPort(addr, strconv.Itoa(port))
				safeHostPort := SanitizeTerminal(hostPort)
				if colorEnabled {
					if i == 0 {
						out.Printf("%sListening%s   : %s\n", ColorGreen, ColorReset, safeHostPort)
					} else {
						out.Printf("              %s\n", safeHostPort)
					}
				} else {
					if i == 0 {
						out.Printf("Listening   : %s\n", safeHostPort)
					} else {
						out.Printf("              %s\n", safeHostPort)
					}
				}
				displayed++
			}
		}
	}

	// Warnings
	if len(r.Warnings) > 0 {
		if colorEnabled {
			out.Printf("\n%sWarnings%s    :\n", ColorRed, ColorReset)
			for _, w := range r.Warnings {
				out.Printf("  • %s\n", SanitizeTerminal(w))
			}
		} else {
			out.Println("\nWarnings    :")
			for _, w := range r.Warnings {
				out.Printf("  • %s\n", SanitizeTerminal(w))
			}
		}
	}

	// Extended information for verbose mode
	if verbose {
		out.Println()
		// Resource context (thermal state, sleep prevention, CPU)
		if r.ResourceContext != nil {
			if colorEnabled {
				if r.ResourceContext.CPUUsage > 70 {
					out.Printf("%sCPU%s         : %s%.1f%%%s\n", ColorRed, ColorReset, ColorDimYellow, r.ResourceContext.CPUUsage, ColorReset)
				} else {
					out.Printf("%sCPU%s         : %.1f%%\n", ColorGreen, ColorReset, r.ResourceContext.CPUUsage)
				}
			} else {
				out.Printf("CPU         : %.1f%%\n", r.ResourceContext.CPUUsage)
			}

			if r.ResourceContext.PreventsSleep {
				if colorEnabled {
					out.Printf("%sEnergy%s      : %sPreventing system sleep%s\n", ColorRed, ColorReset, ColorDimYellow, ColorReset)
				} else {
					out.Printf("Energy      : Preventing system sleep\n")
				}
			}

			if r.ResourceContext.ThermalState != "" {
				thermalState := SanitizeTerminal(r.ResourceContext.ThermalState)
				if colorEnabled {
					out.Printf("%sThermal%s     : %s%s%s\n", ColorRed, ColorReset, ColorDimYellow, thermalState, ColorReset)
				} else {
					out.Printf("Thermal     : %s\n", thermalState)
				}
			}
		}

		// Memory information
		if proc.Memory.VMS > 0 {
			if colorEnabled {
				out.Printf("\n%sMemory%s:\n", ColorGreen, ColorReset)
				out.Printf("  Virtual  : %.1f MB\n", proc.Memory.VMSMB)
				out.Printf("  Resident : %.1f MB\n", proc.Memory.RSSMB)
				if r.ResourceContext != nil && r.ResourceContext.MemoryUsage > 0 {
					out.Printf("  Private  : %.1f MB\n", float64(r.ResourceContext.MemoryUsage)/(1024*1024))
				}
				if proc.Memory.Shared > 0 {
					out.Printf("  Shared   : %.1f MB\n", float64(proc.Memory.Shared)/(1024*1024))
				}
			} else {
				out.Printf("\nMemory:\n")
				out.Printf("  Virtual  : %.1f MB\n", proc.Memory.VMSMB)
				out.Printf("  Resident : %.1f MB\n", proc.Memory.RSSMB)
				if r.ResourceContext != nil && r.ResourceContext.MemoryUsage > 0 {
					out.Printf("  Private  : %.1f MB\n", float64(r.ResourceContext.MemoryUsage)/(1024*1024))
				}
				if proc.Memory.Shared > 0 {
					out.Printf("  Shared   : %.1f MB\n", float64(proc.Memory.Shared)/(1024*1024))
				}
			}
		}

		// I/O statistics
		if proc.IO.ReadBytes > 0 || proc.IO.WriteBytes > 0 {
			if colorEnabled {
				out.Printf("\n%sI/O Statistics%s:\n", ColorGreen, ColorReset)
				if proc.IO.ReadBytes > 0 {
					out.Printf("  Read  : %.1f MB (%d ops)\n", float64(proc.IO.ReadBytes)/(1024*1024), proc.IO.ReadOps)
				}
				if proc.IO.WriteBytes > 0 {
					out.Printf("  Write : %.1f MB (%d ops)\n", float64(proc.IO.WriteBytes)/(1024*1024), proc.IO.WriteOps)
				}
			} else {
				out.Printf("\nI/O Statistics:\n")
				if proc.IO.ReadBytes > 0 {
					out.Printf("  Read  : %.1f MB (%d ops)\n", float64(proc.IO.ReadBytes)/(1024*1024), proc.IO.ReadOps)
				}
				if proc.IO.WriteBytes > 0 {
					out.Printf("  Write : %.1f MB (%d ops)\n", float64(proc.IO.WriteBytes)/(1024*1024), proc.IO.WriteOps)
				}
			}
		}

		// File context (open files, locks)
		if r.FileContext != nil {
			if r.FileContext.OpenFiles > 0 && r.FileContext.FileLimit == 0 {
				if colorEnabled {
					out.Printf("\n%sOpen Files%s  : %d of unlimited\n", ColorGreen, ColorReset, r.FileContext.OpenFiles)
				} else {
					out.Printf("\nOpen Files  : %d of unlimited\n", r.FileContext.OpenFiles)
				}
			}
			if r.FileContext.OpenFiles > 0 && r.FileContext.FileLimit > 0 {
				usagePercent := float64(r.FileContext.OpenFiles) / float64(r.FileContext.FileLimit) * 100
				if colorEnabled {
					if usagePercent > 80 {
						out.Printf("\n%sOpen Files%s  : %s%d of %d (%.0f%%)%s\n", ColorRed, ColorReset, ColorDimYellow, r.FileContext.OpenFiles, r.FileContext.FileLimit, usagePercent, ColorReset)
					} else {
						out.Printf("\n%sOpen Files%s  : %d of %d (%.0f%%)\n", ColorGreen, ColorReset, r.FileContext.OpenFiles, r.FileContext.FileLimit, usagePercent)
					}
				} else {
					out.Printf("\nOpen Files  : %d of %d (%.0f%%)\n", r.FileContext.OpenFiles, r.FileContext.FileLimit, usagePercent)
				}
			}
			if len(r.FileContext.LockedFiles) > 0 {
				count := len(r.FileContext.LockedFiles)
				firstLocked := SanitizeTerminal(r.FileContext.LockedFiles[0])

				if colorEnabled {
					out.Printf("%sLocks%s       : %s\n", ColorGreen, ColorReset, firstLocked)
				} else {
					out.Printf("Locks       : %s\n", firstLocked)
				}

				for i, f := range r.FileContext.LockedFiles[1:] {
					if 1+i >= MaxDisplayItems {
						remaining := count - (1 + i)
						out.Printf("              ... and %d more\n", remaining)
						break
					}
					out.Printf("              %s\n", SanitizeTerminal(f))
				}
			}
		}

		// File descriptors
		if proc.FDCount > 0 {
			// Sort file descriptors numerically
			sort.Slice(proc.FileDescs, func(i, j int) bool {
				fdI := proc.FileDescs[i]
				fdJ := proc.FileDescs[j]
				idxI := strings.Index(fdI, " ")
				idxJ := strings.Index(fdJ, " ")

				if idxI == -1 || idxJ == -1 {
					return fdI < fdJ
				}

				numI, errI := strconv.Atoi(fdI[:idxI])
				numJ, errJ := strconv.Atoi(fdJ[:idxJ])

				if errI == nil && errJ == nil {
					return numI < numJ
				}
				return fdI < fdJ
			})

			if colorEnabled {
				if proc.FDLimit == 0 {
					out.Printf("\n%sFile Descriptors%s: %d/unlimited\n", ColorGreen, ColorReset, proc.FDCount)
				} else {
					out.Printf("\n%sFile Descriptors%s: %d/%d\n", ColorGreen, ColorReset, proc.FDCount, proc.FDLimit)
				}
				if len(proc.FileDescs) > 0 && len(proc.FileDescs) <= MaxDisplayItems {
					for _, fd := range proc.FileDescs {
						safeFd := SanitizeTerminal(fd)
						safeFd = strings.Replace(safeFd, "->", string(ColorMagenta)+"->"+string(ColorReset), 1)
						out.Printf("  %s\n", ansiString(safeFd))
					}
				} else if len(proc.FileDescs) > MaxDisplayItems {
					out.Printf("  Showing first %d of %d descriptors:\n", MaxDisplayItems, len(proc.FileDescs))
					for i := 0; i < MaxDisplayItems; i++ {
						safeFd := SanitizeTerminal(proc.FileDescs[i])
						safeFd = strings.Replace(safeFd, "->", string(ColorMagenta)+"->"+string(ColorReset), 1)
						out.Printf("  %s\n", ansiString(safeFd))
					}
					out.Printf("  ... and %d more\n", len(proc.FileDescs)-MaxDisplayItems)
				}
			} else {
				if proc.FDLimit == 0 {
					out.Printf("\nFile Descriptors: %d/unlimited\n", proc.FDCount)
				} else {
					out.Printf("\nFile Descriptors: %d/%d\n", proc.FDCount, proc.FDLimit)
				}
				if len(proc.FileDescs) > 0 && len(proc.FileDescs) <= MaxDisplayItems {
					for _, fd := range proc.FileDescs {
						out.Printf("  %s\n", SanitizeTerminal(fd))
					}
				} else if len(proc.FileDescs) > MaxDisplayItems {
					out.Printf("  Showing first %d of %d descriptors:\n", MaxDisplayItems, len(proc.FileDescs))
					for i := 0; i < MaxDisplayItems; i++ {
						out.Printf("  %s\n", SanitizeTerminal(proc.FileDescs[i]))
					}
					out.Printf("  ... and %d more\n", len(proc.FileDescs)-MaxDisplayItems)
				}
			}
		}

		// Socket state (for port queries)
		if r.SocketInfo != nil {
			state := SanitizeTerminal(r.SocketInfo.State)
			explanation := SanitizeTerminal(r.SocketInfo.Explanation)
			workaround := SanitizeTerminal(r.SocketInfo.Workaround)
			if colorEnabled {
				out.Printf("%sSocket%s      : %s\n", ColorGreen, ColorReset, state)
				if explanation != "" {
					out.Printf("              %s\n", explanation)
				}
				if workaround != "" {
					out.Printf("              %s%s%s\n", ColorDimYellow, workaround, ColorReset)
				}
			} else {
				out.Printf("Socket      : %s\n", state)
				if explanation != "" {
					out.Printf("              %s\n", explanation)
				}
				if workaround != "" {
					out.Printf("              %s\n", workaround)
				}
			}
		}

		// Threads
		if proc.ThreadCount > 1 {
			if colorEnabled {
				out.Printf("\n%sThreads%s: %d\n", ColorGreen, ColorReset, proc.ThreadCount)
			} else {
				out.Printf("\nThreads: %d\n", proc.ThreadCount)
			}
		}

		// Child processes
		if len(r.Children) > 0 {
			out.Println("")
			PrintChildren(w, r.Process, r.Children, colorEnabled)
		}
	}
}


================================================
FILE: internal/output/tree.go
================================================
package output

import (
	"io"
	"strings"

	"github.com/pranshuparmar/witr/pkg/model"
)

func PrintTree(w io.Writer, chain []model.Process, children []model.Process, colorEnabled bool) {
	p := NewPrinter(w)

	for i, proc := range chain {
		indent := strings.Repeat("  ", i)
		if i > 0 {
			if colorEnabled {
				p.Printf("%s%s└─ %s", indent, ColorMagenta, ColorReset)
			} else {
				p.Printf("%s└─ ", indent)
			}
		}

		if colorEnabled {
			cmdColor := ansiString("")
			if i == len(chain)-1 {
				cmdColor = ColorGreen
			}
			p.Printf("%s%s%s (%spid %d%s)\n", cmdColor, proc.Command, ColorReset, ColorDim, proc.PID, ColorReset)
		} else {
			p.Printf("%s (pid %d)\n", proc.Command, proc.PID)
		}
	}

	if len(children) == 0 {
		return
	}

	baseIndent := strings.Repeat("  ", len(chain))

	limit := 10
	count := len(children)
	for i, child := range children {
		if i >= limit {
			remaining := count - limit
			if colorEnabled {
				p.Printf("%s%s└─ %s... and %d more\n", baseIndent, ColorMagenta, ColorReset, remaining)
			} else {
				p.Printf("%s└─ ... and %d more\n", baseIndent, remaining)
			}
			break
		}

		connector := "├─ "
		isLast := (i == count-1) || (i == limit-1 && count <= limit)
		if isLast {
			connector = "└─ "
		}

		if colorEnabled {
			p.Printf("%s%s%s%s%s (%spid %d%s)\n", baseIndent, ColorMagenta, connector, ColorReset, child.Command, ColorDim, child.PID, ColorReset)
		} else {
			p.Printf("%s%s%s (pid %d)\n", baseIndent, connector, child.Command, child.PID)
		}
	}
}


================================================
FILE: internal/pipeline/analyze.go
================================================
package pipeline

import (
	"sort"
	"strconv"

	procpkg "github.com/pranshuparmar/witr/internal/proc"
	"github.com/pranshuparmar/witr/internal/source"
	"github.com/pranshuparmar/witr/pkg/model"
)

type AnalyzeConfig struct {
	PID     int
	Verbose bool
	Tree    bool
	Target  model.Target
}

func AnalyzePID(cfg AnalyzeConfig) (model.Result, error) {
	ancestry, err := procpkg.ResolveAncestry(cfg.PID)
	if err != nil {
		return model.Result{}, err
	}

	src := source.Detect(ancestry)

	var proc model.Process
	resolvedTarget := "unknown"
	if len(ancestry) > 0 {
		proc = ancestry[len(ancestry)-1]
		resolvedTarget = proc.Command
	}

	// Collect child PIDs once and reuse for both extended info and tree output
	var childPIDs []int
	var childProcesses []model.Process
	if (cfg.Verbose || cfg.Tree) && proc.PID > 0 {
		snapshot, err := procpkg.ListProcessSnapshot()
		if err == nil {
			for _, p := range snapshot {
				if p.PPID == proc.PID {
					childPIDs = append(childPIDs, p.PID)
					childProcesses = append(childProcesses, p)
				}
			}
			sort.Slice(childProcesses, func(i, j int) bool {
				return childProcesses[i].PID < childProcesses[j].PID
			})
			sort.Ints(childPIDs)
		}
	}

	if cfg.Verbose && len(ancestry) > 0 {
		memInfo, ioStats, fileDescs, fdCount, fdLimit, threadCount, err := procpkg.ReadExtendedInfo(cfg.PID)
		if err == nil {
			proc.Memory = memInfo
			proc.IO = ioStats
			proc.FileDescs = fileDescs
			proc.FDCount = fdCount
			proc.FDLimit = fdLimit
			proc.Children = childPIDs
			proc.ThreadCount = threadCount
			ancestry[len(ancestry)-1] = proc
		}
	}

	var resCtx *model.ResourceContext
	var fileCtx *model.FileContext
	if cfg.Verbose {
		resCtx = procpkg.GetResourceContext(cfg.PID)
		fileCtx = procpkg.GetFileContext(cfg.PID)
	}

	restartCount := 0
	if src.Type == model.SourceSystemd {
		if v, ok := src.Details["NRestarts"]; ok {
			if count, err := strconv.Atoi(v); err == nil {
				restartCount = count
			}
		}
	}

	res := model.Result{
		Target:          cfg.Target,
		ResolvedTarget:  resolvedTarget,
		Process:         proc,
		RestartCount:    restartCount,
		Ancestry:        ancestry,
		Source:          src,
		Warnings:        source.Warnings(ancestry, src.Type),
		ResourceContext: resCtx,
		FileContext:     fileCtx,
		Children:        childProcesses,
	}

	return res, nil
}


================================================
FILE: internal/proc/ancestry.go
================================================
package proc

import (
	"fmt"

	"github.com/pranshuparmar/witr/pkg/model"
)

func ResolveAncestry(pid int) ([]model.Process, error) {
	var chain []model.Process
	seen := make(map[int]bool)

	current := pid

	for current > 0 {
		if seen[current] {
			break // loop protection
		}
		seen[current] = true

		p, err := ReadProcess(current)
		if err != nil {
			break
		}

		chain = append(chain, p)

		if p.PPID == 0 || p.PID == 1 {
			break
		}
		current = p.PPID
	}

	if len(chain) == 0 {
		return nil, fmt.Errorf("no process ancestry found")
	}

	// Reverse the chain to get root
	for i, j := 0, len(chain)-1; i < j; i, j = i+1, j-1 {
		chain[i], chain[j] = chain[j], chain[i]
	}

	return chain, nil
}


================================================
FILE: internal/proc/boot_darwin.go
================================================
//go:build darwin

package proc

import (
	"os/exec"
	"strconv"
	"strings"
	"time"
)

func bootTime() time.Time {
	// Use sysctl kern.boottime on macOS
	out, err := exec.Command("sysctl", "-n", "kern.boottime").Output()
	if err != nil {
		return time.Now()
	}

	// Output format: { sec = 1703123456, usec = 123456 } ...
	outStr := string(out)
	if idx := strings.Index(outStr, "sec = "); idx != -1 {
		start := idx + 6
		end := strings.Index(outStr[start:], ",")
		if end != -1 {
			secStr := outStr[start : start+end]
			sec, err := strconv.ParseInt(strings.TrimSpace(secStr), 10, 64)
			if err == nil {
				return time.Unix(sec, 0)
			}
		}
	}

	return time.Now()
}

func ticksPerSecond() int {
	return 100 // macOS default (same as Linux)
}


================================================
FILE: internal/proc/boot_freebsd.go
================================================
//go:build freebsd

package proc

import (
	"os/exec"
	"strconv"
	"strings"
	"time"
)

func bootTime() time.Time {
	// Use sysctl kern.boottime on FreeBSD (same format as macOS)
	out, err := exec.Command("sysctl", "-n", "kern.boottime").Output()
	if err != nil {
		return time.Now()
	}

	// Output format: { sec = 1703123456, usec = 123456 } ...
	outStr := string(out)
	if idx := strings.Index(outStr, "sec = "); idx != -1 {
		start := idx + 6
		end := strings.Index(outStr[start:], ",")
		if end != -1 {
			secStr := outStr[start : start+end]
			sec, err := strconv.ParseInt(strings.TrimSpace(secStr), 10, 64)
			if err == nil {
				return time.Unix(sec, 0)
			}
		}
	}

	return time.Now()
}

func ticksPerSecond() int {
	// FreeBSD default (same as Linux/macOS)
	return 100
}


================================================
FILE: internal/proc/boot_linux.go
================================================
//go:build linux

package proc

import (
	"bufio"
	"os"
	"strconv"
	"strings"
	"time"
)

func bootTime() time.Time {
	f, err := os.Open("/proc/stat")
	if err != nil {
		return time.Now()
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()
		if strings.HasPrefix(line, "btime") {
			parts := strings.Fields(line)
			if len(parts) < 2 {
				continue
			}
			sec, _ := strconv.ParseInt(parts[1], 10, 64)
			return time.Unix(sec, 0)
		}
	}
	return time.Now()
}

func ticksPerSecond() int {
	return 100 // Linux default; portable enough for now
}


================================================
FILE: internal/proc/boot_windows.go
================================================
//go:build windows

package proc

import (
	"os/exec"
	"strings"
	"time"
)

func bootTime() time.Time {
	// powershell Get-CimInstance Win32_OperatingSystem
	out, err := exec.Command("powershell", "-NoProfile", "-NonInteractive", "Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty LastBootUpTime | Get-Date -Format 'yyyyMMddHHmmss'").Output()
	if err != nil {
		return time.Now()
	}
	// Output format:
	// 20231025123456
	val := strings.TrimSpace(string(out))
	if len(val) < 14 {
		return time.Now()
	}
	// Parse 20231025123456
	t, err := time.ParseInLocation("20060102150405", val[:14], time.Local)
	if err != nil {
		return time.Now()
	}
	return t
}


================================================
FILE: internal/proc/capabilities_linux.go
================================================
//go:build linux

package proc

import (
	"fmt"
	"os"
	"strconv"
	"strings"
)

// Capability bit positions from include/uapi/linux/capability.h
var capNames = map[int]string{
	0:  "CAP_CHOWN",
	1:  "CAP_DAC_OVERRIDE",
	2:  "CAP_DAC_READ_SEARCH",
	3:  "CAP_FOWNER",
	4:  "CAP_FSETID",
	5:  "CAP_KILL",
	6:  "CAP_SETGID",
	7:  "CAP_SETUID",
	8:  "CAP_SETPCAP",
	9:  "CAP_LINUX_IMMUTABLE",
	10: "CAP_NET_BIND_SERVICE",
	11: "CAP_NET_BROADCAST",
	12: "CAP_NET_ADMIN",
	13: "CAP_NET_RAW",
	14: "CAP_IPC_LOCK",
	15: "CAP_IPC_OWNER",
	16: "CAP_SYS_MODULE",
	17: "CAP_SYS_RAWIO",
	18: "CAP_SYS_CHROOT",
	19: "CAP_SYS_PTRACE",
	20: "CAP_SYS_PACCT",
	21: "CAP_SYS_ADMIN",
	22: "CAP_SYS_BOOT",
	23: "CAP_SYS_NICE",
	24: "CAP_SYS_RESOURCE",
	25: "CAP_SYS_TIME",
	26: "CAP_SYS_TTY_CONFIG",
	27: "CAP_MKNOD",
	28: "CAP_LEASE",
	29: "CAP_AUDIT_WRITE",
	30: "CAP_AUDIT_CONTROL",
	31: "CAP_SETFCAP",
	32: "CAP_MAC_OVERRIDE",
	33: "CAP_MAC_ADMIN",
	34: "CAP_SYSLOG",
	35: "CAP_WAKE_ALARM",
	36: "CAP_BLOCK_SUSPEND",
	37: "CAP_AUDIT_READ",
	38: "CAP_PERFMON",
	39: "CAP_BPF",
	40: "CAP_CHECKPOINT_RESTORE",
}

// ReadCapabilities reads the effective capabilities of a process from /proc/<pid>/status.
func ReadCapabilities(pid int) []string {
	data, err := os.ReadFile(fmt.Sprintf("/proc/%d/status", pid))
	if err != nil {
		return nil
	}

	for _, line := range strings.Split(string(data), "\n") {
		if strings.HasPrefix(line, "CapEff:\t") {
			hex := strings.TrimSpace(strings.TrimPrefix(line, "CapEff:"))
			return decodeCapabilities(hex)
		}
	}
	return nil
}

// decodeCapabilities converts a hex capability bitmask into named capabilities.
func decodeCapabilities(hex string) []string {
	val, err := strconv.ParseUint(hex, 16, 64)
	if err != nil {
		return nil
	}
	if val == 0 {
		return nil
	}

	var caps []string
	for bit := 0; bit < 64; bit++ {
		if val&(1<<uint(bit)) != 0 {
			if name, ok := capNames[bit]; ok {
				caps = append(caps, name)
			}
		}
	}
	return caps
}


================================================
FILE: internal/proc/children_unix.go
================================================
//go:build linux || darwin || freebsd

package proc

import (
	"fmt"

	"github.com/pranshuparmar/witr/pkg/model"
)

// ResolveChildren returns the direct child processes for the provided PID.
func ResolveChildren(pid int) ([]model.Process, error) {
	if pid <= 0 {
		return nil, fmt.Errorf("invalid pid")
	}

	processes, err := ListProcessSnapshot()
	if err != nil {
		return nil, err
	}

	children := make([]model.Process, 0)
	for _, proc := range processes {
		if proc.PPID == pid {
			children = append(children, proc)
		}
	}

	sortProcesses(children)
	return children, nil
}


================================================
FILE: internal/proc/children_windows.go
================================================
package proc

import (
	"fmt"
	"os/exec"
	"strconv"
	"strings"

	"github.com/pranshuparmar/witr/pkg/model"
)

// ResolveChildren returns the direct child processes for the provided PID.
// Windows implementation using direct powershell query instead of global snapshot.
func ResolveChildren(pid int) ([]model.Process, error) {
	if pid <= 0 {
		return nil, fmt.Errorf("invalid pid")
	}

	children := make([]model.Process, 0)

	// powershell Get-CimInstance Win32_Process
	cmd := exec.Command("powershell", "-NoProfile", "-NonInteractive", fmt.Sprintf("Get-CimInstance -ClassName Win32_Process -Filter \"ParentProcessId=%d\" | Select-Object Name,ProcessId | ConvertTo-Csv -NoTypeInformation", pid))
	out, err := cmd.Output()
	if err != nil {
		return nil, fmt.Errorf("powershell child query: %w", err)
	}

	// Parse CSV output cleanly
	// "Name","ProcessId"
	// "chrome.exe","1234"
	lines := strings.Split(string(out), "\n")
	for _, line := range lines {
		line = strings.TrimSpace(line)
		if line == "" || strings.HasPrefix(line, "\"Name\"") {
			continue
		}

		parts := strings.Split(line, ",")
		// "chrome.exe","1234"
		if len(parts) >= 2 {
			pidStr := strings.Trim(parts[len(parts)-1], "\"")
			name := strings.Trim(parts[len(parts)-2], "\"")

			cpid, err := strconv.Atoi(pidStr)
			if err != nil {
				continue
			}

			children = append(children, model.Process{
				PID:     cpid,
				PPID:    pid,
				Command: name,
			})
		}
	}

	sortProcesses(children)
	return children, nil
}


================================================
FILE: internal/proc/cmdline_darwin.go
================================================
//go:build darwin

package proc

import (
	"os/exec"
	"strconv"
	"strings"
)

// GetCmdline returns the command line for a given PID
func GetCmdline(pid int) string {
	out, err := exec.Command("ps", "-p", strconv.Itoa(pid), "-o", "args=").Output()
	if err != nil {
		return "(unknown)"
	}
	cmdline := strings.TrimSpace(string(out))
	if cmdline == "" {
		return "(unknown)"
	}
	return cmdline
}


================================================
FILE: internal/proc/cmdline_freebsd.go
================================================
//go:build freebsd

package proc

import (
	"os/exec"
	"strconv"
	"strings"
)

// GetCmdline returns the command line for a given PID
func GetCmdline(pid int) string {
	// FreeBSD syntax: ps -p <pid> -o args
	out, err := exec.Command("ps", "-p", strconv.Itoa(pid), "-o", "args").Output()
	if err != nil {
		return "(unknown)"
	}

	// Skip header line
	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
	if len(lines) < 2 {
		return "(unknown)"
	}

	cmdline := strings.TrimSpace(lines[1])
	if cmdline == "" {
		return "(unknown)"
	}
	return cmdline
}


================================================
FILE: internal/proc/cmdline_linux.go
================================================
//go:build linux

package proc

import (
	"fmt"
	"os"
	"strings"
)

// GetCmdline returns the command line for a given PID
func GetCmdline(pid int) string {
	cmdlineBytes, err := os.ReadFile(fmt.Sprintf("/proc/%d/cmdline", pid))
	if err != nil {
		return "(unknown)"
	}
	cmd := strings.ReplaceAll(string(cmdlineBytes), "\x00", " ")
	cmdline := strings.TrimSpace(cmd)
	if cmdline == "" {
		return "(unknown)"
	}
	return cmdline
}


================================================
FILE: internal/proc/cmdline_windows.go
================================================
//go:build windows

package proc

import (
	"fmt"
	"os/exec"
	"strings"
)

// GetCmdline returns the command line for a given PID
func GetCmdline(pid int) string {
	// powershell Get-CimInstance ...
	out, err := exec.Command("powershell", "-NoProfile", "-NonInteractive", fmt.Sprintf("Get-CimInstance -ClassName Win32_Process -Filter \"ProcessId=%d\" | Select-Object -ExpandProperty CommandLine", pid)).Output()
	if err != nil {
		return "(unknown)"
	}
	val := strings.TrimSpace(string(out))
	if val == "" {
		return "(unknown)"
	}
	return val
}


================================================
FILE: internal/proc/command.go
================================================
package proc

import (
	"path/filepath"
	"strings"
)

// deriveDisplayCommand returns a human-readable command name that avoids
// kernel comm-field truncation (typically 15-16 chars on Linux/macOS/FreeBSD)
// by falling back to the executable name extracted from the full command line
// when the short name looks clipped.
func deriveDisplayCommand(comm, cmdline string) string {
	trimmedComm := strings.TrimSpace(comm)
	exe := extractExecutableName(cmdline)
	if trimmedComm == "" {
		return exe
	}
	if exe == "" {
		return trimmedComm
	}
	if strings.HasPrefix(exe, trimmedComm) && len(trimmedComm) < len(exe) {
		return exe
	}
	return trimmedComm
}

// containsWholeWord checks if s contains word as a standalone token,
// not as a substring of a larger number or identifier.
func containsWholeWord(s, word string) bool {
	idx := 0
	for {
		i := strings.Index(s[idx:], word)
		if i < 0 {
			return false
		}
		start := idx + i
		end := start + len(word)

		leftOK := start == 0 || !isWordChar(s[start-1])
		rightOK := end == len(s) || !isWordChar(s[end])
		if leftOK && rightOK {
			return true
		}
		idx = start + 1
	}
}

func isWordChar(c byte) bool {
	return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
}

func extractExecutableName(cmdline string) string {
	args := splitCmdline(cmdline)
	for _, arg := range args {
		if arg == "" {
			continue
		}
		if strings.Contains(arg, "=") && !strings.Contains(arg, "/") {
			// Skip leading environment assignments.
			continue
		}
		clean := strings.Trim(arg, "\"'")
		if clean == "" {
			continue
		}
		base := filepath.Base(clean)
		if base == "." || base == "" || base == "/" {
			continue
		}
		return base
	}
	return ""
}


================================================
FILE: internal/proc/command_test.go
================================================
package proc

import (
	"testing"
)

func TestDeriveDisplayCommand(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name    string
		comm    string
		cmdline string
		want    string
	}{
		{
			name:    "falls back to executable when ps truncates name",
			comm:    "AccessibilityVis",
			cmdline: "/System/Library/PrivateFrameworks/AccessibilitySupport.framework/Versions/A/Resources/AccessibilityVisualsAgent.app/Contents/MacOS/AccessibilityVisualsAgent",
			want:    "AccessibilityVisualsAgent",
		},
		{
			name:    "keeps comm when executable does not share prefix",
			comm:    "python3",
			cmdline: "python3 /tmp/script.py",
			want:    "python3",
		},
		{
			name:    "uses executable when comm empty",
			comm:    "",
			cmdline: "\"/Applications/App Name/MyBinary\" --flag",
			want:    "MyBinary",
		},
		{
			name:    "ignores env assignments before executable",
			comm:    "AccessibilityUIServer",
			cmdline: "PATH=/usr/bin /System/Library/CoreServices/AccessibilityUIServer.app/Contents/MacOS/AccessibilityUIServer",
			want:    "AccessibilityUIServer",
		},
		{
			name:    "recovers truncated Linux comm (15 char limit)",
			comm:    "my-very-long-pr",
			cmdline: "/usr/local/bin/my-very-long-process-name --daemon",
			want:    "my-very-long-process-name",
		},
		{
			name:    "handles nginx-style cmdline where first token has colon",
			comm:    "nginx",
			cmdline: "nginx: master process /usr/sbin/nginx",
			want:    "nginx:",
		},
		{
			name:    "keeps comm when it matches exe exactly",
			comm:    "nginx",
			cmdline: "/usr/sbin/nginx -g daemon off;",
			want:    "nginx",
		},
		{
			name:    "returns comm when both empty",
			comm:    "",
			cmdline: "",
			want:    "",
		},
	}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			if got := deriveDisplayCommand(tt.comm, tt.cmdline); got != tt.want {
				t.Fatalf("deriveDisplayCommand(%q, %q) = %q, want %q", tt.comm, tt.cmdline, got, tt.want)
			}
		})
	}
}

func TestContainsWholeWord(t *testing.T) {
	t.Parallel()

	tests := []struct {
		s, word string
		want    bool
	}{
		{"pid 12 sleep", "12", true},
		{"pid 120 sleep", "12", false},
		{"pid 312 sleep", "12", false},
		{"12 sleep", "12", true},
		{"sleep 12", "12", true},
		{"(12)", "12", true},
		{"pid:12:sleep", "12", true},
		{"", "12", false},
		{"no match here", "12", false},
	}

	for _, tt := range tests {
		if got := containsWholeWord(tt.s, tt.word); got != tt.want {
			t.Errorf("containsWholeWord(%q, %q) = %v, want %v", tt.s, tt.word, got, tt.want)
		}
	}
}

func TestExtractExecutableName(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name    string
		cmdline string
		want    string
	}{
		{
			name:    "handles quoted path with spaces",
			cmdline: "\"/Applications/Visual Tool.app/Contents/MacOS/Visual Tool\" --flag",
			want:    "Visual Tool",
		},
		{
			name:    "skips env assignment tokens",
			cmdline: "FOO=bar BAR=baz /usr/local/bin/server --mode production",
			want:    "server",
		},
		{
			name:    "returns empty when no executable found",
			cmdline: "",
			want:    "",
		},
		{
			name:    "handles simple command",
			cmdline: "/usr/bin/my-very-long-process-name --flag",
			want:    "my-very-long-process-name",
		},
	}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			if got := extractExecutableName(tt.cmdline); got != tt.want {
				t.Fatalf("extractExecutableName(%q) = %q, want %q", tt.cmdline, got, tt.want)
			}
		})
	}
}


================================================
FILE: internal/proc/container.go
================================================
package proc

import (
	"context"
	"fmt"
	"os/exec"
	"strings"
	"time"
	"unicode"

	"github.com/pranshuparmar/witr/pkg/model"
)

// ResolveContainerByPort queries the Docker CLI for a container publishing the given port.
// Returns nil if Docker is not available or no container matches.
func ResolveContainerByPort(port int) *model.DockerPortMatch {
	if _, err := exec.LookPath("docker"); err != nil {
		return nil
	}

	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	format := "{{.ID}}|{{.Names}}|{{.Image}}|{{.Ports}}|{{.Label \"com.docker.compose.project\"}}|{{.Label \"com.docker.compose.service\"}}"
	cmd := exec.CommandContext(ctx, "docker", "ps", "--filter", fmt.Sprintf("publish=%d", port), "--format", format)
	out, err := cmd.Output()
	if err != nil {
		return nil
	}

	line := strings.TrimSpace(string(out))
	if line == "" {
		return nil
	}

	// Take the first matching container if multiple lines
	if idx := strings.Index(line, "\n"); idx >= 0 {
		line = line[:idx]
	}

	parts := strings.SplitN(line, "|", 6)
	if len(parts) < 6 {
		return nil
	}

	return &model.DockerPortMatch{
		ID:             parts[0],
		Name:           parts[1],
		Image:          parts[2],
		Ports:          parts[3],
		ComposeProject: parts[4],
		ComposeService: parts[5],
	}
}

// resolveContainerName attempts to resolve a container ID to a name using the specified runtime CLI.
func resolveContainerName(id, runtime string) string {
	var cmd *exec.Cmd
	var prefix string

	switch runtime {
	case "docker":
		if _, err := exec.LookPath("docker"); err != nil {
			return ""
		}
		cmd = exec.Command("docker", "inspect", id, "--format", "{{.Name}}|{{index .Config.Labels \"com.docker.compose.project\"}}|{{index .Config.Labels \"com.docker.compose.service\"}}")
		prefix = "docker: "
	case "podman":
		if _, err := exec.LookPath("podman"); err != nil {
			return ""
		}
		cmd = exec.Command("podman", "inspect", id, "--format", "{{.Name}}")
		prefix = "podman: "
	case "crictl":
		if _, err := exec.LookPath("crictl"); err != nil {
			return ""
		}
		cmd = exec.Command("crictl", "inspect", id, "-o", "go-template", "--template", "{{.status.metadata.name}}")
		prefix = "" // crictl names are usually clean
	case "nerdctl":
		if _, err := exec.LookPath("nerdctl"); err != nil {
			return ""
		}
		cmd = exec.Command("nerdctl", "inspect", id, "--format", "{{.Name}}")
		prefix = "containerd: "
	default:
		return ""
	}

	out, err := cmd.Output()
	if err != nil {
		return ""
	}
	output := strings.TrimSpace(string(out))

	if runtime == "docker" {
		parts := strings.Split(output, "|")
		if len(parts) == 3 {
			name := strings.TrimPrefix(parts[0], "/")
			project := parts[1]
			service := parts[2]

			if project != "" && service != "" {
				return "docker: " + project + "/" + service + " (" + name + ")"
			}
			if name != "" {
				return "docker: " + name
			}
			return ""
		}
	}

	name := strings.TrimPrefix(output, "/")
	if name != "" {
		if prefix != "" {
			return prefix + name
		}
		return name
	}
	return ""
}

// findLongHexID searches for a 64-character hexadecimal string in the input.
func findLongHexID(s string) string {
	for i := 0; i <= len(s)-64; i++ {
		if s[i] < '0' || (s[i] > '9' && s[i] < 'a') {
			continue
		}
		sub := s[i : i+64]
		isHex := true
		for j := 0; j < 64; j++ {
			c := sub[j]
			if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
				isHex = false
				break
			}
		}
		if isHex {
			return sub
		}
	}
	return ""
}

// shortID returns the first 12 characters of a container ID, or the full
// string if it is shorter than 12 characters.
func shortID(id string) string {
	if len(id) > 12 {
		return id[:12]
	}
	return id
}

// extractFlagValue extracts the value of a specific flag from a command line string.
func extractFlagValue(cmdline string, flags ...string) string {
	args := splitCmdline(cmdline)
	for i, arg := range args {
		for _, flag := range flags {
			if arg == flag && i+1 < len(args) {
				return args[i+1]
			}
		}
	}
	return ""
}

// splitCmdline splits a command line string into arguments, handling quotes and escapes.
func splitCmdline(cmdline string) []string {
	var args []string
	var current strings.Builder
	var quote rune
	escaped := false
	for _, r := range cmdline {
		switch {
		case escaped:
			current.WriteRune(r)
			escaped = false
		case r == '\\':
			escaped = true
		case r == '"' || r == '\'':
			if quote == 0 {
				quote = r
				continue
			}
			if quote == r {
				quote = 0
				continue
			}
			current.WriteRune(r)
		case unicode.IsSpace(r) && quote == 0:
			if current.Len() > 0 {
				args = append(args, current.String())
				current.Reset()
			}
		default:
			current.WriteRune(r)
		}
	}
	if current.Len() > 0 {
		args = append(args, current.String())
	}
	return args
}


================================================
FILE: internal/proc/container_detect.go
================================================
package proc

import "strings"

// detectContainerFromCmdline checks the command line for container runtime patterns.
// Used by darwin, freebsd, and windows where cgroup-based detection is not available.
func detectContainerFromCmdline(cmdline string) string {
	if cmdline == "" {
		return ""
	}
	lowerCmd := strings.ToLower(cmdline)

	switch {
	case strings.Contains(lowerCmd, "docker"):
		if name := extractFlagValue(cmdline, "--name"); name != "" {
			return "docker: " + name
		}
		return "docker"
	case strings.Contains(lowerCmd, "podman"), strings.Contains(lowerCmd, "libpod"):
		if name := extractFlagValue(cmdline, "--name"); name != "" {
			return "podman: " + name
		}
		return "podman"
	case strings.Contains(lowerCmd, "minikube"):
		if profile := extractFlagValue(cmdline, "-p", "--profile"); profile != "" {
			return "k8s: " + profile
		}
		return "kubernetes"
	case strings.Contains(lowerCmd, "kind"):
		if name := extractFlagValue(cmdline, "--name"); name != "" {
			return "k8s: " + name
		}
		return "kubernetes"
	case strings.Contains(lowerCmd, "kubepods"):
		if id := findLongHexID(cmdline); id != "" {
			if name := resolveContainerName(id, "crictl"); name != "" {
				return "k8s: " + name
			}
			return "k8s (" + shortID(id) + ")"
		}
		return "kubernetes"
	case strings.Contains(lowerCmd, "colima"):
		if profile := extractFlagValue(cmdline, "-p", "--profile"); profile != "" {
			return "colima: " + profile
		}
		return "colima: default"
	case strings.Contains(lowerCmd, "nerdctl"):
		if name := extractFlagValue(cmdline, "--name"); name != "" {
			return "containerd: " + name
		}
		return "containerd"
	case strings.Contains(lowerCmd, "containerd"):
		if name := extractFlagValue(cmdline, "--name"); name != "" {
			return "containerd: " + name
		}
		return "containerd"
	}

	return ""
}


================================================
FILE: internal/proc/container_test.go
================================================
package proc

import (
	"testing"
)

func TestSplitCmdline(t *testing.T) {
	tests := []struct {
		name string
		in   string
		want []string
	}{
		{"simple", "docker ps", []string{"docker", "ps"}},
		{"quoted", `docker inspect --format "{{.Name}}"`, []string{"docker", "inspect", "--format", "{{.Name}}"}},
		{"empty", "", nil},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := splitCmdline(tt.in)
			if len(got) != len(tt.want) {
				t.Fatalf("splitCmdline(%q) = %v, want %v", tt.in, got, tt.want)
			}
			for i := range got {
				if got[i] != tt.want[i] {
					t.Fatalf("splitCmdline(%q)[%d] = %q, want %q", tt.in, i, got[i], tt.want[i])
				}
			}
		})
	}
}

func TestFindLongHexID(t *testing.T) {
	tests := []struct {
		name string
		in   string
		want string
	}{
		{"found", "/docker/" + "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" + "/cgroup", "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"},
		{"not found", "no hex here", ""},
		{"too short", "a1b2c3d4e5f6", ""},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := findLongHexID(tt.in)
			if got != tt.want {
				t.Fatalf("findLongHexID() = %q, want %q", got, tt.want)
			}
		})
	}
}

func TestExtractFlagValue(t *testing.T) {
	tests := []struct {
		name    string
		cmdline string
		flags   []string
		want    string
	}{
		{"found", "docker run --name myapp", []string{"--name"}, "myapp"},
		{"not found", "docker run myapp", []string{"--name"}, ""},
		{"at end", "docker run --name", []string{"--name"}, ""},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := extractFlagValue(tt.cmdline, tt.flags...)
			if got != tt.want {
				t.Fatalf("extractFlagValue() = %q, want %q", got, tt.want)
			}
		})
	}
}


================================================
FILE: internal/proc/docker_proxy.go
================================================
package proc

import (
	"os/exec"
	"strings"
)

func resolveDockerProxyContainer(cmdline string) string {
	var containerIP string
	parts := strings.Fields(cmdline)
	for i, part := range parts {
		if part == "-container-ip" && i+1 < len(parts) {
			containerIP = parts[i+1]
			break
		}
	}
	if containerIP == "" {
		return ""
	}

	out, err := exec.Command("docker", "network", "inspect", "bridge",
		"--format", "{{range .Containers}}{{.Name}}:{{.IPv4Address}}{{\"\\n\"}}{{end}}").Output()
	if err != nil {
		return ""
	}

	for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
		if line == "" {
			continue
		}
		colonIdx := strings.Index(line, ":")
		if colonIdx == -1 {
			continue
		}
		name := line[:colonIdx]
		ip := strings.Split(line[colonIdx+1:], "/")[0]
		if ip == containerIP {
			return "target: " + name
		}
	}
	return ""
}


================================================
FILE: internal/proc/extended_darwin.go
================================================
//go:build darwin

package proc

import (
	"errors"
	"os/exec"
	"strconv"
	"strings"

	"github.com/pranshuparmar/witr/pkg/model"
)

// ReadExtendedInfo assembles the additional process facts.
// Child PID discovery is handled by the caller to avoid redundant process scans.
func ReadExtendedInfo(pid int) (model.MemoryInfo, model.IOStats, []string, int, uint64, int, error) {
	memInfo, threadCount, memErr := readDarwinTaskInfo(pid)
	fdCount, fileDescs, fdErr := readDarwinFDs(pid)
	ioStats, ioErr := readDarwinIO(pid)
	fdLimit := detectDarwinFileLimit()

	if memErr != nil && fdErr != nil && ioErr != nil {
		return memInfo, ioStats, fileDescs, fdCount, fdLimit, threadCount, errors.Join(memErr, fdErr, ioErr)
	}

	return memInfo, ioStats, fileDescs, fdCount, fdLimit, threadCount, nil
}

// detectDarwinFileLimit reads launchctl's maxfiles limit (soft cap) so we can
// compute descriptor headroom, falling back to the shell's ulimit if launchctl
// is unavailable.
func detectDarwinFileLimit() uint64 {
	if data, err := exec.Command("launchctl", "limit", "maxfiles").Output(); err == nil {
		for line := range strings.Lines(string(data)) {
			if strings.Contains(line, "maxfiles") {
				if limit, ok := parseLaunchctlLimitLine(line); ok {
					return limit
				}
			}
		}
	}
	if data, err := exec.Command("sh", "-c", "ulimit -n").Output(); err == nil {
		if limit, err := strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64); err == nil {
			return limit
		}
	}
	return 0
}

func parseLaunchctlLimitLine(line string) (uint64, bool) {
	fields := strings.Fields(line)
	if len(fields) < 2 {
		return 0, false
	}
	soft := fields[1]
	if strings.EqualFold(soft, "unlimited") {
		return 0, true
	}
	limit, err := strconv.ParseUint(soft, 10, 64)
	if err != nil {
		return 0, false
	}
	return limit, true
}


================================================
FILE: internal/proc/extended_darwin_test.go
================================================
//go:build darwin

package proc

import "testing"

func TestParseLaunchctlLimitLine(t *testing.T) {
	for name, tc := range map[string]struct {
		line  string
		limit uint64
		valid bool
	}{
		"numeric":   {line: "maxfiles    1024            unlimited", limit: 1024, valid: true},
		"unlimited": {line: "maxfiles    unlimited       unlimited", limit: 0, valid: true},
		"invalid":   {line: "maxfiles --", limit: 0, valid: false},
		"short":     {line: "oops", limit: 0, valid: false},
	} {
		name := name
		tc := tc
		t.Run(name, func(t *testing.T) {
			t.Parallel()
			limit, ok := parseLaunchctlLimitLine(tc.line)
			if ok != tc.valid || limit != tc.limit {
				t.Fatalf("parseLaunchctlLimitLine(%q) = (%d, %t), want (%d, %t)", tc.line, limit, ok, tc.limit, tc.valid)
			}
		})
	}
}


================================================
FILE: internal/proc/extended_freebsd.go
================================================
//go:build freebsd

package proc

import (
	"fmt"
	"os/exec"
	"strconv"
	"strings"

	"github.com/pranshuparmar/witr/pkg/model"
)

// ReadExtendedInfo reads extended process information for verbose output on FreeBSD.
// Child PID discovery is handled by the caller to avoid redundant process scans.
func ReadExtendedInfo(pid int) (model.MemoryInfo, model.IOStats, []string, int, uint64, int, error) {
	var memInfo model.MemoryInfo
	var ioStats model.IOStats
	var fileDescs []string
	var threadCount int
	var fdCount int
	var fdLimit uint64

	// 1. Get Memory info using ps
	// rss = resident set size in 1024 byte blocks
	// vsz = virtual size in 1024 byte blocks
	cmd := exec.Command("ps", "-o", "rss,vsz", "-p", strconv.Itoa(pid))
	out, err := cmd.Output()
	if err == nil {
		lines := strings.Split(strings.TrimSpace(string(out)), "\n")
		if len(lines) >= 2 {
			fields := strings.Fields(lines[1])
			if len(fields) >= 2 {
				// RSS
				if rss, err := strconv.ParseUint(fields[0], 10, 64); err == nil {
					memInfo.RSS = rss * 1024
					memInfo.RSSMB = float64(memInfo.RSS) / (1024 * 1024)
				}
				// VSZ
				if vsz, err := strconv.ParseUint(fields[1], 10, 64); err == nil {
					memInfo.VMS = vsz * 1024
					memInfo.VMSMB = float64(memInfo.VMS) / (1024 * 1024)
				}
			}
		}
	}

	// 2. Count threads using ps -H (threads) check
	// `ps -H`
	threadCmd := exec.Command("ps", "-H", "-p", strconv.Itoa(pid))
	if threadOut, err := threadCmd.Output(); err == nil {
		lines := strings.Split(strings.TrimSpace(string(threadOut)), "\n")
		if len(lines) > 1 {
			threadCount = len(lines) - 1
		}
	}

	// 3. Get file descriptors using lsof (best effort)
	fdCmd := exec.Command("sh", "-c", fmt.Sprintf("lsof -p %d | wc -l", pid))
	if fdOut, err := fdCmd.Output(); err == nil {
		str := strings.TrimSpace(string(fdOut))
		if count, err := strconv.Atoi(str); err == nil {
			if count > 0 {
				fdCount = count - 1
			}
		}
	}

	return memInfo, ioStats, fileDescs, fdCount, fdLimit, threadCount, nil
}


================================================
FILE: internal/proc/extended_linux.go
================================================
//go:build linux

package proc

import (
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/pranshuparmar/witr/pkg/model"
)

// ReadExtendedInfo reads extended process information for verbose output.
// Child PID discovery is handled by the caller to avoid redundant /proc scans.
func ReadExtendedInfo(pid int) (model.MemoryInfo, model.IOStats, []string, int, uint64, int, error) {
	var memInfo model.MemoryInfo
	var ioStats model.IOStats
	var fileDescs []string
	var threadCount int
	fdCount := 0
	var fdLimit uint64

	// Read memory info from /proc/[pid]/statm
	if statmData, err := os.ReadFile(fmt.Sprintf("/proc/%d/statm", pid)); err == nil {
		fields := strings.Fields(string(statmData))
		if len(fields) >= 7 {
			pageSize := uint64(os.Getpagesize())

			// statm fields: total resident shared text lib data dirty
			total, _ := strconv.ParseUint(fields[0], 10, 64)
			resident, _ := strconv.ParseUint(fields[1], 10, 64)
			shared, _ := strconv.ParseUint(fields[2], 10, 64)
			text, _ := strconv.ParseUint(fields[3], 10, 64)
			lib, _ := strconv.ParseUint(fields[4], 10, 64)
			data, _ := strconv.ParseUint(fields[5], 10, 64)
			dirty, _ := strconv.ParseUint(fields[6], 10, 64)

			memInfo = model.MemoryInfo{
				VMS:    total * pageSize,
				RSS:    resident * pageSize,
				VMSMB:  float64(total*pageSize) / (1024 * 1024),
				RSSMB:  float64(resident*pageSize) / (1024 * 1024),
				Shared: shared * pageSize,
				Text:   text * pageSize,
				Lib:    lib * pageSize,
				Data:   data * pageSize,
				Dirty:  dirty * pageSize,
			}
		}
	}

	// Read I/O stats from /proc/[pid]/io
	if ioData, err := os.ReadFile(fmt.Sprintf("/proc/%d/io", pid)); err == nil {
		lines := strings.Split(string(ioData), "\n")
		for _, line := range lines {
			if strings.HasPrefix(line, "read_bytes:") {
				if val, err := strconv.ParseUint(strings.TrimSpace(strings.TrimPrefix(line, "read_bytes:")), 10, 64); err == nil {
					ioStats.ReadBytes = val
				}
			} else if strings.HasPrefix(line, "write_bytes:") {
				if val, err := strconv.ParseUint(strings.TrimSpace(strings.TrimPrefix(line, "write_bytes:")), 10, 64); err == nil {
					ioStats.WriteBytes = val
				}
			} else if strings.HasPrefix(line, "syscr:") {
				if val, err := strconv.ParseUint(strings.TrimSpace(strings.TrimPrefix(line, "syscr:")), 10, 64); err == nil {
					ioStats.ReadOps = val
				}
			} else if strings.HasPrefix(line, "syscw:") {
				if val, err := strconv.ParseUint(strings.TrimSpace(strings.TrimPrefix(line, "syscw:")), 10, 64); err == nil {
					ioStats.WriteOps = val
				}
			}
		}
	}

	// Read file descriptors from /proc/[pid]/fd
	if fdDir, err := os.ReadDir(fmt.Sprintf("/proc/%d/fd", pid)); err == nil {
		fdCount = len(fdDir)
		for _, fdEntry := range fdDir {
			fdPath := fmt.Sprintf("/proc/%d/fd/%s", pid, fdEntry.Name())
			if linkTarget, err := os.Readlink(fdPath); err == nil {
				fileDescs = append(fileDescs, fmt.Sprintf("%s -> %s", fdEntry.Name(), linkTarget))
			}
		}
	}

	// Reuse the shared file limit parser
	fdLimit = uint64(getFileLimit(pid))

	// Get thread count from /proc/[pid]/status
	if statusData, err := os.ReadFile(fmt.Sprintf("/proc/%d/status", pid)); err == nil {
		lines := strings.Split(string(statusData), "\n")
		for _, line := range lines {
			if strings.HasPrefix(line, "Threads:") {
				if count, err := strconv.Atoi(strings.TrimSpace(strings.TrimPrefix(line, "Threads:"))); err == nil {
					threadCount = count
				}
				break
			}
		}
	}

	return memInfo, ioStats, fileDescs, fdCount, fdLimit, threadCount, nil
}


================================================
FILE: internal/proc/extended_windows.go
================================================
//go:build windows

package proc

import (
	"fmt"
	"os/exec"
	"strconv"
	"strings"

	"github.com/pranshuparmar/witr/pkg/model"
)

// ReadExtendedInfo reads extended process information for verbose output.
// Child PID discovery is handled by the caller to avoid redundant process scans.
func ReadExtendedInfo(pid int) (model.MemoryInfo, model.IOStats, []string, int
Download .txt
gitextract_4kvh9lo7/

├── .agent/
│   └── workflows/
│       └── validate-pr-check.md
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   └── feature_request.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── e2e-tests.yml
│       ├── pr-check.yml
│       ├── release.yml
│       └── update-docs.yml
├── .gitignore
├── .goreleaser.yml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── cmd/
│   └── witr/
│       ├── main.go
│       └── unsupported.go
├── docs/
│   └── cli/
│       ├── witr.1
│       └── witr.md
├── flake.nix
├── go.mod
├── go.sum
├── install.ps1
├── install.sh
├── internal/
│   ├── app/
│   │   └── app.go
│   ├── launchd/
│   │   └── plist.go
│   ├── output/
│   │   ├── children.go
│   │   ├── colors.go
│   │   ├── docker.go
│   │   ├── docker_test.go
│   │   ├── envonly.go
│   │   ├── json.go
│   │   ├── printer.go
│   │   ├── safe_writer.go
│   │   ├── sanitize.go
│   │   ├── sanitize_test.go
│   │   ├── short.go
│   │   ├── standard.go
│   │   └── tree.go
│   ├── pipeline/
│   │   └── analyze.go
│   ├── proc/
│   │   ├── ancestry.go
│   │   ├── boot_darwin.go
│   │   ├── boot_freebsd.go
│   │   ├── boot_linux.go
│   │   ├── boot_windows.go
│   │   ├── capabilities_linux.go
│   │   ├── children_unix.go
│   │   ├── children_windows.go
│   │   ├── cmdline_darwin.go
│   │   ├── cmdline_freebsd.go
│   │   ├── cmdline_linux.go
│   │   ├── cmdline_windows.go
│   │   ├── command.go
│   │   ├── command_test.go
│   │   ├── container.go
│   │   ├── container_detect.go
│   │   ├── container_test.go
│   │   ├── docker_proxy.go
│   │   ├── extended_darwin.go
│   │   ├── extended_darwin_test.go
│   │   ├── extended_freebsd.go
│   │   ├── extended_linux.go
│   │   ├── extended_windows.go
│   │   ├── fd_darwin.go
│   │   ├── fd_freebsd.go
│   │   ├── fd_linux.go
│   │   ├── filecontext_darwin.go
│   │   ├── filecontext_freebsd.go
│   │   ├── filecontext_linux.go
│   │   ├── filecontext_windows.go
│   │   ├── git.go
│   │   ├── libproc_darwin_cgo.go
│   │   ├── libproc_darwin_stub.go
│   │   ├── libproc_darwin_test.go
│   │   ├── net_darwin.go
│   │   ├── net_freebsd.go
│   │   ├── net_linux.go
│   │   ├── net_linux_test.go
│   │   ├── net_windows.go
│   │   ├── peb_windows.go
│   │   ├── process_darwin.go
│   │   ├── process_darwin_test.go
│   │   ├── process_freebsd.go
│   │   ├── process_linux.go
│   │   ├── process_list_darwin.go
│   │   ├── process_list_freebsd.go
│   │   ├── process_list_linux.go
│   │   ├── process_list_windows.go
│   │   ├── process_windows.go
│   │   ├── psenv_unix.go
│   │   ├── resource_darwin.go
│   │   ├── resource_freebsd.go
│   │   ├── resource_linux.go
│   │   ├── resource_windows.go
│   │   ├── socketstate_darwin.go
│   │   ├── socketstate_freebsd.go
│   │   ├── socketstate_linux.go
│   │   ├── socketstate_windows.go
│   │   ├── sort.go
│   │   ├── systemd_linux.go
│   │   ├── systemd_stub.go
│   │   ├── user_darwin.go
│   │   ├── user_freebsd.go
│   │   ├── user_linux.go
│   │   └── user_windows.go
│   ├── source/
│   │   ├── bsdrc_darwin.go
│   │   ├── bsdrc_freebsd.go
│   │   ├── bsdrc_linux.go
│   │   ├── bsdrc_windows.go
│   │   ├── container.go
│   │   ├── cron.go
│   │   ├── detect.go
│   │   ├── detect_test.go
│   │   ├── init.go
│   │   ├── launchd_darwin.go
│   │   ├── launchd_freebsd.go
│   │   ├── launchd_linux.go
│   │   ├── launchd_windows.go
│   │   ├── network.go
│   │   ├── service_other.go
│   │   ├── service_windows.go
│   │   ├── shell.go
│   │   ├── ssh.go
│   │   ├── supervisor.go
│   │   ├── systemd_darwin.go
│   │   ├── systemd_freebsd.go
│   │   ├── systemd_linux.go
│   │   └── systemd_windows.go
│   ├── target/
│   │   ├── file_darwin.go
│   │   ├── file_freebsd.go
│   │   ├── file_linux.go
│   │   ├── file_windows.go
│   │   ├── name_darwin.go
│   │   ├── name_freebsd.go
│   │   ├── name_linux.go
│   │   ├── name_windows.go
│   │   ├── port_darwin.go
│   │   ├── port_freebsd.go
│   │   ├── port_linux.go
│   │   ├── port_windows.go
│   │   ├── resolve.go
│   │   └── resolve_test.go
│   ├── tools/
│   │   └── docgen/
│   │       └── main.go
│   ├── tui/
│   │   ├── actions.go
│   │   ├── actions_windows.go
│   │   ├── data.go
│   │   ├── helpers.go
│   │   ├── model.go
│   │   ├── mouse.go
│   │   ├── update.go
│   │   └── view.go
│   └── version/
│       ├── VERSION
│       └── version.go
├── pkg/
│   └── model/
│       ├── docker.go
│       ├── filecontext.go
│       ├── net.go
│       ├── process.go
│       ├── resource.go
│       ├── result.go
│       ├── socket.go
│       ├── source.go
│       └── target.go
└── vendor/
    ├── github.com/
    │   ├── atotto/
    │   │   └── clipboard/
    │   │       ├── .travis.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── clipboard.go
    │   │       ├── clipboard_darwin.go
    │   │       ├── clipboard_plan9.go
    │   │       ├── clipboard_unix.go
    │   │       └── clipboard_windows.go
    │   ├── aymanbagabas/
    │   │   └── go-osc52/
    │   │       └── v2/
    │   │           ├── LICENSE
    │   │           ├── README.md
    │   │           └── osc52.go
    │   ├── charmbracelet/
    │   │   ├── bubbles/
    │   │   │   ├── LICENSE
    │   │   │   ├── cursor/
    │   │   │   │   └── cursor.go
    │   │   │   ├── help/
    │   │   │   │   └── help.go
    │   │   │   ├── key/
    │   │   │   │   └── key.go
    │   │   │   ├── runeutil/
    │   │   │   │   └── runeutil.go
    │   │   │   ├── table/
    │   │   │   │   └── table.go
    │   │   │   ├── textinput/
    │   │   │   │   └── textinput.go
    │   │   │   └── viewport/
    │   │   │       ├── keymap.go
    │   │   │       └── viewport.go
    │   │   ├── bubbletea/
    │   │   │   ├── .gitattributes
    │   │   │   ├── .gitignore
    │   │   │   ├── .golangci.yml
    │   │   │   ├── .goreleaser.yml
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── Taskfile.yaml
    │   │   │   ├── commands.go
    │   │   │   ├── exec.go
    │   │   │   ├── focus.go
    │   │   │   ├── inputreader_other.go
    │   │   │   ├── inputreader_windows.go
    │   │   │   ├── key.go
    │   │   │   ├── key_other.go
    │   │   │   ├── key_sequences.go
    │   │   │   ├── key_windows.go
    │   │   │   ├── logging.go
    │   │   │   ├── mouse.go
    │   │   │   ├── nil_renderer.go
    │   │   │   ├── options.go
    │   │   │   ├── renderer.go
    │   │   │   ├── screen.go
    │   │   │   ├── signals_unix.go
    │   │   │   ├── signals_windows.go
    │   │   │   ├── standard_renderer.go
    │   │   │   ├── tea.go
    │   │   │   ├── tea_init.go
    │   │   │   ├── tty.go
    │   │   │   ├── tty_unix.go
    │   │   │   └── tty_windows.go
    │   │   ├── colorprofile/
    │   │   │   ├── .golangci.yml
    │   │   │   ├── .goreleaser.yml
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── doc.go
    │   │   │   ├── env.go
    │   │   │   ├── env_other.go
    │   │   │   ├── env_windows.go
    │   │   │   ├── profile.go
    │   │   │   └── writer.go
    │   │   ├── lipgloss/
    │   │   │   ├── .gitignore
    │   │   │   ├── .golangci.yml
    │   │   │   ├── .goreleaser.yml
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── Taskfile.yaml
    │   │   │   ├── align.go
    │   │   │   ├── ansi_unix.go
    │   │   │   ├── ansi_windows.go
    │   │   │   ├── borders.go
    │   │   │   ├── color.go
    │   │   │   ├── get.go
    │   │   │   ├── join.go
    │   │   │   ├── position.go
    │   │   │   ├── ranges.go
    │   │   │   ├── renderer.go
    │   │   │   ├── runes.go
    │   │   │   ├── set.go
    │   │   │   ├── size.go
    │   │   │   ├── style.go
    │   │   │   ├── unset.go
    │   │   │   └── whitespace.go
    │   │   └── x/
    │   │       ├── ansi/
    │   │       │   ├── LICENSE
    │   │       │   ├── ansi.go
    │   │       │   ├── ascii.go
    │   │       │   ├── background.go
    │   │       │   ├── c0.go
    │   │       │   ├── c1.go
    │   │       │   ├── charset.go
    │   │       │   ├── clipboard.go
    │   │       │   ├── color.go
    │   │       │   ├── ctrl.go
    │   │       │   ├── cursor.go
    │   │       │   ├── cwd.go
    │   │       │   ├── doc.go
    │   │       │   ├── finalterm.go
    │   │       │   ├── focus.go
    │   │       │   ├── graphics.go
    │   │       │   ├── hyperlink.go
    │   │       │   ├── inband.go
    │   │       │   ├── iterm2.go
    │   │       │   ├── keypad.go
    │   │       │   ├── kitty.go
    │   │       │   ├── method.go
    │   │       │   ├── mode.go
    │   │       │   ├── mode_deprecated.go
    │   │       │   ├── modes.go
    │   │       │   ├── mouse.go
    │   │       │   ├── notification.go
    │   │       │   ├── palette.go
    │   │       │   ├── parser/
    │   │       │   │   ├── const.go
    │   │       │   │   ├── seq.go
    │   │       │   │   └── transition_table.go
    │   │       │   ├── parser.go
    │   │       │   ├── parser_decode.go
    │   │       │   ├── parser_handler.go
    │   │       │   ├── parser_sync.go
    │   │       │   ├── passthrough.go
    │   │       │   ├── paste.go
    │   │       │   ├── progress.go
    │   │       │   ├── reset.go
    │   │       │   ├── screen.go
    │   │       │   ├── sgr.go
    │   │       │   ├── status.go
    │   │       │   ├── style.go
    │   │       │   ├── termcap.go
    │   │       │   ├── title.go
    │   │       │   ├── truncate.go
    │   │       │   ├── urxvt.go
    │   │       │   ├── util.go
    │   │       │   ├── width.go
    │   │       │   ├── winop.go
    │   │       │   ├── wrap.go
    │   │       │   └── xterm.go
    │   │       ├── cellbuf/
    │   │       │   ├── LICENSE
    │   │       │   ├── buffer.go
    │   │       │   ├── cell.go
    │   │       │   ├── errors.go
    │   │       │   ├── geom.go
    │   │       │   ├── hardscroll.go
    │   │       │   ├── hashmap.go
    │   │       │   ├── link.go
    │   │       │   ├── pen.go
    │   │       │   ├── screen.go
    │   │       │   ├── sequence.go
    │   │       │   ├── style.go
    │   │       │   ├── tabstop.go
    │   │       │   ├── utils.go
    │   │       │   ├── wrap.go
    │   │       │   └── writer.go
    │   │       └── term/
    │   │           ├── LICENSE
    │   │           ├── term.go
    │   │           ├── term_other.go
    │   │           ├── term_plan9.go
    │   │           ├── term_unix.go
    │   │           ├── term_unix_bsd.go
    │   │           ├── term_unix_other.go
    │   │           ├── term_windows.go
    │   │           ├── terminal.go
    │   │           └── util.go
    │   ├── clipperhouse/
    │   │   ├── displaywidth/
    │   │   │   ├── .gitignore
    │   │   │   ├── AGENTS.md
    │   │   │   ├── CHANGELOG.md
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── gen.go
    │   │   │   ├── graphemes.go
    │   │   │   ├── trie.go
    │   │   │   └── width.go
    │   │   ├── stringish/
    │   │   │   ├── .gitignore
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   └── interface.go
    │   │   └── uax29/
    │   │       └── v2/
    │   │           ├── LICENSE
    │   │           └── graphemes/
    │   │               ├── README.md
    │   │               ├── iterator.go
    │   │               ├── reader.go
    │   │               ├── splitfunc.go
    │   │               └── trie.go
    │   ├── cpuguy83/
    │   │   └── go-md2man/
    │   │       └── v2/
    │   │           ├── LICENSE.md
    │   │           └── md2man/
    │   │               ├── debug.go
    │   │               ├── md2man.go
    │   │               └── roff.go
    │   ├── erikgeiser/
    │   │   └── coninput/
    │   │       ├── .gitignore
    │   │       ├── .golangci.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── keycodes.go
    │   │       ├── mode.go
    │   │       ├── read.go
    │   │       └── records.go
    │   ├── inconshreveable/
    │   │   └── mousetrap/
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── trap_others.go
    │   │       └── trap_windows.go
    │   ├── mattn/
    │   │   ├── go-isatty/
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── doc.go
    │   │   │   ├── go.test.sh
    │   │   │   ├── isatty_bsd.go
    │   │   │   ├── isatty_others.go
    │   │   │   ├── isatty_plan9.go
    │   │   │   ├── isatty_solaris.go
    │   │   │   ├── isatty_tcgets.go
    │   │   │   └── isatty_windows.go
    │   │   ├── go-localereader/
    │   │   │   ├── README.md
    │   │   │   ├── localereader.go
    │   │   │   ├── localereader_unix.go
    │   │   │   └── localereader_windows.go
    │   │   └── go-runewidth/
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── benchstat.txt
    │   │       ├── new.txt
    │   │       ├── old.txt
    │   │       ├── runewidth.go
    │   │       ├── runewidth_appengine.go
    │   │       ├── runewidth_js.go
    │   │       ├── runewidth_posix.go
    │   │       ├── runewidth_table.go
    │   │       └── runewidth_windows.go
    │   ├── muesli/
    │   │   ├── ansi/
    │   │   │   ├── .gitignore
    │   │   │   ├── .golangci.yml
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── ansi.go
    │   │   │   ├── buffer.go
    │   │   │   ├── compressor/
    │   │   │   │   └── writer.go
    │   │   │   └── writer.go
    │   │   ├── cancelreader/
    │   │   │   ├── .gitignore
    │   │   │   ├── .golangci-soft.yml
    │   │   │   ├── .golangci.yml
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── cancelreader.go
    │   │   │   ├── cancelreader_bsd.go
    │   │   │   ├── cancelreader_default.go
    │   │   │   ├── cancelreader_linux.go
    │   │   │   ├── cancelreader_select.go
    │   │   │   ├── cancelreader_unix.go
    │   │   │   └── cancelreader_windows.go
    │   │   ├── reflow/
    │   │   │   ├── LICENSE
    │   │   │   ├── ansi/
    │   │   │   │   ├── ansi.go
    │   │   │   │   ├── buffer.go
    │   │   │   │   └── writer.go
    │   │   │   └── wrap/
    │   │   │       └── wrap.go
    │   │   └── termenv/
    │   │       ├── .gitignore
    │   │       ├── .golangci-soft.yml
    │   │       ├── .golangci.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── ansi_compat.md
    │   │       ├── ansicolors.go
    │   │       ├── color.go
    │   │       ├── constants_linux.go
    │   │       ├── constants_solaris.go
    │   │       ├── constants_unix.go
    │   │       ├── constants_zos.go
    │   │       ├── copy.go
    │   │       ├── hyperlink.go
    │   │       ├── notification.go
    │   │       ├── output.go
    │   │       ├── profile.go
    │   │       ├── screen.go
    │   │       ├── style.go
    │   │       ├── templatehelper.go
    │   │       ├── termenv.go
    │   │       ├── termenv_other.go
    │   │       ├── termenv_posix.go
    │   │       ├── termenv_solaris.go
    │   │       ├── termenv_unix.go
    │   │       └── termenv_windows.go
    │   ├── rivo/
    │   │   └── uniseg/
    │   │       ├── LICENSE.txt
    │   │       ├── README.md
    │   │       ├── doc.go
    │   │       ├── eastasianwidth.go
    │   │       ├── emojipresentation.go
    │   │       ├── gen_breaktest.go
    │   │       ├── gen_properties.go
    │   │       ├── grapheme.go
    │   │       ├── graphemeproperties.go
    │   │       ├── graphemerules.go
    │   │       ├── line.go
    │   │       ├── lineproperties.go
    │   │       ├── linerules.go
    │   │       ├── properties.go
    │   │       ├── sentence.go
    │   │       ├── sentenceproperties.go
    │   │       ├── sentencerules.go
    │   │       ├── step.go
    │   │       ├── width.go
    │   │       ├── word.go
    │   │       ├── wordproperties.go
    │   │       └── wordrules.go
    │   ├── russross/
    │   │   └── blackfriday/
    │   │       └── v2/
    │   │           ├── .gitignore
    │   │           ├── .travis.yml
    │   │           ├── LICENSE.txt
    │   │           ├── README.md
    │   │           ├── block.go
    │   │           ├── doc.go
    │   │           ├── entities.go
    │   │           ├── esc.go
    │   │           ├── html.go
    │   │           ├── inline.go
    │   │           ├── markdown.go
    │   │           ├── node.go
    │   │           └── smartypants.go
    │   ├── spf13/
    │   │   ├── cobra/
    │   │   │   ├── .gitignore
    │   │   │   ├── .golangci.yml
    │   │   │   ├── .mailmap
    │   │   │   ├── CONDUCT.md
    │   │   │   ├── CONTRIBUTING.md
    │   │   │   ├── LICENSE.txt
    │   │   │   ├── MAINTAINERS
    │   │   │   ├── Makefile
    │   │   │   ├── README.md
    │   │   │   ├── SECURITY.md
    │   │   │   ├── active_help.go
    │   │   │   ├── args.go
    │   │   │   ├── bash_completions.go
    │   │   │   ├── bash_completionsV2.go
    │   │   │   ├── cobra.go
    │   │   │   ├── command.go
    │   │   │   ├── command_notwin.go
    │   │   │   ├── command_win.go
    │   │   │   ├── completions.go
    │   │   │   ├── doc/
    │   │   │   │   ├── man_docs.go
    │   │   │   │   ├── md_docs.go
    │   │   │   │   ├── rest_docs.go
    │   │   │   │   ├── util.go
    │   │   │   │   └── yaml_docs.go
    │   │   │   ├── fish_completions.go
    │   │   │   ├── flag_groups.go
    │   │   │   ├── powershell_completions.go
    │   │   │   ├── shell_completions.go
    │   │   │   └── zsh_completions.go
    │   │   └── pflag/
    │   │       ├── .editorconfig
    │   │       ├── .gitignore
    │   │       ├── .golangci.yaml
    │   │       ├── .travis.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── bool.go
    │   │       ├── bool_func.go
    │   │       ├── bool_slice.go
    │   │       ├── bytes.go
    │   │       ├── count.go
    │   │       ├── duration.go
    │   │       ├── duration_slice.go
    │   │       ├── errors.go
    │   │       ├── flag.go
    │   │       ├── float32.go
    │   │       ├── float32_slice.go
    │   │       ├── float64.go
    │   │       ├── float64_slice.go
    │   │       ├── func.go
    │   │       ├── golangflag.go
    │   │       ├── int.go
    │   │       ├── int16.go
    │   │       ├── int32.go
    │   │       ├── int32_slice.go
    │   │       ├── int64.go
    │   │       ├── int64_slice.go
    │   │       ├── int8.go
    │   │       ├── int_slice.go
    │   │       ├── ip.go
    │   │       ├── ip_slice.go
    │   │       ├── ipmask.go
    │   │       ├── ipnet.go
    │   │       ├── ipnet_slice.go
    │   │       ├── string.go
    │   │       ├── string_array.go
    │   │       ├── string_slice.go
    │   │       ├── string_to_int.go
    │   │       ├── string_to_int64.go
    │   │       ├── string_to_string.go
    │   │       ├── text.go
    │   │       ├── time.go
    │   │       ├── uint.go
    │   │       ├── uint16.go
    │   │       ├── uint32.go
    │   │       ├── uint64.go
    │   │       ├── uint8.go
    │   │       └── uint_slice.go
    │   └── xo/
    │       └── terminfo/
    │           ├── .gitignore
    │           ├── LICENSE
    │           ├── README.md
    │           ├── caps.go
    │           ├── capvals.go
    │           ├── color.go
    │           ├── dec.go
    │           ├── load.go
    │           ├── param.go
    │           ├── stack.go
    │           └── terminfo.go
    ├── go.yaml.in/
    │   └── yaml/
    │       └── v3/
    │           ├── LICENSE
    │           ├── NOTICE
    │           ├── README.md
    │           ├── apic.go
    │           ├── decode.go
    │           ├── emitterc.go
    │           ├── encode.go
    │           ├── parserc.go
    │           ├── readerc.go
    │           ├── resolve.go
    │           ├── scannerc.go
    │           ├── sorter.go
    │           ├── writerc.go
    │           ├── yaml.go
    │           ├── yamlh.go
    │           └── yamlprivateh.go
    ├── golang.org/
    │   └── x/
    │       ├── sys/
    │       │   ├── LICENSE
    │       │   ├── PATENTS
    │       │   ├── unix/
    │       │   │   ├── .gitignore
    │       │   │   ├── README.md
    │       │   │   ├── affinity_linux.go
    │       │   │   ├── aliases.go
    │       │   │   ├── asm_aix_ppc64.s
    │       │   │   ├── asm_bsd_386.s
    │       │   │   ├── asm_bsd_amd64.s
    │       │   │   ├── asm_bsd_arm.s
    │       │   │   ├── asm_bsd_arm64.s
    │       │   │   ├── asm_bsd_ppc64.s
    │       │   │   ├── asm_bsd_riscv64.s
    │       │   │   ├── asm_linux_386.s
    │       │   │   ├── asm_linux_amd64.s
    │       │   │   ├── asm_linux_arm.s
    │       │   │   ├── asm_linux_arm64.s
    │       │   │   ├── asm_linux_loong64.s
    │       │   │   ├── asm_linux_mips64x.s
    │       │   │   ├── asm_linux_mipsx.s
    │       │   │   ├── asm_linux_ppc64x.s
    │       │   │   ├── asm_linux_riscv64.s
    │       │   │   ├── asm_linux_s390x.s
    │       │   │   ├── asm_openbsd_mips64.s
    │       │   │   ├── asm_solaris_amd64.s
    │       │   │   ├── asm_zos_s390x.s
    │       │   │   ├── auxv.go
    │       │   │   ├── auxv_unsupported.go
    │       │   │   ├── bluetooth_linux.go
    │       │   │   ├── bpxsvc_zos.go
    │       │   │   ├── bpxsvc_zos.s
    │       │   │   ├── cap_freebsd.go
    │       │   │   ├── constants.go
    │       │   │   ├── dev_aix_ppc.go
    │       │   │   ├── dev_aix_ppc64.go
    │       │   │   ├── dev_darwin.go
    │       │   │   ├── dev_dragonfly.go
    │       │   │   ├── dev_freebsd.go
    │       │   │   ├── dev_linux.go
    │       │   │   ├── dev_netbsd.go
    │       │   │   ├── dev_openbsd.go
    │       │   │   ├── dev_zos.go
    │       │   │   ├── dirent.go
    │       │   │   ├── endian_big.go
    │       │   │   ├── endian_little.go
    │       │   │   ├── env_unix.go
    │       │   │   ├── fcntl.go
    │       │   │   ├── fcntl_darwin.go
    │       │   │   ├── fcntl_linux_32bit.go
    │       │   │   ├── fdset.go
    │       │   │   ├── gccgo.go
    │       │   │   ├── gccgo_c.c
    │       │   │   ├── gccgo_linux_amd64.go
    │       │   │   ├── ifreq_linux.go
    │       │   │   ├── ioctl_linux.go
    │       │   │   ├── ioctl_signed.go
    │       │   │   ├── ioctl_unsigned.go
    │       │   │   ├── ioctl_zos.go
    │       │   │   ├── mkall.sh
    │       │   │   ├── mkerrors.sh
    │       │   │   ├── mmap_nomremap.go
    │       │   │   ├── mremap.go
    │       │   │   ├── pagesize_unix.go
    │       │   │   ├── pledge_openbsd.go
    │       │   │   ├── ptrace_darwin.go
    │       │   │   ├── ptrace_ios.go
    │       │   │   ├── race.go
    │       │   │   ├── race0.go
    │       │   │   ├── readdirent_getdents.go
    │       │   │   ├── readdirent_getdirentries.go
    │       │   │   ├── sockcmsg_dragonfly.go
    │       │   │   ├── sockcmsg_linux.go
    │       │   │   ├── sockcmsg_unix.go
    │       │   │   ├── sockcmsg_unix_other.go
    │       │   │   ├── sockcmsg_zos.go
    │       │   │   ├── symaddr_zos_s390x.s
    │       │   │   ├── syscall.go
    │       │   │   ├── syscall_aix.go
    │       │   │   ├── syscall_aix_ppc.go
    │       │   │   ├── syscall_aix_ppc64.go
    │       │   │   ├── syscall_bsd.go
    │       │   │   ├── syscall_darwin.go
    │       │   │   ├── syscall_darwin_amd64.go
    │       │   │   ├── syscall_darwin_arm64.go
    │       │   │   ├── syscall_darwin_libSystem.go
    │       │   │   ├── syscall_dragonfly.go
    │       │   │   ├── syscall_dragonfly_amd64.go
    │       │   │   ├── syscall_freebsd.go
    │       │   │   ├── syscall_freebsd_386.go
    │       │   │   ├── syscall_freebsd_amd64.go
    │       │   │   ├── syscall_freebsd_arm.go
    │       │   │   ├── syscall_freebsd_arm64.go
    │       │   │   ├── syscall_freebsd_riscv64.go
    │       │   │   ├── syscall_hurd.go
    │       │   │   ├── syscall_hurd_386.go
    │       │   │   ├── syscall_illumos.go
    │       │   │   ├── syscall_linux.go
    │       │   │   ├── syscall_linux_386.go
    │       │   │   ├── syscall_linux_alarm.go
    │       │   │   ├── syscall_linux_amd64.go
    │       │   │   ├── syscall_linux_amd64_gc.go
    │       │   │   ├── syscall_linux_arm.go
    │       │   │   ├── syscall_linux_arm64.go
    │       │   │   ├── syscall_linux_gc.go
    │       │   │   ├── syscall_linux_gc_386.go
    │       │   │   ├── syscall_linux_gc_arm.go
    │       │   │   ├── syscall_linux_gccgo_386.go
    │       │   │   ├── syscall_linux_gccgo_arm.go
    │       │   │   ├── syscall_linux_loong64.go
    │       │   │   ├── syscall_linux_mips64x.go
    │       │   │   ├── syscall_linux_mipsx.go
    │       │   │   ├── syscall_linux_ppc.go
    │       │   │   ├── syscall_linux_ppc64x.go
    │       │   │   ├── syscall_linux_riscv64.go
    │       │   │   ├── syscall_linux_s390x.go
    │       │   │   ├── syscall_linux_sparc64.go
    │       │   │   ├── syscall_netbsd.go
    │       │   │   ├── syscall_netbsd_386.go
    │       │   │   ├── syscall_netbsd_amd64.go
    │       │   │   ├── syscall_netbsd_arm.go
    │       │   │   ├── syscall_netbsd_arm64.go
    │       │   │   ├── syscall_openbsd.go
    │       │   │   ├── syscall_openbsd_386.go
    │       │   │   ├── syscall_openbsd_amd64.go
    │       │   │   ├── syscall_openbsd_arm.go
    │       │   │   ├── syscall_openbsd_arm64.go
    │       │   │   ├── syscall_openbsd_libc.go
    │       │   │   ├── syscall_openbsd_mips64.go
    │       │   │   ├── syscall_openbsd_ppc64.go
    │       │   │   ├── syscall_openbsd_riscv64.go
    │       │   │   ├── syscall_solaris.go
    │       │   │   ├── syscall_solaris_amd64.go
    │       │   │   ├── syscall_unix.go
    │       │   │   ├── syscall_unix_gc.go
    │       │   │   ├── syscall_unix_gc_ppc64x.go
    │       │   │   ├── syscall_zos_s390x.go
    │       │   │   ├── sysvshm_linux.go
    │       │   │   ├── sysvshm_unix.go
    │       │   │   ├── sysvshm_unix_other.go
    │       │   │   ├── timestruct.go
    │       │   │   ├── unveil_openbsd.go
    │       │   │   ├── vgetrandom_linux.go
    │       │   │   ├── vgetrandom_unsupported.go
    │       │   │   ├── xattr_bsd.go
    │       │   │   ├── zerrors_aix_ppc.go
    │       │   │   ├── zerrors_aix_ppc64.go
    │       │   │   ├── zerrors_darwin_amd64.go
    │       │   │   ├── zerrors_darwin_arm64.go
    │       │   │   ├── zerrors_dragonfly_amd64.go
    │       │   │   ├── zerrors_freebsd_386.go
    │       │   │   ├── zerrors_freebsd_amd64.go
    │       │   │   ├── zerrors_freebsd_arm.go
    │       │   │   ├── zerrors_freebsd_arm64.go
    │       │   │   ├── zerrors_freebsd_riscv64.go
    │       │   │   ├── zerrors_linux.go
    │       │   │   ├── zerrors_linux_386.go
    │       │   │   ├── zerrors_linux_amd64.go
    │       │   │   ├── zerrors_linux_arm.go
    │       │   │   ├── zerrors_linux_arm64.go
    │       │   │   ├── zerrors_linux_loong64.go
    │       │   │   ├── zerrors_linux_mips.go
    │       │   │   ├── zerrors_linux_mips64.go
    │       │   │   ├── zerrors_linux_mips64le.go
    │       │   │   ├── zerrors_linux_mipsle.go
    │       │   │   ├── zerrors_linux_ppc.go
    │       │   │   ├── zerrors_linux_ppc64.go
    │       │   │   ├── zerrors_linux_ppc64le.go
    │       │   │   ├── zerrors_linux_riscv64.go
    │       │   │   ├── zerrors_linux_s390x.go
    │       │   │   ├── zerrors_linux_sparc64.go
    │       │   │   ├── zerrors_netbsd_386.go
    │       │   │   ├── zerrors_netbsd_amd64.go
    │       │   │   ├── zerrors_netbsd_arm.go
    │       │   │   ├── zerrors_netbsd_arm64.go
    │       │   │   ├── zerrors_openbsd_386.go
    │       │   │   ├── zerrors_openbsd_amd64.go
    │       │   │   ├── zerrors_openbsd_arm.go
    │       │   │   ├── zerrors_openbsd_arm64.go
    │       │   │   ├── zerrors_openbsd_mips64.go
    │       │   │   ├── zerrors_openbsd_ppc64.go
    │       │   │   ├── zerrors_openbsd_riscv64.go
    │       │   │   ├── zerrors_solaris_amd64.go
    │       │   │   ├── zerrors_zos_s390x.go
    │       │   │   ├── zptrace_armnn_linux.go
    │       │   │   ├── zptrace_linux_arm64.go
    │       │   │   ├── zptrace_mipsnn_linux.go
    │       │   │   ├── zptrace_mipsnnle_linux.go
    │       │   │   ├── zptrace_x86_linux.go
    │       │   │   ├── zsymaddr_zos_s390x.s
    │       │   │   ├── zsyscall_aix_ppc.go
    │       │   │   ├── zsyscall_aix_ppc64.go
    │       │   │   ├── zsyscall_aix_ppc64_gc.go
    │       │   │   ├── zsyscall_aix_ppc64_gccgo.go
    │       │   │   ├── zsyscall_darwin_amd64.go
    │       │   │   ├── zsyscall_darwin_amd64.s
    │       │   │   ├── zsyscall_darwin_arm64.go
    │       │   │   ├── zsyscall_darwin_arm64.s
    │       │   │   ├── zsyscall_dragonfly_amd64.go
    │       │   │   ├── zsyscall_freebsd_386.go
    │       │   │   ├── zsyscall_freebsd_amd64.go
    │       │   │   ├── zsyscall_freebsd_arm.go
    │       │   │   ├── zsyscall_freebsd_arm64.go
    │       │   │   ├── zsyscall_freebsd_riscv64.go
    │       │   │   ├── zsyscall_illumos_amd64.go
    │       │   │   ├── zsyscall_linux.go
    │       │   │   ├── zsyscall_linux_386.go
    │       │   │   ├── zsyscall_linux_amd64.go
    │       │   │   ├── zsyscall_linux_arm.go
    │       │   │   ├── zsyscall_linux_arm64.go
    │       │   │   ├── zsyscall_linux_loong64.go
    │       │   │   ├── zsyscall_linux_mips.go
    │       │   │   ├── zsyscall_linux_mips64.go
    │       │   │   ├── zsyscall_linux_mips64le.go
    │       │   │   ├── zsyscall_linux_mipsle.go
    │       │   │   ├── zsyscall_linux_ppc.go
    │       │   │   ├── zsyscall_linux_ppc64.go
    │       │   │   ├── zsyscall_linux_ppc64le.go
    │       │   │   ├── zsyscall_linux_riscv64.go
    │       │   │   ├── zsyscall_linux_s390x.go
    │       │   │   ├── zsyscall_linux_sparc64.go
    │       │   │   ├── zsyscall_netbsd_386.go
    │       │   │   ├── zsyscall_netbsd_amd64.go
    │       │   │   ├── zsyscall_netbsd_arm.go
    │       │   │   ├── zsyscall_netbsd_arm64.go
    │       │   │   ├── zsyscall_openbsd_386.go
    │       │   │   ├── zsyscall_openbsd_386.s
    │       │   │   ├── zsyscall_openbsd_amd64.go
    │       │   │   ├── zsyscall_openbsd_amd64.s
    │       │   │   ├── zsyscall_openbsd_arm.go
    │       │   │   ├── zsyscall_openbsd_arm.s
    │       │   │   ├── zsyscall_openbsd_arm64.go
    │       │   │   ├── zsyscall_openbsd_arm64.s
    │       │   │   ├── zsyscall_openbsd_mips64.go
    │       │   │   ├── zsyscall_openbsd_mips64.s
    │       │   │   ├── zsyscall_openbsd_ppc64.go
    │       │   │   ├── zsyscall_openbsd_ppc64.s
    │       │   │   ├── zsyscall_openbsd_riscv64.go
    │       │   │   ├── zsyscall_openbsd_riscv64.s
    │       │   │   ├── zsyscall_solaris_amd64.go
    │       │   │   ├── zsyscall_zos_s390x.go
    │       │   │   ├── zsysctl_openbsd_386.go
    │       │   │   ├── zsysctl_openbsd_amd64.go
    │       │   │   ├── zsysctl_openbsd_arm.go
    │       │   │   ├── zsysctl_openbsd_arm64.go
    │       │   │   ├── zsysctl_openbsd_mips64.go
    │       │   │   ├── zsysctl_openbsd_ppc64.go
    │       │   │   ├── zsysctl_openbsd_riscv64.go
    │       │   │   ├── zsysnum_darwin_amd64.go
    │       │   │   ├── zsysnum_darwin_arm64.go
    │       │   │   ├── zsysnum_dragonfly_amd64.go
    │       │   │   ├── zsysnum_freebsd_386.go
    │       │   │   ├── zsysnum_freebsd_amd64.go
    │       │   │   ├── zsysnum_freebsd_arm.go
    │       │   │   ├── zsysnum_freebsd_arm64.go
    │       │   │   ├── zsysnum_freebsd_riscv64.go
    │       │   │   ├── zsysnum_linux_386.go
    │       │   │   ├── zsysnum_linux_amd64.go
    │       │   │   ├── zsysnum_linux_arm.go
    │       │   │   ├── zsysnum_linux_arm64.go
    │       │   │   ├── zsysnum_linux_loong64.go
    │       │   │   ├── zsysnum_linux_mips.go
    │       │   │   ├── zsysnum_linux_mips64.go
    │       │   │   ├── zsysnum_linux_mips64le.go
    │       │   │   ├── zsysnum_linux_mipsle.go
    │       │   │   ├── zsysnum_linux_ppc.go
    │       │   │   ├── zsysnum_linux_ppc64.go
    │       │   │   ├── zsysnum_linux_ppc64le.go
    │       │   │   ├── zsysnum_linux_riscv64.go
    │       │   │   ├── zsysnum_linux_s390x.go
    │       │   │   ├── zsysnum_linux_sparc64.go
    │       │   │   ├── zsysnum_netbsd_386.go
    │       │   │   ├── zsysnum_netbsd_amd64.go
    │       │   │   ├── zsysnum_netbsd_arm.go
    │       │   │   ├── zsysnum_netbsd_arm64.go
    │       │   │   ├── zsysnum_openbsd_386.go
    │       │   │   ├── zsysnum_openbsd_amd64.go
    │       │   │   ├── zsysnum_openbsd_arm.go
    │       │   │   ├── zsysnum_openbsd_arm64.go
    │       │   │   ├── zsysnum_openbsd_mips64.go
    │       │   │   ├── zsysnum_openbsd_ppc64.go
    │       │   │   ├── zsysnum_openbsd_riscv64.go
    │       │   │   ├── zsysnum_zos_s390x.go
    │       │   │   ├── ztypes_aix_ppc.go
    │       │   │   ├── ztypes_aix_ppc64.go
    │       │   │   ├── ztypes_darwin_amd64.go
    │       │   │   ├── ztypes_darwin_arm64.go
    │       │   │   ├── ztypes_dragonfly_amd64.go
    │       │   │   ├── ztypes_freebsd_386.go
    │       │   │   ├── ztypes_freebsd_amd64.go
    │       │   │   ├── ztypes_freebsd_arm.go
    │       │   │   ├── ztypes_freebsd_arm64.go
    │       │   │   ├── ztypes_freebsd_riscv64.go
    │       │   │   ├── ztypes_linux.go
    │       │   │   ├── ztypes_linux_386.go
    │       │   │   ├── ztypes_linux_amd64.go
    │       │   │   ├── ztypes_linux_arm.go
    │       │   │   ├── ztypes_linux_arm64.go
    │       │   │   ├── ztypes_linux_loong64.go
    │       │   │   ├── ztypes_linux_mips.go
    │       │   │   ├── ztypes_linux_mips64.go
    │       │   │   ├── ztypes_linux_mips64le.go
    │       │   │   ├── ztypes_linux_mipsle.go
    │       │   │   ├── ztypes_linux_ppc.go
    │       │   │   ├── ztypes_linux_ppc64.go
    │       │   │   ├── ztypes_linux_ppc64le.go
    │       │   │   ├── ztypes_linux_riscv64.go
    │       │   │   ├── ztypes_linux_s390x.go
    │       │   │   ├── ztypes_linux_sparc64.go
    │       │   │   ├── ztypes_netbsd_386.go
    │       │   │   ├── ztypes_netbsd_amd64.go
    │       │   │   ├── ztypes_netbsd_arm.go
    │       │   │   ├── ztypes_netbsd_arm64.go
    │       │   │   ├── ztypes_openbsd_386.go
    │       │   │   ├── ztypes_openbsd_amd64.go
    │       │   │   ├── ztypes_openbsd_arm.go
    │       │   │   ├── ztypes_openbsd_arm64.go
    │       │   │   ├── ztypes_openbsd_mips64.go
    │       │   │   ├── ztypes_openbsd_ppc64.go
    │       │   │   ├── ztypes_openbsd_riscv64.go
    │       │   │   ├── ztypes_solaris_amd64.go
    │       │   │   └── ztypes_zos_s390x.go
    │       │   └── windows/
    │       │       ├── aliases.go
    │       │       ├── dll_windows.go
    │       │       ├── env_windows.go
    │       │       ├── eventlog.go
    │       │       ├── exec_windows.go
    │       │       ├── memory_windows.go
    │       │       ├── mkerrors.bash
    │       │       ├── mkknownfolderids.bash
    │       │       ├── mksyscall.go
    │       │       ├── race.go
    │       │       ├── race0.go
    │       │       ├── security_windows.go
    │       │       ├── service.go
    │       │       ├── setupapi_windows.go
    │       │       ├── str.go
    │       │       ├── syscall.go
    │       │       ├── syscall_windows.go
    │       │       ├── types_windows.go
    │       │       ├── types_windows_386.go
    │       │       ├── types_windows_amd64.go
    │       │       ├── types_windows_arm.go
    │       │       ├── types_windows_arm64.go
    │       │       ├── zerrors_windows.go
    │       │       ├── zknownfolderids_windows.go
    │       │       └── zsyscall_windows.go
    │       └── text/
    │           ├── LICENSE
    │           ├── PATENTS
    │           └── transform/
    │               └── transform.go
    └── modules.txt
Download .txt
Showing preview only (8,654K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (103001 symbols across 738 files)

FILE: cmd/witr/main.go
  function main (line 16) | func main() {

FILE: cmd/witr/unsupported.go
  function main (line 10) | func main() {

FILE: internal/app/app.go
  function _genExamples (line 44) | func _genExamples() string {
  constant ExitOK (line 98) | ExitOK            = 0
  constant ExitWarnings (line 99) | ExitWarnings      = 1
  constant ExitInternalError (line 100) | ExitInternalError = 1
  constant ExitNotFound (line 101) | ExitNotFound      = 2
  constant ExitPermission (line 102) | ExitPermission    = 3
  constant ExitInvalidInput (line 103) | ExitInvalidInput  = 4
  type exitCodeError (line 107) | type exitCodeError struct
    method Error (line 112) | func (e *exitCodeError) Error() string { return e.err.Error() }
    method Unwrap (line 113) | func (e *exitCodeError) Unwrap() error { return e.err }
  function withExitCode (line 115) | func withExitCode(code int, err error) error {
  function Execute (line 119) | func Execute() {
  function init (line 132) | func init() {
  type appFlags (line 154) | type appFlags struct
  function runApp (line 165) | func runApp(cmd *cobra.Command, args []string) error {
  function boolFlag (line 241) | func boolFlag(cmd *cobra.Command, name string) bool {
  function collectTargetsInOrder (line 248) | func collectTargetsInOrder(rawArgs []string, positionalArgs []string) []...
  function targetLabel (line 322) | func targetLabel(t model.Target) string {
  function printDivider (line 335) | func printDivider(outp output.Printer, t model.Target, colorEnabled bool...
  function jsonErrorEntry (line 348) | func jsonErrorEntry(t model.Target, errMsg string) string {
  function processTarget (line 359) | func processTarget(cmd *cobra.Command, outw io.Writer, outp output.Print...
  function processEnvTarget (line 442) | func processEnvTarget(outw io.Writer, outp output.Printer, t model.Targe...
  function handleResolveError (line 501) | func handleResolveError(cmd *cobra.Command, outw io.Writer, outp output....
  function renderResult (line 556) | func renderResult(outw io.Writer, res model.Result, flags appFlags, mult...
  function Root (line 593) | func Root() *cobra.Command { return rootCmd }
  function runInteractive (line 595) | func runInteractive() error {
  function printMultiMatch (line 603) | func printMultiMatch(outp output.Printer, pids []int, colorEnabled bool,...
  function classifyError (line 629) | func classifyError(err error) int {
  function SetVersion (line 649) | func SetVersion(v string, c string, bd string) {

FILE: internal/launchd/plist.go
  type LaunchdInfo (line 17) | type LaunchdInfo struct
    method FormatTriggers (line 457) | func (info *LaunchdInfo) FormatTriggers() []string {
    method DomainDescription (line 501) | func (info *LaunchdInfo) DomainDescription() string {
  type plistDict (line 37) | type plistDict struct
  type plistValue (line 42) | type plistValue struct
  function GetServiceLabel (line 60) | func GetServiceLabel(pid int) (string, string, error) {
  function findServiceByPID (line 108) | func findServiceByPID(pid int) (string, string) {
  function FindPlistPath (line 133) | func FindPlistPath(label string) string {
  function ParsePlist (line 152) | func ParsePlist(path string) (*LaunchdInfo, error) {
  function parsePlistXML (line 172) | func parsePlistXML(data []byte, info *LaunchdInfo) error {
  function parseArray (line 253) | func parseArray(decoder *xml.Decoder) []string {
  function parseCalendarDict (line 283) | func parseCalendarDict(decoder *xml.Decoder) map[string]int {
  function parseCalendarArray (line 319) | func parseCalendarArray(decoder *xml.Decoder) string {
  function formatCalendarInterval (line 353) | func formatCalendarInterval(cal map[string]int) string {
  function handleStringValue (line 388) | func handleStringValue(info *LaunchdInfo, key, val string) {
  function handleIntValue (line 399) | func handleIntValue(info *LaunchdInfo, key string, val int) {
  function handleBoolValue (line 406) | func handleBoolValue(info *LaunchdInfo, key string, val bool) {
  function handleArrayValue (line 415) | func handleArrayValue(info *LaunchdInfo, key string, val []string) {
  function GetLaunchdInfo (line 427) | func GetLaunchdInfo(pid int) (*LaunchdInfo, error) {
  function formatDuration (line 487) | func formatDuration(seconds int) string {

FILE: internal/output/children.go
  function PrintChildren (line 9) | func PrintChildren(w io.Writer, root model.Process, children []model.Pro...

FILE: internal/output/docker.go
  function dockerSourceLabel (line 12) | func dockerSourceLabel(match *model.DockerPortMatch) string {
  function RenderDockerFallback (line 21) | func RenderDockerFallback(w io.Writer, portValue string, match *model.Do...
  function RenderDockerFallbackShort (line 88) | func RenderDockerFallbackShort(w io.Writer, portValue string, match *mod...
  function DockerFallbackToJSON (line 101) | func DockerFallbackToJSON(portValue string, match *model.DockerPortMatch...

FILE: internal/output/docker_test.go
  function TestRenderDockerFallback (line 12) | func TestRenderDockerFallback(t *testing.T) {
  function TestRenderDockerFallbackWithCompose (line 42) | func TestRenderDockerFallbackWithCompose(t *testing.T) {
  function TestRenderDockerFallbackShort (line 61) | func TestRenderDockerFallbackShort(t *testing.T) {
  function TestDockerFallbackToJSON (line 88) | func TestDockerFallbackToJSON(t *testing.T) {
  function TestDockerFallbackToJSONCompose (line 119) | func TestDockerFallbackToJSONCompose(t *testing.T) {
  function TestRenderDockerFallbackSanitizesOutput (line 144) | func TestRenderDockerFallbackSanitizesOutput(t *testing.T) {

FILE: internal/output/envonly.go
  function RenderEnvOnly (line 10) | func RenderEnvOnly(w io.Writer, r model.Result, colorEnabled bool) {

FILE: internal/output/json.go
  function ToJSON (line 9) | func ToJSON(r model.Result) (string, error) {
  type shortProcess (line 17) | type shortProcess struct
  function ToShortJSON (line 22) | func ToShortJSON(r model.Result) (string, error) {
  function ToTreeJSON (line 34) | func ToTreeJSON(r model.Result) (string, error) {
  function ToWarningsJSON (line 62) | func ToWarningsJSON(r model.Result) (string, error) {
  function ToEnvJSON (line 101) | func ToEnvJSON(r model.Result) (string, error) {

FILE: internal/output/printer.go
  type ansiString (line 8) | type ansiString
  type Printer (line 12) | type Printer struct
    method Printf (line 20) | func (p Printer) Printf(format string, args ...any) {
    method Print (line 24) | func (p Printer) Print(args ...any) {
    method Println (line 28) | func (p Printer) Println(args ...any) {
  function NewPrinter (line 16) | func NewPrinter(w io.Writer) Printer {
  function sanitizePrintArgs (line 32) | func sanitizePrintArgs(args []any) []any {

FILE: internal/output/safe_writer.go
  type SafeTerminalWriter (line 8) | type SafeTerminalWriter struct
    method Write (line 12) | func (w SafeTerminalWriter) Write(p []byte) (int, error) {
  function NewSafeTerminalWriter (line 23) | func NewSafeTerminalWriter(w io.Writer) io.Writer {

FILE: internal/output/sanitize.go
  constant hexDigits (line 9) | hexDigits = "0123456789abcdef"
  function SanitizeTerminal (line 18) | func SanitizeTerminal(s string) string {
  function appendEscapedByte (line 71) | func appendEscapedByte(b *strings.Builder, bt byte) {
  function appendEscapedRune (line 81) | func appendEscapedRune(b *strings.Builder, r rune) {

FILE: internal/output/sanitize_test.go
  function FuzzAppendEscapedRune (line 10) | func FuzzAppendEscapedRune(f *testing.F) {

FILE: internal/output/short.go
  function RenderShort (line 9) | func RenderShort(w io.Writer, r model.Result, colorEnabled bool) {

FILE: internal/output/standard.go
  constant MaxDisplayItems (line 16) | MaxDisplayItems = 10
  function formatDetailLabel (line 25) | func formatDetailLabel(key string) string {
  function RenderWarnings (line 32) | func RenderWarnings(w io.Writer, r model.Result, colorEnabled bool) {
  function RenderStandard (line 80) | func RenderStandard(w io.Writer, r model.Result, colorEnabled bool, verb...

FILE: internal/output/tree.go
  function PrintTree (line 10) | func PrintTree(w io.Writer, chain []model.Process, children []model.Proc...

FILE: internal/pipeline/analyze.go
  type AnalyzeConfig (line 12) | type AnalyzeConfig struct
  function AnalyzePID (line 19) | func AnalyzePID(cfg AnalyzeConfig) (model.Result, error) {

FILE: internal/proc/ancestry.go
  function ResolveAncestry (line 9) | func ResolveAncestry(pid int) ([]model.Process, error) {

FILE: internal/proc/boot_darwin.go
  function bootTime (line 12) | func bootTime() time.Time {
  function ticksPerSecond (line 36) | func ticksPerSecond() int {

FILE: internal/proc/boot_freebsd.go
  function bootTime (line 12) | func bootTime() time.Time {
  function ticksPerSecond (line 36) | func ticksPerSecond() int {

FILE: internal/proc/boot_linux.go
  function bootTime (line 13) | func bootTime() time.Time {
  function ticksPerSecond (line 35) | func ticksPerSecond() int {

FILE: internal/proc/boot_windows.go
  function bootTime (line 11) | func bootTime() time.Time {

FILE: internal/proc/capabilities_linux.go
  function ReadCapabilities (line 58) | func ReadCapabilities(pid int) []string {
  function decodeCapabilities (line 74) | func decodeCapabilities(hex string) []string {

FILE: internal/proc/children_unix.go
  function ResolveChildren (line 12) | func ResolveChildren(pid int) ([]model.Process, error) {

FILE: internal/proc/children_windows.go
  function ResolveChildren (line 14) | func ResolveChildren(pid int) ([]model.Process, error) {

FILE: internal/proc/cmdline_darwin.go
  function GetCmdline (line 12) | func GetCmdline(pid int) string {

FILE: internal/proc/cmdline_freebsd.go
  function GetCmdline (line 12) | func GetCmdline(pid int) string {

FILE: internal/proc/cmdline_linux.go
  function GetCmdline (line 12) | func GetCmdline(pid int) string {

FILE: internal/proc/cmdline_windows.go
  function GetCmdline (line 12) | func GetCmdline(pid int) string {

FILE: internal/proc/command.go
  function deriveDisplayCommand (line 12) | func deriveDisplayCommand(comm, cmdline string) string {
  function containsWholeWord (line 29) | func containsWholeWord(s, word string) bool {
  function isWordChar (line 48) | func isWordChar(c byte) bool {
  function extractExecutableName (line 52) | func extractExecutableName(cmdline string) string {

FILE: internal/proc/command_test.go
  function TestDeriveDisplayCommand (line 7) | func TestDeriveDisplayCommand(t *testing.T) {
  function TestContainsWholeWord (line 77) | func TestContainsWholeWord(t *testing.T) {
  function TestExtractExecutableName (line 102) | func TestExtractExecutableName(t *testing.T) {

FILE: internal/proc/container.go
  function ResolveContainerByPort (line 16) | func ResolveContainerByPort(port int) *model.DockerPortMatch {
  function resolveContainerName (line 57) | func resolveContainerName(id, runtime string) string {
  function findLongHexID (line 124) | func findLongHexID(s string) string {
  function shortID (line 147) | func shortID(id string) string {
  function extractFlagValue (line 155) | func extractFlagValue(cmdline string, flags ...string) string {
  function splitCmdline (line 168) | func splitCmdline(cmdline string) []string {

FILE: internal/proc/container_detect.go
  function detectContainerFromCmdline (line 7) | func detectContainerFromCmdline(cmdline string) string {

FILE: internal/proc/container_test.go
  function TestSplitCmdline (line 7) | func TestSplitCmdline(t *testing.T) {
  function TestFindLongHexID (line 32) | func TestFindLongHexID(t *testing.T) {
  function TestExtractFlagValue (line 52) | func TestExtractFlagValue(t *testing.T) {

FILE: internal/proc/docker_proxy.go
  function resolveDockerProxyContainer (line 8) | func resolveDockerProxyContainer(cmdline string) string {

FILE: internal/proc/extended_darwin.go
  function ReadExtendedInfo (line 16) | func ReadExtendedInfo(pid int) (model.MemoryInfo, model.IOStats, []strin...
  function detectDarwinFileLimit (line 32) | func detectDarwinFileLimit() uint64 {
  function parseLaunchctlLimitLine (line 50) | func parseLaunchctlLimitLine(line string) (uint64, bool) {

FILE: internal/proc/extended_darwin_test.go
  function TestParseLaunchctlLimitLine (line 7) | func TestParseLaunchctlLimitLine(t *testing.T) {

FILE: internal/proc/extended_freebsd.go
  function ReadExtendedInfo (line 16) | func ReadExtendedInfo(pid int) (model.MemoryInfo, model.IOStats, []strin...

FILE: internal/proc/extended_linux.go
  function ReadExtendedInfo (line 16) | func ReadExtendedInfo(pid int) (model.MemoryInfo, model.IOStats, []strin...

FILE: internal/proc/extended_windows.go
  function ReadExtendedInfo (line 16) | func ReadExtendedInfo(pid int) (model.MemoryInfo, model.IOStats, []strin...

FILE: internal/proc/fd_darwin.go
  function socketsForPID (line 13) | func socketsForPID(pid int) []string {

FILE: internal/proc/fd_freebsd.go
  function socketsForPID (line 13) | func socketsForPID(pid int) []string {

FILE: internal/proc/fd_linux.go
  function socketsForPID (line 12) | func socketsForPID(pid int) []string {

FILE: internal/proc/filecontext_darwin.go
  function GetFileContext (line 15) | func GetFileContext(pid int) *model.FileContext {
  function getOpenFileCount (line 43) | func getOpenFileCount(pid int) (int, int) {
  function getFileLimit (line 69) | func getFileLimit(pid int) int {
  function getLockedFiles (line 92) | func getLockedFiles(pid int) []string {

FILE: internal/proc/filecontext_freebsd.go
  function GetFileContext (line 15) | func GetFileContext(pid int) *model.FileContext {
  function getOpenFileCount (line 43) | func getOpenFileCount(fstatOut []byte, pid int) (int, int) {
  function getFileLimit (line 65) | func getFileLimit(pid int) int {
  function getLockedFiles (line 96) | func getLockedFiles(fstatOut []byte) []string {

FILE: internal/proc/filecontext_linux.go
  function GetFileContext (line 20) | func GetFileContext(pid int) *model.FileContext {
  function getFileLimit (line 37) | func getFileLimit(pid int) int {
  function getDefaultMaxOpenFiles (line 74) | func getDefaultMaxOpenFiles() int {
  function getLockedFiles (line 88) | func getLockedFiles(pid int) []string {
  function getLockedFilesLslocks (line 96) | func getLockedFilesLslocks(pid int) ([]string, error) {
  function getLockedFilesProc (line 118) | func getLockedFilesProc(pid int) []string {
  function getWatchedDirs (line 158) | func getWatchedDirs(fdDir string, entries []os.DirEntry) []string {

FILE: internal/proc/filecontext_windows.go
  function GetFileContext (line 7) | func GetFileContext(pid int) *model.FileContext {

FILE: internal/proc/git.go
  function detectGitInfo (line 9) | func detectGitInfo(cwd string) (string, string) {

FILE: internal/proc/libproc_darwin_cgo.go
  function readDarwinIO (line 117) | func readDarwinIO(pid int) (model.IOStats, error) {
  function readDarwinTaskInfo (line 135) | func readDarwinTaskInfo(pid int) (model.MemoryInfo, int, error) {
  function readDarwinFDs (line 156) | func readDarwinFDs(pid int) (int, []string, error) {
  function formatFDEntries (line 184) | func formatFDEntries(pid int, entries []C.struct_proc_fdinfo) []string {
  function fdTypeLabel (line 218) | func fdTypeLabel(fdType C.uint32_t) string {
  function describeSocket (line 239) | func describeSocket(info *C.struct_socket_fdinfo) string {

FILE: internal/proc/libproc_darwin_stub.go
  function readDarwinIO (line 7) | func readDarwinIO(pid int) (model.IOStats, error) {
  function readDarwinTaskInfo (line 11) | func readDarwinTaskInfo(pid int) (model.MemoryInfo, int, error) {
  function readDarwinFDs (line 15) | func readDarwinFDs(pid int) (int, []string, error) {

FILE: internal/proc/libproc_darwin_test.go
  function TestReadDarwinIO (line 10) | func TestReadDarwinIO(t *testing.T) {

FILE: internal/proc/net_darwin.go
  function ListOpenPorts (line 13) | func ListOpenPorts() ([]model.OpenPort, error) {
  function parseNetstatAddr (line 89) | func parseNetstatAddr(addr string) (string, int) {

FILE: internal/proc/net_freebsd.go
  function ListOpenPorts (line 15) | func ListOpenPorts() ([]model.OpenPort, error) {
  function extractPID (line 41) | func extractPID(inode string) int {
  function readListeningSockets (line 50) | func readListeningSockets() (map[string]model.Socket, error) {
  function parseSockstatOutput (line 71) | func parseSockstatOutput(output string, sockets map[string]model.Socket) {
  function parseSockstatAddr (line 124) | func parseSockstatAddr(addr string, proto string) (string, int) {

FILE: internal/proc/net_linux.go
  function readSocketsCached (line 28) | func readSocketsCached() (map[string]model.Socket, error) {
  function readSockets (line 59) | func readSockets() (map[string]model.Socket, error) {
  function parseAddr (line 106) | func parseAddr(raw string, ipv6 bool) (string, int) {
  function ListOpenPorts (line 147) | func ListOpenPorts() ([]model.OpenPort, error) {

FILE: internal/proc/net_linux_test.go
  function encodeProcNetTCP6 (line 12) | func encodeProcNetTCP6(ip net.IP, port int) string {
  function TestParseAddr (line 32) | func TestParseAddr(t *testing.T) {

FILE: internal/proc/net_windows.go
  function ListOpenPorts (line 12) | func ListOpenPorts() ([]model.OpenPort, error) {
  function GetListeningPortsForPID (line 82) | func GetListeningPortsForPID(pid int) ([]int, []string) {

FILE: internal/proc/peb_windows.go
  constant PROCESS_QUERY_INFORMATION (line 15) | PROCESS_QUERY_INFORMATION         = 0x0400
  constant PROCESS_VM_READ (line 16) | PROCESS_VM_READ                   = 0x0010
  constant PROCESS_QUERY_LIMITED_INFORMATION (line 17) | PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
  constant TH32CS_SNAPPROCESS (line 19) | TH32CS_SNAPPROCESS = 0x00000002
  type processBasicInformation (line 34) | type processBasicInformation struct
  type unicodeString (line 43) | type unicodeString struct
  type rtlUserProcessParameters (line 50) | type rtlUserProcessParameters struct
  type PROCESSENTRY32 (line 61) | type PROCESSENTRY32 struct
  type Win32ProcessInfo (line 74) | type Win32ProcessInfo struct
  function GetProcessDetailedInfo (line 83) | func GetProcessDetailedInfo(pid int) (Win32ProcessInfo, error) {
  function getFullProcessInfo (line 135) | func getFullProcessInfo(handle syscall.Handle, pid int, info *Win32Proce...
  function readProcessMemory (line 182) | func readProcessMemory(handle syscall.Handle, addr uintptr, dest unsafe....
  function readUnicodeString (line 194) | func readUnicodeString(handle syscall.Handle, us unicodeString) string {
  function getProcessStartTime (line 205) | func getProcessStartTime(handle syscall.Handle) time.Time {
  function getProcessImageName (line 220) | func getProcessImageName(handle syscall.Handle) string {
  function getInfoFromSnapshot (line 236) | func getInfoFromSnapshot(pid int) (int, string, error) {

FILE: internal/proc/process_darwin.go
  function ReadProcess (line 16) | func ReadProcess(pid int) (model.Process, error) {
  function getCwdAndBinaryPath (line 145) | func getCwdAndBinaryPath(pid int) (cwd string, binPath string) {
  function getEnvironment (line 183) | func getEnvironment(pid int) []string {
  function isEnvVarName (line 217) | func isEnvVarName(name string) bool {
  function detectLaunchdService (line 230) | func detectLaunchdService(pid int) string {

FILE: internal/proc/process_darwin_test.go
  function TestGetCwdAndBinaryPath (line 12) | func TestGetCwdAndBinaryPath(t *testing.T) {

FILE: internal/proc/process_freebsd.go
  function ReadProcess (line 16) | func ReadProcess(pid int) (model.Process, error) {
  function getCwdAndBinaryPath (line 145) | func getCwdAndBinaryPath(pid int) (cwd string, binPath string) {
  function parseLstart (line 172) | func parseLstart(lstartStr string) time.Time {
  function getEnvironment (line 191) | func getEnvironment(pid int) []string {
  function detectContainerFreeBSD (line 221) | func detectContainerFreeBSD(jid, cmdline string) string {
  function detectRcService (line 231) | func detectRcService(pid int) string {
  function resolveJailName (line 262) | func resolveJailName(jid string) string {

FILE: internal/proc/process_linux.go
  function isValidSymlinkTarget (line 17) | func isValidSymlinkTarget(target string) bool {
  function ReadProcess (line 21) | func ReadProcess(pid int) (model.Process, error) {
  function isBinaryDeleted (line 287) | func isBinaryDeleted(pid int) bool {
  function processState (line 296) | func processState(fields []string) string {
  function isDualStackEnabled (line 309) | func isDualStackEnabled() bool {
  function extractContainerID (line 317) | func extractContainerID(cgroup, dashPrefix, slashPrefix string) string {

FILE: internal/proc/process_list_darwin.go
  function ListProcesses (line 18) | func ListProcesses() ([]model.Process, error) {
  function ListProcessSnapshot (line 97) | func ListProcessSnapshot() ([]model.Process, error) {

FILE: internal/proc/process_list_freebsd.go
  function ListProcesses (line 18) | func ListProcesses() ([]model.Process, error) {
  function ListProcessSnapshot (line 96) | func ListProcessSnapshot() ([]model.Process, error) {

FILE: internal/proc/process_list_linux.go
  function ListProcesses (line 18) | func ListProcesses() ([]model.Process, error) {
  function ListProcessSnapshot (line 97) | func ListProcessSnapshot() ([]model.Process, error) {
  function parseStatSnapshot (line 131) | func parseStatSnapshot(pid int, stat []byte) (model.Process, error) {

FILE: internal/proc/process_list_windows.go
  function ListProcesses (line 17) | func ListProcesses() ([]model.Process, error) {
  function ListProcessSnapshot (line 24) | func ListProcessSnapshot() ([]model.Process, error) {

FILE: internal/proc/process_windows.go
  function ReadProcess (line 15) | func ReadProcess(pid int) (model.Process, error) {
  function isWindowsBinaryDeleted (line 53) | func isWindowsBinaryDeleted(path string) bool {
  function detectWindowsServiceSource (line 63) | func detectWindowsServiceSource(pid int) string {

FILE: internal/proc/psenv_unix.go
  function buildEnvForPS (line 10) | func buildEnvForPS() []string {

FILE: internal/proc/resource_darwin.go
  function GetResourceContext (line 15) | func GetResourceContext(pid int) *model.ResourceContext {
  function checkPreventsSleep (line 39) | func checkPreventsSleep(pid int) bool {
  function getThermalState (line 64) | func getThermalState() string {
  function GetEnergyImpact (line 126) | func GetEnergyImpact(pid int) string {
  function getCPUAndMemoryUsage (line 134) | func getCPUAndMemoryUsage(pid int) (float64, uint64, error) {

FILE: internal/proc/resource_freebsd.go
  function GetResourceContext (line 16) | func GetResourceContext(pid int) *model.ResourceContext {

FILE: internal/proc/resource_linux.go
  function GetResourceContext (line 18) | func GetResourceContext(pid int) *model.ResourceContext {
  function getThermalState (line 33) | func getThermalState() string {
  function checkPreventsSleep (line 62) | func checkPreventsSleep(pid int) bool {
  function getAppNapped (line 87) | func getAppNapped(pid int) bool {
  function GetEnergyImpact (line 110) | func GetEnergyImpact(pid int, usePs ...bool) string {
  function GetCPUPercent (line 132) | func GetCPUPercent(pid int, usePs ...bool) (float64, error) {

FILE: internal/proc/resource_windows.go
  function GetResourceContext (line 14) | func GetResourceContext(pid int) *model.ResourceContext {

FILE: internal/proc/socketstate_darwin.go
  function GetSocketStates (line 15) | func GetSocketStates(port int) ([]model.SocketInfo, error) {
  function GetSocketStateForPort (line 65) | func GetSocketStateForPort(port int) *model.SocketInfo {
  function addStateExplanation (line 94) | func addStateExplanation(info *model.SocketInfo) {
  function GetTIMEWAITRemaining (line 135) | func GetTIMEWAITRemaining() string {
  function CountSocketsByState (line 142) | func CountSocketsByState(port int) map[string]int {
  function GetMSLDuration (line 159) | func GetMSLDuration() int {

FILE: internal/proc/socketstate_freebsd.go
  function GetSocketStates (line 15) | func GetSocketStates(port int) ([]model.SocketInfo, error) {
  function GetSocketStateForPort (line 66) | func GetSocketStateForPort(port int) *model.SocketInfo {
  function addStateExplanation (line 95) | func addStateExplanation(info *model.SocketInfo) {
  function GetMSLDuration (line 136) | func GetMSLDuration() int {

FILE: internal/proc/socketstate_linux.go
  function GetSocketStateForPort (line 17) | func GetSocketStateForPort(port int) *model.SocketInfo {
  function mapTCPState (line 92) | func mapTCPState(state int) string {
  function isProblematicState (line 121) | func isProblematicState(state string) bool {
  function addStateExplanation (line 129) | func addStateExplanation(info *model.SocketInfo) {

FILE: internal/proc/socketstate_windows.go
  function GetSocketStateForPort (line 13) | func GetSocketStateForPort(port int) *model.SocketInfo {
  function addStateExplanation (line 74) | func addStateExplanation(info *model.SocketInfo) {

FILE: internal/proc/sort.go
  function sortProcesses (line 9) | func sortProcesses(processes []model.Process) {

FILE: internal/proc/systemd_linux.go
  function GetSystemdRestartCount (line 13) | func GetSystemdRestartCount(unitName string) (int, error) {
  function ResolveSystemdService (line 40) | func ResolveSystemdService(port int) (string, error) {

FILE: internal/proc/systemd_stub.go
  function ResolveSystemdService (line 7) | func ResolveSystemdService(port int) (string, error) {
  function GetSystemdRestartCount (line 11) | func GetSystemdRestartCount(unitName string) (int, error) {

FILE: internal/proc/user_darwin.go
  function readUser (line 10) | func readUser(pid int) string {
  function readUserByUID (line 16) | func readUserByUID(uid int) string {
  function resolveUID (line 20) | func resolveUID(uid int) string {

FILE: internal/proc/user_freebsd.go
  function readUser (line 10) | func readUser(pid int) string {
  function readUserByUID (line 16) | func readUserByUID(uid int) string {
  function resolveUID (line 20) | func resolveUID(uid int) string {

FILE: internal/proc/user_linux.go
  function loadUserCache (line 18) | func loadUserCache() map[int]string {
  function readUser (line 38) | func readUser(pid int) string {

FILE: internal/proc/user_windows.go
  function readUser (line 10) | func readUser(pid int) string {

FILE: internal/source/bsdrc_darwin.go
  function detectBsdRc (line 7) | func detectBsdRc(_ []model.Process) *model.Source {

FILE: internal/source/bsdrc_freebsd.go
  function loadShellsFromEtc (line 20) | func loadShellsFromEtc() map[string]bool {
  function getShells (line 46) | func getShells() map[string]bool {
  function detectBsdRc (line 53) | func detectBsdRc(ancestry []model.Process) *model.Source {
  function readRcDescription (line 110) | func readRcDescription(path string) string {
  function resolveRcScript (line 141) | func resolveRcScript(serviceName string) string {

FILE: internal/source/bsdrc_linux.go
  function detectBsdRc (line 7) | func detectBsdRc(_ []model.Process) *model.Source {

FILE: internal/source/bsdrc_windows.go
  function detectBsdRc (line 7) | func detectBsdRc(_ []model.Process) *model.Source {

FILE: internal/source/container.go
  function detectContainer (line 11) | func detectContainer(ancestry []model.Process) *model.Source {
  function itoa (line 70) | func itoa(n int) string {

FILE: internal/source/cron.go
  function detectCron (line 9) | func detectCron(ancestry []model.Process) *model.Source {

FILE: internal/source/detect.go
  function isDangerousCapability (line 24) | func isDangerousCapability(cap string) bool {
  type envSuspiciousRule (line 28) | type envSuspiciousRule struct
  function Detect (line 52) | func Detect(ancestry []model.Process) model.Source {
  function envSuspiciousWarnings (line 92) | func envSuspiciousWarnings(env []string) []string {
  function Warnings (line 146) | func Warnings(p []model.Process, srcType ...model.SourceType) []string {
  function EnrichSocketInfo (line 247) | func EnrichSocketInfo(si *model.SocketInfo) {

FILE: internal/source/detect_test.go
  function TestWarningsDetectsLDPreload (line 12) | func TestWarningsDetectsLDPreload(t *testing.T) {
  function TestWarningsDetectsDYLDVars (line 31) | func TestWarningsDetectsDYLDVars(t *testing.T) {
  function TestWarningsIgnoresEmptyPreloadVars (line 54) | func TestWarningsIgnoresEmptyPreloadVars(t *testing.T) {
  function FuzzEnvSuspiciousWarningsDeterministic (line 80) | func FuzzEnvSuspiciousWarningsDeterministic(f *testing.F) {
  function TestEnvSuspiciousWarnings (line 105) | func TestEnvSuspiciousWarnings(t *testing.T) {
  function FuzzWarningsNoPanic (line 155) | func FuzzWarningsNoPanic(f *testing.F) {
  function TestWarningsDetectsDeletedExecutable (line 180) | func TestWarningsDetectsDeletedExecutable(t *testing.T) {
  function TestEnrichSocketInfo (line 197) | func TestEnrichSocketInfo(t *testing.T) {

FILE: internal/source/init.go
  function detectInit (line 12) | func detectInit(ancestry []model.Process) *model.Source {
  function isShell (line 54) | func isShell(name string) bool {

FILE: internal/source/launchd_darwin.go
  function detectLaunchd (line 12) | func detectLaunchd(ancestry []model.Process) *model.Source {

FILE: internal/source/launchd_freebsd.go
  function detectLaunchd (line 7) | func detectLaunchd(_ []model.Process) *model.Source {

FILE: internal/source/launchd_linux.go
  function detectLaunchd (line 7) | func detectLaunchd(_ []model.Process) *model.Source {

FILE: internal/source/launchd_windows.go
  function detectLaunchd (line 7) | func detectLaunchd(ancestry []model.Process) *model.Source {

FILE: internal/source/network.go
  function IsPublicBind (line 3) | func IsPublicBind(addrs []string) bool {

FILE: internal/source/service_other.go
  function detectWindowsService (line 7) | func detectWindowsService(ancestry []model.Process) *model.Source {

FILE: internal/source/service_windows.go
  function detectWindowsService (line 12) | func detectWindowsService(ancestry []model.Process) *model.Source {
  function resolveWindowsServiceDescription (line 71) | func resolveWindowsServiceDescription(serviceName string) string {

FILE: internal/source/shell.go
  function detectShell (line 57) | func detectShell(ancestry []model.Process) *model.Source {
  function enrichMultiplexer (line 107) | func enrichMultiplexer(src *model.Source, ancestry []model.Process) {
  function findEnvVar (line 141) | func findEnvVar(ancestry []model.Process, key string) string {

FILE: internal/source/ssh.go
  function detectSSH (line 11) | func detectSSH(ancestry []model.Process) *model.Source {

FILE: internal/source/supervisor.go
  function detectSupervisor (line 41) | func detectSupervisor(ancestry []model.Process) *model.Source {
  function matchCmdlineTokens (line 84) | func matchCmdlineTokens(cmdline string, hasShell bool) string {

FILE: internal/source/systemd_darwin.go
  function detectSystemd (line 7) | func detectSystemd(_ []model.Process) *model.Source {
  function IsSystemdRunning (line 12) | func IsSystemdRunning() bool { return false }

FILE: internal/source/systemd_freebsd.go
  function detectSystemd (line 7) | func detectSystemd(_ []model.Process) *model.Source {
  function IsSystemdRunning (line 13) | func IsSystemdRunning() bool { return false }

FILE: internal/source/systemd_linux.go
  function IsSystemdRunning (line 17) | func IsSystemdRunning() bool {
  function detectSystemd (line 22) | func detectSystemd(ancestry []model.Process) *model.Source {
  function resolveSystemdProperties (line 71) | func resolveSystemdProperties(pid int) map[string]string {
  function querySystemdProperties (line 119) | func querySystemdProperties(props []string, target string) map[string]st...
  function resolveTimerSchedule (line 148) | func resolveTimerSchedule(timerUnit string) string {
  function extractTimerSpec (line 189) | func extractTimerSpec(raw string) string {
  function formatRelativeTime (line 225) | func formatRelativeTime(t time.Time) string {
  function getUnitNameFromCgroup (line 252) | func getUnitNameFromCgroup(pid int) string {

FILE: internal/source/systemd_windows.go
  function detectSystemd (line 7) | func detectSystemd(ancestry []model.Process) *model.Source {
  function IsSystemdRunning (line 12) | func IsSystemdRunning() bool { return false }

FILE: internal/target/file_darwin.go
  function ResolveFile (line 10) | func ResolveFile(path string) ([]int, error) {

FILE: internal/target/file_freebsd.go
  function ResolveFile (line 10) | func ResolveFile(path string) ([]int, error) {

FILE: internal/target/file_linux.go
  function ResolveFile (line 11) | func ResolveFile(path string) ([]int, error) {

FILE: internal/target/file_windows.go
  function ResolveFile (line 7) | func ResolveFile(path string) ([]int, error) {

FILE: internal/target/name_darwin.go
  function isValidServiceLabel (line 22) | func isValidServiceLabel(label string) bool {
  function ResolveName (line 29) | func ResolveName(name string, exact bool) ([]int, error) {
  function resolveLaunchdServicePID (line 140) | func resolveLaunchdServicePID(name string) (int, error) {

FILE: internal/target/name_freebsd.go
  function isValidServiceLabel (line 22) | func isValidServiceLabel(label string) bool {
  function ResolveName (line 29) | func ResolveName(name string, exact bool) ([]int, error) {
  function resolveRcServicePID (line 146) | func resolveRcServicePID(name string) (int, error) {

FILE: internal/target/name_linux.go
  function ResolveName (line 16) | func ResolveName(name string, exact bool) ([]int, error) {
  function resolveSystemdServiceMainPID (line 115) | func resolveSystemdServiceMainPID(name string) (int, error) {

FILE: internal/target/name_windows.go
  function ResolveName (line 15) | func ResolveName(name string, exact bool) ([]int, error) {

FILE: internal/target/port_darwin.go
  function ResolvePort (line 13) | func ResolvePort(port int) ([]int, error) {
  function resolvePortNetstat (line 50) | func resolvePortNetstat(port int) ([]int, error) {

FILE: internal/target/port_freebsd.go
  function ResolvePort (line 16) | func ResolvePort(port int) ([]int, error) {
  function resolvePortNetstat (line 96) | func resolvePortNetstat(port int) ([]int, error) {
  function resolvePortFstat (line 132) | func resolvePortFstat(port int) ([]int, error) {
  function handlePortAmbiguity (line 182) | func handlePortAmbiguity(port int, addressToPID map[string]int) ([]int, ...

FILE: internal/target/port_linux.go
  function findSocketInodes (line 14) | func findSocketInodes(port int) (map[string]bool, error) {
  function ResolvePort (line 76) | func ResolvePort(port int) ([]int, error) {

FILE: internal/target/port_windows.go
  function ResolvePort (line 12) | func ResolvePort(port int) ([]int, error) {

FILE: internal/target/resolve.go
  function matchesExactToken (line 15) | func matchesExactToken(cmdline, name string) bool {
  function Resolve (line 31) | func Resolve(t model.Target, exact bool) ([]int, error) {

FILE: internal/target/resolve_test.go
  function TestResolveWithExactFlag (line 11) | func TestResolveWithExactFlag(t *testing.T) {
  function TestResolvePIDWithExactFlag (line 44) | func TestResolvePIDWithExactFlag(t *testing.T) {
  function TestResolvePortWithExactFlag (line 77) | func TestResolvePortWithExactFlag(t *testing.T) {

FILE: internal/tools/docgen/main.go
  function main (line 17) | func main() {

FILE: internal/tui/actions.go
  function killProcess (line 11) | func killProcess(pid int) error   { return sendSignal(pid, syscall.SIGKI...
  function termProcess (line 12) | func termProcess(pid int) error   { return sendSignal(pid, syscall.SIGTE...
  function pauseProcess (line 13) | func pauseProcess(pid int) error  { return sendSignal(pid, syscall.SIGST...
  function resumeProcess (line 14) | func resumeProcess(pid int) error { return sendSignal(pid, syscall.SIGCO...
  function sendSignal (line 16) | func sendSignal(pid int, sig syscall.Signal) error {
  function setNice (line 28) | func setNice(pid, value int) error {

FILE: internal/tui/actions_windows.go
  function killProcess (line 7) | func killProcess(pid int) error    { return fmt.Errorf("not supported on...
  function termProcess (line 8) | func termProcess(pid int) error    { return fmt.Errorf("not supported on...
  function pauseProcess (line 9) | func pauseProcess(pid int) error   { return fmt.Errorf("not supported on...
  function resumeProcess (line 10) | func resumeProcess(pid int) error  { return fmt.Errorf("not supported on...
  function setNice (line 11) | func setNice(pid, value int) error { return fmt.Errorf("not supported on...

FILE: internal/tui/data.go
  method refreshProcesses (line 21) | func (m MainModel) refreshProcesses() tea.Cmd {
  method refreshPorts (line 43) | func (m MainModel) refreshPorts() tea.Cmd {
  method fetchTree (line 53) | func (m MainModel) fetchTree(p model.Process) tea.Cmd {
  method fetchProcessDetail (line 69) | func (m MainModel) fetchProcessDetail(pid int) tea.Cmd {
  type processSorter (line 83) | type processSorter struct
    method Len (line 90) | func (s processSorter) Len() int { return len(s.procs) }
    method Swap (line 92) | func (s processSorter) Swap(i, j int) {
    method Less (line 99) | func (s processSorter) Less(i, j int) bool {
  method sortProcesses (line 122) | func (m *MainModel) sortProcesses() {
  method sortPorts (line 143) | func (m *MainModel) sortPorts() {
  function formatBytes (line 165) | func formatBytes(bytes uint64) string {
  method filterProcesses (line 181) | func (m *MainModel) filterProcesses() {
  function centerHeader (line 223) | func centerHeader(title string, width int) string {
  method getColumns (line 233) | func (m *MainModel) getColumns() []table.Column {
  method getPortColumns (line 273) | func (m *MainModel) getPortColumns() []table.Column {
  method updatePortTable (line 302) | func (m *MainModel) updatePortTable() {
  method updatePortDetails (line 359) | func (m *MainModel) updatePortDetails() {
  method updatePortDetailsWithMap (line 367) | func (m *MainModel) updatePortDetailsWithMap(procMap map[int]model.Proce...
  method updateDetailViewport (line 420) | func (m *MainModel) updateDetailViewport() {
  method updateEnvViewport (line 436) | func (m *MainModel) updateEnvViewport() {
  method updateTreeViewport (line 459) | func (m *MainModel) updateTreeViewport(res model.Result) {
  method rerenderTree (line 528) | func (m *MainModel) rerenderTree() {
  method renderTreeContent (line 535) | func (m *MainModel) renderTreeContent(res model.Result, ancestry []model...

FILE: internal/tui/helpers.go
  function stripAnsi (line 7) | func stripAnsi(str string) string {

FILE: internal/tui/model.go
  type tab (line 101) | type tab
  constant tabProcesses (line 104) | tabProcesses tab = iota
  constant tabPorts (line 105) | tabPorts
  type modelState (line 108) | type modelState
  constant stateList (line 111) | stateList modelState = iota
  constant stateDetail (line 112) | stateDetail
  type focusState (line 115) | type focusState
  constant focusDetail (line 118) | focusDetail focusState = iota
  constant focusEnv (line 119) | focusEnv
  constant focusMain (line 120) | focusMain
  constant focusSide (line 121) | focusSide
  type actionKind (line 124) | type actionKind
  constant actionNone (line 127) | actionNone   actionKind = iota
  constant actionKill (line 128) | actionKill
  constant actionTerm (line 129) | actionTerm
  constant actionPause (line 130) | actionPause
  constant actionResume (line 131) | actionResume
  constant actionRenice (line 132) | actionRenice
  type MainModel (line 135) | type MainModel struct
    method Init (line 297) | func (m MainModel) Init() tea.Cmd {
  function InitialModel (line 185) | func InitialModel(version string) MainModel {
  function Start (line 285) | func Start(version string) error {

FILE: internal/tui/mouse.go
  method getColumnAtX (line 6) | func (m *MainModel) getColumnAtX(x int, cols []table.Column) int {
  method handleProcessHeaderClick (line 18) | func (m *MainModel) handleProcessHeaderClick(x int) {
  method handlePortHeaderClick (line 60) | func (m *MainModel) handlePortHeaderClick(x int) {

FILE: internal/tui/update.go
  type treeMsg (line 13) | type treeMsg
  type debounceMsg (line 15) | type debounceMsg struct
  type tickMsg (line 20) | type tickMsg
  function waitTick (line 22) | func waitTick() tea.Cmd {
  method Update (line 28) | func (m MainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {

FILE: internal/tui/view.go
  method View (line 10) | func (m MainModel) View() string {

FILE: internal/version/version.go
  function init (line 21) | func init() {

FILE: pkg/model/docker.go
  type DockerPortMatch (line 4) | type DockerPortMatch struct

FILE: pkg/model/filecontext.go
  type FileContext (line 4) | type FileContext struct

FILE: pkg/model/net.go
  type OpenPort (line 3) | type OpenPort struct

FILE: pkg/model/process.go
  type Process (line 5) | type Process struct
  type MemoryInfo (line 52) | type MemoryInfo struct
  type IOStats (line 65) | type IOStats struct

FILE: pkg/model/resource.go
  type ResourceContext (line 4) | type ResourceContext struct

FILE: pkg/model/result.go
  type Result (line 3) | type Result struct

FILE: pkg/model/socket.go
  type Socket (line 3) | type Socket struct
  type SocketInfo (line 12) | type SocketInfo struct

FILE: pkg/model/source.go
  type SourceType (line 3) | type SourceType
  constant SourceContainer (line 6) | SourceContainer      SourceType = "container"
  constant SourceSystemd (line 7) | SourceSystemd        SourceType = "systemd"
  constant SourceLaunchd (line 8) | SourceLaunchd        SourceType = "launchd"
  constant SourceBsdRc (line 9) | SourceBsdRc          SourceType = "bsdrc"
  constant SourceSupervisor (line 10) | SourceSupervisor     SourceType = "supervisor"
  constant SourceCron (line 11) | SourceCron           SourceType = "cron"
  constant SourceSSH (line 12) | SourceSSH            SourceType = "ssh"
  constant SourceShell (line 13) | SourceShell          SourceType = "shell"
  constant SourceWindowsService (line 14) | SourceWindowsService SourceType = "windows_service"
  constant SourceInit (line 15) | SourceInit           SourceType = "init"
  constant SourceUnknown (line 16) | SourceUnknown        SourceType = "unknown"
  type Source (line 19) | type Source struct

FILE: pkg/model/target.go
  type TargetType (line 3) | type TargetType
  constant TargetName (line 6) | TargetName TargetType = "name"
  constant TargetPID (line 7) | TargetPID  TargetType = "pid"
  constant TargetPort (line 8) | TargetPort TargetType = "port"
  constant TargetFile (line 9) | TargetFile TargetType = "file"
  type Target (line 12) | type Target struct

FILE: vendor/github.com/atotto/clipboard/clipboard.go
  function ReadAll (line 9) | func ReadAll() (string, error) {
  function WriteAll (line 14) | func WriteAll(text string) error {

FILE: vendor/github.com/atotto/clipboard/clipboard_darwin.go
  function getPasteCommand (line 18) | func getPasteCommand() *exec.Cmd {
  function getCopyCommand (line 22) | func getCopyCommand() *exec.Cmd {
  function readAll (line 26) | func readAll() (string, error) {
  function writeAll (line 35) | func writeAll(text string) error {

FILE: vendor/github.com/atotto/clipboard/clipboard_plan9.go
  function readAll (line 14) | func readAll() (string, error) {
  function writeAll (line 29) | func writeAll(text string) error {

FILE: vendor/github.com/atotto/clipboard/clipboard_unix.go
  constant xsel (line 16) | xsel               = "xsel"
  constant xclip (line 17) | xclip              = "xclip"
  constant powershellExe (line 18) | powershellExe      = "powershell.exe"
  constant clipExe (line 19) | clipExe            = "clip.exe"
  constant wlcopy (line 20) | wlcopy             = "wl-copy"
  constant wlpaste (line 21) | wlpaste            = "wl-paste"
  constant termuxClipboardGet (line 22) | termuxClipboardGet = "termux-clipboard-get"
  constant termuxClipboardSet (line 23) | termuxClipboardSet = "termux-clipboard-set"
  function init (line 51) | func init() {
  function getPasteCommand (line 99) | func getPasteCommand() *exec.Cmd {
  function getCopyCommand (line 106) | func getCopyCommand() *exec.Cmd {
  function readAll (line 113) | func readAll() (string, error) {
  function writeAll (line 129) | func writeAll(text string) error {

FILE: vendor/github.com/atotto/clipboard/clipboard_windows.go
  constant cfUnicodetext (line 17) | cfUnicodetext = 13
  constant gmemMoveable (line 18) | gmemMoveable  = 0x0002
  function waitOpenClipboard (line 39) | func waitOpenClipboard() error {
  function readAll (line 54) | func readAll() (string, error) {
  function writeAll (line 94) | func writeAll(text string) error {

FILE: vendor/github.com/aymanbagabas/go-osc52/v2/osc52.go
  type Clipboard (line 64) | type Clipboard
  constant SystemClipboard (line 68) | SystemClipboard Clipboard = 'c'
  constant PrimaryClipboard (line 70) | PrimaryClipboard = 'p'
  type Mode (line 74) | type Mode
  constant DefaultMode (line 78) | DefaultMode Mode = iota
  constant ScreenMode (line 80) | ScreenMode
  constant TmuxMode (line 83) | TmuxMode
  type Operation (line 87) | type Operation
  constant SetOperation (line 91) | SetOperation Operation = iota
  constant QueryOperation (line 93) | QueryOperation
  constant ClearOperation (line 95) | ClearOperation
  type Sequence (line 99) | type Sequence struct
    method String (line 112) | func (s Sequence) String() string {
    method WriteTo (line 163) | func (s Sequence) WriteTo(out io.Writer) (int64, error) {
    method Mode (line 169) | func (s Sequence) Mode(m Mode) Sequence {
    method Tmux (line 181) | func (s Sequence) Tmux() Sequence {
    method Screen (line 189) | func (s Sequence) Screen() Sequence {
    method Clipboard (line 194) | func (s Sequence) Clipboard(c Clipboard) Sequence {
    method Primary (line 203) | func (s Sequence) Primary() Sequence {
    method Limit (line 213) | func (s Sequence) Limit(l int) Sequence {
    method Operation (line 224) | func (s Sequence) Operation(o Operation) Sequence {
    method Clear (line 233) | func (s Sequence) Clear() Sequence {
    method Query (line 241) | func (s Sequence) Query() Sequence {
    method SetString (line 247) | func (s Sequence) SetString(strs ...string) Sequence {
    method seqStart (line 281) | func (s Sequence) seqStart() string {
    method seqEnd (line 294) | func (s Sequence) seqEnd() string {
  function New (line 254) | func New(strs ...string) Sequence {
  function Query (line 269) | func Query() Sequence {
  function Clear (line 277) | func Clear() Sequence {

FILE: vendor/github.com/charmbracelet/bubbles/cursor/cursor.go
  constant defaultBlinkSpeed (line 12) | defaultBlinkSpeed = time.Millisecond * 530
  type initialBlinkMsg (line 15) | type initialBlinkMsg struct
  type BlinkMsg (line 19) | type BlinkMsg struct
  type blinkCanceled (line 25) | type blinkCanceled struct
  type blinkCtx (line 28) | type blinkCtx struct
  type Mode (line 34) | type Mode
    method String (line 45) | func (c Mode) String() string {
  constant CursorBlink (line 38) | CursorBlink Mode = iota
  constant CursorStatic (line 39) | CursorStatic
  constant CursorHide (line 40) | CursorHide
  type Model (line 54) | type Model struct
    method Update (line 93) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method Mode (line 141) | func (m Model) Mode() Mode {
    method SetMode (line 148) | func (m *Model) SetMode(mode Mode) tea.Cmd {
    method BlinkCmd (line 162) | func (m *Model) BlinkCmd() tea.Cmd {
    method Focus (line 194) | func (m *Model) Focus() tea.Cmd {
    method Blur (line 205) | func (m *Model) Blur() {
    method SetChar (line 211) | func (m *Model) SetChar(char string) {
    method View (line 216) | func (m Model) View() string {
  function New (line 79) | func New() Model {
  function Blink (line 189) | func Blink() tea.Msg {

FILE: vendor/github.com/charmbracelet/bubbles/help/help.go
  type KeyMap (line 18) | type KeyMap interface
  type Styles (line 31) | type Styles struct
  type Model (line 46) | type Model struct
    method Update (line 99) | func (m Model) Update(_ tea.Msg) (Model, tea.Cmd) {
    method View (line 104) | func (m Model) View(k KeyMap) string {
    method ShortHelpView (line 114) | func (m Model) ShortHelpView(bindings []key.Binding) string {
    method FullHelpView (line 157) | func (m Model) FullHelpView(groups [][]key.Binding) string {
    method shouldAddItem (line 221) | func (m Model) shouldAddItem(totalWidth, width int) (tail string, ok b...
  function New (line 61) | func New() Model {
  function shouldRenderColumn (line 233) | func shouldRenderColumn(b []key.Binding) (ok bool) {

FILE: vendor/github.com/charmbracelet/bubbles/key/key.go
  type Binding (line 43) | type Binding struct
    method SetKeys (line 84) | func (b *Binding) SetKeys(keys ...string) {
    method Keys (line 89) | func (b Binding) Keys() []string {
    method SetHelp (line 94) | func (b *Binding) SetHelp(key, desc string) {
    method Help (line 99) | func (b Binding) Help() Help {
    method Enabled (line 106) | func (b Binding) Enabled() bool {
    method SetEnabled (line 111) | func (b *Binding) SetEnabled(v bool) {
    method Unbind (line 118) | func (b *Binding) Unbind() {
  type BindingOpt (line 51) | type BindingOpt
  function NewBinding (line 54) | func NewBinding(opts ...BindingOpt) Binding {
  function WithKeys (line 63) | func WithKeys(keys ...string) BindingOpt {
  function WithHelp (line 70) | func WithHelp(key, desc string) BindingOpt {
  function WithDisabled (line 77) | func WithDisabled() BindingOpt {
  type Help (line 124) | type Help struct
  function Matches (line 130) | func Matches[Key fmt.Stringer](k Key, b ...Binding) bool {

FILE: vendor/github.com/charmbracelet/bubbles/runeutil/runeutil.go
  type Sanitizer (line 12) | type Sanitizer interface
  function NewSanitizer (line 24) | func NewSanitizer(opts ...Option) Sanitizer {
  type Option (line 36) | type Option
  function ReplaceTabs (line 39) | func ReplaceTabs(tabRepl string) Option {
  function ReplaceNewlines (line 47) | func ReplaceNewlines(nlRepl string) Option {
  type sanitizer (line 99) | type sanitizer struct
    method Sanitize (line 54) | func (s *sanitizer) Sanitize(runes []rune) []rune {

FILE: vendor/github.com/charmbracelet/bubbles/table/table.go
  type Model (line 17) | type Model struct
    method SetStyles (line 124) | func (m *Model) SetStyles(s Styles) {
    method Update (line 204) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method Focused (line 235) | func (m Model) Focused() bool {
    method Focus (line 241) | func (m *Model) Focus() {
    method Blur (line 247) | func (m *Model) Blur() {
    method View (line 253) | func (m Model) View() string {
    method HelpView (line 260) | func (m Model) HelpView() string {
    method UpdateViewport (line 266) | func (m *Model) UpdateViewport() {
    method SelectedRow (line 289) | func (m Model) SelectedRow() Row {
    method Rows (line 298) | func (m Model) Rows() []Row {
    method Columns (line 303) | func (m Model) Columns() []Column {
    method SetRows (line 308) | func (m *Model) SetRows(r []Row) {
    method SetColumns (line 319) | func (m *Model) SetColumns(c []Column) {
    method SetWidth (line 325) | func (m *Model) SetWidth(w int) {
    method SetHeight (line 331) | func (m *Model) SetHeight(h int) {
    method Height (line 337) | func (m Model) Height() int {
    method Width (line 342) | func (m Model) Width() int {
    method Cursor (line 347) | func (m Model) Cursor() int {
    method SetCursor (line 352) | func (m *Model) SetCursor(n int) {
    method MoveUp (line 359) | func (m *Model) MoveUp(n int) {
    method MoveDown (line 374) | func (m *Model) MoveDown(n int) {
    method GotoTop (line 390) | func (m *Model) GotoTop() {
    method GotoBottom (line 395) | func (m *Model) GotoBottom() {
    method FromValues (line 402) | func (m *Model) FromValues(value, separator string) {
    method headersView (line 415) | func (m Model) headersView() string {
    method renderRow (line 428) | func (m *Model) renderRow(r int) string {
  type Row (line 33) | type Row
  type Column (line 36) | type Column struct
  type KeyMap (line 43) | type KeyMap struct
    method ShortHelp (line 55) | func (km KeyMap) ShortHelp() []key.Binding {
    method FullHelp (line 60) | func (km KeyMap) FullHelp() [][]key.Binding {
  function DefaultKeyMap (line 68) | func DefaultKeyMap() KeyMap {
  type Styles (line 108) | type Styles struct
  function DefaultStyles (line 115) | func DefaultStyles() Styles {
  type Option (line 132) | type Option
  function New (line 135) | func New(opts ...Option) Model {
  function WithColumns (line 155) | func WithColumns(cols []Column) Option {
  function WithRows (line 162) | func WithRows(rows []Row) Option {
  function WithHeight (line 169) | func WithHeight(h int) Option {
  function WithWidth (line 176) | func WithWidth(w int) Option {
  function WithFocused (line 183) | func WithFocused(f bool) Option {
  function WithStyles (line 190) | func WithStyles(s Styles) Option {
  function WithKeyMap (line 197) | func WithKeyMap(km KeyMap) Option {
  function clamp (line 448) | func clamp(v, low, high int) int {

FILE: vendor/github.com/charmbracelet/bubbles/textinput/textinput.go
  type pasteMsg (line 24) | type pasteMsg
  type pasteErrMsg (line 25) | type pasteErrMsg struct
  type EchoMode (line 29) | type EchoMode
  constant EchoNormal (line 33) | EchoNormal EchoMode = iota
  constant EchoPassword (line 37) | EchoPassword
  constant EchoNone (line 41) | EchoNone
  type ValidateFunc (line 45) | type ValidateFunc
  type KeyMap (line 48) | type KeyMap struct
  type Model (line 89) | type Model struct
    method SetValue (line 185) | func (m *Model) SetValue(s string) {
    method setValueInternal (line 193) | func (m *Model) setValueInternal(runes []rune, err error) {
    method Value (line 210) | func (m Model) Value() string {
    method Position (line 215) | func (m Model) Position() int {
    method SetCursor (line 221) | func (m *Model) SetCursor(pos int) {
    method CursorStart (line 227) | func (m *Model) CursorStart() {
    method CursorEnd (line 232) | func (m *Model) CursorEnd() {
    method Focused (line 237) | func (m Model) Focused() bool {
    method Focus (line 243) | func (m *Model) Focus() tea.Cmd {
    method Blur (line 250) | func (m *Model) Blur() {
    method Reset (line 256) | func (m *Model) Reset() {
    method SetSuggestions (line 262) | func (m *Model) SetSuggestions(suggestions []string) {
    method san (line 272) | func (m *Model) san() runeutil.Sanitizer {
    method insertRunesFromUserInput (line 282) | func (m *Model) insertRunesFromUserInput(v []rune) {
    method handleOverflow (line 330) | func (m *Model) handleOverflow() {
    method deleteBeforeCursor (line 374) | func (m *Model) deleteBeforeCursor() {
    method deleteAfterCursor (line 384) | func (m *Model) deleteAfterCursor() {
    method deleteWordBackward (line 391) | func (m *Model) deleteWordBackward() {
    method deleteWordForward (line 438) | func (m *Model) deleteWordForward() {
    method wordBackward (line 479) | func (m *Model) wordBackward() {
    method wordForward (line 511) | func (m *Model) wordForward() {
    method echoTransform (line 541) | func (m Model) echoTransform(v string) string {
    method Update (line 555) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method View (line 652) | func (m Model) View() string {
    method placeholderView (line 703) | func (m Model) placeholderView() string {
    method CursorMode (line 779) | func (m Model) CursorMode() CursorMode {
    method SetCursorMode (line 786) | func (m *Model) SetCursorMode(mode CursorMode) tea.Cmd {
    method completionView (line 790) | func (m Model) completionView(offset int) string {
    method getSuggestions (line 805) | func (m *Model) getSuggestions(sugs [][]rune) []string {
    method AvailableSuggestions (line 814) | func (m *Model) AvailableSuggestions() []string {
    method MatchedSuggestions (line 819) | func (m *Model) MatchedSuggestions() []string {
    method CurrentSuggestionIndex (line 824) | func (m *Model) CurrentSuggestionIndex() int {
    method CurrentSuggestion (line 829) | func (m *Model) CurrentSuggestion() string {
    method canAcceptSuggestion (line 839) | func (m *Model) canAcceptSuggestion() bool {
    method updateSuggestions (line 844) | func (m *Model) updateSuggestions() {
    method nextSuggestion (line 870) | func (m *Model) nextSuggestion() {
    method previousSuggestion (line 878) | func (m *Model) previousSuggestion() {
    method validate (line 885) | func (m Model) validate(v []rune) error {
  function New (line 161) | func New() Model {
  function Blink (line 735) | func Blink() tea.Msg {
  function Paste (line 740) | func Paste() tea.Msg {
  function clamp (line 748) | func clamp(v, low, high int) int {
  type CursorMode (line 760) | type CursorMode
    method String (line 772) | func (c CursorMode) String() string {
  constant CursorBlink (line 765) | CursorBlink = CursorMode(cursor.CursorBlink)
  constant CursorStatic (line 767) | CursorStatic = CursorMode(cursor.CursorStatic)
  constant CursorHide (line 769) | CursorHide = CursorMode(cursor.CursorHide)

FILE: vendor/github.com/charmbracelet/bubbles/viewport/keymap.go
  constant spacebar (line 7) | spacebar = " "
  type KeyMap (line 13) | type KeyMap struct
  function DefaultKeyMap (line 25) | func DefaultKeyMap() KeyMap {

FILE: vendor/github.com/charmbracelet/bubbles/viewport/viewport.go
  function New (line 15) | func New(width, height int) (m Model) {
  type Model (line 23) | type Model struct
    method setInitialValues (line 70) | func (m *Model) setInitialValues() {
    method Init (line 78) | func (m Model) Init() tea.Cmd {
    method AtTop (line 83) | func (m Model) AtTop() bool {
    method AtBottom (line 89) | func (m Model) AtBottom() bool {
    method PastBottom (line 95) | func (m Model) PastBottom() bool {
    method ScrollPercent (line 100) | func (m Model) ScrollPercent() float64 {
    method HorizontalScrollPercent (line 113) | func (m Model) HorizontalScrollPercent() float64 {
    method SetContent (line 125) | func (m *Model) SetContent(s string) {
    method maxYOffset (line 137) | func (m Model) maxYOffset() int {
    method visibleLines (line 143) | func (m Model) visibleLines() (lines []string) {
    method scrollArea (line 167) | func (m Model) scrollArea() (top, bottom int) {
    method SetYOffset (line 177) | func (m *Model) SetYOffset(n int) {
    method ViewDown (line 185) | func (m *Model) ViewDown() []string {
    method PageDown (line 190) | func (m *Model) PageDown() []string {
    method ViewUp (line 202) | func (m *Model) ViewUp() []string {
    method PageUp (line 207) | func (m *Model) PageUp() []string {
    method HalfViewDown (line 218) | func (m *Model) HalfViewDown() (lines []string) {
    method HalfPageDown (line 223) | func (m *Model) HalfPageDown() (lines []string) {
    method HalfViewUp (line 234) | func (m *Model) HalfViewUp() (lines []string) {
    method HalfPageUp (line 239) | func (m *Model) HalfPageUp() (lines []string) {
    method LineDown (line 250) | func (m *Model) LineDown(n int) (lines []string) {
    method ScrollDown (line 255) | func (m *Model) ScrollDown(n int) (lines []string) {
    method LineUp (line 277) | func (m *Model) LineUp(n int) (lines []string) {
    method ScrollUp (line 283) | func (m *Model) ScrollUp(n int) (lines []string) {
    method SetHorizontalStep (line 306) | func (m *Model) SetHorizontalStep(n int) {
    method SetXOffset (line 311) | func (m *Model) SetXOffset(n int) {
    method ScrollLeft (line 316) | func (m *Model) ScrollLeft(n int) {
    method ScrollRight (line 321) | func (m *Model) ScrollRight(n int) {
    method TotalLineCount (line 326) | func (m Model) TotalLineCount() int {
    method VisibleLineCount (line 331) | func (m Model) VisibleLineCount() int {
    method GotoTop (line 336) | func (m *Model) GotoTop() (lines []string) {
    method GotoBottom (line 346) | func (m *Model) GotoBottom() (lines []string) {
    method Update (line 402) | func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
    method updateAsModel (line 410) | func (m Model) updateAsModel(msg tea.Msg) (Model, tea.Cmd) {
    method View (line 500) | func (m Model) View() string {
  function Sync (line 358) | func Sync(m Model) tea.Cmd {
  function ViewDown (line 374) | func ViewDown(m Model, lines []string) tea.Cmd {
  function ViewUp (line 390) | func ViewUp(m Model, lines []string) tea.Cmd {
  function clamp (line 529) | func clamp(v, low, high int) int {
  function findLongestLineWidth (line 536) | func findLongestLineWidth(lines []string) int {

FILE: vendor/github.com/charmbracelet/bubbletea/commands.go
  function Batch (line 15) | func Batch(cmds ...Cmd) Cmd {
  type BatchMsg (line 21) | type BatchMsg
  function Sequence (line 25) | func Sequence(cmds ...Cmd) Cmd {
  type sequenceMsg (line 30) | type sequenceMsg
  function compactCmds (line 36) | func compactCmds[T ~[]Cmd](cmds []Cmd) Cmd {
  function Every (line 102) | func Every(duration time.Duration, fn func(time.Time) Msg) Cmd {
  function Tick (line 154) | func Tick(d time.Duration, fn func(time.Time) Msg) Cmd {
  function Sequentially (line 180) | func Sequentially(cmds ...Cmd) Cmd {
  type setWindowTitleMsg (line 195) | type setWindowTitleMsg
  function SetWindowTitle (line 205) | func SetWindowTitle(title string) Cmd {
  type windowSizeMsg (line 211) | type windowSizeMsg struct
  function WindowSize (line 218) | func WindowSize() Cmd {

FILE: vendor/github.com/charmbracelet/bubbletea/exec.go
  type execMsg (line 10) | type execMsg struct
  function Exec (line 22) | func Exec(c ExecCommand, fn ExecCallback) Cmd {
  function ExecProcess (line 50) | func ExecProcess(c *exec.Cmd, fn ExecCallback) Cmd {
  type ExecCallback (line 56) | type ExecCallback
  type ExecCommand (line 60) | type ExecCommand interface
  function wrapExecCommand (line 69) | func wrapExecCommand(c *exec.Cmd) ExecCommand {
  type osExecCommand (line 75) | type osExecCommand struct
    method SetStdin (line 78) | func (c *osExecCommand) SetStdin(r io.Reader) {
    method SetStdout (line 86) | func (c *osExecCommand) SetStdout(w io.Writer) {
    method SetStderr (line 94) | func (c *osExecCommand) SetStderr(w io.Writer) {
  method exec (line 102) | func (p *Program) exec(c ExecCommand, fn ExecCallback) {

FILE: vendor/github.com/charmbracelet/bubbletea/focus.go
  type FocusMsg (line 5) | type FocusMsg struct
  type BlurMsg (line 9) | type BlurMsg struct

FILE: vendor/github.com/charmbracelet/bubbletea/inputreader_other.go
  function newInputReader (line 13) | func newInputReader(r io.Reader, _ bool) (cancelreader.CancelReader, err...

FILE: vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go
  type conInputReader (line 18) | type conInputReader struct
    method Cancel (line 67) | func (r *conInputReader) Cancel() bool {
    method Close (line 76) | func (r *conInputReader) Close() error {
    method Read (line 88) | func (r *conInputReader) Read(_ []byte) (n int, err error) {
  function newInputReader (line 28) | func newInputReader(r io.Reader, enableMouse bool) (cancelreader.CancelR...
  function prepareConsole (line 95) | func prepareConsole(input windows.Handle, modes ...uint32) (originalMode...
  type cancelMixin (line 112) | type cancelMixin struct
    method setCanceled (line 117) | func (c *cancelMixin) setCanceled() {
    method isCanceled (line 124) | func (c *cancelMixin) isCanceled() bool {

FILE: vendor/github.com/charmbracelet/bubbletea/key.go
  type KeyMsg (line 45) | type KeyMsg
    method String (line 49) | func (k KeyMsg) String() (str string) {
  type Key (line 54) | type Key struct
    method String (line 67) | func (k Key) String() (str string) {
  type KeyType (line 108) | type KeyType
    method String (line 110) | func (k KeyType) String() (str string) {
  constant keyNUL (line 123) | keyNUL KeyType = 0
  constant keySOH (line 124) | keySOH KeyType = 1
  constant keySTX (line 125) | keySTX KeyType = 2
  constant keyETX (line 126) | keyETX KeyType = 3
  constant keyEOT (line 127) | keyEOT KeyType = 4
  constant keyENQ (line 128) | keyENQ KeyType = 5
  constant keyACK (line 129) | keyACK KeyType = 6
  constant keyBEL (line 130) | keyBEL KeyType = 7
  constant keyBS (line 131) | keyBS  KeyType = 8
  constant keyHT (line 132) | keyHT  KeyType = 9
  constant keyLF (line 133) | keyLF  KeyType = 10
  constant keyVT (line 134) | keyVT  KeyType = 11
  constant keyFF (line 135) | keyFF  KeyType = 12
  constant keyCR (line 136) | keyCR  KeyType = 13
  constant keySO (line 137) | keySO  KeyType = 14
  constant keySI (line 138) | keySI  KeyType = 15
  constant keyDLE (line 139) | keyDLE KeyType = 16
  constant keyDC1 (line 140) | keyDC1 KeyType = 17
  constant keyDC2 (line 141) | keyDC2 KeyType = 18
  constant keyDC3 (line 142) | keyDC3 KeyType = 19
  constant keyDC4 (line 143) | keyDC4 KeyType = 20
  constant keyNAK (line 144) | keyNAK KeyType = 21
  constant keySYN (line 145) | keySYN KeyType = 22
  constant keyETB (line 146) | keyETB KeyType = 23
  constant keyCAN (line 147) | keyCAN KeyType = 24
  constant keyEM (line 148) | keyEM  KeyType = 25
  constant keySUB (line 149) | keySUB KeyType = 26
  constant keyESC (line 150) | keyESC KeyType = 27
  constant keyFS (line 151) | keyFS  KeyType = 28
  constant keyGS (line 152) | keyGS  KeyType = 29
  constant keyRS (line 153) | keyRS  KeyType = 30
  constant keyUS (line 154) | keyUS  KeyType = 31
  constant keyDEL (line 155) | keyDEL KeyType = 127
  constant KeyNull (line 160) | KeyNull      KeyType = keyNUL
  constant KeyBreak (line 161) | KeyBreak     KeyType = keyETX
  constant KeyEnter (line 162) | KeyEnter     KeyType = keyCR
  constant KeyBackspace (line 163) | KeyBackspace KeyType = keyDEL
  constant KeyTab (line 164) | KeyTab       KeyType = keyHT
  constant KeyEsc (line 165) | KeyEsc       KeyType = keyESC
  constant KeyEscape (line 166) | KeyEscape    KeyType = keyESC
  constant KeyCtrlAt (line 168) | KeyCtrlAt           KeyType = keyNUL
  constant KeyCtrlA (line 169) | KeyCtrlA            KeyType = keySOH
  constant KeyCtrlB (line 170) | KeyCtrlB            KeyType = keySTX
  constant KeyCtrlC (line 171) | KeyCtrlC            KeyType = keyETX
  constant KeyCtrlD (line 172) | KeyCtrlD            KeyType = keyEOT
  constant KeyCtrlE (line 173) | KeyCtrlE            KeyType = keyENQ
  constant KeyCtrlF (line 174) | KeyCtrlF            KeyType = keyACK
  constant KeyCtrlG (line 175) | KeyCtrlG            KeyType = keyBEL
  constant KeyCtrlH (line 176) | KeyCtrlH            KeyType = keyBS
  constant KeyCtrlI (line 177) | KeyCtrlI            KeyType = keyHT
  constant KeyCtrlJ (line 178) | KeyCtrlJ            KeyType = keyLF
  constant KeyCtrlK (line 179) | KeyCtrlK            KeyType = keyVT
  constant KeyCtrlL (line 180) | KeyCtrlL            KeyType = keyFF
  constant KeyCtrlM (line 181) | KeyCtrlM            KeyType = keyCR
  constant KeyCtrlN (line 182) | KeyCtrlN            KeyType = keySO
  constant KeyCtrlO (line 183) | KeyCtrlO            KeyType = keySI
  constant KeyCtrlP (line 184) | KeyCtrlP            KeyType = keyDLE
  constant KeyCtrlQ (line 185) | KeyCtrlQ            KeyType = keyDC1
  constant KeyCtrlR (line 186) | KeyCtrlR            KeyType = keyDC2
  constant KeyCtrlS (line 187) | KeyCtrlS            KeyType = keyDC3
  constant KeyCtrlT (line 188) | KeyCtrlT            KeyType = keyDC4
  constant KeyCtrlU (line 189) | KeyCtrlU            KeyType = keyNAK
  constant KeyCtrlV (line 190) | KeyCtrlV            KeyType = keySYN
  constant KeyCtrlW (line 191) | KeyCtrlW            KeyType = keyETB
  constant KeyCtrlX (line 192) | KeyCtrlX            KeyType = keyCAN
  constant KeyCtrlY (line 193) | KeyCtrlY            KeyType = keyEM
  constant KeyCtrlZ (line 194) | KeyCtrlZ            KeyType = keySUB
  constant KeyCtrlOpenBracket (line 195) | KeyCtrlOpenBracket  KeyType = keyESC
  constant KeyCtrlBackslash (line 196) | KeyCtrlBackslash    KeyType = keyFS
  constant KeyCtrlCloseBracket (line 197) | KeyCtrlCloseBracket KeyType = keyGS
  constant KeyCtrlCaret (line 198) | KeyCtrlCaret        KeyType = keyRS
  constant KeyCtrlUnderscore (line 199) | KeyCtrlUnderscore   KeyType = keyUS
  constant KeyCtrlQuestionMark (line 200) | KeyCtrlQuestionMark KeyType = keyDEL
  constant KeyRunes (line 205) | KeyRunes KeyType = -(iota + 1)
  constant KeyUp (line 206) | KeyUp
  constant KeyDown (line 207) | KeyDown
  constant KeyRight (line 208) | KeyRight
  constant KeyLeft (line 209) | KeyLeft
  constant KeyShiftTab (line 210) | KeyShiftTab
  constant KeyHome (line 211) | KeyHome
  constant KeyEnd (line 212) | KeyEnd
  constant KeyPgUp (line 213) | KeyPgUp
  constant KeyPgDown (line 214) | KeyPgDown
  constant KeyCtrlPgUp (line 215) | KeyCtrlPgUp
  constant KeyCtrlPgDown (line 216) | KeyCtrlPgDown
  constant KeyDelete (line 217) | KeyDelete
  constant KeyInsert (line 218) | KeyInsert
  constant KeySpace (line 219) | KeySpace
  constant KeyCtrlUp (line 220) | KeyCtrlUp
  constant KeyCtrlDown (line 221) | KeyCtrlDown
  constant KeyCtrlRight (line 222) | KeyCtrlRight
  constant KeyCtrlLeft (line 223) | KeyCtrlLeft
  constant KeyCtrlHome (line 224) | KeyCtrlHome
  constant KeyCtrlEnd (line 225) | KeyCtrlEnd
  constant KeyShiftUp (line 226) | KeyShiftUp
  constant KeyShiftDown (line 227) | KeyShiftDown
  constant KeyShiftRight (line 228) | KeyShiftRight
  constant KeyShiftLeft (line 229) | KeyShiftLeft
  constant KeyShiftHome (line 230) | KeyShiftHome
  constant KeyShiftEnd (line 231) | KeyShiftEnd
  constant KeyCtrlShiftUp (line 232) | KeyCtrlShiftUp
  constant KeyCtrlShiftDown (line 233) | KeyCtrlShiftDown
  constant KeyCtrlShiftLeft (line 234) | KeyCtrlShiftLeft
  constant KeyCtrlShiftRight (line 235) | KeyCtrlShiftRight
  constant KeyCtrlShiftHome (line 236) | KeyCtrlShiftHome
  constant KeyCtrlShiftEnd (line 237) | KeyCtrlShiftEnd
  constant KeyF1 (line 238) | KeyF1
  constant KeyF2 (line 239) | KeyF2
  constant KeyF3 (line 240) | KeyF3
  constant KeyF4 (line 241) | KeyF4
  constant KeyF5 (line 242) | KeyF5
  constant KeyF6 (line 243) | KeyF6
  constant KeyF7 (line 244) | KeyF7
  constant KeyF8 (line 245) | KeyF8
  constant KeyF9 (line 246) | KeyF9
  constant KeyF10 (line 247) | KeyF10
  constant KeyF11 (line 248) | KeyF11
  constant KeyF12 (line 249) | KeyF12
  constant KeyF13 (line 250) | KeyF13
  constant KeyF14 (line 251) | KeyF14
  constant KeyF15 (line 252) | KeyF15
  constant KeyF16 (line 253) | KeyF16
  constant KeyF17 (line 254) | KeyF17
  constant KeyF18 (line 255) | KeyF18
  constant KeyF19 (line 256) | KeyF19
  constant KeyF20 (line 257) | KeyF20
  type unknownInputByteMsg (line 538) | type unknownInputByteMsg
    method String (line 540) | func (u unknownInputByteMsg) String() string {
  type unknownCSISequenceMsg (line 548) | type unknownCSISequenceMsg
    method String (line 550) | func (u unknownCSISequenceMsg) String() string {
  function readAnsiInputs (line 558) | func readAnsiInputs(ctx context.Context, msgs chan<- Msg, input io.Reade...
  function detectOneMsg (line 614) | func detectOneMsg(b []byte, canHaveMoreData bool) (w int, msg Msg) {

FILE: vendor/github.com/charmbracelet/bubbletea/key_other.go
  function readInputs (line 11) | func readInputs(ctx context.Context, msgs chan<- Msg, input io.Reader) e...

FILE: vendor/github.com/charmbracelet/bubbletea/key_sequences.go
  function detectSequence (line 57) | func detectSequence(input []byte) (hasSeq bool, width int, msg Msg) {
  function detectBracketedPaste (line 83) | func detectBracketedPaste(input []byte) (hasBp bool, width int, msg Msg) {
  function detectReportFocus (line 122) | func detectReportFocus(input []byte) (hasRF bool, width int, msg Msg) {

FILE: vendor/github.com/charmbracelet/bubbletea/key_windows.go
  function readInputs (line 17) | func readInputs(ctx context.Context, msgs chan<- Msg, input io.Reader) e...
  function readConInputs (line 25) | func readConInputs(ctx context.Context, msgsch chan<- Msg, con *conInput...
  function peekAndReadConsInput (line 97) | func peekAndReadConsInput(con *conInputReader) ([]coninput.InputRecord, ...
  function intToUint32OrDie (line 113) | func intToUint32OrDie(i int) uint32 {
  function peekConsInput (line 121) | func peekConsInput(con *conInputReader) ([]coninput.InputRecord, error) {
  function mouseEventButton (line 138) | func mouseEventButton(p, s coninput.ButtonState) (button MouseButton, ac...
  function mouseEvent (line 177) | func mouseEvent(p coninput.ButtonState, e coninput.MouseEventRecord) Mou...
  function keyType (line 228) | func keyType(e coninput.KeyEventRecord) KeyType {

FILE: vendor/github.com/charmbracelet/bubbletea/logging.go
  function LogToFile (line 23) | func LogToFile(path string, prefix string) (*os.File, error) {
  type LogOptionsSetter (line 29) | type LogOptionsSetter interface
  function LogToFileWith (line 35) | func LogToFileWith(path string, prefix string, log LogOptionsSetter) (*o...

FILE: vendor/github.com/charmbracelet/bubbletea/mouse.go
  type MouseMsg (line 8) | type MouseMsg
    method String (line 11) | func (m MouseMsg) String() string {
  type MouseEvent (line 17) | type MouseEvent struct
    method IsWheel (line 31) | func (m MouseEvent) IsWheel() bool {
    method String (line 37) | func (m MouseEvent) String() (s string) {
  type MouseAction (line 71) | type MouseAction
  constant MouseActionPress (line 75) | MouseActionPress MouseAction = iota
  constant MouseActionRelease (line 76) | MouseActionRelease
  constant MouseActionMotion (line 77) | MouseActionMotion
  type MouseButton (line 87) | type MouseButton
  constant MouseButtonNone (line 107) | MouseButtonNone MouseButton = iota
  constant MouseButtonLeft (line 108) | MouseButtonLeft
  constant MouseButtonMiddle (line 109) | MouseButtonMiddle
  constant MouseButtonRight (line 110) | MouseButtonRight
  constant MouseButtonWheelUp (line 111) | MouseButtonWheelUp
  constant MouseButtonWheelDown (line 112) | MouseButtonWheelDown
  constant MouseButtonWheelLeft (line 113) | MouseButtonWheelLeft
  constant MouseButtonWheelRight (line 114) | MouseButtonWheelRight
  constant MouseButtonBackward (line 115) | MouseButtonBackward
  constant MouseButtonForward (line 116) | MouseButtonForward
  constant MouseButton10 (line 117) | MouseButton10
  constant MouseButton11 (line 118) | MouseButton11
  type MouseEventType (line 139) | type MouseEventType
  constant MouseUnknown (line 145) | MouseUnknown MouseEventType = iota
  constant MouseLeft (line 146) | MouseLeft
  constant MouseRight (line 147) | MouseRight
  constant MouseMiddle (line 148) | MouseMiddle
  constant MouseRelease (line 149) | MouseRelease
  constant MouseWheelUp (line 150) | MouseWheelUp
  constant MouseWheelDown (line 151) | MouseWheelDown
  constant MouseWheelLeft (line 152) | MouseWheelLeft
  constant MouseWheelRight (line 153) | MouseWheelRight
  constant MouseBackward (line 154) | MouseBackward
  constant MouseForward (line 155) | MouseForward
  constant MouseMotion (line 156) | MouseMotion
  function parseSGRMouseEvent (line 172) | func parseSGRMouseEvent(buf []byte) MouseEvent {
  constant x10MouseByteOffset (line 203) | x10MouseByteOffset = 32
  function parseX10MouseEvent (line 214) | func parseX10MouseEvent(buf []byte) MouseEvent {
  function parseMouseButton (line 226) | func parseMouseButton(b int, isSGR bool) MouseEvent {

FILE: vendor/github.com/charmbracelet/bubbletea/nil_renderer.go
  type nilRenderer (line 3) | type nilRenderer struct
    method start (line 5) | func (n nilRenderer) start()                     {}
    method stop (line 6) | func (n nilRenderer) stop()                      {}
    method kill (line 7) | func (n nilRenderer) kill()                      {}
    method write (line 8) | func (n nilRenderer) write(_ string)             {}
    method repaint (line 9) | func (n nilRenderer) repaint()                   {}
    method clearScreen (line 10) | func (n nilRenderer) clearScreen()               {}
    method altScreen (line 11) | func (n nilRenderer) altScreen() bool            { return false }
    method enterAltScreen (line 12) | func (n nilRenderer) enterAltScreen()            {}
    method exitAltScreen (line 13) | func (n nilRenderer) exitAltScreen()             {}
    method showCursor (line 14) | func (n nilRenderer) showCursor()                {}
    method hideCursor (line 15) | func (n nilRenderer) hideCursor()                {}
    method enableMouseCellMotion (line 16) | func (n nilRenderer) enableMouseCellMotion()     {}
    method disableMouseCellMotion (line 17) | func (n nilRenderer) disableMouseCellMotion()    {}
    method enableMouseAllMotion (line 18) | func (n nilRenderer) enableMouseAllMotion()      {}
    method disableMouseAllMotion (line 19) | func (n nilRenderer) disableMouseAllMotion()     {}
    method enableBracketedPaste (line 20) | func (n nilRenderer) enableBracketedPaste()      {}
    method disableBracketedPaste (line 21) | func (n nilRenderer) disableBracketedPaste()     {}
    method enableMouseSGRMode (line 22) | func (n nilRenderer) enableMouseSGRMode()        {}
    method disableMouseSGRMode (line 23) | func (n nilRenderer) disableMouseSGRMode()       {}
    method bracketedPasteActive (line 24) | func (n nilRenderer) bracketedPasteActive() bool { return false }
    method setWindowTitle (line 25) | func (n nilRenderer) setWindowTitle(_ string)    {}
    method reportFocus (line 26) | func (n nilRenderer) reportFocus() bool          { return false }
    method enableReportFocus (line 27) | func (n nilRenderer) enableReportFocus()         {}
    method disableReportFocus (line 28) | func (n nilRenderer) disableReportFocus()        {}
    method resetLinesRendered (line 29) | func (n nilRenderer) resetLinesRendered()        {}

FILE: vendor/github.com/charmbracelet/bubbletea/options.go
  type ProgramOption (line 15) | type ProgramOption
  function WithContext (line 20) | func WithContext(ctx context.Context) ProgramOption {
  function WithOutput (line 28) | func WithOutput(output io.Writer) ProgramOption {
  function WithInput (line 38) | func WithInput(input io.Reader) ProgramOption {
  function WithInputTTY (line 46) | func WithInputTTY() ProgramOption {
  function WithEnvironment (line 63) | func WithEnvironment(env []string) ProgramOption {
  function WithoutSignalHandler (line 71) | func WithoutSignalHandler() ProgramOption {
  function WithoutCatchPanics (line 81) | func WithoutCatchPanics() ProgramOption {
  function WithoutSignals (line 89) | func WithoutSignals() ProgramOption {
  function WithAltScreen (line 109) | func WithAltScreen() ProgramOption {
  function WithoutBracketedPaste (line 116) | func WithoutBracketedPaste() ProgramOption {
  function WithMouseCellMotion (line 137) | func WithMouseCellMotion() ProgramOption {
  function WithMouseAllMotion (line 162) | func WithMouseAllMotion() ProgramOption {
  function WithoutRenderer (line 177) | func WithoutRenderer() ProgramOption {
  function WithANSICompressor (line 191) | func WithANSICompressor() ProgramOption {
  function WithFilter (line 226) | func WithFilter(filter func(Model, Msg) Msg) ProgramOption {
  function WithFPS (line 235) | func WithFPS(fps int) ProgramOption {
  function WithReportFocus (line 248) | func WithReportFocus() ProgramOption {

FILE: vendor/github.com/charmbracelet/bubbletea/renderer.go
  type renderer (line 4) | type renderer interface
  type repaintMsg (line 88) | type repaintMsg struct

FILE: vendor/github.com/charmbracelet/bubbletea/screen.go
  type WindowSizeMsg (line 7) | type WindowSizeMsg struct
  function ClearScreen (line 18) | func ClearScreen() Msg {
  type clearScreenMsg (line 24) | type clearScreenMsg struct
  function EnterAltScreen (line 32) | func EnterAltScreen() Msg {
  type enterAltScreenMsg (line 39) | type enterAltScreenMsg struct
  function ExitAltScreen (line 47) | func ExitAltScreen() Msg {
  type exitAltScreenMsg (line 53) | type exitAltScreenMsg struct
  function EnableMouseCellMotion (line 61) | func EnableMouseCellMotion() Msg {
  type enableMouseCellMotionMsg (line 68) | type enableMouseCellMotionMsg struct
  function EnableMouseAllMotion (line 79) | func EnableMouseAllMotion() Msg {
  type enableMouseAllMotionMsg (line 86) | type enableMouseAllMotionMsg struct
  function DisableMouse (line 89) | func DisableMouse() Msg {
  type disableMouseMsg (line 95) | type disableMouseMsg struct
  function HideCursor (line 101) | func HideCursor() Msg {
  type hideCursorMsg (line 107) | type hideCursorMsg struct
  function ShowCursor (line 111) | func ShowCursor() Msg {
  type showCursorMsg (line 117) | type showCursorMsg struct
  function EnableBracketedPaste (line 124) | func EnableBracketedPaste() Msg {
  type enableBracketedPasteMsg (line 131) | type enableBracketedPasteMsg struct
  function DisableBracketedPaste (line 138) | func DisableBracketedPaste() Msg {
  type disableBracketedPasteMsg (line 145) | type disableBracketedPasteMsg struct
  type enableReportFocusMsg (line 149) | type enableReportFocusMsg struct
  function EnableReportFocus (line 153) | func EnableReportFocus() Msg {
  type disableReportFocusMsg (line 159) | type disableReportFocusMsg struct
  function DisableReportFocus (line 163) | func DisableReportFocus() Msg {
  method EnterAltScreen (line 171) | func (p *Program) EnterAltScreen() {
  method ExitAltScreen (line 182) | func (p *Program) ExitAltScreen() {
  method EnableMouseCellMotion (line 194) | func (p *Program) EnableMouseCellMotion() {
  method DisableMouseCellMotion (line 206) | func (p *Program) DisableMouseCellMotion() {
  method EnableMouseAllMotion (line 219) | func (p *Program) EnableMouseAllMotion() {
  method DisableMouseAllMotion (line 231) | func (p *Program) DisableMouseAllMotion() {
  method SetWindowTitle (line 242) | func (p *Program) SetWindowTitle(title string) {

FILE: vendor/github.com/charmbracelet/bubbletea/signals_unix.go
  method listenForResize (line 15) | func (p *Program) listenForResize(done chan struct{}) {

FILE: vendor/github.com/charmbracelet/bubbletea/signals_windows.go
  method listenForResize (line 8) | func (p *Program) listenForResize(done chan struct{}) {

FILE: vendor/github.com/charmbracelet/bubbletea/standard_renderer.go
  constant defaultFPS (line 18) | defaultFPS = 60
  constant maxFPS (line 19) | maxFPS     = 120
  type standardRenderer (line 27) | type standardRenderer struct
    method start (line 86) | func (r *standardRenderer) start() {
    method stop (line 103) | func (r *standardRenderer) stop() {
    method execute (line 127) | func (r *standardRenderer) execute(seq string) {
    method kill (line 132) | func (r *standardRenderer) kill() {
    method listen (line 147) | func (r *standardRenderer) listen() {
    method flush (line 161) | func (r *standardRenderer) flush() {
    method lastLinesRendered (line 294) | func (r *standardRenderer) lastLinesRendered() int {
    method write (line 303) | func (r *standardRenderer) write(s string) {
    method repaint (line 319) | func (r *standardRenderer) repaint() {
    method clearScreen (line 324) | func (r *standardRenderer) clearScreen() {
    method altScreen (line 334) | func (r *standardRenderer) altScreen() bool {
    method enterAltScreen (line 341) | func (r *standardRenderer) enterAltScreen() {
    method exitAltScreen (line 376) | func (r *standardRenderer) exitAltScreen() {
    method showCursor (line 399) | func (r *standardRenderer) showCursor() {
    method hideCursor (line 407) | func (r *standardRenderer) hideCursor() {
    method enableMouseCellMotion (line 415) | func (r *standardRenderer) enableMouseCellMotion() {
    method disableMouseCellMotion (line 422) | func (r *standardRenderer) disableMouseCellMotion() {
    method enableMouseAllMotion (line 429) | func (r *standardRenderer) enableMouseAllMotion() {
    method disableMouseAllMotion (line 436) | func (r *standardRenderer) disableMouseAllMotion() {
    method enableMouseSGRMode (line 443) | func (r *standardRenderer) enableMouseSGRMode() {
    method disableMouseSGRMode (line 450) | func (r *standardRenderer) disableMouseSGRMode() {
    method enableBracketedPaste (line 457) | func (r *standardRenderer) enableBracketedPaste() {
    method disableBracketedPaste (line 465) | func (r *standardRenderer) disableBracketedPaste() {
    method bracketedPasteActive (line 473) | func (r *standardRenderer) bracketedPasteActive() bool {
    method enableReportFocus (line 480) | func (r *standardRenderer) enableReportFocus() {
    method disableReportFocus (line 488) | func (r *standardRenderer) disableReportFocus() {
    method reportFocus (line 496) | func (r *standardRenderer) reportFocus() bool {
    method setWindowTitle (line 504) | func (r *standardRenderer) setWindowTitle(title string) {
    method setIgnoredLines (line 510) | func (r *standardRenderer) setIgnoredLines(from int, to int) {
    method clearIgnoredLines (line 544) | func (r *standardRenderer) clearIgnoredLines() {
    method resetLinesRendered (line 548) | func (r *standardRenderer) resetLinesRendered() {
    method insertTop (line 573) | func (r *standardRenderer) insertTop(lines []string, topBoundary, bott...
    method insertBottom (line 603) | func (r *standardRenderer) insertBottom(lines []string, topBoundary, b...
    method handleMessages (line 621) | func (r *standardRenderer) handleMessages(msg Msg) {
  function newRenderer (line 65) | func newRenderer(out io.Writer, useANSICompressor bool, fps int) renderer {
  type syncScrollAreaMsg (line 676) | type syncScrollAreaMsg struct
  function SyncScrollArea (line 689) | func SyncScrollArea(lines []string, topBoundary int, bottomBoundary int)...
  type clearScrollAreaMsg (line 699) | type clearScrollAreaMsg struct
  function ClearScrollArea (line 707) | func ClearScrollArea() Msg {
  type scrollUpMsg (line 711) | type scrollUpMsg struct
  function ScrollUp (line 724) | func ScrollUp(newLines []string, topBoundary, bottomBoundary int) Cmd {
  type scrollDownMsg (line 734) | type scrollDownMsg struct
  function ScrollDown (line 747) | func ScrollDown(newLines []string, topBoundary, bottomBoundary int) Cmd {
  type printLineMessage (line 757) | type printLineMessage struct
  function Println (line 768) | func Println(args ...interface{}) Cmd {
  function Printf (line 784) | func Printf(template string, args ...interface{}) Cmd {

FILE: vendor/github.com/charmbracelet/bubbletea/tea.go
  type Msg (line 41) | type Msg interface
  type Model (line 44) | type Model interface
  type Cmd (line 65) | type Cmd
  type inputType (line 67) | type inputType
    method String (line 77) | func (i inputType) String() string {
  constant defaultInput (line 70) | defaultInput inputType = iota
  constant ttyInput (line 71) | ttyInput
  constant customInput (line 72) | customInput
  type startupOptions (line 89) | type startupOptions
    method has (line 91) | func (s startupOptions) has(option startupOptions) bool {
  constant withAltScreen (line 96) | withAltScreen startupOptions = 1 << iota
  constant withMouseCellMotion (line 97) | withMouseCellMotion
  constant withMouseAllMotion (line 98) | withMouseAllMotion
  constant withANSICompressor (line 99) | withANSICompressor
  constant withoutSignalHandler (line 100) | withoutSignalHandler
  constant withoutCatchPanics (line 105) | withoutCatchPanics
  constant withoutBracketedPaste (line 106) | withoutBracketedPaste
  constant withReportFocus (line 107) | withReportFocus
  type channelHandlers (line 113) | type channelHandlers
    method add (line 117) | func (h *channelHandlers) add(ch chan struct{}) {
    method shutdown (line 122) | func (h channelHandlers) shutdown() {
  type Program (line 135) | type Program struct
    method handleSignals (line 273) | func (p *Program) handleSignals() chan struct{} {
    method handleResize (line 315) | func (p *Program) handleResize() chan struct{} {
    method handleCommands (line 333) | func (p *Program) handleCommands(cmds chan Cmd) chan struct{} {
    method disableMouse (line 374) | func (p *Program) disableMouse() {
    method eventLoop (line 382) | func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
    method execSequenceMsg (line 507) | func (p *Program) execSequenceMsg(msg sequenceMsg) {
    method execBatchMsg (line 533) | func (p *Program) execBatchMsg(msg BatchMsg) {
    method Run (line 578) | func (p *Program) Run() (returnModel Model, returnErr error) {
    method StartReturningModel (line 753) | func (p *Program) StartReturningModel() (Model, error) {
    method Start (line 762) | func (p *Program) Start() error {
    method Send (line 774) | func (p *Program) Send(msg Msg) {
    method Quit (line 788) | func (p *Program) Quit() {
    method Kill (line 795) | func (p *Program) Kill() {
    method Wait (line 800) | func (p *Program) Wait() {
    method shutdown (line 810) | func (p *Program) shutdown(kill bool) {
    method recoverFromPanic (line 840) | func (p *Program) recoverFromPanic(r interface{}) {
    method recoverFromGoPanic (line 852) | func (p *Program) recoverFromGoPanic(r interface{}) {
    method ReleaseTerminal (line 864) | func (p *Program) ReleaseTerminal() error {
    method RestoreTerminal (line 885) | func (p *Program) RestoreTerminal() error {
    method Println (line 923) | func (p *Program) Println(args ...interface{}) {
    method Printf (line 937) | func (p *Program) Printf(template string, args ...interface{}) {
  function Quit (line 201) | func Quit() Msg {
  type QuitMsg (line 207) | type QuitMsg struct
  function Suspend (line 210) | func Suspend() Msg {
  type SuspendMsg (line 220) | type SuspendMsg struct
  type ResumeMsg (line 224) | type ResumeMsg struct
  type InterruptMsg (line 232) | type InterruptMsg struct
  function Interrupt (line 236) | func Interrupt() Msg {
  function NewProgram (line 241) | func NewProgram(model Model, opts ...ProgramOption) *Program {

FILE: vendor/github.com/charmbracelet/bubbletea/tea_init.go
  function init (line 7) | func init() {

FILE: vendor/github.com/charmbracelet/bubbletea/tty.go
  method suspend (line 13) | func (p *Program) suspend() {
  method initTerminal (line 25) | func (p *Program) initTerminal() error {
  method restoreTerminalState (line 41) | func (p *Program) restoreTerminalState() error {
  method restoreInput (line 63) | func (p *Program) restoreInput() error {
  method initCancelReader (line 78) | func (p *Program) initCancelReader(cancel bool) error {
  method readLoop (line 96) | func (p *Program) readLoop() {
  method waitForReadLoop (line 109) | func (p *Program) waitForReadLoop() {
  method checkResize (line 121) | func (p *Program) checkResize() {

FILE: vendor/github.com/charmbracelet/bubbletea/tty_unix.go
  method initInput (line 15) | func (p *Program) initInput() (err error) {
  function openInputTTY (line 32) | func openInputTTY() (*os.File, error) {
  constant suspendSupported (line 40) | suspendSupported = true
  function suspendProcess (line 43) | func suspendProcess() {

FILE: vendor/github.com/charmbracelet/bubbletea/tty_windows.go
  method initInput (line 14) | func (p *Program) initInput() (err error) {
  function openInputTTY (line 58) | func openInputTTY() (*os.File, error) {
  constant suspendSupported (line 66) | suspendSupported = false
  function suspendProcess (line 68) | func suspendProcess() {}

FILE: vendor/github.com/charmbracelet/colorprofile/env.go
  constant dumbTerm (line 15) | dumbTerm = "dumb"
  function Detect (line 32) | func Detect(output io.Writer, env []string) Profile {
  function Env (line 69) | func Env(env []string) (p Profile) {
  function colorProfile (line 73) | func colorProfile(isatty bool, env environ) (p Profile) {
  function envNoColor (line 114) | func envNoColor(env environ) bool {
  function cliColor (line 119) | func cliColor(env environ) bool {
  function cliColorForced (line 124) | func cliColorForced(env environ) bool {
  function isTTYForced (line 129) | func isTTYForced(env environ) bool {
  function colorTerm (line 134) | func colorTerm(env environ) bool {
  function envColorProfile (line 141) | func envColorProfile(env environ) (p Profile) {
  function Terminfo (line 202) | func Terminfo(term string) (p Profile) {
  function Tmux (line 228) | func Tmux(env []string) Profile {
  function tmux (line 233) | func tmux(env environ) (p Profile) {
  type environ (line 259) | type environ
    method lookup (line 278) | func (e environ) lookup(key string) (string, bool) {
    method get (line 285) | func (e environ) get(key string) string {
  function newEnviron (line 263) | func newEnviron(environ []string) environ {

FILE: vendor/github.com/charmbracelet/colorprofile/env_other.go
  function windowsColorProfile (line 6) | func windowsColorProfile(map[string]string) (Profile, bool) {

FILE: vendor/github.com/charmbracelet/colorprofile/env_windows.go
  function windowsColorProfile (line 12) | func windowsColorProfile(env map[string]string) (Profile, bool) {

FILE: vendor/github.com/charmbracelet/colorprofile/profile.go
  type Profile (line 11) | type Profile
    method String (line 32) | func (p Profile) String() string {
    method Convert (line 58) | func (p Profile) Convert(c color.Color) (cc color.Color) {
  constant Unknown (line 15) | Unknown Profile = iota
  constant NoTTY (line 17) | NoTTY
  constant ASCII (line 19) | ASCII
  constant ANSI (line 21) | ANSI
  constant ANSI256 (line 23) | ANSI256
  constant TrueColor (line 25) | TrueColor
  constant Ascii (line 29) | Ascii = ASCII

FILE: vendor/github.com/charmbracelet/colorprofile/writer.go
  function NewWriter (line 23) | func NewWriter(w io.Writer, environ []string) *Writer {
  type Writer (line 32) | type Writer struct
    method Write (line 38) | func (w *Writer) Write(p []byte) (int, error) {
    method downsample (line 52) | func (w *Writer) downsample(p []byte) (int, error) {
    method WriteString (line 81) | func (w *Writer) WriteString(s string) (n int, err error) {
  function handleSgr (line 85) | func handleSgr(w *Writer, p *ansi.Parser, buf *bytes.Buffer) {

FILE: vendor/github.com/charmbracelet/lipgloss/align.go
  function alignTextHorizontal (line 13) | func alignTextHorizontal(str string, pos Position, width int, style *ter...
  function alignTextVertical (line 62) | func alignTextVertical(str string, pos Position, height int, _ *termenv....

FILE: vendor/github.com/charmbracelet/lipgloss/ansi_unix.go
  function enableLegacyWindowsANSI (line 7) | func enableLegacyWindowsANSI() {}

FILE: vendor/github.com/charmbracelet/lipgloss/ansi_windows.go
  function enableLegacyWindowsANSI (line 18) | func enableLegacyWindowsANSI() {

FILE: vendor/github.com/charmbracelet/lipgloss/borders.go
  type Border (line 13) | type Border struct
    method GetTopSize (line 32) | func (b Border) GetTopSize() int {
    method GetRightSize (line 39) | func (b Border) GetRightSize() int {
    method GetBottomSize (line 46) | func (b Border) GetBottomSize() int {
    method GetLeftSize (line 53) | func (b Border) GetLeftSize() int {
  function getBorderEdgeWidth (line 57) | func getBorderEdgeWidth(borderParts ...string) (maxWidth int) {
  function NormalBorder (line 223) | func NormalBorder() Border {
  function RoundedBorder (line 228) | func RoundedBorder() Border {
  function BlockBorder (line 233) | func BlockBorder() Border {
  function OuterHalfBlockBorder (line 238) | func OuterHalfBlockBorder() Border {
  function InnerHalfBlockBorder (line 243) | func InnerHalfBlockBorder() Border {
  function ThickBorder (line 249) | func ThickBorder() Border {
  function DoubleBorder (line 254) | func DoubleBorder() Border {
  function HiddenBorder (line 262) | func HiddenBorder() Border {
  function MarkdownBorder (line 272) | func MarkdownBorder() Border {
  function ASCIIBorder (line 277) | func ASCIIBorder() Border {
  method applyBorder (line 281) | func (s Style) applyBorder(str string) string {
  function renderHorizontalEdge (line 425) | func renderHorizontalEdge(left, middle, right string, width int) string {
  method styleBorder (line 452) | func (s Style) styleBorder(border string, fg, bg TerminalColor) string {
  function maxRuneWidth (line 469) | func maxRuneWidth(str string) int {
  function getFirstRuneAsString (line 484) | func getFirstRuneAsString(str string) string {

FILE: vendor/github.com/charmbracelet/lipgloss/color.go
  type TerminalColor (line 10) | type TerminalColor interface
  type NoColor (line 24) | type NoColor struct
    method color (line 26) | func (NoColor) color(*Renderer) termenv.Color {
    method RGBA (line 37) | func (n NoColor) RGBA() (r, g, b, a uint32) {
  type Color (line 45) | type Color
    method color (line 47) | func (c Color) color(r *Renderer) termenv.Color {
    method RGBA (line 57) | func (c Color) RGBA() (r, g, b, a uint32) {
  type ANSIColor (line 70) | type ANSIColor
    method color (line 72) | func (ac ANSIColor) color(r *Renderer) termenv.Color {
    method RGBA (line 82) | func (ac ANSIColor) RGBA() (r, g, b, a uint32) {
  type AdaptiveColor (line 94) | type AdaptiveColor struct
    method color (line 99) | func (ac AdaptiveColor) color(r *Renderer) termenv.Color {
    method RGBA (line 112) | func (ac AdaptiveColor) RGBA() (r, g, b, a uint32) {
  type CompleteColor (line 118) | type CompleteColor struct
    method color (line 124) | func (c CompleteColor) color(r *Renderer) termenv.Color {
    method RGBA (line 145) | func (c CompleteColor) RGBA() (r, g, b, a uint32) {
  type CompleteAdaptiveColor (line 152) | type CompleteAdaptiveColor struct
    method color (line 157) | func (cac CompleteAdaptiveColor) color(r *Renderer) termenv.Color {
    method RGBA (line 170) | func (cac CompleteAdaptiveColor) RGBA() (r, g, b, a uint32) {

FILE: vendor/github.com/charmbracelet/lipgloss/get.go
  method GetBold (line 10) | func (s Style) GetBold() bool {
  method GetItalic (line 16) | func (s Style) GetItalic() bool {
  method GetUnderline (line 22) | func (s Style) GetUnderline() bool {
  method GetStrikethrough (line 28) | func (s Style) GetStrikethrough() bool {
  method GetReverse (line 34) | func (s Style) GetReverse() bool {
  method GetBlink (line 40) | func (s Style) GetBlink() bool {
  method GetFaint (line 46) | func (s Style) GetFaint() bool {
  method GetForeground (line 52) | func (s Style) GetForeground() TerminalColor {
  method GetBackground (line 58) | func (s Style) GetBackground() TerminalColor {
  method GetWidth (line 64) | func (s Style) GetWidth() int {
  method GetHeight (line 70) | func (s Style) GetHeight() int {
  method GetAlign (line 76) | func (s Style) GetAlign() Position {
  method GetAlignHorizontal (line 86) | func (s Style) GetAlignHorizontal() Position {
  method GetAlignVertical (line 96) | func (s Style) GetAlignVertical() Position {
  method GetPadding (line 106) | func (s Style) GetPadding() (top, right, bottom, left int) {
  method GetPaddingTop (line 115) | func (s Style) GetPaddingTop() int {
  method GetPaddingRight (line 121) | func (s Style) GetPaddingRight() int {
  method GetPaddingBottom (line 127) | func (s Style) GetPaddingBottom() int {
  method GetPaddingLeft (line 133) | func (s Style) GetPaddingLeft() int {
  method GetHorizontalPadding (line 139) | func (s Style) GetHorizontalPadding() int {
  method GetVerticalPadding (line 145) | func (s Style) GetVerticalPadding() int {
  method GetColorWhitespace (line 151) | func (s Style) GetColorWhitespace() bool {
  method GetMargin (line 157) | func (s Style) GetMargin() (top, right, bottom, left int) {
  method GetMarginTop (line 166) | func (s Style) GetMarginTop() int {
  method GetMarginRight (line 172) | func (s Style) GetMarginRight() int {
  method GetMarginBottom (line 178) | func (s Style) GetMarginBottom() int {
  method GetMarginLeft (line 184) | func (s Style) GetMarginLeft() int {
  method GetHorizontalMargins (line 190) | func (s Style) GetHorizontalMargins() int {
  method GetVerticalMargins (line 196) | func (s Style) GetVerticalMargins() int {
  method GetBorder (line 204) | func (s Style) GetBorder() (b Border, top, right, bottom, left bool) {
  method GetBorderStyle (line 214) | func (s Style) GetBorderStyle() Border {
  method GetBorderTop (line 220) | func (s Style) GetBorderTop() bool {
  method GetBorderRight (line 226) | func (s Style) GetBorderRight() bool {
  method GetBorderBottom (line 232) | func (s Style) GetBorderBottom() bool {
  method GetBorderLeft (line 238) | func (s Style) GetBorderLeft() bool {
  method GetBorderTopForeground (line 244) | func (s Style) GetBorderTopForeground() TerminalColor {
  method GetBorderRightForeground (line 250) | func (s Style) GetBorderRightForeground() TerminalColor {
  method GetBorderBottomForeground (line 256) | func (s Style) GetBorderBottomForeground() TerminalColor {
  method GetBorderLeftForeground (line 262) | func (s Style) GetBorderLeftForeground() TerminalColor {
  method GetBorderTopBackground (line 268) | func (s Style) GetBorderTopBackground() TerminalColor {
  method GetBorderRightBackground (line 274) | func (s Style) GetBorderRightBackground() TerminalColor {
  method GetBorderBottomBackground (line 280) | func (s Style) GetBorderBottomBackground() TerminalColor {
  method GetBorderLeftBackground (line 286) | func (s Style) GetBorderLeftBackground() TerminalColor {
  method GetBorderTopWidth (line 295) | func (s Style) GetBorderTopWidth() int {
  method GetBorderTopSize (line 302) | func (s Style) GetBorderTopSize() int {
  method GetBorderLeftSize (line 312) | func (s Style) GetBorderLeftSize() int {
  method GetBorderBottomSize (line 322) | func (s Style) GetBorderBottomSize() int {
  method GetBorderRightSize (line 332) | func (s Style) GetBorderRightSize() int {
  method GetHorizontalBorderSize (line 342) | func (s Style) GetHorizontalBorderSize() int {
  method GetVerticalBorderSize (line 349) | func (s Style) GetVerticalBorderSize() int {
  method GetInline (line 355) | func (s Style) GetInline() bool {
  method GetMaxWidth (line 361) | func (s Style) GetMaxWidth() int {
  method GetMaxHeight (line 367) | func (s Style) GetMaxHeight() int {
  method GetTabWidth (line 373) | func (s Style) GetTabWidth() int {
  method GetUnderlineSpaces (line 379) | func (s Style) GetUnderlineSpaces() bool {
  method GetStrikethroughSpaces (line 385) | func (s Style) GetStrikethroughSpaces() bool {
  method GetHorizontalFrameSize (line 393) | func (s Style) GetHorizontalFrameSize() int {
  method GetVerticalFrameSize (line 401) | func (s Style) GetVerticalFrameSize() int {
  method GetFrameSize (line 407) | func (s Style) GetFrameSize() (x, y int) {
  method GetTransform (line 413) | func (s Style) GetTransform() func(string) string {
  method isSet (line 418) | func (s Style) isSet(k propKey) bool {
  method getAsBool (line 422) | func (s Style) getAsBool(k propKey, defaultVal bool) bool {
  method getAsColor (line 429) | func (s Style) getAsColor(k propKey) TerminalColor {
  method getAsInt (line 467) | func (s Style) getAsInt(k propKey) int {
  method getAsPosition (line 502) | func (s Style) getAsPosition(k propKey) Position {
  method getBorderStyle (line 515) | func (s Style) getBorderStyle() Border {
  method implicitBorders (line 525) | func (s Style) implicitBorders() bool {
  method getAsTransform (line 536) | func (s Style) getAsTransform(propKey) func(string) string {
  function getLines (line 545) | func getLines(s string) (lines []string, widest int) {

FILE: vendor/github.com/charmbracelet/lipgloss/join.go
  function JoinHorizontal (line 28) | func JoinHorizontal(pos Position, strs ...string) string {
  function JoinVertical (line 116) | func JoinVertical(pos Position, strs ...string) string {

FILE: vendor/github.com/charmbracelet/lipgloss/position.go
  type Position (line 19) | type Position
    method value (line 21) | func (p Position) value() float64 {
  constant Top (line 27) | Top    Position = 0.0
  constant Bottom (line 28) | Bottom Position = 1.0
  constant Center (line 29) | Center Position = 0.5
  constant Left (line 30) | Left   Position = 0.0
  constant Right (line 31) | Right  Position = 1.0
  function Place (line 36) | func Place(width, height int, hPos, vPos Position, str string, opts ...W...
  method Place (line 42) | func (r *Renderer) Place(width, height int, hPos, vPos Position, str str...
  function PlaceHorizontal (line 49) | func PlaceHorizontal(width int, pos Position, str string, opts ...Whites...
  method PlaceHorizontal (line 56) | func (r *Renderer) PlaceHorizontal(width int, pos Position, str string, ...
  function PlaceVertical (line 103) | func PlaceVertical(height int, pos Position, str string, opts ...Whitesp...
  method PlaceVertical (line 110) | func (r *Renderer) PlaceVertical(height int, pos Position, str string, o...

FILE: vendor/github.com/charmbracelet/lipgloss/ranges.go
  function StyleRanges (line 12) | func StyleRanges(s string, ranges ...Range) string {
  function NewRange (line 40) | func NewRange(start, end int, style Style) Range {
  type Range (line 45) | type Range struct

FILE: vendor/github.com/charmbracelet/lipgloss/renderer.go
  type Renderer (line 17) | type Renderer struct
    method Output (line 52) | func (r *Renderer) Output() *termenv.Output {
    method SetOutput (line 59) | func (r *Renderer) SetOutput(o *termenv.Output) {
    method ColorProfile (line 66) | func (r *Renderer) ColorProfile() termenv.Profile {
    method SetColorProfile (line 102) | func (r *Renderer) SetColorProfile(p termenv.Profile) {
    method HasDarkBackground (line 138) | func (r *Renderer) HasDarkBackground() bool {
    method SetHasDarkBackground (line 175) | func (r *Renderer) SetHasDarkBackground(b bool) {
  function DefaultRenderer (line 32) | func DefaultRenderer() *Renderer {
  function SetDefaultRenderer (line 37) | func SetDefaultRenderer(r *Renderer) {
  function NewRenderer (line 44) | func NewRenderer(w io.Writer, opts ...termenv.OutputOption) *Renderer {
  function ColorProfile (line 82) | func ColorProfile() termenv.Profile {
  function SetColorProfile (line 126) | func SetColorProfile(p termenv.Profile) {
  function HasDarkBackground (line 131) | func HasDarkBackground() bool {
  function SetHasDarkBackground (line 162) | func SetHasDarkBackground(b bool) {

FILE: vendor/github.com/charmbracelet/lipgloss/runes.go
  function StyleRunes (line 10) | func StyleRunes(str string, indices []int, matched, unmatched Style) str...

FILE: vendor/github.com/charmbracelet/lipgloss/set.go
  method set (line 4) | func (s *Style) set(key propKey, value interface{}) {
  method setFrom (line 90) | func (s *Style) setFrom(key propKey, i Style) {
  function colorOrNil (line 154) | func colorOrNil(c interface{}) TerminalColor {
  method Bold (line 162) | func (s Style) Bold(v bool) Style {
  method Italic (line 169) | func (s Style) Italic(v bool) Style {
  method Underline (line 177) | func (s Style) Underline(v bool) Style {
  method Strikethrough (line 185) | func (s Style) Strikethrough(v bool) Style {
  method Reverse (line 191) | func (s Style) Reverse(v bool) Style {
  method Blink (line 197) | func (s Style) Blink(v bool) Style {
  method Faint (line 203) | func (s Style) Faint(v bool) Style {
  method Foreground (line 215) | func (s Style) Foreground(c TerminalColor) Style {
  method Background (line 221) | func (s Style) Background(c TerminalColor) Style {
  method Width (line 228) | func (s Style) Width(i int) Style {
  method Height (line 236) | func (s Style) Height(i int) Style {
  method Align (line 247) | func (s Style) Align(p ...Position) Style {
  method AlignHorizontal (line 258) | func (s Style) AlignHorizontal(p Position) Style {
  method AlignVertical (line 264) | func (s Style) AlignVertical(p Position) Style {
  method Padding (line 283) | func (s Style) Padding(i ...int) Style {
  method PaddingLeft (line 297) | func (s Style) PaddingLeft(i int) Style {
  method PaddingRight (line 303) | func (s Style) PaddingRight(i int) Style {
  method PaddingTop (line 309) | func (s Style) PaddingTop(i int) Style {
  method PaddingBottom (line 315) | func (s Style) PaddingBottom(i int) Style {
  method ColorWhitespace (line 326) | func (s Style) ColorWhitespace(v bool) Style {
  method Margin (line 345) | func (s Style) Margin(i ...int) Style {
  method MarginLeft (line 359) | func (s Style) MarginLeft(i int) Style {
  method MarginRight (line 365) | func (s Style) MarginRight(i int) Style {
  method MarginTop (line 371) | func (s Style) MarginTop(i int) Style {
  method MarginBottom (line 377) | func (s Style) MarginBottom(i int) Style {
  method MarginBackground (line 385) | func (s Style) MarginBackground(c TerminalColor) Style {
  method Border (line 413) | func (s Style) Border(b Border, sides ...bool) Style {
  method BorderStyle (line 446) | func (s Style) BorderStyle(b Border) Style {
  method BorderTop (line 452) | func (s Style) BorderTop(v bool) Style {
  method BorderRight (line 458) | func (s Style) BorderRight(v bool) Style {
  method BorderBottom (line 464) | func (s Style) BorderBottom(v bool) Style {
  method BorderLeft (line 470) | func (s Style) BorderLeft(v bool) Style {
  method BorderForeground (line 490) | func (s Style) BorderForeground(c ...TerminalColor) Style {
  method BorderTopForeground (line 509) | func (s Style) BorderTopForeground(c TerminalColor) Style {
  method BorderRightForeground (line 516) | func (s Style) BorderRightForeground(c TerminalColor) Style {
  method BorderBottomForeground (line 523) | func (s Style) BorderBottomForeground(c TerminalColor) Style {
  method BorderLeftForeground (line 530) | func (s Style) BorderLeftForeground(c TerminalColor) Style {
  method BorderBackground (line 550) | func (s Style) BorderBackground(c ...TerminalColor) Style {
  method BorderTopBackground (line 569) | func (s Style) BorderTopBackground(c TerminalColor) Style {
  method BorderRightBackground (line 575) | func (s Style) BorderRightBackground(c TerminalColor) Style {
  method BorderBottomBackground (line 582) | func (s Style) BorderBottomBackground(c TerminalColor) Style {
  method BorderLeftBackground (line 589) | func (s Style) BorderLeftBackground(c TerminalColor) Style {
  method Inline (line 607) | func (s Style) Inline(v bool) Style {
  method MaxWidth (line 625) | func (s Style) MaxWidth(n int) Style {
  method MaxHeight (line 637) | func (s Style) MaxHeight(n int) Style {
  constant NoTabConversion (line 645) | NoTabConversion = -1
  method TabWidth (line 652) | func (s Style) TabWidth(n int) Style {
  method UnderlineSpaces (line 663) | func (s Style) UnderlineSpaces(v bool) Style {
  method StrikethroughSpaces (line 671) | func (s Style) StrikethroughSpaces(v bool) Style {
  method Transform (line 683) | func (s Style) Transform(fn func(string) string) Style {
  method Renderer (line 690) | func (s Style) Renderer(r *Renderer) Style {
  function whichSidesInt (line 705) | func whichSidesInt(i ...int) (top, right, bottom, left int, ok bool) {
  function whichSidesBool (line 738) | func whichSidesBool(i ...bool) (top, right, bottom, left bool, ok bool) {
  function whichSidesColor (line 771) | func whichSidesColor(i ...TerminalColor) (top, right, bottom, left Termi...

FILE: vendor/github.com/charmbracelet/lipgloss/size.go
  function Width (line 15) | func Width(str string) (width int) {
  function Height (line 30) | func Height(str string) int {
  function Size (line 37) | func Size(str string) (width, height int) {

FILE: vendor/github.com/charmbracelet/lipgloss/style.go
  constant tabWidthDefault (line 12) | tabWidthDefault = 4
  type propKey (line 15) | type propKey
  constant boldKey (line 20) | boldKey propKey = 1 << iota
  constant italicKey (line 21) | italicKey
  constant underlineKey (line 22) | underlineKey
  constant strikethroughKey (line 23) | strikethroughKey
  constant reverseKey (line 24) | reverseKey
  constant blinkKey (line 25) | blinkKey
  constant faintKey (line 26) | faintKey
  constant underlineSpacesKey (line 27) | underlineSpacesKey
  constant strikethroughSpacesKey (line 28) | strikethroughSpacesKey
  constant colorWhitespaceKey (line 29) | colorWhitespaceKey
  constant foregroundKey (line 32) | foregroundKey
  constant backgroundKey (line 33) | backgroundKey
  constant widthKey (line 34) | widthKey
  constant heightKey (line 35) | heightKey
  constant alignHorizontalKey (line 36) | alignHorizontalKey
  constant alignVerticalKey (line 37) | alignVerticalKey
  constant paddingTopKey (line 40) | paddingTopKey
  constant paddingRightKey (line 41) | paddingRightKey
  constant paddingBottomKey (line 42) | paddingBottomKey
  constant paddingLeftKey (line 43) | paddingLeftKey
  constant marginTopKey (line 46) | marginTopKey
  constant marginRightKey (line 47) | marginRightKey
  constant marginBottomKey (line 48) | marginBottomKey
  constant marginLeftKey (line 49) | marginLeftKey
  constant marginBackgroundKey (line 50) | marginBackgroundKey
  constant borderStyleKey (line 53) | borderStyleKey
  constant borderTopKey (line 56) | borderTopKey
  constant borderRightKey (line 57) | borderRightKey
  constant borderBottomKey (line 58) | borderBottomKey
  constant borderLeftKey (line 59) | borderLeftKey
  constant borderTopForegroundKey (line 62) | borderTopForegroundKey
  constant borderRightForegroundKey (line 63) | borderRightForegroundKey
  constant borderBottomForegroundKey (line 64) | borderBottomForegroundKey
  constant borderLeftForegroundKey (line 65) | borderLeftForegroundKey
  constant borderTopBackgroundKey (line 68) | borderTopBackgroundKey
  constant borderRightBackgroundKey (line 69) | borderRightBackgroundKey
  constant borderBottomBackgroundKey (line 70) | borderBottomBackgroundKey
  constant borderLeftBackgroundKey (line 71) | borderLeftBackgroundKey
  constant inlineKey (line 73) | inlineKey
  constant maxWidthKey (line 74) | maxWidthKey
  constant maxHeightKey (line 75) | maxHeightKey
  constant tabWidthKey (line 76) | tabWidthKey
  constant transformKey (line 78) | transformKey
  type props (line 82) | type props
    method set (line 85) | func (p props) set(k propKey) props {
    method unset (line 90) | func (p props) unset(k propKey) props {
    method has (line 95) | func (p props) has(k propKey) bool {
  function NewStyle (line 103) | func NewStyle() Style {
  method NewStyle (line 111) | func (r *Renderer) NewStyle() Style {
  type Style (line 117) | type Style struct
    method SetString (line 174) | func (s Style) SetString(strs ...string) Style {
    method Value (line 180) | func (s Style) Value() string {
    method String (line 187) | func (s Style) String() string {
    method Copy (line 195) | func (s Style) Copy() Style {
    method Inherit (line 204) | func (s Style) Inherit(i Style) Style {
    method Render (line 234) | func (s Style) Render(strs ...string) string {
    method maybeConvertTabs (line 472) | func (s Style) maybeConvertTabs(str string) string {
    method applyMargins (line 487) | func (s Style) applyMargins(str string, inline bool) string {
  function joinString (line 165) | func joinString(strs ...string) string {
  function padLeft (line 523) | func padLeft(str string, n int, style *termenv.Style) string {
  function padRight (line 528) | func padRight(str string, n int, style *termenv.Style) string {
  function pad (line 535) | func pad(str string, n int, style *termenv.Style) string {
  function max (line 568) | func max(a, b int) int { //nolint:unparam,predeclared
  function min (line 575) | func min(a, b int) int { //nolint:predeclared
  function abs (line 582) | func abs(a int) int {

FILE: vendor/github.com/charmbracelet/lipgloss/unset.go
  method unset (line 4) | func (s *Style) unset(key propKey) {
  method UnsetBold (line 9) | func (s Style) UnsetBold() Style {
  method UnsetItalic (line 15) | func (s Style) UnsetItalic() Style {
  method UnsetUnderline (line 21) | func (s Style) UnsetUnderline() Style {
  method UnsetStrikethrough (line 27) | func (s Style) UnsetStrikethrough() Style {
  method UnsetReverse (line 33) | func (s Style) UnsetReverse() Style {
  method UnsetBlink (line 39) | func (s Style) UnsetBlink() Style {
  method UnsetFaint (line 45) | func (s Style) UnsetFaint() Style {
  method UnsetForeground (line 51) | func (s Style) UnsetForeground() Style {
  method UnsetBackground (line 57) | func (s Style) UnsetBackground() Style {
  method UnsetWidth (line 63) | func (s Style) UnsetWidth() Style {
  method UnsetHeight (line 69) | func (s Style) UnsetHeight() Style {
  method UnsetAlign (line 75) | func (s Style) UnsetAlign() Style {
  method UnsetAlignHorizontal (line 82) | func (s Style) UnsetAlignHorizontal() Style {
  method UnsetAlignVertical (line 88) | func (s Style) UnsetAlignVertical() Style {
  method UnsetPadding (line 94) | func (s Style) UnsetPadding() Style {
  method UnsetPaddingLeft (line 103) | func (s Style) UnsetPaddingLeft() Style {
  method UnsetPaddingRight (line 109) | func (s Style) UnsetPaddingRight() Style {
  method UnsetPaddingTop (line 115) | func (s Style) UnsetPaddingTop() Style {
  method UnsetPaddingBottom (line 121) | func (s Style) UnsetPaddingBottom() Style {
  method UnsetColorWhitespace (line 127) | func (s Style) UnsetColorWhitespace() Style {
  method UnsetMargins (line 133) | func (s Style) UnsetMargins() Style {
  method UnsetMarginLeft (line 142) | func (s Style) UnsetMarginLeft() Style {
  method UnsetMarginRight (line 148) | func (s Style) UnsetMarginRight() Style {
  method UnsetMarginTop (line 154) | func (s Style) UnsetMarginTop() Style {
  method UnsetMarginBottom (line 160) | func (s Style) UnsetMarginBottom() Style {
  method UnsetMarginBackground (line 168) | func (s Style) UnsetMarginBackground() Style {
  method UnsetBorderStyle (line 174) | func (s Style) UnsetBorderStyle() Style {
  method UnsetBorderTop (line 180) | func (s Style) UnsetBorderTop() Style {
  method UnsetBorderRight (line 186) | func (s Style) UnsetBorderRight() Style {
  method UnsetBorderBottom (line 192) | func (s Style) UnsetBorderBottom() Style {
  method UnsetBorderLeft (line 198) | func (s Style) UnsetBorderLeft() Style {
  method UnsetBorderForeground (line 204) | func (s Style) UnsetBorderForeground() Style {
  method UnsetBorderTopForeground (line 214) | func (s Style) UnsetBorderTopForeground() Style {
  method UnsetBorderRightForeground (line 221) | func (s Style) UnsetBorderRightForeground() Style {
  method UnsetBorderBottomForeground (line 228) | func (s Style) UnsetBorderBottomForeground() Style {
  method UnsetBorderLeftForeground (line 235) | func (s Style) UnsetBorderLeftForeground() Style {
  method UnsetBorderBackground (line 242) | func (s Style) UnsetBorderBackground() Style {
  method UnsetBorderTopBackgroundColor (line 254) | func (s Style) UnsetBorderTopBackgroundColor() Style {
  method UnsetBorderTopBackground (line 260) | func (s Style) UnsetBorderTopBackground() Style {
  method UnsetBorderRightBackground (line 267) | func (s Style) UnsetBorderRightBackground() Style {
  method UnsetBorderBottomBackground (line 274) | func (s Style) UnsetBorderBottomBackground() Style {
  method UnsetBorderLeftBackground (line 280) | func (s Style) UnsetBorderLeftBackground() Style {
  method UnsetInline (line 286) | func (s Style) UnsetInline() Style {
  method UnsetMaxWidth (line 292) | func (s Style) UnsetMaxWidth() Style {
  method UnsetMaxHeight (line 298) | func (s Style) UnsetMaxHeight() Style {
  method UnsetTabWidth (line 304) | func (s Style) UnsetTabWidth() Style {
  method UnsetUnderlineSpaces (line 310) | func (s Style) UnsetUnderlineSpaces() Style {
  method UnsetStrikethroughSpaces (line 316) | func (s Style) UnsetStrikethroughSpaces() Style {
  method UnsetTransform (line 322) | func (s Style) UnsetTransform() Style {
  method UnsetString (line 328) | func (s Style) UnsetString() Style {

FILE: vendor/github.com/charmbracelet/lipgloss/whitespace.go
  type whitespace (line 11) | type whitespace struct
    method render (line 32) | func (w whitespace) render(width int) string {
  function newWhitespace (line 20) | func newWhitespace(r *Renderer, opts ...WhitespaceOption) *whitespace {
  type WhitespaceOption (line 62) | type WhitespaceOption
  function WithWhitespaceForeground (line 65) | func WithWhitespaceForeground(c TerminalColor) WhitespaceOption {
  function WithWhitespaceBackground (line 72) | func WithWhitespaceBackground(c TerminalColor) WhitespaceOption {
  function WithWhitespaceChars (line 79) | func WithWhitespaceChars(s string) WhitespaceOption {

FILE: vendor/github.com/charmbracelet/x/ansi/ansi.go
  function Execute (line 9) | func Execute(w io.Writer, s string) (int, error) {

FILE: vendor/github.com/charmbracelet/x/ansi/ascii.go
  constant SP (line 5) | SP = 0x20
  constant DEL (line 7) | DEL = 0x7F

FILE: vendor/github.com/charmbracelet/x/ansi/background.go
  type HexColor (line 11) | type HexColor
    method RGBA (line 14) | func (h HexColor) RGBA() (r, g, b, a uint32) {
    method Hex (line 24) | func (h HexColor) Hex() string {
    method String (line 34) | func (h HexColor) String() string {
    method color (line 39) | func (h HexColor) color() *colorful.Color {
  type XRGBColor (line 51) | type XRGBColor struct
    method RGBA (line 56) | func (x XRGBColor) RGBA() (r, g, b, a uint32) {
    method String (line 65) | func (x XRGBColor) String() string {
  type XRGBAColor (line 78) | type XRGBAColor struct
    method RGBA (line 83) | func (x XRGBAColor) RGBA() (r, g, b, a uint32) {
    method String (line 92) | func (x XRGBAColor) String() string {
  function SetForegroundColor (line 112) | func SetForegroundColor(s string) string {
  constant RequestForegroundColor (line 120) | RequestForegroundColor = "\x1b]10;?\x07"
  constant ResetForegroundColor (line 126) | ResetForegroundColor = "\x1b]110\x07"
  function SetBackgroundColor (line 139) | func SetBackgroundColor(s string) string {
  constant RequestBackgroundColor (line 147) | RequestBackgroundColor = "\x1b]11;?\x07"
  constant ResetBackgroundColor (line 153) | ResetBackgroundColor = "\x1b]111\x07"
  function SetCursorColor (line 165) | func SetCursorColor(s string) string {
  constant RequestCursorColor (line 173) | RequestCursorColor = "\x1b]12;?\x07"
  constant ResetCursorColor (line 178) | ResetCursorColor = "\x1b]112\x07"

FILE: vendor/github.com/charmbracelet/x/ansi/c0.go
  constant NUL (line 9) | NUL = 0x00
  constant SOH (line 11) | SOH = 0x01
  constant STX (line 13) | STX = 0x02
  constant ETX (line 15) | ETX = 0x03
  constant EOT (line 17) | EOT = 0x04
  constant ENQ (line 19) | ENQ = 0x05
  constant ACK (line 21) | ACK = 0x06
  constant BEL (line 23) | BEL = 0x07
  constant BS (line 25) | BS = 0x08
  constant HT (line 27) | HT = 0x09
  constant LF (line 29) | LF = 0x0A
  constant VT (line 31) | VT = 0x0B
  constant FF (line 33) | FF = 0x0C
  constant CR (line 35) | CR = 0x0D
  constant SO (line 37) | SO = 0x0E
  constant SI (line 39) | SI = 0x0F
  constant DLE (line 41) | DLE = 0x10
  constant DC1 (line 43) | DC1 = 0x11
  constant DC2 (line 45) | DC2 = 0x12
  constant DC3 (line 47) | DC3 = 0x13
  constant DC4 (line 49) | DC4 = 0x14
  constant NAK (line 51) | NAK = 0x15
  constant SYN (line 53) | SYN = 0x16
  constant ETB (line 55) | ETB = 0x17
  constant CAN (line 57) | CAN = 0x18
  constant EM (line 59) | EM = 0x19
  constant SUB (line 61) | SUB = 0x1A
  constant ESC (line 63) | ESC = 0x1B
  constant FS (line 65) | FS = 0x1C
  constant GS (line 67) | GS = 0x1D
  constant RS (line 69) | RS = 0x1E
  constant US (line 71) | US = 0x1F
  constant LS0 (line 75) | LS0 = SI
  constant LS1 (line 78) | LS1 = SO

FILE: vendor/github.com/charmbracelet/x/ansi/c1.go
  constant PAD (line 9) | PAD = 0x80
  constant HOP (line 11) | HOP = 0x81
  constant BPH (line 13) | BPH = 0x82
  constant NBH (line 15) | NBH = 0x83
  constant IND (line 17) | IND = 0x84
  constant NEL (line 19) | NEL = 0x85
  constant SSA (line 21) | SSA = 0x86
  constant ESA (line 23) | ESA = 0x87
  constant HTS (line 25) | HTS = 0x88
  constant HTJ (line 27) | HTJ = 0x89
  constant VTS (line 29) | VTS = 0x8A
  constant PLD (line 31) | PLD = 0x8B
  constant PLU (line 33) | PLU = 0x8C
  constant RI (line 35) | RI = 0x8D
  constant SS2 (line 37) | SS2 = 0x8E
  constant SS3 (line 39) | SS3 = 0x8F
  constant DCS (line 41) | DCS = 0x90
  constant PU1 (line 43) | PU1 = 0x91
  constant PU2 (line 45) | PU2 = 0x92
  constant STS (line 47) | STS = 0x93
  constant CCH (line 49) | CCH = 0x94
  constant MW (line 51) | MW = 0x95
  constant SPA (line 53) | SPA = 0x96
  constant EPA (line 55) | EPA = 0x97
  constant SOS (line 57) | SOS = 0x98
  constant SGCI (line 59) | SGCI = 0x99
  constant SCI (line 61) | SCI = 0x9A
  constant CSI (line 63) | CSI = 0x9B
  constant ST (line 65) | ST = 0x9C
  constant OSC (line 67) | OSC = 0x9D
  constant PM (line 69) | PM = 0x9E
  constant APC (line 71) | APC = 0x9F

FILE: vendor/github.com/charmbracelet/x/ansi/charset.go
  function SelectCharacterSet (line 33) | func SelectCharacterSet(gset byte, charset byte) string {
  function SCS (line 38) | func SCS(gset byte, charset byte) string {
  constant LS1R (line 43) | LS1R = "\x1b~"
  constant LS2 (line 46) | LS2 = "\x1bn"
  constant LS2R (line 49) | LS2R = "\x1b}"
  constant LS3 (line 52) | LS3 = "\x1bo"
  constant LS3R (line 55) | LS3R = "\x1b|"

FILE: vendor/github.com/charmbracelet/x/ansi/clipboard.go
  constant SystemClipboard (line 7) | SystemClipboard  = 'c'
  constant PrimaryClipboard (line 8) | PrimaryClipboard = 'p'
  function SetClipboard (line 20) | func SetClipboard(c byte, d string) string {
  function SetSystemClipboard (line 30) | func SetSystemClipboard(d string) string {
  function SetPrimaryClipboard (line 37) | func SetPrimaryClipboard(d string) string {
  function ResetClipboard (line 46) | func ResetClipboard(c byte) string {
  constant ResetSystemClipboard (line 53) | ResetSystemClipboard = "\x1b]52;c;\x07"
  constant ResetPrimaryClipboard (line 58) | ResetPrimaryClipboard = "\x1b]52;p;\x07"
  function RequestClipboard (line 63) | func RequestClipboard(c byte) string {
  constant RequestSystemClipboard (line 70) | RequestSystemClipboard = "\x1b]52;c;?\x07"
  constant RequestPrimaryClipboard (line 75) | RequestPrimaryClipboard = "\x1b]52;p;?\x07"

FILE: vendor/github.com/charmbracelet/x/ansi/color.go
  type Color (line 11) | type Color interface
  type BasicColor (line 16) | type BasicColor
    method RGBA (line 72) | func (c BasicColor) RGBA() (uint32, uint32, uint32, uint32) {
  constant Black (line 22) | Black BasicColor = iota
  constant Red (line 25) | Red
  constant Green (line 28) | Green
  constant Yellow (line 31) | Yellow
  constant Blue (line 34) | Blue
  constant Magenta (line 37) | Magenta
  constant Cyan (line 40) | Cyan
  constant White (line 43) | White
  constant BrightBlack (line 46) | BrightBlack
  constant BrightRed (line 49) | BrightRed
  constant BrightGreen (line 52) | BrightGreen
  constant BrightYellow (line 55) | BrightYellow
  constant BrightBlue (line 58) | BrightBlue
  constant BrightMagenta (line 61) | BrightMagenta
  constant BrightCyan (line 64) | BrightCyan
  constant BrightWhite (line 67) | BrightWhite
  type IndexedColor (line 82) | type IndexedColor
    method RGBA (line 88) | func (c IndexedColor) RGBA() (uint32, uint32, uint32, uint32) {
  type TrueColor (line 105) | type TrueColor
    method RGBA (line 111) | func (c TrueColor) RGBA() (uint32, uint32, uint32, uint32) {
  type RGBColor (line 118) | type RGBColor struct
    method RGBA (line 126) | func (c RGBColor) RGBA() (uint32, uint32, uint32, uint32) {
  function ansiToRGB (line 133) | func ansiToRGB(ansi byte) color.Color {
  function hexToRGB (line 141) | func hexToRGB(hex uint32) (uint32, uint32, uint32) {
  function toRGBA (line 152) | func toRGBA(r, g, b uint32) (uint32, uint32, uint32, uint32) {
  function distSq (line 160) | func distSq(r1, g1, b1, r2, g2, b2 int) int {
  function to6Cube (line 164) | func to6Cube[T int | float64](v T) int {
  function Convert256 (line 185) | func Convert256(c color.Color) IndexedColor {
  function Convert16 (line 252) | func Convert16(c color.Color) BasicColor {

FILE: vendor/github.com/charmbracelet/x/ansi/ctrl.go
  constant RequestNameVersion (line 17) | RequestNameVersion = "\x1b[>q"
  constant XTVERSION (line 18) | XTVERSION          = RequestNameVersion
  constant RequestXTVersion (line 29) | RequestXTVersion = RequestNameVersion
  function PrimaryDeviceAttributes (line 61) | func PrimaryDeviceAttributes(attrs ...int) string {
  function DA1 (line 76) | func DA1(attrs ...int) string {
  constant RequestPrimaryDeviceAttributes (line 86) | RequestPrimaryDeviceAttributes = "\x1b[c"
  function SecondaryDeviceAttributes (line 96) | func SecondaryDeviceAttributes(attrs ...int) string {
  function DA2 (line 109) | func DA2(attrs ...int) string {
  constant RequestSecondaryDeviceAttributes (line 119) | RequestSecondaryDeviceAttributes = "\x1b[>c"
  function TertiaryDeviceAttributes (line 134) | func TertiaryDeviceAttributes(unitID string) string {
  function DA3 (line 146) | func DA3(unitID string) string {
  constant RequestTertiaryDeviceAttributes (line 156) | RequestTertiaryDeviceAttributes = "\x1b[=c"

FILE: vendor/github.com/charmbracelet/x/ansi/cursor.go
  constant SaveCursor (line 14) | SaveCursor = "\x1b7"
  constant DECSC (line 15) | DECSC      = SaveCursor
  constant RestoreCursor (line 25) | RestoreCursor = "\x1b8"
  constant DECRC (line 26) | DECRC         = RestoreCursor
  constant RequestCursorPosition (line 43) | RequestCursorPosition = "\x1b[6n"
  constant RequestExtendedCursorPosition (line 60) | RequestExtendedCursorPosition = "\x1b[?6n"
  function CursorUp (line 67) | func CursorUp(n int) string {
  function CUU (line 76) | func CUU(n int) string {
  constant CUU1 (line 81) | CUU1 = "\x1b[A"
  constant CursorUp1 (line 88) | CursorUp1 = "\x1b[A"
  function CursorDown (line 95) | func CursorDown(n int) string {
  function CUD (line 104) | func CUD(n int) string {
  constant CUD1 (line 109) | CUD1 = "\x1b[B"
  constant CursorDown1 (line 116) | CursorDown1 = "\x1b[B"
  function CursorForward (line 123) | func CursorForward(n int) string {
  function CUF (line 132) | func CUF(n int) string {
  constant CUF1 (line 137) | CUF1 = "\x1b[C"
  function CursorRight (line 146) | func CursorRight(n int) string {
  constant CursorRight1 (line 155) | CursorRight1 = CUF1
  function CursorBackward (line 162) | func CursorBackward(n int) string {
  function CUB (line 171) | func CUB(n int) string {
  constant CUB1 (line 176) | CUB1 = "\x1b[D"
  function CursorLeft (line 185) | func CursorLeft(n int) string {
  constant CursorLeft1 (line 194) | CursorLeft1 = CUB1
  function CursorNextLine (line 202) | func CursorNextLine(n int) string {
  function CNL (line 211) | func CNL(n int) string {
  function CursorPreviousLine (line 221) | func CursorPreviousLine(n int) string {
  function CPL (line 230) | func CPL(n int) string {
  function CursorHorizontalAbsolute (line 242) | func CursorHorizontalAbsolute(col int) string {
  function CHA (line 251) | func CHA(col int) string {
  function CursorPosition (line 263) | func CursorPosition(col, row int) string {
  function CUP (line 279) | func CUP(col, row int) string {
  constant CursorHomePosition (line 287) | CursorHomePosition = "\x1b[H"
  function SetCursorPosition (line 297) | func SetCursorPosition(col, row int) string {
  constant HomeCursorPosition (line 316) | HomeCursorPosition = CursorHomePosition
  function MoveCursor (line 326) | func MoveCursor(col, row int) string {
  constant CursorOrigin (line 334) | CursorOrigin = "\x1b[1;1H"
  constant MoveCursorOrigin (line 340) | MoveCursorOrigin = CursorOrigin
  function CursorHorizontalForwardTab (line 350) | func CursorHorizontalForwardTab(n int) string {
  function CHT (line 359) | func CHT(n int) string {
  function EraseCharacter (line 371) | func EraseCharacter(n int) string {
  function ECH (line 380) | func ECH(n int) string {
  function CursorBackwardTab (line 392) | func CursorBackwardTab(n int) string {
  function CBT (line 401) | func CBT(n int) string {
  function VerticalPositionAbsolute (line 413) | func VerticalPositionAbsolute(row int) string {
  function VPA (line 422) | func VPA(row int) string {
  function VerticalPositionRelative (line 434) | func VerticalPositionRelative(n int) string {
  function VPR (line 443) | func VPR(n int) string {
  function HorizontalVerticalPosition (line 457) | func HorizontalVerticalPosition(col, row int) string {
  function HVP (line 469) | func HVP(col, row int) string {
  constant HorizontalVerticalHomePosition (line 476) | HorizontalVerticalHomePosition = "\x1b[f"
  constant SaveCurrentCursorPosition (line 488) | SaveCurrentCursorPosition = "\x1b[s"
  constant SCOSC (line 489) | SCOSC                     = SaveCurrentCursorPosition
  constant SaveCursorPosition (line 503) | SaveCursorPosition = "\x1b[s"
  constant RestoreCurrentCursorPosition (line 515) | RestoreCurrentCursorPosition = "\x1b[u"
  constant SCORC (line 516) | SCORC                        = RestoreCurrentCursorPosition
  constant RestoreCursorPosition (line 530) | RestoreCursorPosition = "\x1b[u"
  function SetCursorStyle (line 550) | func SetCursorStyle(style int) string {
  function DECSCUSR (line 558) | func DECSCUSR(style int) string {
  function SetPointerShape (line 580) | func SetPointerShape(shape string) string {
  constant ReverseIndex (line 589) | ReverseIndex = "\x1bM"
  function HorizontalPositionAbsolute (line 599) | func HorizontalPositionAbsolute(col int) string {
  function HPA (line 608) | func HPA(col int) string {
  function HorizontalPositionRelative (line 621) | func HorizontalPositionRelative(n int) string {
  function HPR (line 630) | func HPR(n int) string {
  constant Index (line 637) | Index = "\x1bD"

FILE: vendor/github.com/charmbracelet/x/ansi/cwd.go
  function NotifyWorkingDirectory (line 18) | func NotifyWorkingDirectory(host string, paths ...string) string {

FILE: vendor/github.com/charmbracelet/x/ansi/finalterm.go
  function FinalTerm (line 12) | func FinalTerm(pm ...string) string {
  function FinalTermPrompt (line 21) | func FinalTermPrompt(pm ...string) string {
  function FinalTermCmdStart (line 33) | func FinalTermCmdStart(pm ...string) string {
  function FinalTermCmdExecuted (line 45) | func FinalTermCmdExecuted(pm ...string) string {
  function FinalTermCmdFinished (line 62) | func FinalTermCmdFinished(pm ...string) string {

FILE: vendor/github.com/charmbracelet/x/ansi/focus.go
  constant Focus (line 5) | Focus = "\x1b[I"
  constant Blur (line 9) | Blur = "\x1b[O"

FILE: vendor/github.com/charmbracelet/x/ansi/graphics.go
  function SixelGraphics (line 24) | func SixelGraphics(p1, p2, p3 int, payload []byte) string {
  function KittyGraphics (line 52) | func KittyGraphics(payload []byte, opts ...string) string {

FILE: vendor/github.com/charmbracelet/x/ansi/hyperlink.go
  function SetHyperlink (line 13) | func SetHyperlink(uri string, params ...string) string {
  function ResetHyperlink (line 26) | func ResetHyperlink(params ...string) string {

FILE: vendor/github.com/charmbracelet/x/ansi/inband.go
  function InBandResize (line 10) | func InBandResize(heightCells, widthCells, heightPixels, widthPixels int...

FILE: vendor/github.com/charmbracelet/x/ansi/iterm2.go
  function ITerm2 (line 16) | func ITerm2(data any) string {

FILE: vendor/github.com/charmbracelet/x/ansi/keypad.go
  constant KeypadApplicationMode (line 13) | KeypadApplicationMode = "\x1b="
  constant DECKPAM (line 14) | DECKPAM               = KeypadApplicationMode
  constant KeypadNumericMode (line 26) | KeypadNumericMode = "\x1b>"
  constant DECKPNM (line 27) | DECKPNM           = KeypadNumericMode

FILE: vendor/github.com/charmbracelet/x/ansi/kitty.go
  constant KittyDisambiguateEscapeCodes (line 8) | KittyDisambiguateEscapeCodes = 1 << iota
  constant KittyReportEventTypes (line 9) | KittyReportEventTypes
  constant KittyReportAlternateKeys (line 10) | KittyReportAlternateKeys
  constant KittyReportAllKeysAsEscapeCodes (line 11) | KittyReportAllKeysAsEscapeCodes
  constant KittyReportAssociatedKeys (line 12) | KittyReportAssociatedKeys
  constant KittyAllFlags (line 14) | KittyAllFlags = KittyDisambiguateEscapeCodes | KittyReportEventTypes |
  constant RequestKittyKeyboard (line 22) | RequestKittyKeyboard = "\x1b[?u"
  function KittyKeyboard (line 43) | func KittyKeyboard(flags, mode int) string {
  function PushKittyKeyboard (line 62) | func PushKittyKeyboard(flags int) string {
  constant DisableKittyKeyboard (line 75) | DisableKittyKeyboard = "\x1b[>u"
  function PopKittyKeyboard (line 83) | func PopKittyKeyboard(n int) string {

FILE: vendor/github.com/charmbracelet/x/ansi/method.go
  function init (line 20) | func init() {
  type Method (line 29) | type Method
    method StringWidth (line 41) | func (m Method) StringWidth(s string) int {
    method Truncate (line 49) | func (m Method) Truncate(s string, length int, tail string) string {
    method TruncateLeft (line 57) | func (m Method) TruncateLeft(s string, length int, prefix string) stri...
    method Cut (line 65) | func (m Method) Cut(s string, left, right int) string {
    method Hardwrap (line 75) | func (m Method) Hardwrap(s string, length int, preserveSpace bool) str...
    method Wordwrap (line 87) | func (m Method) Wordwrap(s string, length int, breakpoints string) str...
    method Wrap (line 98) | func (m Method) Wrap(s string, length int, breakpoints string) string {
    method DecodeSequence (line 146) | func (m Method) DecodeSequence(data []byte, state byte, p *Parser) (se...
    method DecodeSequenceInString (line 194) | func (m Method) DecodeSequenceInString(data string, state byte, p *Par...
  constant WcWidth (line 33) | WcWidth Method = iota
  constant GraphemeWidth (line 34) | GraphemeWidth

FILE: vendor/github.com/charmbracelet/x/ansi/mode.go
  type ModeSetting (line 9) | type ModeSetting
    method IsNotRecognized (line 21) | func (m ModeSetting) IsNotRecognized() bool {
    method IsSet (line 26) | func (m ModeSetting) IsSet() bool {
    method IsReset (line 31) | func (m ModeSetting) IsReset() bool {
    method IsPermanentlySet (line 36) | func (m ModeSetting) IsPermanentlySet() bool {
    method IsPermanentlyReset (line 41) | func (m ModeSetting) IsPermanentlyReset() bool {
  constant ModeNotRecognized (line 13) | ModeNotRecognized ModeSetting = iota
  constant ModeSet (line 14) | ModeSet
  constant ModeReset (line 15) | ModeReset
  constant ModePermanentlySet (line 16) | ModePermanentlySet
  constant ModePermanentlyReset (line 17) | ModePermanentlyReset
  type Mode (line 47) | type Mode interface
  function SetMode (line 66) | func SetMode(modes ...Mode) string {
  function SM (line 71) | func SM(modes ...Mode) string {
  function DECSET (line 76) | func DECSET(modes ...Mode) string {
  function ResetMode (line 95) | func ResetMode(modes ...Mode) string {
  function RM (line 100) | func RM(modes ...Mode) string {
  function DECRST (line 105) | func DECRST(modes ...Mode) string {
  function setMode (line 109) | func setMode(reset bool, modes ...Mode) (s string) {
  function RequestMode (line 160) | func RequestMode(m Mode) string {
  function DECRQM (line 170) | func DECRQM(m Mode) string {
  function ReportMode (line 194) | func ReportMode(mode Mode, value ModeSetting) string {
  function DECRPM (line 206) | func DECRPM(mode Mode, value ModeSetting) string {
  type ANSIMode (line 211) | type ANSIMode
    method Mode (line 214) | func (m ANSIMode) Mode() int {
  type DECMode (line 219) | type DECMode
    method Mode (line 222) | func (m DECMode) Mode() int {
  constant ModeKeyboardAction (line 231) | ModeKeyboardAction = ANSIMode(2)
  constant KAM (line 232) | KAM                = ModeKeyboardAction
  constant SetModeKeyboardAction (line 234) | SetModeKeyboardAction     = "\x1b[2h"
  constant ResetModeKeyboardAction (line 235) | ResetModeKeyboardAction   = "\x1b[2l"
  constant RequestModeKeyboardAction (line 236) | RequestModeKeyboardAction = "\x1b[2$p"
  constant ModeInsertReplace (line 248) | ModeInsertReplace = ANSIMode(4)
  constant IRM (line 249) | IRM               = ModeInsertReplace
  constant SetModeInsertReplace (line 251) | SetModeInsertReplace     = "\x1b[4h"
  constant ResetModeInsertReplace (line 252) | ResetModeInsertReplace   = "\x1b[4l"
  constant RequestModeInsertReplace (line 253) | RequestModeInsertReplace = "\x1b[4$p"
  constant ModeBiDirectionalSupport (line 263) | ModeBiDirectionalSupport = ANSIMode(8)
  constant BDSM (line 264) | BDSM                     = ModeBiDirectionalSupport
  constant SetModeBiDirectionalSupport (line 266) | SetModeBiDirectionalSupport     = "\x1b[8h"
  constant ResetModeBiDirectionalSupport (line 267) | ResetModeBiDirectionalSupport   = "\x1b[8l"
  constant RequestModeBiDirectionalSupport (line 268) | RequestModeBiDirectionalSupport = "\x1b[8$p"
  constant ModeSendReceive (line 277) | ModeSendReceive = ANSIMode(12)
  constant ModeLocalEcho (line 278) | ModeLocalEcho   = ModeSendReceive
  constant SRM (line 279) | SRM             = ModeSendReceive
  constant SetModeSendReceive (line 281) | SetModeSendReceive     = "\x1b[12h"
  constant ResetModeSendReceive (line 282) | ResetModeSendReceive   = "\x1b[12l"
  constant RequestModeSendReceive (line 283) | RequestModeSendReceive = "\x1b[12$p"
  constant SetModeLocalEcho (line 285) | SetModeLocalEcho     = "\x1b[12h"
  constant ResetModeLocalEcho (line 286) | ResetModeLocalEcho   = "\x1b[12l"
  constant RequestModeLocalEcho (line 287) | RequestModeLocalEcho = "\x1b[12$p"
  constant ModeLineFeedNewLine (line 302) | ModeLineFeedNewLine = ANSIMode(20)
  constant LNM (line 303) | LNM                 = ModeLineFeedNewLine
  constant SetModeLineFeedNewLine (line 305) | SetModeLineFeedNewLine     = "\x1b[20h"
  constant ResetModeLineFeedNewLine (line 306) | ResetModeLineFeedNewLine   = "\x1b[20l"
  constant RequestModeLineFeedNewLine (line 307) | RequestModeLineFeedNewLine = "\x1b[20$p"
  constant ModeCursorKeys (line 315) | ModeCursorKeys = DECMode(1)
  constant DECCKM (line 316) | DECCKM         = ModeCursorKeys
  constant SetModeCursorKeys (line 318) | SetModeCursorKeys     = "\x1b[?1h"
  constant ResetModeCursorKeys (line 319) | ResetModeCursorKeys   = "\x1b[?1l"
  constant RequestModeCursorKeys (line 320) | RequestModeCursorKeys = "\x1b[?1$p"
  constant ModeOrigin (line 328) | ModeOrigin = DECMode(6)
  constant DECOM (line 329) | DECOM      = ModeOrigin
  constant SetModeOrigin (line 331) | SetModeOrigin     = "\x1b[?6h"
  constant ResetModeOrigin (line 332) | ResetModeOrigin   = "\x1b[?6l"
  constant RequestModeOrigin (line 333) | RequestModeOrigin = "\x1b[?6$p"
  constant ModeAutoWrap (line 341) | ModeAutoWrap = DECMode(7)
  constant DECAWM (line 342) | DECAWM       = ModeAutoWrap
  constant SetModeAutoWrap (line 344) | SetModeAutoWrap     = "\x1b[?7h"
  constant ResetModeAutoWrap (line 345) | ResetModeAutoWrap   = "\x1b[?7l"
  constant RequestModeAutoWrap (line 346) | RequestModeAutoWrap = "\x1b[?7$p"
  constant ModeMouseX10 (line 361) | ModeMouseX10 = DECMode(9)
  constant SetModeMouseX10 (line 363) | SetModeMouseX10     = "\x1b[?9h"
  constant ResetModeMouseX10 (line 364) | ResetModeMouseX10   = "\x1b[?9l"
  constant RequestModeMouseX10 (line 365) | RequestModeMouseX10 = "\x1b[?9$p"
  constant ModeTextCursorEnable (line 372) | ModeTextCursorEnable = DECMode(25)
  constant DECTCEM (line 373) | DECTCEM              = ModeTextCursorEnable
  constant SetModeTextCursorEnable (line 375) | SetModeTextCursorEnable     = "\x1b[?25h"
  constant ResetModeTextCursorEnable (line 376) | ResetModeTextCursorEnable   = "\x1b[?25l"
  constant RequestModeTextCursorEnable (line 377) | RequestModeTextCursorEnable = "\x1b[?25$p"
  constant ShowCursor (line 382) | ShowCursor = SetModeTextCursorEnable
  constant HideCursor (line 383) | HideCursor = ResetModeTextCursorEnable
  constant ModeNumericKeypad (line 393) | ModeNumericKeypad = DECMode(66)
  constant DECNKM (line 394) | DECNKM            = ModeNumericKeypad
  constant SetModeNumericKeypad (line 396) | SetModeNumericKeypad     = "\x1b[?66h"
  constant ResetModeNumericKeypad (line 397) | ResetModeNumericKeypad   = "\x1b[?66l"
  constant RequestModeNumericKeypad (line 398) | RequestModeNumericKeypad = "\x1b[?66$p"
  constant ModeBackarrowKey (line 406) | ModeBackarrowKey = DECMode(67)
  constant DECBKM (line 407) | DECBKM           = ModeBackarrowKey
  constant SetModeBackarrowKey (line 409) | SetModeBackarrowKey     = "\x1b[?67h"
  constant ResetModeBackarrowKey (line 410) | ResetModeBackarrowKey   = "\x1b[?67l"
  constant RequestModeBackarrowKey (line 411) | RequestModeBackarrowKey = "\x1b[?67$p"
  constant ModeLeftRightMargin (line 419) | ModeLeftRightMargin = DECMode(69)
  constant DECLRMM (line 420) | DECLRMM             = ModeLeftRightMargin
  constant SetModeLeftRightMargin (line 422) | SetModeLeftRightMargin     = "\x1b[?69h"
  constant ResetModeLeftRightMargin (line 423) | ResetModeLeftRightMargin   = "\x1b[?69l"
  constant RequestModeLeftRightMargin (line 424) | RequestModeLeftRightMargin = "\x1b[?69$p"
  constant ModeMouseNormal (line 435) | ModeMouseNormal = DECMode(1000)
  constant SetModeMouseNormal (line 437) | SetModeMouseNormal     = "\x1b[?1000h"
  constant ResetModeMouseNormal (line 438) | ResetModeMouseNormal   = "\x1b[?1000l"
  constant RequestModeMouseNormal (line 439) | RequestModeMouseNormal = "\x1b[?1000$p"
  constant ModeMouseHighlight (line 454) | ModeMouseHighlight = DECMode(1001)
  constant SetModeMouseHighlight (line 456) | SetModeMouseHighlight     = "\x1b[?1001h"
  constant ResetModeMouseHighlight (line 457) | ResetModeMouseHighlight   = "\x1b[?1001l"
  constant RequestModeMouseHighlight (line 458) | RequestModeMouseHighlight = "\x1b[?1001$p"
  constant ModeMouseButtonEvent (line 472) | ModeMouseButtonEvent = DECMode(1002)
  constant SetModeMouseButtonEvent (line 474) | SetModeMouseButtonEvent     = "\x1b[?1002h"
  constant ResetModeMouseButtonEvent (line 475) | ResetModeMouseButtonEvent   = "\x1b[?1002l"
  constant RequestModeMouseButtonEvent (line 476) | RequestModeMouseButtonEvent = "\x1b[?1002$p"
  constant ModeMouseAnyEvent (line 484) | ModeMouseAnyEvent = DECMode(1003)
  constant SetModeMouseAnyEvent (line 486) | SetModeMouseAnyEvent     = "\x1b[?1003h"
  constant ResetModeMouseAnyEvent (line 487) | ResetModeMouseAnyEvent   = "\x1b[?1003l"
  constant RequestModeMouseAnyEvent (line 488) | RequestModeMouseAnyEvent = "\x1b[?1003$p"
  constant ModeFocusEvent (line 501) | ModeFocusEvent = DECMode(1004)
  constant SetModeFocusEvent (line 503) | SetModeFocusEvent     = "\x1b[?1004h"
  constant ResetModeFocusEvent (line 504) | ResetModeFocusEvent   = "\x1b[?1004l"
  constant RequestModeFocusEvent (line 505) | RequestModeFocusEvent = "\x1b[?1004$p"
  constant ModeMouseExtSgr (line 519) | ModeMouseExtSgr = DECMode(1006)
  constant SetModeMouseExtSgr (line 521) | SetModeMouseExtSgr     = "\x1b[?1006h"
  constant ResetModeMouseExtSgr (line 522) | ResetModeMouseExtSgr   = "\x1b[?1006l"
  constant RequestModeMouseExtSgr (line 523) | RequestModeMouseExtSgr = "\x1b[?1006$p"
  constant ModeMouseExtUtf8 (line 531) | ModeMouseExtUtf8 = DECMode(1005)
  constant SetModeMouseExtUtf8 (line 533) | SetModeMouseExtUtf8     = "\x1b[?1005h"
  constant ResetModeMouseExtUtf8 (line 534) | ResetModeMouseExtUtf8   = "\x1b[?1005l"
  constant RequestModeMouseExtUtf8 (line 535) | RequestModeMouseExtUtf8 = "\x1b[?1005$p"
  constant ModeMouseExtUrxvt (line 543) | ModeMouseExtUrxvt = DECMode(1015)
  constant SetModeMouseExtUrxvt (line 545) | SetModeMouseExtUrxvt     = "\x1b[?1015h"
  constant ResetModeMouseExtUrxvt (line 546) | ResetModeMouseExtUrxvt   = "\x1b[?1015l"
  constant RequestModeMouseExtUrxvt (line 547) | RequestModeMouseExtUrxvt = "\x1b[?1015$p"
  constant ModeMouseExtSgrPixel (line 557) | ModeMouseExtSgrPixel = DECMode(1016)
  constant SetModeMouseExtSgrPixel (line 559) | SetModeMouseExtSgrPixel     = "\x1b[?1016h"
  constant ResetModeMouseExtSgrPixel (line 560) | ResetModeMouseExtSgrPixel   = "\x1b[?1016l"
  constant RequestModeMouseExtSgrPixel (line 561) | RequestModeMouseExtSgrPixel = "\x1b[?1016$p"
  constant ModeAltScreen (line 570) | ModeAltScreen = DECMode(1047)
  constant SetModeAltScreen (line 572) | SetModeAltScreen     = "\x1b[?1047h"
  constant ResetModeAltScreen (line 573) | ResetModeAltScreen   = "\x1b[?1047l"
  constant RequestModeAltScreen (line 574) | RequestModeAltScreen = "\x1b[?1047$p"
  constant ModeSaveCursor (line 582) | ModeSaveCursor = DECMode(1048)
  constant SetModeSaveCursor (line 584) | SetModeSaveCursor     = "\x1b[?1048h"
  constant ResetModeSaveCursor (line 585) | ResetModeSaveCursor   = "\x1b[?1048l"
  constant RequestModeSaveCursor (line 586) | RequestModeSaveCursor = "\x1b[?1048$p"
  constant ModeAltScreenSaveCursor (line 595) | ModeAltScreenSaveCursor = DECMode(1049)
  constant SetModeAltScreenSaveCursor (line 597) | SetModeAltScreenSaveCursor     = "\x1b[?1049h"
  constant ResetModeAltScreenSaveCursor (line 598) | ResetModeAltScreenSaveCursor   = "\x1b[?1049l"
  constant RequestModeAltScreenSaveCursor (line 599) | RequestModeAltScreenSaveCursor = "\x1b[?1049$p"
  constant ModeBracketedPaste (line 608) | ModeBracketedPaste = DECMode(2004)
  constant SetModeBracketedPaste (line 610) | SetModeBracketedPaste     = "\x1b[?2004h"
  constant ResetModeBracketedPaste (line 611) | ResetModeBracketedPaste   = "\x1b[?2004l"
  constant RequestModeBracketedPaste (line 612) | RequestModeBracketedPaste = "\x1b[?2004$p"
  constant ModeSynchronizedOutput (line 620) | ModeSynchronizedOutput = DECMode(2026)
  constant SetModeSynchronizedOutput (line 622) | SetModeSynchronizedOutput     = "\x1b[?2026h"
  constant ResetModeSynchronizedOutput (line 623) | ResetModeSynchronizedOutput   = "\x1b[?2026l"
  constant RequestModeSynchronizedOutput (line 624) | RequestModeSynchronizedOutput = "\x1b[?2026$p"
  constant ModeUnicodeCore (line 633) | ModeUnicodeCore = DECMode(2027)
  constant SetModeUnicodeCore (line 635) | SetModeUnicodeCore     = "\x1b[?2027h"
  constant ResetModeUnicodeCore (line 636) | ResetModeUnicodeCore   = "\x1b[?2027l"
  constant RequestModeUnicodeCore (line 637) | RequestModeUnicodeCore = "\x1b[?2027$p"
  constant ModeLightDark (line 656) | ModeLightDark = DECMode(2031)
  constant SetModeLightDark (line 658) | SetModeLightDark     = "\x1b[?2031h"
  constant ResetModeLightDark (line 659) | ResetModeLightDark   = "\x1b[?2031l"
  constant RequestModeLightDark (line 660) | RequestModeLightDark = "\x1b[?2031$p"
  constant ModeInBandResize (line 673) | ModeInBandResize = DECMode(2048)
  constant SetModeInBandResize (line 675) | SetModeInBandResize     = "\x1b[?2048h"
  constant ResetModeInBandResize (line 676) | ResetModeInBandResize   = "\x1b[?2048l"
  constant RequestModeInBandResize (line 677) | RequestModeInBandResize = "\x1b[?2048$p"
  constant ModeWin32Input (line 685) | ModeWin32Input = DECMode(9001)
  constant SetModeWin32Input (line 687) | SetModeWin32Input     = "\x1b[?9001h"
  constant ResetModeWin32Input (line 688) | ResetModeWin32Input   = "\x1b[?9001l"
  constant RequestModeWin32Input (line 689) | RequestModeWin32Input = "\x1b[?9001$p"

FILE: vendor/github.com/charmbracelet/x/ansi/mode_deprecated.go
  constant KeyboardActionMode (line 7) | KeyboardActionMode = ANSIMode(2)
  constant SetKeyboardActionMode (line 9) | SetKeyboardActionMode     = "\x1b[2h"
  constant ResetKeyboardActionMode (line 10) | ResetKeyboardActionMode   = "\x1b[2l"
  constant RequestKeyboardActionMode (line 11) | RequestKeyboardActionMode = "\x1b[2$p"
  constant InsertReplaceMode (line 18) | InsertReplaceMode = ANSIMode(4)
  constant SetInsertReplaceMode (line 20) | SetInsertReplaceMode     = "\x1b[4h"
  constant ResetInsertReplaceMode (line 21) | ResetInsertReplaceMode   = "\x1b[4l"
  constant RequestInsertReplaceMode (line 22) | RequestInsertReplaceMode = "\x1b[4$p"
  constant BiDirectionalSupportMode (line 29) | BiDirectionalSupportMode = ANSIMode(8)
  constant SetBiDirectionalSupportMode (line 31) | SetBiDirectionalSupportMode     = "\x1b[8h"
  constant ResetBiDirectionalSupportMode (line 32) | ResetBiDirectionalSupportMode   = "\x1b[8l"
  constant RequestBiDirectionalSupportMode (line 33) | RequestBiDirectionalSupportMode = "\x1b[8$p"
  constant SendReceiveMode (line 40) | SendReceiveMode = ANSIMode(12)
  constant LocalEchoMode (line 41) | LocalEchoMode   = SendReceiveMode
  constant SetSendReceiveMode (line 43) | SetSendReceiveMode     = "\x1b[12h"
  constant ResetSendReceiveMode (line 44) | ResetSendReceiveMode   = "\x1b[12l"
  constant RequestSendReceiveMode (line 45) | RequestSendReceiveMode = "\x1b[12$p"
  constant SetLocalEchoMode (line 47) | SetLocalEchoMode     = "\x1b[12h"
  constant ResetLocalEchoMode (line 48) | ResetLocalEchoMode   = "\x1b[12l"
  constant RequestLocalEchoMode (line 49) | RequestLocalEchoMode = "\x1b[12$p"
  constant LineFeedNewLineMode (line 56) | LineFeedNewLineMode = ANSIMode(20)
  constant SetLineFeedNewLineMode (line 58) | SetLineFeedNewLineMode     = "\x1b[20h"
  constant ResetLineFeedNewLineMode (line 59) | ResetLineFeedNewLineMode   = "\x1b[20l"
  constant RequestLineFeedNewLineMode (line 60) | RequestLineFeedNewLineMode = "\x1b[20$p"
  constant CursorKeysMode (line 67) | CursorKeysMode = DECMode(1)
  constant SetCursorKeysMode (line 69) | SetCursorKeysMode     = "\x1b[?1h"
  constant ResetCursorKeysMode (line 70) | ResetCursorKeysMode   = "\x1b[?1l"
  constant RequestCursorKeysMode (line 71) | RequestCursorKeysMode = "\x1b[?1$p"
  constant EnableCursorKeys (line 78) | EnableCursorKeys  = "\x1b[?1h"
  constant DisableCursorKeys (line 79) | DisableCursorKeys = "\x1b[?1l"
  constant OriginMode (line 86) | OriginMode = DECMode(6)
  constant SetOriginMode (line 88) | SetOriginMode     = "\x1b[?6h"
  constant ResetOriginMode (line 89) | ResetOriginMode   = "\x1b[?6l"
  constant RequestOriginMode (line 90) | RequestOriginMode = "\x1b[?6$p"
  constant AutoWrapMode (line 97) | AutoWrapMode = DECMode(7)
  constant SetAutoWrapMode (line 99) | SetAutoWrapMode     = "\x1b[?7h"
  constant ResetAutoWrapMode (line 100) | ResetAutoWrapMode   = "\x1b[?7l"
  constant RequestAutoWrapMode (line 101) | RequestAutoWrapMode = "\x1b[?7$p"
  constant X10MouseMode (line 108) | X10MouseMode = DECMode(9)
  constant SetX10MouseMode (line 110) | SetX10MouseMode     = "\x1b[?9h"
  constant ResetX10MouseMode (line 111) | ResetX10MouseMode   = "\x1b[?9l"
  constant RequestX10MouseMode (line 112) | RequestX10MouseMode = "\x1b[?9$p"
  constant TextCursorEnableMode (line 119) | TextCursorEnableMode = DECMode(25)
  constant SetTextCursorEnableMode (line 121) | SetTextCursorEnableMode     = "\x1b[?25h"
  constant ResetTextCursorEnableMode (line 122) | ResetTextCursorEnableMode   = "\x1b[?25l"
  constant RequestTextCursorEnableMode (line 123) | RequestTextCursorEnableMode = "\x1b[?25$p"
  constant CursorEnableMode (line 130) | CursorEnableMode        = DECMode(25)
  constant RequestCursorVisibility (line 131) | RequestCursorVisibility = "\x1b[?25$p"
  constant NumericKeypadMode (line 138) | NumericKeypadMode = DECMode(66)
  constant SetNumericKeypadMode (line 140) | SetNumericKeypadMode     = "\x1b[?66h"
  constant ResetNumericKeypadMode (line 141) | ResetNumericKeypadMode   = "\x1b[?66l"
  constant RequestNumericKeypadMode (line 142) | RequestNumericKeypadMode = "\x1b[?66$p"
  constant BackarrowKeyMode (line 149) | BackarrowKeyMode = DECMode(67)
  constant SetBackarrowKeyMode (line 151) | SetBackarrowKeyMode     = "\x1b[?67h"
  constant ResetBackarrowKeyMode (line 152) | ResetBackarrowKeyMode   = "\x1b[?67l"
  constant RequestBackarrowKeyMode (line 153) | RequestBackarrowKeyMode = "\x1b[?67$p"
  constant LeftRightMarginMode (line 160) | LeftRightMarginMode = DECMode(69)
  constant SetLeftRightMarginMode (line 162) | SetLeftRightMarginMode     = "\x1b[?69h"
  constant ResetLeftRightMarginMode (line 163) | ResetLeftRightMarginMode   = "\x1b[?69l"
  constant RequestLeftRightMarginMode (line 164) | RequestLeftRightMarginMode = "\x1b[?69$p"
  constant NormalMouseMode (line 171) | NormalMouseMode = DECMode(1000)
  constant SetNormalMouseMode (line 173) | SetNormalMouseMode     = "\x1b[?1000h"
  constant ResetNormalMouseMode (line 174) | ResetNormalMouseMode   = "\x1b[?1000l"
  constant RequestNormalMouseMode (line 175) | RequestNormalMouseMode = "\x1b[?1000$p"
  constant MouseMode (line 182) | MouseMode = DECMode(1000)
  constant EnableMouse (line 184) | EnableMouse  = "\x1b[?1000h"
  constant DisableMouse (line 185) | DisableMouse = "\x1b[?1000l"
  constant RequestMouse (line 186) | RequestMouse = "\x1b[?1000$p"
  constant HighlightMouseMode (line 193) | HighlightMouseMode = DECMode(1001)
  constant SetHighlightMouseMode (line 195) | SetHighlightMouseMode     = "\x1b[?1001h"
  constant ResetHighlightMouseMode (line 196) | ResetHighlightMouseMode   = "\x1b[?1001l"
  constant RequestHighlightMouseMode (line 197) | RequestHighlightMouseMode = "\x1b[?1001$p"
  constant MouseHiliteMode (line 204) | MouseHiliteMode = DECMode(1001)
  constant EnableMouseHilite (line 206) | EnableMouseHilite  = "\x1b[?1001h"
  constant DisableMouseHilite (line 207) | DisableMouseHilite = "\x1b[?1001l"
  constant RequestMouseHilite (line 208) | RequestMouseHilite = "\x1b[?1001$p"
  constant ButtonEventMouseMode (line 215) | ButtonEventMouseMode = DECMode(1002)
  constant SetButtonEventMouseMode (line 217) | SetButtonEventMouseMode     = "\x1b[?1002h"
  constant ResetButtonEventMouseMode (line 218) | ResetButtonEventMouseMode   = "\x1b[?1002l"
  constant RequestButtonEventMouseMode (line 219) | RequestButtonEventMouseMode = "\x1b[?1002$p"
  constant MouseCellMotionMode (line 226) | MouseCellMotionMode = DECMode(1002)
  constant EnableMouseCellMotion (line 228) | EnableMouseCellMotion  = "\x1b[?1002h"
  constant DisableMouseCellMotion (line 229) | DisableMouseCellMotion = "\x1b[?1002l"
  constant RequestMouseCellMotion (line 230) | RequestMouseCellMotion = "\x1b[?1002$p"
  constant AnyEventMouseMode (line 237) | AnyEventMouseMode = DECMode(1003)
  constant SetAnyEventMouseMode (line 239) | SetAnyEventMouseMode     = "\x1b[?1003h"
  constant ResetAnyEventMouseMode (line 240) | ResetAnyEventMouseMode   = "\x1b[?1003l"
  constant RequestAnyEventMouseMode (line 241) | RequestAnyEventMouseMode = "\x1b[?1003$p"
  constant MouseAllMotionMode (line 248) | MouseAllMotionMode = DECMode(1003)
  constant EnableMouseAllMotion (line 250) | EnableMouseAllMotion  = "\x1b[?1003h"
  constant DisableMouseAllMotion (line 251) | DisableMouseAllMotion = "\x1b[?1003l"
  constant RequestMouseAllMotion (line 252) | RequestMouseAllMotion = "\x1b[?1003$p"
  constant FocusEventMode (line 259) | FocusEventMode = DECMode(1004)
  constant SetFocusEventMode (line 261) | SetFocusEventMode     = "\x1b[?1004h"
  constant ResetFocusEventMode (line 262) | ResetFocusEventMode   = "\x1b[?1004l"
  constant RequestFocusEventMode (line 263) | RequestFocusEventMode = "\x1b[?1004$p"
  constant ReportFocusMode (line 271) | ReportFocusMode = DECMode(1004)
  constant EnableReportFocus (line 273) | EnableReportFocus  = "\x1b[?1004h"
  constant DisableReportFocus (line 274) | DisableReportFocus = "\x1b[?1004l"
  constant RequestReportFocus (line 275) | RequestReportFocus = "\x1b[?1004$p"
  constant Utf8ExtMouseMode (line 282) | Utf8ExtMouseMode = DECMode(1005)
  constant SetUtf8ExtMouseMode (line 284) | SetUtf8ExtMouseMode     = "\x1b[?1005h"
  constant ResetUtf8ExtMouseMode (line 285) | ResetUtf8ExtMouseMode   = "\x1b[?1005l"
  constant RequestUtf8ExtMouseMode (line 286) | RequestUtf8ExtMouseMode = "\x1b[?1005$p"
  constant SgrExtMouseMode (line 293) | SgrExtMouseMode = DECMode(1006)
  constant SetSgrExtMouseMode (line 295) | SetSgrExtMouseMode     = "\x1b[?1006h"
  constant ResetSgrExtMouseMode (line 296) | ResetSgrExtMouseMode   = "\x1b[?1006l"
  constant RequestSgrExtMouseMode (line 297) | RequestSgrExtMouseMode = "\x1b[?1006$p"
  constant MouseSgrExtMode (line 305) | MouseSgrExtMode    = DECMode(1006)
  constant EnableMouseSgrExt (line 306) | EnableMouseSgrExt  = "\x1b[?1006h"
  constant DisableMouseSgrExt (line 307) | DisableMouseSgrExt = "\x1b[?1006l"
  constant RequestMouseSgrExt (line 308) | RequestMouseSgrExt = "\x1b[?1006$p"
  constant UrxvtExtMouseMode (line 315) | UrxvtExtMouseMode = DECMode(1015)
  constant SetUrxvtExtMouseMode (line 317) | SetUrxvtExtMouseMode     = "\x1b[?1015h"
  constant ResetUrxvtExtMouseMode (line 318) | ResetUrxvtExtMouseMode   = "\x1b[?1015l"
  constant RequestUrxvtExtMouseMode (line 319) | RequestUrxvtExtMouseMode = "\x1b[?1015$p"
  constant SgrPixelExtMouseMode (line 326) | SgrPixelExtMouseMode = DECMode(1016)
  constant SetSgrPixelExtMouseMode (line 328) | SetSgrPixelExtMouseMode     = "\x1b[?1016h"
  constant ResetSgrPixelExtMouseMode (line 329) | ResetSgrPixelExtMouseMode   = "\x1b[?1016l"
  constant RequestSgrPixelExtMouseMode (line 330) | RequestSgrPixelExtMouseMode = "\x1b[?1016$p"
  constant AltScreenMode (line 337) | AltScreenMode = DECMode(1047)
  constant SetAltScreenMode (line 339) | SetAltScreenMode     = "\x1b[?1047h"
  constant ResetAltScreenMode (line 340) | ResetAltScreenMode   = "\x1b[?1047l"
  constant RequestAltScreenMode (line 341) | RequestAltScreenMode = "\x1b[?1047$p"
  constant SaveCursorMode (line 348) | SaveCursorMode = DECMode(1048)
  constant SetSaveCursorMode (line 350) | SetSaveCursorMode     = "\x1b[?1048h"
  constant ResetSaveCursorMode (line 351) | ResetSaveCursorMode   = "\x1b[?1048l"
  constant RequestSaveCursorMode (line 352) | RequestSaveCursorMode = "\x1b[?1048$p"
  constant AltScreenSaveCursorMode (line 359) | AltScreenSaveCursorMode = DECMode(1049)
  constant SetAltScreenSaveCursorMode (line 361) | SetAltScreenSaveCursorMode     = "\x1b[?1049h"
  constant ResetAltScreenSaveCursorMode (line 362) | ResetAltScreenSaveCursorMode   = "\x1b[?1049l"
  constant RequestAltScreenSaveCursorMode (line 363) | RequestAltScreenSaveCursorMode = "\x1b[?1049$p"
  constant AltScreenBufferMode (line 370) | AltScreenBufferMode = DECMode(1049)
  constant SetAltScreenBufferMode (line 372) | SetAltScreenBufferMode     = "\x1b[?1049h"
  constant ResetAltScreenBufferMode (line 373) | ResetAltScreenBufferMode   = "\x1b[?1049l"
  constant RequestAltScreenBufferMode (line 374) | RequestAltScreenBufferMode = "\x1b[?1049$p"
  constant EnableAltScreenBuffer (line 376) | EnableAltScreenBuffer  = "\x1b[?1049h"
  constant DisableAltScreenBuffer (line 377) | DisableAltScreenBuffer = "\x1b[?1049l"
  constant RequestAltScreenBuffer (line 378) | RequestAltScreenBuffer = "\x1b[?1049$p"
  constant BracketedPasteMode (line 385) | BracketedPasteMode = DECMode(2004)
  constant SetBracketedPasteMode (line 387) | SetBracketedPasteMode     = "\x1b[?2004h"
  constant ResetBracketedPasteMode (line 388) | ResetBracketedPasteMode   = "\x1b[?2004l"
  constant RequestBracketedPasteMode (line 389) | RequestBracketedPasteMode = "\x1b[?2004$p"
  constant EnableBracketedPaste (line 395) | EnableBracketedPaste  = "\x1b[?2004h"
  constant DisableBracketedPaste (line 396) | DisableBracketedPaste = "\x1b[?2004l"
  constant RequestBracketedPaste (line 397) | RequestBracketedPaste = "\x1b[?2004$p"
  constant SynchronizedOutputMode (line 404) | SynchronizedOutputMode = DECMode(2026)
  constant SetSynchronizedOutputMode (line 406) | SetSynchronizedOutputMode     = "\x1b[?2026h"
  constant ResetSynchronizedOutputMode (line 407) | ResetSynchronizedOutputMode   = "\x1b[?2026l"
  constant RequestSynchronizedOutputMode (line 408) | RequestSynchronizedOutputMode = "\x1b[?2026$p"
  constant SyncdOutputMode (line 416) | SyncdOutputMode = DECMode(2026)
  constant EnableSyncdOutput (line 418) | EnableSyncdOutput  = "\x1b[?2026h"
  constant DisableSyncdOutput (line 419) | DisableSyncdOutput = "\x1b[?2026l"
  constant RequestSyncdOutput (line 420) | RequestSyncdOutput = "\x1b[?2026$p"
  constant UnicodeCoreMode (line 427) | UnicodeCoreMode = DECMode(2027)
  constant SetUnicodeCoreMode (line 429) | SetUnicodeCoreMode     = "\x1b[?2027h"
  constant ResetUnicodeCoreMode (line 430) | ResetUnicodeCoreMode   = "\x1b[?2027l"
  constant RequestUnicodeCoreMode (line 431) | RequestUnicodeCoreMode = "\x1b[?2027$p"
  constant GraphemeClusteringMode (line 439) | GraphemeClusteringMode = DECMode(2027)
  constant SetGraphemeClusteringMode (line 441) | SetGraphemeClusteringMode     = "\x1b[?2027h"
  constant ResetGraphemeClusteringMode (line 442) | ResetGraphemeClusteringMode   = "\x1b[?2027l"
  constant RequestGraphemeClusteringMode (line 443) | RequestGraphemeClusteringMode = "\x1b[?2027$p"
  constant EnableGraphemeClustering (line 451) | EnableGraphemeClustering  = "\x1b[?2027h"
  constant DisableGraphemeClustering (line 452) | DisableGraphemeClustering = "\x1b[?2027l"
  constant RequestGraphemeClustering (line 453) | RequestGraphemeClustering = "\x1b[?2027$p"
  constant LightDarkMode (line 460) | LightDarkMode = DECMode(2031)
  constant SetLightDarkMode (line 462) | SetLightDarkMode     = "\x1b[?2031h"
  constant ResetLightDarkMode (line 463) | ResetLightDarkMode   = "\x1b[?2031l"
  constant RequestLightDarkMode (line 464) | RequestLightDarkMode = "\x1b[?2031$p"
  constant InBandResizeMode (line 471) | InBandResizeMode = DECMode(2048)
  constant SetInBandResizeMode (line 473) | SetInBandResizeMode     = "\x1b[?2048h"
  constant ResetInBandResizeMode (line 474) | ResetInBandResizeMode   = "\x1b[?2048l"
  constant RequestInBandResizeMode (line 475) | RequestInBandResizeMode = "\x1b[?2048$p"
  constant Win32InputMode (line 482) | Win32InputMode = DECMode(9001)
  constant SetWin32InputMode (line 484) | SetWin32InputMode     = "\x1b[?9001h"
  constant ResetWin32InputMode (line 485) | ResetWin32InputMode   = "\x1b[?9001l"
  constant RequestWin32InputMode (line 486) | RequestWin32InputMode = "\x1b[?9001$p"
  constant EnableWin32Input (line 492) | EnableWin32Input  = "\x1b[?9001h"
  constant DisableWin32Input (line 493) | DisableWin32Input = "\x1b[?9001l"
  constant RequestWin32Input (line 494) | RequestWin32Input = "\x1b[?9001$p"

FILE: vendor/github.com/charmbracelet/x/ansi/modes.go
  type Modes (line 5) | type Modes
    method Get (line 9) | func (m Modes) Get(mode Mode) ModeSetting {
    method Delete (line 15) | func (m Modes) Delete(mode Mode) {
    method Set (line 20) | func (m Modes) Set(modes ...Mode) {
    method PermanentlySet (line 27) | func (m Modes) PermanentlySet(modes ...Mode) {
    method Reset (line 34) | func (m Modes) Reset(modes ...Mode) {
    method PermanentlyReset (line 41) | func (m Modes) PermanentlyReset(modes ...Mode) {
    method IsSet (line 48) | func (m Modes) IsSet(mode Mode) bool {
    method IsPermanentlySet (line 53) | func (m Modes) IsPermanentlySet(mode Mode) bool {
    method IsReset (line 58) | func (m Modes) IsReset(mode Mode) bool {
    method IsPermanentlyReset (line 63) | func (m Modes) IsPermanentlyReset(mode Mode) bool {

FILE: vendor/github.com/charmbracelet/x/ansi/mouse.go
  type MouseButton (line 8) | type MouseButton
    method String (line 69) | func (b MouseButton) String() string {
  constant MouseNone (line 28) | MouseNone MouseButton = iota
  constant MouseButton1 (line 29) | MouseButton1
  constant MouseButton2 (line 30) | MouseButton2
  constant MouseButton3 (line 31) | MouseButton3
  constant MouseButton4 (line 32) | MouseButton4
  constant MouseButton5 (line 33) | MouseButton5
  constant MouseButton6 (line 34) | MouseButton6
  constant MouseButton7 (line 35) | MouseButton7
  constant MouseButton8 (line 36) | MouseButton8
  constant MouseButton9 (line 37) | MouseButton9
  constant MouseButton10 (line 38) | MouseButton10
  constant MouseButton11 (line 39) | MouseButton11
  constant MouseLeft (line 41) | MouseLeft       = MouseButton1
  constant MouseMiddle (line 42) | MouseMiddle     = MouseButton2
  constant MouseRight (line 43) | MouseRight      = MouseButton3
  constant MouseWheelUp (line 44) | MouseWheelUp    = MouseButton4
  constant MouseWheelDown (line 45) | MouseWheelDown  = MouseButton5
  constant MouseWheelLeft (line 46) | MouseWheelLeft  = MouseButton6
  constant MouseWheelRight (line 47) | MouseWheelRight = MouseButton7
  constant MouseBackward (line 48) | MouseBackward   = MouseButton8
  constant MouseForward (line 49) | MouseForward    = MouseButton9
  constant MouseRelease (line 50) | MouseRelease    = MouseNone
  function EncodeMouseButton (line 97) | func EncodeMouseButton(b MouseButton, motion, shift, alt, ctrl bool) (m ...
  constant x10Offset (line 142) | x10Offset = 32
  function MouseX10 (line 150) | func MouseX10(b byte, x, y int) string {
  function MouseSgr (line 160) | func MouseSgr(b byte, x, y int, release bool) string {

FILE: vendor/github.com/charmbracelet/x/ansi/notification.go
  function Notify (line 16) | func Notify(s string) string {
  function DesktopNotification (line 30) | func DesktopNotification(payload string, metadata ...string) string {

FILE: vendor/github.com/charmbracelet/x/ansi/palette.go
  function SetPalette (line 20) | func SetPalette(i int, c color.Color) string {
  constant ResetPalette (line 34) | ResetPalette = "\x1b]R\x07"

FILE: vendor/github.com/charmbracelet/x/ansi/parser.go
  type Parser (line 19) | type Parser struct
    method SetParamsSize (line 68) | func (p *Parser) SetParamsSize(size int) {
    method SetDataSize (line 76) | func (p *Parser) SetDataSize(size int) {
    method Params (line 85) | func (p *Parser) Params() Params {
    method Param (line 92) | func (p *Parser) Param(i, def int) (int, bool) {
    method Command (line 101) | func (p *Parser) Command() int {
    method Rune (line 106) | func (p *Parser) Rune() rune {
    method Control (line 116) | func (p *Parser) Control() byte {
    method Data (line 121) | func (p *Parser) Data() []byte {
    method Reset (line 126) | func (p *Parser) Reset() {
    method clear (line 132) | func (p *Parser) clear() {
    method State (line 141) | func (p *Parser) State() parser.State {
    method StateName (line 146) | func (p *Parser) StateName() string {
    method Parse (line 152) | func (p *Parser) Parse(b []byte) {
    method Advance (line 160) | func (p *Parser) Advance(b byte) parser.Action {
    method collectRune (line 170) | func (p *Parser) collectRune(b byte) {
    method advanceUtf8 (line 181) | func (p *Parser) advanceUtf8(b byte) parser.Action {
    method advance (line 206) | func (p *Parser) advance(b byte) parser.Action {
    method parseStringCmd (line 242) | func (p *Parser) parseStringCmd() {
    method performAction (line 261) | func (p *Parser) performAction(action parser.Action, state parser.Stat...
  function NewParser (line 59) | func NewParser() *Parser {
  function utf8ByteLen (line 406) | func utf8ByteLen(b byte) int {

FILE: vendor/github.com/charmbracelet/x/ansi/parser/const.go
  constant NoneAction (line 9) | NoneAction Action = iota
  constant ClearAction (line 10) | ClearAction
  constant CollectAction (line 11) | CollectAction
  constant PrefixAction (line 12) | PrefixAction
  constant DispatchAction (line 13) | DispatchAction
  constant ExecuteAction (line 14) | ExecuteAction
  constant StartAction (line 15) | StartAction
  constant PutAction (line 16) | PutAction
  constant ParamAction (line 17) | ParamAction
  constant PrintAction (line 18) | PrintAction
  constant IgnoreAction (line 20) | IgnoreAction = NoneAction
  constant GroundState (line 42) | GroundState State = iota
  constant CsiEntryState (line 43) | CsiEntryState
  constant CsiIntermediateState (line 44) | CsiIntermediateState
  constant CsiParamState (line 45) | CsiParamState
  constant DcsEntryState (line 46) | DcsEntryState
  constant DcsIntermediateState (line 47) | DcsIntermediateState
  constant DcsParamState (line 48) | DcsParamState
  constant DcsStringState (line 49) | DcsStringState
  constant EscapeState (line 50) | EscapeState
  constant EscapeIntermediateState (line 51) | EscapeIntermediateState
  constant OscStringState (line 52) | OscStringState
  constant SosStringState (line 53) | SosStringState
  constant PmStringState (line 54) | PmStringState
  constant ApcStringState (line 55) | ApcStringState
  constant Utf8State (line 59) | Utf8State

FILE: vendor/github.com/charmbracelet/x/ansi/parser/seq.go
  constant PrefixShift (line 7) | PrefixShift    = 8
  constant IntermedShift (line 8) | IntermedShift  = 16
  constant FinalMask (line 9) | FinalMask      = 0xff
  constant HasMoreFlag (line 10) | HasMoreFlag    = math.MinInt32
  constant ParamMask (line 11) | ParamMask      = ^HasMoreFlag
  constant MissingParam (line 12) | MissingParam   = ParamMask
  constant MissingCommand (line 13) | MissingCommand = MissingParam
  constant MaxParam (line 14) | MaxParam       = math.MaxUint16
  constant MaxParamsSize (line 19) | MaxParamsSize = 32
  constant DefaultParamValue (line 22) | DefaultParamValue = 0
  function Prefix (line 29) | func Prefix(cmd int) int {
  function Intermediate (line 38) | func Intermediate(cmd int) int {
  function Command (line 43) | func Command(cmd int) int {
  function Param (line 49) | func Param(params []int, i int) int {
  function HasMore (line 63) | func HasMore(params []int, i int) bool {
  function Subparams (line 73) | func Subparams(params []int, i int) []int {
  function Len (line 117) | func Len(params []int) int {
  function Range (line 130) | func Range(params []int, fn func(i int, param int, hasMore bool) bool) {

FILE: vendor/github.com/charmbracelet/x/ansi/parser/transition_table.go
  constant TransitionActionShift (line 8) | TransitionActionShift = 4
  constant TransitionStateMask (line 9) | TransitionStateMask   = 15
  constant IndexStateShift (line 10) | IndexStateShift       = 8
  constant DefaultTableSize (line 13) | DefaultTableSize = 4096
  type TransitionTable (line 21) | type TransitionTable
    method SetDefault (line 32) | func (t TransitionTable) SetDefault(action Action, state State) {
    method AddOne (line 39) | func (t TransitionTable) AddOne(code byte, state State, action Action,...
    method AddMany (line 46) | func (t TransitionTable) AddMany(codes []byte, state State, action Act...
    method AddRange (line 53) | func (t TransitionTable) AddRange(start, end byte, state State, action...
    method Transition (line 60) | func (t TransitionTable) Transition(state State, code byte) (State, Ac...
  function NewTransitionTable (line 24) | func NewTransitionTable(size int) TransitionTable {
  function r (line 67) | func r(start, end byte) []byte {
  function GenerateTransitionTable (line 87) | func GenerateTransitionTable() TransitionTable {

FILE: vendor/github.com/charmbracelet/x/ansi/parser_decode.go
  constant NormalState (line 16) | NormalState State = iota
  constant PrefixState (line 17) | PrefixState
  constant ParamsState (line 18) | ParamsState
  constant IntermedState (line 19) | IntermedState
  constant EscapeState (line 20) | EscapeState
  constant StringState (line 21) | StringState
  function DecodeSequence (line 70) | func DecodeSequence[T string | []byte](b T, state byte, p *Parser) (seq ...
  function DecodeSequenceWc (line 120) | func DecodeSequenceWc[T string | []byte](b T, state byte, p *Parser) (se...
  function decodeSequence (line 124) | func decodeSequence[T string | []byte](m Method, b T, state State, p *Pa...
  function parseOscCmd (line 354) | func parseOscCmd(p *Parser) {
  function Equal (line 372) | func Equal[T string | []byte](a, b T) bool {
  function HasPrefix (line 377) | func HasPrefix[T string | []byte](b, prefix T) bool {
  function HasSuffix (line 382) | func HasSuffix[T string | []byte](b, suffix T) bool {
  function HasCsiPrefix (line 387) | func HasCsiPrefix[T string | []byte](b T) bool {
  function HasOscPrefix (line 393) | func HasOscPrefix[T string | []byte](b T) bool {
  function HasApcPrefix (line 399) | func HasApcPrefix[T string | []byte](b T) bool {
  function HasDcsPrefix (line 405) | func HasDcsPrefix[T string | []byte](b T) bool {
  function HasSosPrefix (line 411) | func HasSosPrefix[T string | []byte](b T) bool {
  function HasPmPrefix (line 417) | func HasPmPrefix[T string | []byte](b T) bool {
  function HasStPrefix (line 423) | func HasStPrefix[T string | []byte](b T) bool {
  function HasEscPrefix (line 429) | func HasEscPrefix[T string | []byte](b T) bool {
  function FirstGraphemeCluster (line 435) | func FirstGraphemeCluster[T string | []byte](b T, m Method) (T, int) {
  type Cmd (line 456) | type Cmd
    method Prefix (line 462) | func (c Cmd) Prefix() byte {
    method Intermediate (line 471) | func (c Cmd) Intermediate() byte {
    method Final (line 476) | func (c Cmd) Final() byte {
  function Command (line 490) | func Command(prefix, inter, final byte) (c int) {
  type Param (line 500) | type Param
    method Param (line 504) | func (s Param) Param(def int) int {
    method HasMore (line 513) | func (s Param) HasMore() bool {
  function Parameter (line 519) | func Parameter(p int, hasMore bool) (s int) {

FILE: vendor/github.com/charmbracelet/x/ansi/parser_handler.go
  type Params (line 6) | type Params
    method Param (line 12) | func (p Params) Param(i, def int) (int, bool, bool) {
    method ForEach (line 23) | func (p Params) ForEach(def int, f func(i, param int, hasMore bool)) {
  function ToParams (line 30) | func ToParams(params []int) Params {
  type Handler (line 36) | type Handler struct
  method SetHandler (line 58) | func (p *Parser) SetHandler(h Handler) {

FILE: vendor/github.com/charmbracelet/x/ansi/parser_sync.go
  function GetParser (line 19) | func GetParser() *Parser {
  function PutParser (line 25) | func PutParser(p *Parser) {

FILE: vendor/github.com/charmbracelet/x/ansi/passthrough.go
  function ScreenPassthrough (line 19) | func ScreenPassthrough(seq string, limit int) string {
  function TmuxPassthrough (line 49) | func TmuxPassthrough(seq string) string {

FILE: vendor/github.com/charmbracelet/x/ansi/paste.go
  constant BracketedPasteStart (line 4) | BracketedPasteStart = "\x1b[200~"
  constant BracketedPasteEnd (line 7) | BracketedPasteEnd = "\x1b[201~"

FILE: vendor/github.com/charmbracelet/x/ansi/progress.go
  constant ResetProgressBar (line 11) | ResetProgressBar = "\x1b]9;4;0\x07"
  function SetProgressBar (line 19) | func SetProgressBar(percentage int) string {
  function SetErrorProgressBar (line 29) | func SetErrorProgressBar(percentage int) string {
  constant SetIndeterminateProgressBar (line 39) | SetIndeterminateProgressBar = "\x1b]9;4;3\x07"
  function SetWarningProgressBar (line 47) | func SetWarningProgressBar(percentage int) string {

FILE: vendor/github.com/charmbracelet/x/ansi/reset.go
  constant ResetInitialState (line 9) | ResetInitialState = "\x1bc"
  constant RIS (line 10) | RIS               = ResetInitialState

FILE: vendor/github.com/charmbracelet/x/ansi/screen.go
  function EraseDisplay (line 22) | func EraseDisplay(n int) string {
  function ED (line 31) | func ED(n int) string {
  constant EraseScreenBelow (line 38) | EraseScreenBelow   = "\x1b[J"
  constant EraseScreenAbove (line 39) | EraseScreenAbove   = "\x1b[1J"
  constant EraseEntireScreen (line 40) | EraseEntireScreen  = "\x1b[2J"
  constant EraseEntireDisplay (line 41) | EraseEntireDisplay = "\x1b[3J"
  function EraseLine (line 55) | func EraseLine(n int) string {
  function EL (line 64) | func EL(n int) string {
  constant EraseLineRight (line 71) | EraseLineRight  = "\x1b[K"
  constant EraseLineLeft (line 72) | EraseLineLeft   = "\x1b[1K"
  constant EraseEntireLine (line 73) | EraseEntireLine = "\x1b[2K"
  function ScrollUp (line 82) | func ScrollUp(n int) string {
  function PanDown (line 91) | func PanDown(n int) string {
  function SU (line 96) | func SU(n int) string {
  function ScrollDown (line 106) | func ScrollDown(n int) string {
  function PanUp (line 115) | func PanUp(n int) string {
  function SD (line 120) | func SD(n int) string {
  function InsertLine (line 130) | func InsertLine(n int) string {
  function IL (line 139) | func IL(n int) string {
  function DeleteLine (line 149) | func DeleteLine(n int) string {
  function DL (line 158) | func DL(n int) string {
  function SetTopBottomMargins (line 170) | func SetTopBottomMargins(top, bot int) string {
  function DECSTBM (line 182) | func DECSTBM(top, bot int) string {
  function SetLeftRightMargins (line 194) | func SetLeftRightMargins(left, right int) string {
  function DECSLRM (line 206) | func DECSLRM(left, right int) string {
  function SetScrollingRegion (line 218) | func SetScrollingRegion(t, b int) string {
  function InsertCharacter (line 237) | func InsertCharacter(n int) string {
  function ICH (line 246) | func ICH(n int) string {
  function DeleteCharacter (line 259) | func DeleteCharacter(n int) string {
  function DCH (line 268) | func DCH(n int) string {
  constant SetTabEvery8Columns (line 278) | SetTabEvery8Columns = "\x1b[?5W"
  constant DECST8C (line 279) | DECST8C             = SetTabEvery8Columns
  constant HorizontalTabSet (line 290) | HorizontalTabSet = "\x1bH"
  function TabClear (line 303) | func TabClear(n int) string {
  function TBC (line 312) | func TBC(n int) string {
  function RequestPresentationStateReport (line 330) | func RequestPresentationStateReport(n int) string {
  function DECRQPSR (line 339) | func DECRQPSR(n int) string {
  function TabStopReport (line 353) | func TabStopReport(stops ...int) string {
  function DECTABSR (line 362) | func DECTABSR(stops ...int) string {
  function CursorInformationReport (line 378) | func CursorInformationReport(values ...int) string {
  function DECCIR (line 387) | func DECCIR(values ...int) string {
  function RepeatPreviousCharacter (line 399) | func RepeatPreviousCharacter(n int) string {
  function REP (line 408) | func REP(n int) string {

FILE: vendor/github.com/charmbracelet/x/ansi/sgr.go
  function SelectGraphicRendition (line 10) | func SelectGraphicRendition(ps ...Attr) string {
  function SGR (line 19) | func SGR(ps ...Attr) string {

FILE: vendor/github.com/charmbracelet/x/ansi/status.go
  type StatusReport (line 9) | type StatusReport interface
  type ANSIStatusReport (line 15) | type ANSIStatusReport
    method StatusReport (line 18) | func (s ANSIStatusReport) StatusReport() int {
  type DECStatusReport (line 23) | type DECStatusReport
    method StatusReport (line 26) | func (s DECStatusReport) StatusReport() int {
  function DeviceStatusReport (line 41) | func DeviceStatusReport(statues ...StatusReport) string {
  function DSR (line 59) | func DSR(status StatusReport) string {
  constant RequestCursorPositionReport (line 75) | RequestCursorPositionReport = "\x1b[6n"
  constant RequestExtendedCursorPositionReport (line 90) | RequestExtendedCursorPositionReport = "\x1b[?6n"
  constant RequestLightDarkReport (line 100) | RequestLightDarkReport = "\x1b[?996n"
  function CursorPositionReport (line 110) | func CursorPositionReport(line, column int) string {
  function CPR (line 121) | func CPR(line, column int) string {
  function ExtendedCursorPositionReport (line 138) | func ExtendedCursorPositionReport(line, column, page int) string {
  function DECXCPR (line 152) | func DECXCPR(line, column, page int) string {
  function LightDarkReport (line 163) | func LightDarkReport(dark bool) string {

FILE: vendor/github.com/charmbracelet/x/ansi/style.go
  constant ResetStyle (line 12) | ResetStyle = "\x1b[m"
  type Style (line 18) | type Style
    method String (line 44) | func (s Style) String() string {
    method Styled (line 53) | func (s Style) Styled(str string) string {
    method Reset (line 62) | func (s Style) Reset() Style {
    method Bold (line 68) | func (s Style) Bold() Style {
    method Faint (line 74) | func (s Style) Faint() Style {
    method Italic (line 80) | func (s Style) Italic(v bool) Style {
    method Underline (line 89) | func (s Style) Underline(v bool) Style {
    method UnderlineStyle (line 99) | func (s Style) UnderlineStyle(u Underline) Style {
    method Blink (line 120) | func (s Style) Blink(v bool) Style {
    method RapidBlink (line 132) | func (s Style) RapidBlink(v bool) Style {
    method Reverse (line 142) | func (s Style) Reverse(v bool) Style {
    method Conceal (line 152) | func (s Style) Conceal(v bool) Style {
    method Strikethrough (line 162) | func (s Style) Strikethrough(v bool) Style {
    method Normal (line 171) | func (s Style) Normal() Style {
    method NoItalic (line 178) | func (s Style) NoItalic() Style {
    method NoUnderline (line 185) | func (s Style) NoUnderline() Style {
    method NoBlink (line 192) | func (s Style) NoBlink() Style {
    method NoReverse (line 199) | func (s Style) NoReverse() Style {
    method NoConceal (line 206) | func (s Style) NoConceal() Style {
    method NoStrikethrough (line 213) | func (s Style) NoStrikethrough() Style {
    method DefaultForegroundColor (line 220) | func (s Style) DefaultForegroundColor() Style {
    method DefaultBackgroundColor (line 227) | func (s Style) DefaultBackgroundColor() Style {
    method DefaultUnderlineColor (line 234) | func (s Style) DefaultUnderlineColor() Style {
    method ForegroundColor (line 241) | func (s Style) ForegroundColor(c Color) Style {
    method BackgroundColor (line 251) | func (s Style) BackgroundColor(c Color) Style {
    method UnderlineColor (line 261) | func (s Style) UnderlineColor(c Color) Style {
  function NewStyle (line 23) | func NewStyle(attrs ...Attr) Style {
  constant underlineDouble (line 278) | underlineDouble = "4:2"
  constant underlineCurly (line 279) | underlineCurly  = "4:3"
  constant underlineDotted (line 280) | underlineDotted = "4:4"
  constant underlineDashed (line 281) | underlineDashed = "4:5"
  constant UnderlineNone (line 286) | UnderlineNone Underline = iota
  constant UnderlineSingle (line 287) | UnderlineSingle
  constant UnderlineDouble (line 288) | UnderlineDouble
  constant UnderlineCurly (line 289) | UnderlineCurly
  constant UnderlineDotted (line 290) | UnderlineDotted
  constant UnderlineDashed (line 291) | UnderlineDashed
  constant NoUnderlineStyle (line 298) | NoUnderlineStyle Underline = iota
  constant SingleUnderlineStyle (line 299) | SingleUnderlineStyle
  constant DoubleUnderlineStyle (line 300) | DoubleUnderlineStyle
  constant CurlyUnderlineStyle (line 301) | CurlyUnderlineStyle
  constant DottedUnderlineStyle (line 302) | DottedUnderlineStyle
  constant DashedUnderlineStyle (line 303) | DashedUnderlineStyle
  constant UnderlineStyleNone (line 310) | UnderlineStyleNone Underline = iota
  constant UnderlineStyleSingle (line 311) | UnderlineStyleSingle
  constant UnderlineStyleDouble (line 312) | UnderlineStyleDouble
  constant UnderlineStyleCurly (line 313) | UnderlineStyleCurly
  constant UnderlineStyleDotted (line 314) | UnderlineStyleDotted
  constant UnderlineStyleDashed (line 315) | UnderlineStyleDashed
  constant AttrReset (line 321) | AttrReset                        Attr = 0
  constant AttrBold (line 322) | AttrBold                         Attr = 1
  constant AttrFaint (line 323) | AttrFaint                        Attr = 2
  constant AttrItalic (line 324) | AttrItalic                       Attr = 3
  constant AttrUnderline (line 325) | AttrUnderline                    Attr = 4
  constant AttrBlink (line 326) | AttrBlink                        Attr = 5
  constant AttrRapidBlink (line 327) | AttrRapidBlink                   Attr = 6
  constant AttrReverse (line 328) | AttrReverse                      Attr = 7
  constant AttrConceal (line 329) | AttrConceal                      Attr = 8
  constant AttrStrikethrough (line 330) | AttrStrikethrough                Attr = 9
  constant AttrNormalIntensity (line 331) | AttrNormalIntensity              Attr = 22
  constant AttrNoItalic (line 332) | AttrNoItalic                     Attr = 23
  constant AttrNoUnderline (line 333) | AttrNoUnderline                  Attr = 24
  constant AttrNoBlink (line 334) | AttrNoBlink                      Attr = 25
  constant AttrNoReverse (line 335) | AttrNoReverse                    Attr = 27
  constant AttrNoConceal (line 336) | AttrNoConceal                    Attr = 28
  constant AttrNoStrikethrough (line 337) | AttrNoStrikethrough              Attr = 29
  constant AttrBlackForegroundColor (line 338) | AttrBlackForegroundColor         Attr = 30
  constant AttrRedForegroundColor (line 339) | AttrRedForegroundColor           Attr = 31
  constant AttrGreenForegroundColor (line 340) | AttrGreenForegroundColor         Attr = 32
  constant AttrYellowForegroundColor (line 341) | AttrYellowForegroundColor        Attr = 33
  constant AttrBlueForegroundColor (line 342) | AttrBlueForegroundColor          Attr = 34
  constant AttrMagentaForegroundColor (line 343) | AttrMagentaForegroundColor       Attr = 35
  constant AttrCyanForegroundColor (line 344) | AttrCyanForegroundColor          Attr = 36
  constant AttrWhiteForegroundColor (line 345) | AttrWhiteForegroundColor         Attr = 37
  constant AttrExtendedForegroundColor (line 346) | AttrExtendedForegroundColor      Attr = 38
  constant AttrDefaultForegroundColor (line 347) | AttrDefaultForegroundColor       Attr = 39
  constant AttrBlackBackgroundColor (line 348) | AttrBlackBackgroundColor         Attr = 40
  constant AttrRedBackgroundColor (line 349) | AttrRedBackgroundColor           Attr = 41
  constant AttrGreenBackgroundColor (line 350) | AttrGreenBackgroundColor         Attr = 42
  constant AttrYellowBackgroundColor (line 351) | AttrYellowBackgroundColor        Attr = 43
  constant AttrBlueBackgroundColor (line 352) | AttrBlueBackgroundColor          Attr = 44
  constant AttrMagentaBackgroundColor (line 353) | AttrMagentaBackgroundColor       Attr = 45
  constant AttrCyanBackgroundColor (line 354) | AttrCyanBackgroundColor          Attr = 46
  constant AttrWhiteBackgroundColor (line 355) | AttrWhiteBackgroundColor         Attr = 47
  constant AttrExtendedBackgroundColor (line 356) | AttrExtendedBackgroundColor      Attr = 48
  constant AttrDefaultBackgroundColor (line 357) | AttrDefaultBackgroundColor       Attr = 49
  constant AttrExtendedUnderlineColor (line 358) | AttrExtendedUnderlineColor       Attr = 58
  constant AttrDefaultUnderlineColor (line 359) | AttrDefaultUnderlineColor        Attr = 59
  constant AttrBrightBlackForegroundColor (line 360) | AttrBrightBlackForegroundColor   Attr = 90
  constant AttrBrightRedForegroundColor (line 361) | AttrBrightRedForegroundColor     Attr = 91
  constant AttrBrightGreenForegroundColor (line 362) | AttrBrightGreenForegroundColor   Attr = 92
  constant AttrBrightYellowForegroundColor (line 363) | AttrBrightYellowForegroundColor  Attr = 93
  constant AttrBrightBlueForegroundColor (line 364) | AttrBrightBlueForegroundColor    Attr = 94
  constant AttrBrightMagentaForegroundColor (line 365) | AttrBrightMagentaForegroundColor Attr = 95
  constant AttrBrightCyanForegroundColor (line 366) | AttrBrightCyanForegroundColor    Attr = 96
  constant AttrBrightWhiteForegroundColor (line 367) | AttrBrightWhiteForegroundColor   Attr = 97
  constant AttrBrightBlackBackgroundColor (line 368) | AttrBrightBlackBackgroundColor   Attr = 100
  constant AttrBrightRedBackgroundColor (line 369) | AttrBrightRedBackgroundColor     Attr = 101
  constant AttrBrightGreenBackgroundColor (line 370) | AttrBrightGreenBackgroundColor   Attr = 102
  constant AttrBrightYellowBackgroundColor (line 371) | AttrBrightYellowBackgroundColor  Attr = 103
  constant AttrBrightBlueBackgroundColor (line 372) | AttrBrightBlueBackgroundColor    Attr = 104
  constant AttrBrightMagentaBackgroundColor (line 373) | AttrBrightMagentaBackgroundColor Attr = 105
  constant AttrBrightCyanBackgroundColor (line 374) | AttrBrightCyanBackgroundColor    Attr = 106
  constant AttrBrightWhiteBackgroundColor (line 375) | AttrBrightWhiteBackgroundColor   Attr = 107
  constant AttrRGBColorIntroducer (line 377) | AttrRGBColorIntroducer      Attr = 2
  constant AttrExtendedColorIntroducer (line 378) | AttrExtendedColorIntroducer Attr = 5
  constant ResetAttr (line 385) | ResetAttr                        = AttrReset
  constant BoldAttr (line 386) | BoldAttr                         = AttrBold
  constant FaintAttr (line 387) | FaintAttr                        = AttrFaint
  constant ItalicAttr (line 388) | ItalicAttr                       = AttrItalic
  constant UnderlineAttr (line 389) | UnderlineAttr                    = AttrUnderline
  constant SlowBlinkAttr (line 390) | SlowBlinkAttr                    = AttrBlink
  constant RapidBlinkAttr (line 391) | RapidBlinkAttr                   = AttrRapidBlink
  constant ReverseAttr (line 392) | ReverseAttr                      = AttrReverse
  constant ConcealAttr (line 393) | ConcealAttr                      = AttrConceal
  constant StrikethroughAttr (line 394) | StrikethroughAttr                = AttrStrikethrough
  constant NormalIntensityAttr (line 395) | NormalIntensityAttr              = AttrNormalIntensity
  constant NoItalicAttr (line 396) | NoItalicAttr                     = AttrNoItalic
  constant NoUnderlineAttr (line 397) | NoUnderlineAttr                  = AttrNoUnderline
  constant NoBlinkAttr (line 398) | NoBlinkAttr                      = AttrNoBlink
  constant NoReverseAttr (line 399) | NoReverseAttr                    = AttrNoReverse
  constant NoConcealAttr (line 400) | NoConcealAttr                    = AttrNoConceal
  constant NoStrikethroughAttr (line 401) | NoStrikethroughAttr              = AttrNoStrikethrough
  constant BlackForegroundColorAttr (line 402) | BlackForegroundColorAttr         = AttrBlackForegroundColor
  constant RedForegroundColorAttr (line 403) | RedForegroundColorAttr           = AttrRedForegroundColor
  constant GreenForegroundColorAttr (line 404) | GreenForegroundColorAttr         = AttrGreenForegroundColor
  constant YellowForegroundColorAttr (line 405) | YellowForegroundColorAttr        = AttrYellowForegroundColor
  constant BlueForegroundColorAttr (line 406) | BlueForegroundColorAttr          = AttrBlueForegroundColor
  constant MagentaForegroundColorAttr (line 407) | MagentaForegroundColorAttr       = AttrMagentaForegroundColor
  constant CyanForegroundColorAttr (line 408) | CyanForegroundColorAttr          = AttrCyanForegroundColor
  constant WhiteForegroundColorAttr (line 409) | WhiteForegroundColorAttr         = AttrWhiteForegroundColor
  constant ExtendedForegroundColorAttr (line 410) | ExtendedForegroundColorAttr      = AttrExtendedForegroundColor
  constant DefaultForegroundColorAttr (line 411) | DefaultForegroundColorAttr       = AttrDefaultForegroundColor
  constant BlackBackgroundColorAttr (line 412) | BlackBackgroundColorAttr         = AttrBlackBackgroundColor
  constant RedBackgroundColorAttr (line 413) | RedBackgroundColorAttr           = AttrRedBackgroundColor
  constant GreenBackgroundColorAttr (line 414) | GreenBackgroundColorAttr         = AttrGreenBackgroundColor
  constant YellowBackgroundColorAttr (line 415) | YellowBackgroundColorAttr        = AttrYellowBackgroundColor
  constant BlueBackgroundColorAttr (line 416) | BlueBackgroundColorAttr          = AttrBlueBackgroundColor
  constant MagentaBackgroundColorAttr (line 417) | MagentaBackgroundColorAttr       = AttrMagentaBackgroundColor
  constant CyanBackgroundColorAttr (line 418) | CyanBackgroundColorAttr          = AttrCyanBackgroundColor
  constant WhiteBackgroundColorAttr (line 419) | WhiteBackgroundColorAttr         = AttrWhiteBackgroundColor
  constant ExtendedBackgroundColorAttr (line 420) | ExtendedBackgroundColorAttr      = AttrExtendedBackgroundColor
  constant DefaultBackgroundColorAttr (line 421) | DefaultBackgroundColorAttr       = AttrDefaultBackgroundColor
  constant ExtendedUnderlineColorAttr (line 422) | ExtendedUnderlineColorAttr       = AttrExtendedUnderlineColor
  constant DefaultUnderlineColorAttr (line 423) | DefaultUnderlineColorAttr        = AttrDefaultUnderlineColor
  constant BrightBlackForegroundColorAttr (line 424) | BrightBlackForegroundColorAttr   = AttrBrightBlackForegroundColor
  constant BrightRedForegroundColorAttr (line 425) | BrightRedForegroundColorAttr     = AttrBrightRedForegroundColor
  constant BrightGreenForegroundColorAttr (line 426) | BrightGreenForegroundColorAttr   = AttrBrightGreenForegroundColor
  constant BrightYellowForegroundColorAttr (line 427) | BrightYellowForegroundColorAttr  = AttrBrightYellowForegroundColor
  constant BrightBlueForegroundColorAttr (line 428) | BrightBlueForegroundColorAttr    = AttrBrightBlueForegroundColor
  constant BrightMagentaForegroundColorAttr (line 429) | BrightMagentaForegroundColorAttr = AttrBrightMagentaForegroundColor
  constant BrightCyanForegroundColorAttr (line 430) | BrightCyanForegroundColorAttr    = AttrBrightCyanForegroundColor
  constant BrightWhiteForegroundColorAttr (line 431) | BrightWhiteForegroundColorAttr   = AttrBrightWhiteForegroundColor
  constant BrightBlackBackgroundColorAttr (line 432) | BrightBlackBackgroundColorAttr   = AttrBrightBlackBackgroundColor
  constant BrightRedBackgroundColorAttr (line 433) | BrightRedBackgroundColorAttr     = AttrBrightRedBackgroundColor
  constant BrightGreenBackgroundColorAttr (line 434) | BrightGreenBackgroundColorAttr   = AttrBrightGreenBackgroundColor
  constant BrightYellowBackgroundColorAttr (line 435) | BrightYellowBackgroundColorAttr  = AttrBrightYellowBackgroundColor
  constant BrightBlueBackgroundColorAttr (line 436) | BrightBlueBackgroundColorAttr    = AttrBrightBlueBackgroundColor
  constant BrightMagentaBackgroundColorAttr (line 437) | BrightMagentaBackgroundColorAttr = AttrBrightMagentaBackgroundColor
  constant BrightCyanBackgroundColorAttr (line 438) | BrightCyanBackgroundColorAttr    = AttrBrightCyanBackgroundColor
  constant BrightWhiteBackgroundColorAttr (line 439) | BrightWhiteBackgroundColorAttr   = AttrBrightWhiteBackgroundColor
  constant RGBColorIntroducerAttr (line 440) | RGBColorIntroducerAttr           = AttrRGBColorIntroducer
  constant ExtendedColorIntroducerAttr (line 441) | ExtendedColorIntroducerAttr      = AttrExtendedColorIntroducer
  constant attrReset (line 445) | attrReset                        = "0"
  constant attrBold (line 446) | attrBold                         = "1"
  constant attrFaint (line 447) | attrFaint                        = "2"
  constant attrItalic (line 448) | attrItalic                       = "3"
  constant attrUnderline (line 449) | attrUnderline                    = "4"
  constant attrBlink (line 450) | attrBlink                        = "5"
  constant attrRapidBlink (line 451) | attrRapidBlink                   = "6"
  constant attrReverse (line 452) | attrReverse                      = "7"
  constant attrConceal (line 453) | attrConceal                      = "8"
  constant attrStrikethrough (line 454) | attrStrikethrough                = "9"
  constant attrNormalIntensity (line 455) | attrNormalIntensity              = "22"
  constant attrNoItalic (line 456) | attrNoItalic                     = "23"
  constant attrNoUnderline (line 457) | attrNoUnderline                  = "24"
  constant attrNoBlink (line 458) | attrNoBlink                      = "25"
  constant attrNoReverse (line 459) | attrNoReverse                    = "27"
  constant attrNoConceal (line 460) | attrNoConceal                    = "28"
  constant attrNoStrikethrough (line 461) | attrNoStrikethrough              = "29"
  constant attrBlackForegroundColor (line 462) | attrBlackForegroundColor   
Copy disabled (too large) Download .json
Condensed preview — 925 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (13,062K chars).
[
  {
    "path": ".agent/workflows/validate-pr-check.md",
    "chars": 1079,
    "preview": "---\ndescription: How to validate the PR check workflow locally\n---\n\n# Validate PR Check Locally\n\nYou can validate the PR"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 22,
    "preview": "github: pranshuparmar\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "chars": 1229,
    "preview": "name: Bug report\ndescription: Create a report to help us improve\ntitle: \"[Bug]: \"\nlabels: [\"bug\"]\nbody:\n  - type: markdo"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "chars": 914,
    "preview": "name: Feature request\ntitle: \"[Feature]: \"\ndescription: Suggest an idea for this project\nlabels: [\"enhancement\"]\nbody:\n "
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 977,
    "preview": "\n## Description\n\nBriefly describe what this PR does. Mention existing issue number, if applicable.\n\n## Type of change\n\nC"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 614,
    "preview": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where "
  },
  {
    "path": ".github/workflows/e2e-tests.yml",
    "chars": 1577,
    "preview": "name: E2E Tests\n\non:\n  pull_request:\n    branches: [ \"main\" ]\n\npermissions: read-all\n\njobs:\n  build-and-test:\n    name: "
  },
  {
    "path": ".github/workflows/pr-check.yml",
    "chars": 1807,
    "preview": "name: PR Check\n\non:\n  pull_request:\n    types: [opened, synchronize, reopened, edited]\n  push:\n    branches:\n      - mai"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 778,
    "preview": "# .github/workflows/release.yml\nname: Release\n\non:\n  push:\n    tags:\n      - 'v*'\n\npermissions:\n  contents: write\n\nconcu"
  },
  {
    "path": ".github/workflows/update-docs.yml",
    "chars": 1363,
    "preview": "name: Update Documentation\non:\n  push:\n    branches:\n      - main\n  workflow_dispatch:\n\n\n\npermissions:\n  contents: write"
  },
  {
    "path": ".gitignore",
    "chars": 453,
    "preview": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, built with `go test -c`\n*.test\n\n# Co"
  },
  {
    "path": ".goreleaser.yml",
    "chars": 1363,
    "preview": "version: 2\n\nproject_name: witr\n\nbuilds:\n  - id: witr\n    main: ./cmd/witr\n    binary: witr\n    goos:\n      - linux\n     "
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5202,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 7152,
    "preview": "# Contributing to witr\n\nFirst off, thank you for considering contributing to **witr**! It's people like you that make th"
  },
  {
    "path": "LICENSE",
    "chars": 10759,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "Makefile",
    "chars": 399,
    "preview": ".PHONY: build test lint docs man clean\n\nBINARY := witr\nCMD    := ./cmd/witr\n\nbuild:\n\tCGO_ENABLED=0 go build -o $(BINARY)"
  },
  {
    "path": "README.md",
    "chars": 26691,
    "preview": "<div align=\"center\">\n\n# witr\n\n### Why is this running?\n*with* [**Interactive TUI Mode**](#3-interactive-mode-tui) ✨\n\n[!["
  },
  {
    "path": "SECURITY.md",
    "chars": 1517,
    "preview": "# Security Policy\n\n## Supported Versions\n\nWe currently support the following versions of **witr** with security updates:"
  },
  {
    "path": "cmd/witr/main.go",
    "chars": 764,
    "preview": "//go:build linux || darwin || freebsd || windows\n\n//go:generate go run ../../internal/tools/docgen -format man -out ../."
  },
  {
    "path": "cmd/witr/unsupported.go",
    "chars": 393,
    "preview": "//go:build !linux && !darwin && !freebsd && !windows\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\nfunc main() {\n\tfmt.Fprintln"
  },
  {
    "path": "docs/cli/witr.1",
    "chars": 2187,
    "preview": ".nh\n.TH \"WITR\" \"1\" \"Mar 2026\" \"\" \"\"\n\n.SH NAME\nwitr - Why is this running?\n\n\n.SH SYNOPSIS\n\\fBwitr [process name...] [flag"
  },
  {
    "path": "docs/cli/witr.md",
    "chars": 2008,
    "preview": "## witr\n\nWhy is this running?\n\n### Synopsis\n\nwitr explains why a process or port is running by tracing its ancestry.\n\n``"
  },
  {
    "path": "flake.nix",
    "chars": 2473,
    "preview": "{\n  inputs = {\n    nixpkgs.url = \"github:NixOS/nixpkgs/nixos-25.11\";\n  };\n  outputs =\n    {\n      self,\n      nixpkgs,\n "
  },
  {
    "path": "go.mod",
    "chars": 1674,
    "preview": "module github.com/pranshuparmar/witr\n\ngo 1.25\n\nrequire (\n\tgithub.com/charmbracelet/bubbles v1.0.0\n\tgithub.com/charmbrace"
  },
  {
    "path": "go.sum",
    "chars": 7103,
    "preview": "github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=\ngithub.com/atotto/clipboard v0.1.4/go"
  },
  {
    "path": "install.ps1",
    "chars": 2903,
    "preview": "$ErrorActionPreference = \"Stop\"\n\n$Repo = \"pranshuparmar/witr\"\n$InstallDir = Join-Path $env:LOCALAPPDATA \"witr\\bin\"\n$User"
  },
  {
    "path": "install.sh",
    "chars": 2938,
    "preview": "#!/usr/bin/env bash\n# Installs the latest release of witr from GitHub\n# Repo: https://github.com/pranshuparmar/witr\n\nset"
  },
  {
    "path": "internal/app/app.go",
    "chars": 18287,
    "preview": "//go:build linux || darwin || freebsd || windows\n\npackage app\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\""
  },
  {
    "path": "internal/launchd/plist.go",
    "chars": 11962,
    "preview": "//go:build darwin\n\npackage launchd\n\nimport (\n\t\"bytes\"\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strconv"
  },
  {
    "path": "internal/output/children.go",
    "chars": 1553,
    "preview": "package output\n\nimport (\n\t\"io\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nfunc PrintChildren(w io.Writer, root model"
  },
  {
    "path": "internal/output/colors.go",
    "chars": 352,
    "preview": "package output\n\nvar (\n\tColorReset     = ansiString(\"\\033[0m\")\n\tColorRed       = ansiString(\"\\033[31m\")\n\tColorGreen     ="
  },
  {
    "path": "internal/output/docker.go",
    "chars": 4237,
    "preview": "package output\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\n// dockerSourceLab"
  },
  {
    "path": "internal/output/docker_test.go",
    "chars": 4135,
    "preview": "package output\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\n"
  },
  {
    "path": "internal/output/envonly.go",
    "chars": 1333,
    "preview": "package output\n\nimport (\n\t\"io\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\n// RenderEnvOnly prints only the command a"
  },
  {
    "path": "internal/output/json.go",
    "chars": 2530,
    "preview": "package output\n\nimport (\n\t\"encoding/json\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nfunc ToJSON(r model.Result) (st"
  },
  {
    "path": "internal/output/printer.go",
    "chars": 1108,
    "preview": "package output\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype ansiString string\n\n// Printer writes terminal-safe output to an io.Writer\n"
  },
  {
    "path": "internal/output/safe_writer.go",
    "chars": 599,
    "preview": "package output\n\nimport \"io\"\n\n// SafeTerminalWriter sanitizes all bytes written to it so the output is safe to\n// display"
  },
  {
    "path": "internal/output/sanitize.go",
    "chars": 2579,
    "preview": "package output\n\nimport (\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n)\n\nconst hexDigits = \"0123456789abcdef\"\n\n// SanitizeTermi"
  },
  {
    "path": "internal/output/sanitize_test.go",
    "chars": 1021,
    "preview": "package output\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\t\"unicode\"\n)\n\nfunc FuzzAppendEscapedRune(f *testing.F) {\n\tf.Add(ui"
  },
  {
    "path": "internal/output/short.go",
    "chars": 628,
    "preview": "package output\n\nimport (\n\t\"io\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nfunc RenderShort(w io.Writer, r model.Resu"
  },
  {
    "path": "internal/output/standard.go",
    "chars": 18377,
    "preview": "package output\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/pranshuparmar/witr/pkg/"
  },
  {
    "path": "internal/output/tree.go",
    "chars": 1500,
    "preview": "package output\n\nimport (\n\t\"io\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nfunc PrintTree(w io.Writer, cha"
  },
  {
    "path": "internal/pipeline/analyze.go",
    "chars": 2322,
    "preview": "package pipeline\n\nimport (\n\t\"sort\"\n\t\"strconv\"\n\n\tprocpkg \"github.com/pranshuparmar/witr/internal/proc\"\n\t\"github.com/prans"
  },
  {
    "path": "internal/proc/ancestry.go",
    "chars": 701,
    "preview": "package proc\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nfunc ResolveAncestry(pid int) ([]model.Proc"
  },
  {
    "path": "internal/proc/boot_darwin.go",
    "chars": 743,
    "preview": "//go:build darwin\n\npackage proc\n\nimport (\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\nfunc bootTime() time.Time {\n\t// Us"
  },
  {
    "path": "internal/proc/boot_freebsd.go",
    "chars": 778,
    "preview": "//go:build freebsd\n\npackage proc\n\nimport (\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\nfunc bootTime() time.Time {\n\t// U"
  },
  {
    "path": "internal/proc/boot_linux.go",
    "chars": 590,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"bufio\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\nfunc bootTime() time.Time {\n\tf,"
  },
  {
    "path": "internal/proc/boot_windows.go",
    "chars": 683,
    "preview": "//go:build windows\n\npackage proc\n\nimport (\n\t\"os/exec\"\n\t\"strings\"\n\t\"time\"\n)\n\nfunc bootTime() time.Time {\n\t// powershell G"
  },
  {
    "path": "internal/proc/capabilities_linux.go",
    "chars": 1959,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// Capability bit positions from include/"
  },
  {
    "path": "internal/proc/children_unix.go",
    "chars": 578,
    "preview": "//go:build linux || darwin || freebsd\n\npackage proc\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\n// R"
  },
  {
    "path": "internal/proc/children_windows.go",
    "chars": 1489,
    "preview": "package proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\n// Resolve"
  },
  {
    "path": "internal/proc/cmdline_darwin.go",
    "chars": 394,
    "preview": "//go:build darwin\n\npackage proc\n\nimport (\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// GetCmdline returns the command line for"
  },
  {
    "path": "internal/proc/cmdline_freebsd.go",
    "chars": 561,
    "preview": "//go:build freebsd\n\npackage proc\n\nimport (\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// GetCmdline returns the command line fo"
  },
  {
    "path": "internal/proc/cmdline_linux.go",
    "chars": 429,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n)\n\n// GetCmdline returns the command line for a given P"
  },
  {
    "path": "internal/proc/cmdline_windows.go",
    "chars": 546,
    "preview": "//go:build windows\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strings\"\n)\n\n// GetCmdline returns the command line for a "
  },
  {
    "path": "internal/proc/command.go",
    "chars": 1719,
    "preview": "package proc\n\nimport (\n\t\"path/filepath\"\n\t\"strings\"\n)\n\n// deriveDisplayCommand returns a human-readable command name that"
  },
  {
    "path": "internal/proc/command_test.go",
    "chars": 3514,
    "preview": "package proc\n\nimport (\n\t\"testing\"\n)\n\nfunc TestDeriveDisplayCommand(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struct {\n\t"
  },
  {
    "path": "internal/proc/container.go",
    "chars": 4816,
    "preview": "package proc\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"time\"\n\t\"unicode\"\n\n\t\"github.com/pranshuparmar/witr/pkg/m"
  },
  {
    "path": "internal/proc/container_detect.go",
    "chars": 1818,
    "preview": "package proc\n\nimport \"strings\"\n\n// detectContainerFromCmdline checks the command line for container runtime patterns.\n//"
  },
  {
    "path": "internal/proc/container_test.go",
    "chars": 1791,
    "preview": "package proc\n\nimport (\n\t\"testing\"\n)\n\nfunc TestSplitCmdline(t *testing.T) {\n\ttests := []struct {\n\t\tname string\n\t\tin   str"
  },
  {
    "path": "internal/proc/docker_proxy.go",
    "chars": 857,
    "preview": "package proc\n\nimport (\n\t\"os/exec\"\n\t\"strings\"\n)\n\nfunc resolveDockerProxyContainer(cmdline string) string {\n\tvar container"
  },
  {
    "path": "internal/proc/extended_darwin.go",
    "chars": 1807,
    "preview": "//go:build darwin\n\npackage proc\n\nimport (\n\t\"errors\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pk"
  },
  {
    "path": "internal/proc/extended_darwin_test.go",
    "chars": 784,
    "preview": "//go:build darwin\n\npackage proc\n\nimport \"testing\"\n\nfunc TestParseLaunchctlLimitLine(t *testing.T) {\n\tfor name, tc := ran"
  },
  {
    "path": "internal/proc/extended_freebsd.go",
    "chars": 1995,
    "preview": "//go:build freebsd\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/"
  },
  {
    "path": "internal/proc/extended_linux.go",
    "chars": 3528,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n"
  },
  {
    "path": "internal/proc/extended_windows.go",
    "chars": 2384,
    "preview": "//go:build windows\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/"
  },
  {
    "path": "internal/proc/fd_darwin.go",
    "chars": 1236,
    "preview": "//go:build darwin\n\npackage proc\n\nimport (\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// socketsForPID returns socket inodes/ide"
  },
  {
    "path": "internal/proc/fd_freebsd.go",
    "chars": 1242,
    "preview": "//go:build freebsd\n\npackage proc\n\nimport (\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// socketsForPID returns socket inodes/id"
  },
  {
    "path": "internal/proc/fd_linux.go",
    "chars": 652,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nfunc socketsForPID(pid int) []s"
  },
  {
    "path": "internal/proc/filecontext_darwin.go",
    "chars": 3872,
    "preview": "//go:build darwin\n\npackage proc\n\nimport (\n\t\"os/exec\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pk"
  },
  {
    "path": "internal/proc/filecontext_freebsd.go",
    "chars": 2682,
    "preview": "//go:build freebsd\n\npackage proc\n\nimport (\n\t\"os/exec\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/p"
  },
  {
    "path": "internal/proc/filecontext_linux.go",
    "chars": 4243,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\t\"syscall\"\n\n\t"
  },
  {
    "path": "internal/proc/filecontext_windows.go",
    "chars": 148,
    "preview": "//go:build windows\n\npackage proc\n\nimport \"github.com/pranshuparmar/witr/pkg/model\"\n\nfunc GetFileContext(pid int) *model."
  },
  {
    "path": "internal/proc/git.go",
    "chars": 848,
    "preview": "package proc\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\nfunc detectGitInfo(cwd string) (string, string) {\n\tif cwd =="
  },
  {
    "path": "internal/proc/libproc_darwin_cgo.go",
    "chars": 6735,
    "preview": "//go:build darwin && cgo && !internal_witr_cgo_disabled\n\npackage proc\n\n/*\n#cgo CFLAGS: -mmacosx-version-min=11.0\n#cgo LD"
  },
  {
    "path": "internal/proc/libproc_darwin_stub.go",
    "chars": 386,
    "preview": "//go:build darwin && (!cgo || internal_witr_cgo_disabled)\n\npackage proc\n\nimport \"github.com/pranshuparmar/witr/pkg/model"
  },
  {
    "path": "internal/proc/libproc_darwin_test.go",
    "chars": 371,
    "preview": "//go:build darwin && !internal_witr_cgo_disabled\n\npackage proc\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestReadDarwinIO(t *te"
  },
  {
    "path": "internal/proc/net_darwin.go",
    "chars": 3116,
    "preview": "//go:build darwin\n\npackage proc\n\nimport (\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)"
  },
  {
    "path": "internal/proc/net_freebsd.go",
    "chars": 4410,
    "preview": "//go:build freebsd\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/"
  },
  {
    "path": "internal/proc/net_linux.go",
    "chars": 3852,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"bufio\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"net\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"ti"
  },
  {
    "path": "internal/proc/net_linux_test.go",
    "chars": 2790,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"net\"\n\t\"testing\"\n)\n\nfunc encodeProcNetTCP6(ip net.IP, p"
  },
  {
    "path": "internal/proc/net_windows.go",
    "chars": 3193,
    "preview": "package proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nfunc ListO"
  },
  {
    "path": "internal/proc/peb_windows.go",
    "chars": 7428,
    "preview": "//go:build windows\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"syscall\"\n\t\"time\"\n\t\"unsafe\"\n)\n\n// Win32 API constant"
  },
  {
    "path": "internal/proc/process_darwin.go",
    "chars": 5671,
    "preview": "//go:build darwin\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/pranshupar"
  },
  {
    "path": "internal/proc/process_darwin_test.go",
    "chars": 1528,
    "preview": "//go:build darwin\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n)\n\nfunc TestGetCwdAndBinaryPath(t *te"
  },
  {
    "path": "internal/proc/process_freebsd.go",
    "chars": 6154,
    "preview": "//go:build freebsd\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/pranshupa"
  },
  {
    "path": "internal/proc/process_linux.go",
    "chars": 9210,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/pranshuparm"
  },
  {
    "path": "internal/proc/process_list_darwin.go",
    "chars": 3160,
    "preview": "//go:build darwin\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"time\"\n\n\t\"github.com/pranshuparmar/w"
  },
  {
    "path": "internal/proc/process_list_freebsd.go",
    "chars": 3101,
    "preview": "//go:build freebsd\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"time\"\n\n\t\"github.com/pranshuparmar/"
  },
  {
    "path": "internal/proc/process_list_linux.go",
    "chars": 3626,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/pranshuparm"
  },
  {
    "path": "internal/proc/process_list_windows.go",
    "chars": 2075,
    "preview": "//go:build windows\n\npackage proc\n\nimport (\n\t\"encoding/csv\"\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshu"
  },
  {
    "path": "internal/proc/process_windows.go",
    "chars": 1783,
    "preview": "//go:build windows\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/pranshuparm"
  },
  {
    "path": "internal/proc/psenv_unix.go",
    "chars": 315,
    "preview": "//go:build darwin || freebsd\n\npackage proc\n\nimport (\n\t\"os\"\n\t\"strings\"\n)\n\nfunc buildEnvForPS() []string {\n\tvar env []stri"
  },
  {
    "path": "internal/proc/resource_darwin.go",
    "chars": 4112,
    "preview": "//go:build darwin\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/m"
  },
  {
    "path": "internal/proc/resource_freebsd.go",
    "chars": 1088,
    "preview": "//go:build freebsd\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/"
  },
  {
    "path": "internal/proc/resource_linux.go",
    "chars": 4071,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/"
  },
  {
    "path": "internal/proc/resource_windows.go",
    "chars": 1235,
    "preview": "//go:build windows\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/"
  },
  {
    "path": "internal/proc/socketstate_darwin.go",
    "chars": 4390,
    "preview": "//go:build darwin\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/m"
  },
  {
    "path": "internal/proc/socketstate_freebsd.go",
    "chars": 3815,
    "preview": "//go:build freebsd\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/"
  },
  {
    "path": "internal/proc/socketstate_linux.go",
    "chars": 3519,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pk"
  },
  {
    "path": "internal/proc/socketstate_windows.go",
    "chars": 2151,
    "preview": "//go:build windows\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nf"
  },
  {
    "path": "internal/proc/sort.go",
    "chars": 222,
    "preview": "package proc\n\nimport (\n\t\"sort\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nfunc sortProcesses(processes []model.Proce"
  },
  {
    "path": "internal/proc/systemd_linux.go",
    "chars": 1617,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nfunc GetSystemdRestartCount"
  },
  {
    "path": "internal/proc/systemd_stub.go",
    "chars": 288,
    "preview": "//go:build !linux\n\npackage proc\n\nimport \"fmt\"\n\nfunc ResolveSystemdService(port int) (string, error) {\n\treturn \"\", fmt.Er"
  },
  {
    "path": "internal/proc/user_darwin.go",
    "chars": 593,
    "preview": "//go:build darwin\n\npackage proc\n\nimport (\n\t\"os/user\"\n\t\"strconv\"\n)\n\nfunc readUser(pid int) string {\n\t// On macOS, we get "
  },
  {
    "path": "internal/proc/user_freebsd.go",
    "chars": 598,
    "preview": "//go:build freebsd\n\npackage proc\n\nimport (\n\t\"os/user\"\n\t\"strconv\"\n)\n\nfunc readUser(pid int) string {\n\t// On FreeBSD, we g"
  },
  {
    "path": "internal/proc/user_linux.go",
    "chars": 923,
    "preview": "//go:build linux\n\npackage proc\n\nimport (\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"syscall\"\n)\n\nvar (\n\tuserCache     map[int]"
  },
  {
    "path": "internal/proc/user_windows.go",
    "chars": 1384,
    "preview": "//go:build windows\n\npackage proc\n\nimport (\n\t\"fmt\"\n\t\"syscall\"\n)\n\nfunc readUser(pid int) string {\n\t// 1. Open Process\n\t// "
  },
  {
    "path": "internal/source/bsdrc_darwin.go",
    "chars": 186,
    "preview": "//go:build darwin\n\npackage source\n\nimport \"github.com/pranshuparmar/witr/pkg/model\"\n\nfunc detectBsdRc(_ []model.Process)"
  },
  {
    "path": "internal/source/bsdrc_freebsd.go",
    "chars": 3151,
    "preview": "//go:build freebsd\n\npackage source\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/pranshuparmar/witr/"
  },
  {
    "path": "internal/source/bsdrc_linux.go",
    "chars": 185,
    "preview": "//go:build linux\n\npackage source\n\nimport \"github.com/pranshuparmar/witr/pkg/model\"\n\nfunc detectBsdRc(_ []model.Process) "
  },
  {
    "path": "internal/source/bsdrc_windows.go",
    "chars": 189,
    "preview": "//go:build windows\n\npackage source\n\nimport \"github.com/pranshuparmar/witr/pkg/model\"\n\nfunc detectBsdRc(_ []model.Process"
  },
  {
    "path": "internal/source/container.go",
    "chars": 1523,
    "preview": "package source\n\nimport (\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nfunc detectContainer"
  },
  {
    "path": "internal/source/cron.go",
    "chars": 350,
    "preview": "package source\n\nimport (\n\t\"path/filepath\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nfunc detectCron(ancestry []mode"
  },
  {
    "path": "internal/source/detect.go",
    "chars": 7122,
    "preview": "package source\n\nimport (\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nvar suspiciousDirs = "
  },
  {
    "path": "internal/source/detect_test.go",
    "chars": 5409,
    "preview": "package source\n\nimport (\n\t\"slices\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nfunc Tes"
  },
  {
    "path": "internal/source/init.go",
    "chars": 1359,
    "preview": "package source\n\nimport (\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\n// detectInit checks"
  },
  {
    "path": "internal/source/launchd_darwin.go",
    "chars": 1911,
    "preview": "//go:build darwin\n\npackage source\n\nimport (\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/internal/launchd\"\n\t\"github.com/p"
  },
  {
    "path": "internal/source/launchd_freebsd.go",
    "chars": 186,
    "preview": "//go:build freebsd\n\npackage source\n\nimport \"github.com/pranshuparmar/witr/pkg/model\"\n\nfunc detectLaunchd(_ []model.Proce"
  },
  {
    "path": "internal/source/launchd_linux.go",
    "chars": 152,
    "preview": "//go:build linux\n\npackage source\n\nimport \"github.com/pranshuparmar/witr/pkg/model\"\n\nfunc detectLaunchd(_ []model.Process"
  },
  {
    "path": "internal/source/launchd_windows.go",
    "chars": 161,
    "preview": "//go:build windows\n\npackage source\n\nimport \"github.com/pranshuparmar/witr/pkg/model\"\n\nfunc detectLaunchd(ancestry []mode"
  },
  {
    "path": "internal/source/network.go",
    "chars": 157,
    "preview": "package source\n\nfunc IsPublicBind(addrs []string) bool {\n\tfor _, a := range addrs {\n\t\tif a == \"0.0.0.0\" || a == \"::\" {\n\t"
  },
  {
    "path": "internal/source/service_other.go",
    "chars": 169,
    "preview": "//go:build !windows\n\npackage source\n\nimport \"github.com/pranshuparmar/witr/pkg/model\"\n\nfunc detectWindowsService(ancestr"
  },
  {
    "path": "internal/source/service_windows.go",
    "chars": 2124,
    "preview": "//go:build windows\n\npackage source\n\nimport (\n\t\"os/exec\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nfunc d"
  },
  {
    "path": "internal/source/shell.go",
    "chars": 3599,
    "preview": "package source\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nvar shells = "
  },
  {
    "path": "internal/source/ssh.go",
    "chars": 1773,
    "preview": "package source\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nfunc detectSS"
  },
  {
    "path": "internal/source/supervisor.go",
    "chars": 2381,
    "preview": "package source\n\nimport (\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\nvar knownSupervisors"
  },
  {
    "path": "internal/source/systemd_darwin.go",
    "chars": 251,
    "preview": "//go:build darwin\n\npackage source\n\nimport \"github.com/pranshuparmar/witr/pkg/model\"\n\nfunc detectSystemd(_ []model.Proces"
  },
  {
    "path": "internal/source/systemd_freebsd.go",
    "chars": 286,
    "preview": "//go:build freebsd\n\npackage source\n\nimport \"github.com/pranshuparmar/witr/pkg/model\"\n\nfunc detectSystemd(_ []model.Proce"
  },
  {
    "path": "internal/source/systemd_linux.go",
    "chars": 7298,
    "preview": "//go:build linux\n\npackage source\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/pranshuparmar/witr/p"
  },
  {
    "path": "internal/source/systemd_windows.go",
    "chars": 261,
    "preview": "//go:build windows\n\npackage source\n\nimport \"github.com/pranshuparmar/witr/pkg/model\"\n\nfunc detectSystemd(ancestry []mode"
  },
  {
    "path": "internal/target/file_darwin.go",
    "chars": 835,
    "preview": "package target\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nfunc ResolveFile(path string) ([]int, error) {\n\t// U"
  },
  {
    "path": "internal/target/file_freebsd.go",
    "chars": 673,
    "preview": "package target\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nfunc ResolveFile(path string) ([]int, error) {\n\t// f"
  },
  {
    "path": "internal/target/file_linux.go",
    "chars": 1088,
    "preview": "package target\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n)\n\n// ResolveFile finds processes holding a lock on th"
  },
  {
    "path": "internal/target/file_windows.go",
    "chars": 163,
    "preview": "package target\n\nimport (\n\t\"fmt\"\n)\n\nfunc ResolveFile(path string) ([]int, error) {\n\treturn nil, fmt.Errorf(\"finding proce"
  },
  {
    "path": "internal/target/name_darwin.go",
    "chars": 4162,
    "preview": "//go:build darwin\n\npackage target\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\tprocpkg \"g"
  },
  {
    "path": "internal/target/name_freebsd.go",
    "chars": 4583,
    "preview": "//go:build freebsd\n\npackage target\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\tprocpkg \""
  },
  {
    "path": "internal/target/name_linux.go",
    "chars": 2995,
    "preview": "//go:build linux\n\npackage target\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\tprocpkg \"github.com/p"
  },
  {
    "path": "internal/target/name_windows.go",
    "chars": 2221,
    "preview": "//go:build windows\n\npackage target\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\tprocpkg \"github.com/pranshu"
  },
  {
    "path": "internal/target/port_darwin.go",
    "chars": 2511,
    "preview": "//go:build darwin\n\npackage target\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nfunc ResolvePort(port int"
  },
  {
    "path": "internal/target/port_freebsd.go",
    "chars": 6069,
    "preview": "//go:build freebsd\n\npackage target\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshu"
  },
  {
    "path": "internal/target/port_linux.go",
    "chars": 2474,
    "preview": "//go:build linux\n\npackage target\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nfunc findSocke"
  },
  {
    "path": "internal/target/port_windows.go",
    "chars": 1267,
    "preview": "//go:build windows\n\npackage target\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nfunc ResolvePort(port int) ([]in"
  },
  {
    "path": "internal/target/resolve.go",
    "chars": 1531,
    "preview": "package target\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pranshuparmar/witr/pkg/model\"\n)\n\n// matchesExactToke"
  },
  {
    "path": "internal/target/resolve_test.go",
    "chars": 1841,
    "preview": "//go:build linux || darwin || freebsd || windows\n\npackage target\n\nimport (\n\t\"testing\"\n\n\t\"github.com/pranshuparmar/witr/p"
  },
  {
    "path": "internal/tools/docgen/main.go",
    "chars": 1564,
    "preview": "//go:build linux || darwin || freebsd\n\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t"
  },
  {
    "path": "internal/tui/actions.go",
    "chars": 1046,
    "preview": "//go:build !windows\n\npackage tui\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"syscall\"\n)\n\nfunc killProcess(pid int) error   { return sendSig"
  },
  {
    "path": "internal/tui/actions_windows.go",
    "chars": 472,
    "preview": "//go:build windows\n\npackage tui\n\nimport \"fmt\"\n\nfunc killProcess(pid int) error    { return fmt.Errorf(\"not supported on "
  },
  {
    "path": "internal/tui/data.go",
    "chars": 13710,
    "preview": "package tui\n\nimport (\n\t\"cmp\"\n\t\"fmt\"\n\t\"os\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/bubbles/table\"\n\ttea "
  },
  {
    "path": "internal/tui/helpers.go",
    "chars": 272,
    "preview": "package tui\n\nimport \"regexp\"\n\nvar ansiRegex = regexp.MustCompile(`[\\x1b\\x9b][[\\\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\"
  },
  {
    "path": "internal/tui/model.go",
    "chars": 7182,
    "preview": "package tui\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/charmbracelet/bubbles/table\"\n\t\"github.com/charmbracelet/bubbles"
  },
  {
    "path": "internal/tui/mouse.go",
    "chars": 1545,
    "preview": "package tui\n\nimport \"github.com/charmbracelet/bubbles/table\"\n\n// returns the column index at x pixels, or -1 if not foun"
  },
  {
    "path": "internal/tui/update.go",
    "chars": 28010,
    "preview": "package tui\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/charmbracelet/bubbles/textinput\"\n\ttea \"github.com/charmbra"
  },
  {
    "path": "internal/tui/view.go",
    "chars": 9737,
    "preview": "package tui\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/lipgloss\"\n)\n\nfunc (m MainModel) View() string {\n\tif "
  },
  {
    "path": "internal/version/VERSION",
    "chars": 6,
    "preview": "0.3.1\n"
  },
  {
    "path": "internal/version/version.go",
    "chars": 972,
    "preview": "package version\n\nimport (\n\t_ \"embed\"\n\t\"runtime/debug\"\n\t\"strings\"\n)\n\n//go:embed VERSION\nvar embedded string\n\n// Version, "
  },
  {
    "path": "pkg/model/docker.go",
    "chars": 279,
    "preview": "package model\n\n// DockerPortMatch holds information about a Docker container that publishes a specific port.\ntype Docker"
  },
  {
    "path": "pkg/model/filecontext.go",
    "chars": 342,
    "preview": "package model\n\n// FileContext holds file-related context for a process\ntype FileContext struct {\n\t// Number of open file"
  },
  {
    "path": "pkg/model/net.go",
    "chars": 119,
    "preview": "package model\n\ntype OpenPort struct {\n\tPID      int\n\tPort     int\n\tAddress  string\n\tProtocol string\n\tState    string\n}\n"
  },
  {
    "path": "pkg/model/process.go",
    "chars": 1930,
    "preview": "package model\n\nimport \"time\"\n\ntype Process struct {\n\tPID           int\n\tPPID          int\n\tCommand       string\n\tCmdline"
  },
  {
    "path": "pkg/model/resource.go",
    "chars": 511,
    "preview": "package model\n\n// ResourceContext holds resource usage context for a process\ntype ResourceContext struct {\n\t// Energy im"
  },
  {
    "path": "pkg/model/result.go",
    "chars": 505,
    "preview": "package model\n\ntype Result struct {\n\tTarget         Target\n\tResolvedTarget string\n\tProcess        Process\n\tRestartCount "
  },
  {
    "path": "pkg/model/socket.go",
    "chars": 479,
    "preview": "package model\n\ntype Socket struct {\n\tInode    string\n\tPort     int\n\tAddress  string // 0.0.0.0, 127.0.0.1, ::\n\tState    "
  },
  {
    "path": "pkg/model/source.go",
    "chars": 682,
    "preview": "package model\n\ntype SourceType string\n\nconst (\n\tSourceContainer      SourceType = \"container\"\n\tSourceSystemd        Sour"
  },
  {
    "path": "pkg/model/target.go",
    "chars": 232,
    "preview": "package model\n\ntype TargetType string\n\nconst (\n\tTargetName TargetType = \"name\"\n\tTargetPID  TargetType = \"pid\"\n\tTargetPor"
  },
  {
    "path": "vendor/github.com/atotto/clipboard/.travis.yml",
    "chars": 321,
    "preview": "language: go\n\nos:\n - linux\n - osx\n - windows\n\ngo:\n - go1.13.x\n - go1.x\n\nservices:\n - xvfb\n\nbefore_install:\n - export DIS"
  },
  {
    "path": "vendor/github.com/atotto/clipboard/LICENSE",
    "chars": 1471,
    "preview": "Copyright (c) 2013 Ato Araki. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nm"
  },
  {
    "path": "vendor/github.com/atotto/clipboard/README.md",
    "chars": 912,
    "preview": "[![Build Status](https://travis-ci.org/atotto/clipboard.svg?branch=master)](https://travis-ci.org/atotto/clipboard)\n\n[!["
  },
  {
    "path": "vendor/github.com/atotto/clipboard/clipboard.go",
    "chars": 554,
    "preview": "// Copyright 2013 @atotto. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that ca"
  },
  {
    "path": "vendor/github.com/atotto/clipboard/clipboard_darwin.go",
    "chars": 908,
    "preview": "// Copyright 2013 @atotto. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that ca"
  },
  {
    "path": "vendor/github.com/atotto/clipboard/clipboard_plan9.go",
    "chars": 663,
    "preview": "// Copyright 2013 @atotto. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that ca"
  },
  {
    "path": "vendor/github.com/atotto/clipboard/clipboard_unix.go",
    "chars": 3249,
    "preview": "// Copyright 2013 @atotto. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that ca"
  },
  {
    "path": "vendor/github.com/atotto/clipboard/clipboard_windows.go",
    "chars": 4190,
    "preview": "// Copyright 2013 @atotto. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that ca"
  },
  {
    "path": "vendor/github.com/aymanbagabas/go-osc52/v2/LICENSE",
    "chars": 1070,
    "preview": "MIT License\n\nCopyright (c) 2022 Ayman Bagabas\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
  },
  {
    "path": "vendor/github.com/aymanbagabas/go-osc52/v2/README.md",
    "chars": 2370,
    "preview": "\n# go-osc52\n\n<p>\n    <a href=\"https://github.com/aymanbagabas/go-osc52/releases\"><img src=\"https://img.shields.io/github"
  },
  {
    "path": "vendor/github.com/aymanbagabas/go-osc52/v2/osc52.go",
    "chars": 7978,
    "preview": "// OSC52 is a terminal escape sequence that allows copying text to the clipboard.\n//\n// The sequence consists of the fol"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbles/LICENSE",
    "chars": 1080,
    "preview": "MIT License\n\nCopyright (c) 2020-2025 Charmbracelet, Inc\n\nPermission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbles/cursor/cursor.go",
    "chars": 4788,
    "preview": "// Package cursor provides cursor functionality for Bubble Tea applications.\npackage cursor\n\nimport (\n\t\"context\"\n\t\"time\""
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbles/help/help.go",
    "chars": 5810,
    "preview": "// Package help provides a simple help view for Bubble Tea applications.\npackage help\n\nimport (\n\t\"strings\"\n\n\t\"github.com"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbles/key/key.go",
    "chars": 3588,
    "preview": "// Package key provides some types and functions for generating user-definable\n// keymappings useful in Bubble Tea compo"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbles/runeutil/runeutil.go",
    "chars": 2747,
    "preview": "// Package runeutil provides a utility function for use in Bubbles\n// that can process Key messages containing runes.\npa"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbles/table/table.go",
    "chars": 10973,
    "preview": "// Package table provides a simple table component for Bubble Tea applications.\npackage table\n\nimport (\n\t\"strings\"\n\n\ttea"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbles/textinput/textinput.go",
    "chars": 23044,
    "preview": "// Package textinput provides a text input component for Bubble Tea\n// applications.\npackage textinput\n\nimport (\n\t\"refle"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbles/viewport/keymap.go",
    "chars": 1551,
    "preview": "// Package viewport provides a component for rendering a viewport in a Bubble\n// Tea.\npackage viewport\n\nimport \"github.c"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbles/viewport/viewport.go",
    "chars": 14900,
    "preview": "package viewport\n\nimport (\n\t\"math\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/bubbles/key\"\n\ttea \"github.com/charmbracelet/bu"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/.gitattributes",
    "chars": 15,
    "preview": "*.golden -text\n"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/.gitignore",
    "chars": 525,
    "preview": ".DS_Store\n.envrc\n\nexamples/fullscreen/fullscreen\nexamples/help/help\nexamples/http/http\nexamples/list-default/list-defaul"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/.golangci.yml",
    "chars": 695,
    "preview": "version: \"2\"\nrun:\n  tests: false\nlinters:\n  enable:\n    - bodyclose\n    - exhaustive\n    - goconst\n    - godot\n    - gom"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/.goreleaser.yml",
    "chars": 168,
    "preview": "# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json\nversion: 2\nincludes:\n  - from_url:\n      u"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/LICENSE",
    "chars": 1080,
    "preview": "MIT License\n\nCopyright (c) 2020-2025 Charmbracelet, Inc\n\nPermission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/README.md",
    "chars": 14725,
    "preview": "# Bubble Tea\n\n<p>\n    <picture>\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/bubbl"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/Taskfile.yaml",
    "chars": 183,
    "preview": "# https://taskfile.dev\n\nversion: '3'\n\ntasks:\n  lint:\n    desc: Run lint\n    cmds:\n      - golangci-lint run\n\n  test:\n   "
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/commands.go",
    "chars": 5922,
    "preview": "package tea\n\nimport (\n\t\"time\"\n)\n\n// Batch performs a bunch of commands concurrently with no ordering guarantees\n// about"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/exec.go",
    "chars": 3666,
    "preview": "package tea\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n)\n\n// execMsg is used internally to run an ExecCommand sent with Exec.\ntype"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/focus.go",
    "chars": 247,
    "preview": "package tea\n\n// FocusMsg represents a terminal focus message.\n// This occurs when the terminal gains focus.\ntype FocusMs"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/inputreader_other.go",
    "chars": 344,
    "preview": "//go:build !windows\n// +build !windows\n\npackage tea\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/muesli/cancelreader\"\n)\n\nfunc ne"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go",
    "chars": 2967,
    "preview": "//go:build windows\n// +build windows\n\npackage tea\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"sync\"\n\n\t\"github.com/charmbracelet/x/ter"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/key.go",
    "chars": 21809,
    "preview": "package tea\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"regexp\"\n\t\"strings\"\n\t\"unicode/utf8\"\n)\n\n// KeyMsg contains information abo"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/key_other.go",
    "chars": 204,
    "preview": "//go:build !windows\n// +build !windows\n\npackage tea\n\nimport (\n\t\"context\"\n\t\"io\"\n)\n\nfunc readInputs(ctx context.Context, m"
  },
  {
    "path": "vendor/github.com/charmbracelet/bubbletea/key_sequences.go",
    "chars": 3547,
    "preview": "package tea\n\nimport (\n\t\"bytes\"\n\t\"sort\"\n\t\"unicode/utf8\"\n)\n\n// extSequences is used by the map-based algorithm below. It c"
  }
]

// ... and 725 more files (download for full content)

About this extraction

This page contains the full source code of the pranshuparmar/witr GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 925 files (11.7 MB), approximately 3.1M tokens, and a symbol index with 103001 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!