docker-orb 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. docker_orb-1.0.0/.gitignore +9 -0
  2. docker_orb-1.0.0/CLAUDE.md +134 -0
  3. docker_orb-1.0.0/LICENSE +21 -0
  4. docker_orb-1.0.0/PKG-INFO +192 -0
  5. docker_orb-1.0.0/README.md +139 -0
  6. docker_orb-1.0.0/docs/USER_GUIDE.md +309 -0
  7. docker_orb-1.0.0/docs/demo.tape +269 -0
  8. docker_orb-1.0.0/docs/screenshot-viewer.png +0 -0
  9. docker_orb-1.0.0/infra/Makefile +57 -0
  10. docker_orb-1.0.0/infra/README.md +126 -0
  11. docker_orb-1.0.0/infra/docker-compose.yml +87 -0
  12. docker_orb-1.0.0/infra/services/api-gateway/Dockerfile +5 -0
  13. docker_orb-1.0.0/infra/services/api-gateway/app.py +125 -0
  14. docker_orb-1.0.0/infra/services/auth-service/Dockerfile +5 -0
  15. docker_orb-1.0.0/infra/services/auth-service/app.py +126 -0
  16. docker_orb-1.0.0/infra/services/cache/Dockerfile +5 -0
  17. docker_orb-1.0.0/infra/services/cache/app.py +110 -0
  18. docker_orb-1.0.0/infra/services/database/Dockerfile +5 -0
  19. docker_orb-1.0.0/infra/services/database/app.py +131 -0
  20. docker_orb-1.0.0/infra/services/notification-service/Dockerfile +5 -0
  21. docker_orb-1.0.0/infra/services/notification-service/app.py +174 -0
  22. docker_orb-1.0.0/infra/services/scheduler/Dockerfile +5 -0
  23. docker_orb-1.0.0/infra/services/scheduler/app.py +137 -0
  24. docker_orb-1.0.0/infra/services/user-service/Dockerfile +5 -0
  25. docker_orb-1.0.0/infra/services/user-service/app.py +132 -0
  26. docker_orb-1.0.0/infra/services/worker/Dockerfile +5 -0
  27. docker_orb-1.0.0/infra/services/worker/app.py +143 -0
  28. docker_orb-1.0.0/pyproject.toml +76 -0
  29. docker_orb-1.0.0/scripts/run-safe.sh +21 -0
  30. docker_orb-1.0.0/src/docker_orb/__init__.py +0 -0
  31. docker_orb-1.0.0/src/docker_orb/__main__.py +5 -0
  32. docker_orb-1.0.0/src/docker_orb/_scrollbar.py +136 -0
  33. docker_orb-1.0.0/src/docker_orb/cli.py +167 -0
  34. docker_orb-1.0.0/src/docker_orb/colors.py +60 -0
  35. docker_orb-1.0.0/src/docker_orb/compose.py +391 -0
  36. docker_orb-1.0.0/src/docker_orb/config.py +244 -0
  37. docker_orb-1.0.0/src/docker_orb/inject.py +160 -0
  38. docker_orb-1.0.0/src/docker_orb/jsonlog.py +125 -0
  39. docker_orb-1.0.0/src/docker_orb/models.py +132 -0
  40. docker_orb-1.0.0/src/docker_orb/viewer/__init__.py +0 -0
  41. docker_orb-1.0.0/src/docker_orb/viewer/app.py +824 -0
  42. docker_orb-1.0.0/src/docker_orb/viewer/panels/__init__.py +0 -0
  43. docker_orb-1.0.0/src/docker_orb/viewer/panels/health.py +239 -0
  44. docker_orb-1.0.0/src/docker_orb/viewer/panels/main_stream.py +389 -0
  45. docker_orb-1.0.0/src/docker_orb/viewer/panels/monitor.py +233 -0
  46. docker_orb-1.0.0/src/docker_orb/viewer/panels/search.py +182 -0
  47. docker_orb-1.0.0/src/docker_orb/viewer/viewer.tcss +205 -0
  48. docker_orb-1.0.0/src/docker_orb/viewer/widgets.py +668 -0
  49. docker_orb-1.0.0/src/docker_orb/wizard/__init__.py +0 -0
  50. docker_orb-1.0.0/src/docker_orb/wizard/app.py +40 -0
  51. docker_orb-1.0.0/src/docker_orb/wizard/screens.py +692 -0
  52. docker_orb-1.0.0/src/docker_orb/wizard/wizard.tcss +329 -0
  53. docker_orb-1.0.0/tests/__init__.py +0 -0
  54. docker_orb-1.0.0/tests/features/wizard.feature +48 -0
  55. docker_orb-1.0.0/tests/test_colors.py +50 -0
  56. docker_orb-1.0.0/tests/test_compose.py +188 -0
  57. docker_orb-1.0.0/tests/test_config.py +173 -0
  58. docker_orb-1.0.0/tests/test_health_panel.py +43 -0
  59. docker_orb-1.0.0/tests/test_jsonlog.py +69 -0
  60. docker_orb-1.0.0/tests/test_scrollbar.py +59 -0
  61. docker_orb-1.0.0/tests/test_viewer_backfill.py +162 -0
  62. docker_orb-1.0.0/tests/test_viewer_collapse_repeats.py +173 -0
  63. docker_orb-1.0.0/tests/test_viewer_color_mode.py +155 -0
  64. docker_orb-1.0.0/tests/test_viewer_edit_behaviors.py +145 -0
  65. docker_orb-1.0.0/tests/test_viewer_json_format.py +170 -0
  66. docker_orb-1.0.0/tests/test_viewer_keybindings.py +56 -0
  67. docker_orb-1.0.0/tests/test_viewer_monitor_context.py +189 -0
  68. docker_orb-1.0.0/tests/test_viewer_monitor_double_click.py +68 -0
  69. docker_orb-1.0.0/tests/test_viewer_pane_size_modal.py +149 -0
  70. docker_orb-1.0.0/tests/test_viewer_pause_resume.py +103 -0
  71. docker_orb-1.0.0/tests/test_viewer_resize.py +76 -0
  72. docker_orb-1.0.0/tests/test_viewer_string_edit_modal.py +88 -0
  73. docker_orb-1.0.0/tests/test_wizard_bdd_scenarios.py +163 -0
  74. docker_orb-1.0.0/tests/test_wizard_screens.py +109 -0
@@ -0,0 +1,9 @@
1
+ *.egg-info/
2
+ *.pyc
3
+ .DS_Store
4
+ .fuse_hidden*
5
+ .git-broken-lockissue/
6
+ .pytest_cache/
7
+ .venv/
8
+ __pycache__/
9
+ dist/
@@ -0,0 +1,134 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Commands
6
+
7
+ ```bash
8
+ # Install in editable mode (sets up both entry points)
9
+ # NOTE: dev deps are a PEP 735 dependency group, not an extra — `.[dev]`
10
+ # silently installs nothing (pip just warns "does not provide the extra").
11
+ pip install -e . --group dev
12
+ # or with uv:
13
+ uv pip install -e . --group dev
14
+
15
+ # Run the TUI app (dev mode with live reload via textual-dev)
16
+ hatch run dev
17
+ # or directly:
18
+ textual run --dev src/docker_orb/__main__.py
19
+
20
+ # Run the app normally
21
+ docker-orb
22
+
23
+ # Run all tests
24
+ pytest
25
+ # or via hatch:
26
+ hatch run test
27
+
28
+ # Run a single test file
29
+ pytest tests/test_config.py
30
+
31
+ # Run a single test class or method
32
+ pytest tests/test_config.py::TestParseStringInput::test_comma_separated
33
+ ```
34
+
35
+ ### Test infrastructure (local Compose stack)
36
+
37
+ ```bash
38
+ cd infra
39
+ make up # one-shot: build + start 8 fake log-generating services
40
+ make status # docker compose ps
41
+ make logs # tail all services
42
+ make logs SERVICE=worker # tail one service
43
+ make restart # recreate all services (picks up code changes)
44
+ make teardown # stop and remove everything
45
+ ```
46
+
47
+ The stack runs under the fixed Compose project name `logviewer-demo` (8
48
+ services: `api-gateway`, `auth-service`, `user-service`,
49
+ `notification-service`, `worker`, `database`, `cache`, `scheduler` — the
50
+ busier five run 2 containers each). It's deliberately not named
51
+ `docker-orb-*` — docker-orb doesn't prepend its own name to anything, and
52
+ container names here (`logviewer-demo-api-gateway-1`, etc.) are just this
53
+ demo's own Compose project name, same as any other stack. It also stops
54
+ itself automatically after 4 hours by default (a `reaper` service in
55
+ `docker-compose.yml`, socket-mounted, `docker stop`s the project's
56
+ containers on a timer — see `infra/README.md#auto-shutdown-after-4-hours`
57
+ for overriding/disabling it) so it's never left running unattended
58
+ indefinitely. Point docker-orb at it with:
59
+
60
+ ```bash
61
+ docker-orb -n logviewer-demo --all-containers --health
62
+ docker-orb-inject -n logviewer-demo -d worker -m "ERROR: test error"
63
+ ```
64
+
65
+ `docker-orb-inject` writes directly to a container's PID 1 stdout via
66
+ `docker exec ... sh -c "echo ... > /proc/1/fd/1"`, so injected messages show
67
+ up in the live stream exactly like real application logs — handy for
68
+ exercising filters/highlights/monitors without waiting for a real error.
69
+
70
+ This is a straight Compose port of kube-orb's k3d test cluster: same
71
+ Python log-generator scripts under `infra/services/`, unchanged (none of
72
+ them depended on anything Kubernetes-specific), just wired up with
73
+ `infra/docker-compose.yml` instead of k3d + k8s manifests. It also still
74
+ works fine, of course, to point docker-orb at any other real
75
+ `docker-compose.yml` project you have running.
76
+
77
+ ## Architecture
78
+
79
+ docker-orb is a **Textual TUI** app with two entry points:
80
+
81
+ - `docker-orb` (`src/docker_orb/cli.py`) — main CLI. If enough args are provided, launches the viewer directly; otherwise falls through to the wizard.
82
+ - `docker-orb-inject` (`src/docker_orb/inject.py`) — test utility that writes messages to a container's stdout via `docker exec`, causing them to appear in the live log stream.
83
+
84
+ ### Data flow
85
+
86
+ ```
87
+ CLI args / Wizard
88
+
89
+ SessionConfig (models.py)
90
+
91
+ ViewerApp (viewer/app.py)
92
+ ↓ asyncio workers (one per container)
93
+ compose.stream_logs() (compose.py) — async subprocess, `docker logs -f`
94
+ ↓ LogLine objects
95
+ _ingest() → filter → _deliver_to_panels()
96
+
97
+ MainStreamPanel / MonitorPanel / HealthPanel / SearchPanel
98
+ ```
99
+
100
+ ### Key modules
101
+
102
+ | Module | Purpose |
103
+ |---|---|
104
+ | `models.py` | All shared dataclasses: `SessionConfig`, `LogLine`, `Service`, `Container`, `ContainerStatus`, `HealthConfig` |
105
+ | `compose.py` | All Docker/Compose interaction via subprocess (`docker`, `docker compose`). No Python Docker SDK. `stream_logs()` runs `docker logs -f --timestamps <container>` per container (one coroutine per container, same fan-out pattern as kube-orb's per-pod streaming) rather than a single multiplexed `docker compose logs -f`; `dump_logs()` is one-shot. `stream_logs()` normalizes `since` to `"1s"` when unset/zero (`_normalize_since()`) so a live session only collects new lines instead of replaying history. **Untested against a live Docker daemon in the environment this was written in** — verify service/container discovery (`docker compose ps --format json` shape) and the `--since` normalization against a real Compose project before relying on it. |
106
+ | `config.py` | Persists session configs to `~/.config/docker-orb/projects/<project>/<name>.yaml` and global saved strings to `~/.config/docker-orb/strings.yaml`. Also owns pattern compilation: plain strings are `re.escape`d; `/regex/`-wrapped strings compile as real regex. |
107
+ | `colors.py` | Assigns a distinct ANSI/CSS color to each container name. |
108
+ | `jsonlog.py` | Detects single-JSON-object log lines and extracts level/message/timestamp (checking a few conventional key names) for the optional readable-formatting toggle. Detection runs regardless of the toggle, since the Enter-for-detail view needs it too. |
109
+ | `viewer/app.py` | `ViewerApp` — the main Textual `App`. Owns the log buffer, pause state, pattern state, and container/service lifecycle. |
110
+ | `viewer/panels/` | Four panels: `MainStreamPanel` (primary log display), `SearchPanel` (live search), `MonitorPanel` (passive pattern accumulation), `HealthPanel` (restart/health alerts). |
111
+ | `viewer/widgets.py` | Shared widgets: `StringEditModal` (F/H/M editing), `SaveDialog`, `ContainerSelectorModal`, `PaneSizeModal`, `JsonDetailModal`, `MonitorContextModal`. |
112
+ | `wizard/` | Three-tab Textual wizard (`SinglePageWizard` screen) — Targets → Strings → Options — produces a `SessionConfig`. |
113
+
114
+ ### Pattern matching
115
+
116
+ Filters, highlights, and monitors all share the same matching syntax (in `config.py`):
117
+ - Plain strings are matched as literals (dots and special chars are escaped).
118
+ - `/pattern/` strings are compiled as regex.
119
+ - Comma-separated input is parsed by `parse_string_input()`.
120
+
121
+ ### Package layout
122
+
123
+ `src/docker_orb/` is the canonical source package.
124
+
125
+ ### Provenance
126
+
127
+ docker-orb started as a sibling port of [kube-orb](https://github.com/adlidev/kube-orb):
128
+ the Textual viewer/wizard/panel layer (~3900 lines) was carried over largely
129
+ unchanged since it only ever depended on generic `LogLine`/container-name
130
+ concepts, not Kubernetes specifics. The Kubernetes-coupled layer — `kubectl.py`, the `Deployment`/`Pod` models, and
131
+ the k3d test infra — was replaced with `compose.py`, `Service`/`Container`
132
+ models, and an `infra/docker-compose.yml` port of the same test-log
133
+ services. The two projects are maintained independently going forward;
134
+ changes to one don't automatically apply to the other.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Adli Waziri
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,192 @@
1
+ Metadata-Version: 2.4
2
+ Name: docker-orb
3
+ Version: 1.0.0
4
+ Summary: Interactive terminal UI for streaming and filtering Docker Compose container logs across multiple services
5
+ Project-URL: Homepage, https://github.com/adlidev/docker-orb
6
+ Project-URL: Repository, https://github.com/adlidev/docker-orb
7
+ Project-URL: Documentation, https://github.com/adlidev/docker-orb/blob/main/docs/USER_GUIDE.md
8
+ Project-URL: Issues, https://github.com/adlidev/docker-orb/issues
9
+ Author-email: Adli Waziri <boulderadli@gmail.com>
10
+ License: MIT License
11
+
12
+ Copyright (c) 2026 Adli Waziri
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Keywords: compose,devops,docker,docker-compose,logs,observability,sre,textual,tui
33
+ Classifier: Development Status :: 5 - Production/Stable
34
+ Classifier: Environment :: Console
35
+ Classifier: Intended Audience :: Developers
36
+ Classifier: Intended Audience :: System Administrators
37
+ Classifier: License :: OSI Approved :: MIT License
38
+ Classifier: Operating System :: MacOS
39
+ Classifier: Operating System :: POSIX :: Linux
40
+ Classifier: Programming Language :: Python :: 3
41
+ Classifier: Programming Language :: Python :: 3.10
42
+ Classifier: Programming Language :: Python :: 3.11
43
+ Classifier: Programming Language :: Python :: 3.12
44
+ Classifier: Topic :: System :: Logging
45
+ Classifier: Topic :: System :: Monitoring
46
+ Classifier: Topic :: System :: Systems Administration
47
+ Classifier: Topic :: Utilities
48
+ Requires-Python: >=3.10
49
+ Requires-Dist: click>=8.1
50
+ Requires-Dist: pyyaml>=6.0
51
+ Requires-Dist: textual>=0.61.0
52
+ Description-Content-Type: text/markdown
53
+
54
+ # docker-orb
55
+
56
+ Watching logs across a multi-container Compose stack usually means juggling
57
+ multiple `docker compose logs` windows and grepping after the fact, or
58
+ writing complex regex just to add a couple of filters. docker-orb streams
59
+ logs from every container in your selected services into one merged,
60
+ colorized view — and lets you filter, highlight, and search *while it's
61
+ streaming*.
62
+
63
+ Built with [Textual](https://textual.textualize.io/), docker-orb is a full
64
+ terminal UI: an interactive setup wizard walks you through picking a
65
+ project, services, and filter patterns — no flags required — or skip
66
+ straight to the viewer with CLI arguments if you prefer. Save named session
67
+ configs to reload your exact setup later; passively collect rare events in
68
+ a monitor panel without losing your scroll position; get alerted when
69
+ containers restart or go unhealthy; and add or remove services from the
70
+ live stream without restarting.
71
+
72
+ ![docker-orb viewer](docs/screenshot-viewer.png)
73
+
74
+ ## Features
75
+
76
+ - **Multi-container live tail** — stream logs from any number of
77
+ containers/services at once, each with a distinct color.
78
+ - **Filters** — hide lines matching a pattern, live-editable mid-session.
79
+ - **Highlights** — emphasize lines matching a pattern without hiding anything else.
80
+ - **Monitors** — passively collect matching lines into a separate panel so you
81
+ can watch for rare events (e.g. `job failed`) without losing your scroll
82
+ position in the main stream.
83
+ - **Live search** — search the whole buffered session, jump to a result, and
84
+ keep streaming.
85
+ - **Container health panel** — flags containers that aren't `Running` or have
86
+ crossed a restart threshold; restart a container or recreate a service from
87
+ inside the app.
88
+ - **Dump mode** — fetch existing logs once (with `--tail`/`--since`) and exit,
89
+ for scripting or one-off inspection, instead of a live stream.
90
+ - **Saved configs** — save a named combination of project, services, and
91
+ patterns, and reload it later by name.
92
+ - **JSON log formatting** — auto-detects structured JSON log lines and shows
93
+ `time LEVEL message key=value ...` instead of a raw JSON blob, with a
94
+ toggle back to raw and a detail view (Enter on a clicked line) for the full
95
+ pretty-printed object.
96
+ - **Collapse repeated lines** — journalctl-style: consecutive identical lines
97
+ from the same container fold into a single "last line repeated N times"
98
+ marker, toggleable, so a crash-looping container doesn't flood the stream.
99
+
100
+ ## Installation
101
+
102
+ Requires Python 3.10+, and `docker` with the Compose v2 plugin on your
103
+ `PATH` (i.e. `docker compose` works). docker-orb shells out to your existing
104
+ `docker` CLI and inherits its context/auth — no separate credentials or
105
+ Docker SDK involved.
106
+
107
+ ```bash
108
+ # Recommended — pipx keeps CLI tools in isolated environments. Not on PyPI
109
+ # yet, so install straight from GitHub:
110
+ pipx install git+https://github.com/adlidev/docker-orb
111
+
112
+ # Or with plain pip, inside your own venv:
113
+ git clone https://github.com/adlidev/docker-orb.git
114
+ cd docker-orb
115
+ pip install -e .
116
+ ```
117
+
118
+ This installs two commands: `docker-orb` and `docker-orb-inject` (a small
119
+ test utility for injecting fake log lines into a running container — see
120
+ the [User Guide](docs/USER_GUIDE.md#docker-orb-inject)).
121
+
122
+ **For development / contributing:**
123
+
124
+ ```bash
125
+ git clone https://github.com/adlidev/docker-orb.git
126
+ cd docker-orb
127
+ pip install -e . --group dev
128
+ ```
129
+
130
+ ## Quick start
131
+
132
+ ```bash
133
+ # No arguments — launches the interactive setup wizard
134
+ docker-orb
135
+
136
+ # Skip the wizard: watch two services live
137
+ docker-orb -n myapp -p api -p worker
138
+
139
+ # Watch every service in a project
140
+ docker-orb -n myapp --all-containers
141
+
142
+ # One-shot dump instead of a live stream
143
+ docker-orb -n myapp --dump --tail 500
144
+
145
+ # Pre-filter/highlight from the command line
146
+ docker-orb -n myapp -p worker -f DEBUG -H ERROR --health
147
+ ```
148
+
149
+ `-n/--project` takes the Compose project name (what `docker compose -p`
150
+ expects — usually the directory name your `docker-compose.yml` lives in,
151
+ unless overridden by a top-level `name:` key or `COMPOSE_PROJECT_NAME`). If
152
+ omitted, docker-orb resolves it the same way `docker compose` does for the
153
+ current directory.
154
+
155
+ Once you're in the viewer, press `F` / `H` / `M` to edit filters, highlights,
156
+ or monitors live, `/` to search, `P` to add/remove streamed services, and
157
+ `Space` to pause. See the [User Guide](docs/USER_GUIDE.md) for the full
158
+ keybinding reference and pattern syntax.
159
+
160
+ ## Development
161
+
162
+ ```bash
163
+ pip install -e . --group dev
164
+ pytest # run the test suite
165
+ textual run --dev src/docker_orb/__main__.py # live-reload dev mode
166
+ ```
167
+
168
+ A local Compose stack with 8 fake log-generating services is included for
169
+ manual testing:
170
+
171
+ ```bash
172
+ cd infra
173
+ make up
174
+ docker-orb -n logviewer-demo --all-containers --health
175
+ ```
176
+
177
+ See [`infra/README.md`](infra/README.md) for the service list and good
178
+ filter/monitor test patterns, and [`CLAUDE.md`](CLAUDE.md) for architecture
179
+ notes.
180
+
181
+ ## Relationship to kube-orb
182
+
183
+ docker-orb is a sibling project to [kube-orb](https://github.com/adlidev/kube-orb),
184
+ Adli's Kubernetes-flavored log viewer. They share a UI architecture (Textual
185
+ viewer, wizard, filters/highlights/monitors, JSON formatting) but each talks
186
+ to its own backend directly — docker-orb shells out to `docker`/`docker
187
+ compose`, kube-orb shells out to `kubectl` — and they're maintained as
188
+ independent tools rather than one project trying to do both.
189
+
190
+ ## License
191
+
192
+ [MIT License](LICENSE)
@@ -0,0 +1,139 @@
1
+ # docker-orb
2
+
3
+ Watching logs across a multi-container Compose stack usually means juggling
4
+ multiple `docker compose logs` windows and grepping after the fact, or
5
+ writing complex regex just to add a couple of filters. docker-orb streams
6
+ logs from every container in your selected services into one merged,
7
+ colorized view — and lets you filter, highlight, and search *while it's
8
+ streaming*.
9
+
10
+ Built with [Textual](https://textual.textualize.io/), docker-orb is a full
11
+ terminal UI: an interactive setup wizard walks you through picking a
12
+ project, services, and filter patterns — no flags required — or skip
13
+ straight to the viewer with CLI arguments if you prefer. Save named session
14
+ configs to reload your exact setup later; passively collect rare events in
15
+ a monitor panel without losing your scroll position; get alerted when
16
+ containers restart or go unhealthy; and add or remove services from the
17
+ live stream without restarting.
18
+
19
+ ![docker-orb viewer](docs/screenshot-viewer.png)
20
+
21
+ ## Features
22
+
23
+ - **Multi-container live tail** — stream logs from any number of
24
+ containers/services at once, each with a distinct color.
25
+ - **Filters** — hide lines matching a pattern, live-editable mid-session.
26
+ - **Highlights** — emphasize lines matching a pattern without hiding anything else.
27
+ - **Monitors** — passively collect matching lines into a separate panel so you
28
+ can watch for rare events (e.g. `job failed`) without losing your scroll
29
+ position in the main stream.
30
+ - **Live search** — search the whole buffered session, jump to a result, and
31
+ keep streaming.
32
+ - **Container health panel** — flags containers that aren't `Running` or have
33
+ crossed a restart threshold; restart a container or recreate a service from
34
+ inside the app.
35
+ - **Dump mode** — fetch existing logs once (with `--tail`/`--since`) and exit,
36
+ for scripting or one-off inspection, instead of a live stream.
37
+ - **Saved configs** — save a named combination of project, services, and
38
+ patterns, and reload it later by name.
39
+ - **JSON log formatting** — auto-detects structured JSON log lines and shows
40
+ `time LEVEL message key=value ...` instead of a raw JSON blob, with a
41
+ toggle back to raw and a detail view (Enter on a clicked line) for the full
42
+ pretty-printed object.
43
+ - **Collapse repeated lines** — journalctl-style: consecutive identical lines
44
+ from the same container fold into a single "last line repeated N times"
45
+ marker, toggleable, so a crash-looping container doesn't flood the stream.
46
+
47
+ ## Installation
48
+
49
+ Requires Python 3.10+, and `docker` with the Compose v2 plugin on your
50
+ `PATH` (i.e. `docker compose` works). docker-orb shells out to your existing
51
+ `docker` CLI and inherits its context/auth — no separate credentials or
52
+ Docker SDK involved.
53
+
54
+ ```bash
55
+ # Recommended — pipx keeps CLI tools in isolated environments. Not on PyPI
56
+ # yet, so install straight from GitHub:
57
+ pipx install git+https://github.com/adlidev/docker-orb
58
+
59
+ # Or with plain pip, inside your own venv:
60
+ git clone https://github.com/adlidev/docker-orb.git
61
+ cd docker-orb
62
+ pip install -e .
63
+ ```
64
+
65
+ This installs two commands: `docker-orb` and `docker-orb-inject` (a small
66
+ test utility for injecting fake log lines into a running container — see
67
+ the [User Guide](docs/USER_GUIDE.md#docker-orb-inject)).
68
+
69
+ **For development / contributing:**
70
+
71
+ ```bash
72
+ git clone https://github.com/adlidev/docker-orb.git
73
+ cd docker-orb
74
+ pip install -e . --group dev
75
+ ```
76
+
77
+ ## Quick start
78
+
79
+ ```bash
80
+ # No arguments — launches the interactive setup wizard
81
+ docker-orb
82
+
83
+ # Skip the wizard: watch two services live
84
+ docker-orb -n myapp -p api -p worker
85
+
86
+ # Watch every service in a project
87
+ docker-orb -n myapp --all-containers
88
+
89
+ # One-shot dump instead of a live stream
90
+ docker-orb -n myapp --dump --tail 500
91
+
92
+ # Pre-filter/highlight from the command line
93
+ docker-orb -n myapp -p worker -f DEBUG -H ERROR --health
94
+ ```
95
+
96
+ `-n/--project` takes the Compose project name (what `docker compose -p`
97
+ expects — usually the directory name your `docker-compose.yml` lives in,
98
+ unless overridden by a top-level `name:` key or `COMPOSE_PROJECT_NAME`). If
99
+ omitted, docker-orb resolves it the same way `docker compose` does for the
100
+ current directory.
101
+
102
+ Once you're in the viewer, press `F` / `H` / `M` to edit filters, highlights,
103
+ or monitors live, `/` to search, `P` to add/remove streamed services, and
104
+ `Space` to pause. See the [User Guide](docs/USER_GUIDE.md) for the full
105
+ keybinding reference and pattern syntax.
106
+
107
+ ## Development
108
+
109
+ ```bash
110
+ pip install -e . --group dev
111
+ pytest # run the test suite
112
+ textual run --dev src/docker_orb/__main__.py # live-reload dev mode
113
+ ```
114
+
115
+ A local Compose stack with 8 fake log-generating services is included for
116
+ manual testing:
117
+
118
+ ```bash
119
+ cd infra
120
+ make up
121
+ docker-orb -n logviewer-demo --all-containers --health
122
+ ```
123
+
124
+ See [`infra/README.md`](infra/README.md) for the service list and good
125
+ filter/monitor test patterns, and [`CLAUDE.md`](CLAUDE.md) for architecture
126
+ notes.
127
+
128
+ ## Relationship to kube-orb
129
+
130
+ docker-orb is a sibling project to [kube-orb](https://github.com/adlidev/kube-orb),
131
+ Adli's Kubernetes-flavored log viewer. They share a UI architecture (Textual
132
+ viewer, wizard, filters/highlights/monitors, JSON formatting) but each talks
133
+ to its own backend directly — docker-orb shells out to `docker`/`docker
134
+ compose`, kube-orb shells out to `kubectl` — and they're maintained as
135
+ independent tools rather than one project trying to do both.
136
+
137
+ ## License
138
+
139
+ [MIT License](LICENSE)