|
1 | 1 | # Something in the Background |
2 | 2 |
|
3 | | -A lightweight native macOS utility for running scripts and commands in the background - powered by Rust. |
4 | | - |
5 | | -`something_bg` is a tiny menu/tray app (macOS, Linux, Windows) designed to take any script or command you already use and run it quietly in the background. No terminals to keep open, no remembering where scripts live, no complicated setup. |
6 | | - |
7 | | -If you’ve ever left a Terminal window open _“just to keep a command running”_, this app is for you. |
| 3 | +A native menu bar utility for managing background processes, SSH tunnels, and scheduled tasks. |
8 | 4 |
|
9 | 5 | <img src="something_bg_menu.png" alt="Menu Bar Screenshot" width="600"> |
10 | 6 |
|
11 | | -## Repository layout |
12 | | - |
13 | | -- `core/` — platform-agnostic logic (config, scheduler, tunnel management). |
14 | | -- `app-macos/` — macOS shell (tray UI, oslog, wake detection) that links to `core`. |
15 | | -- `app-linux/` — Linux tray shell that links to `core`. |
16 | | -- `app-windows/` — Windows tray shell that links to `core`. |
17 | | - |
18 | 7 | ## Features |
19 | 8 |
|
20 | | -- Tiny native macOS app with a Rust core (less than 1MB) |
21 | | -- Run any script or CLI task without keeping a terminal open |
22 | | -- Run scripts on a schedule without cron, or launchd |
23 | | -- Controlled from the menu bar |
24 | | -- Everything is configured with one simple config file |
| 9 | +- Run SSH tunnels, port forwards, and development servers without keeping terminals open |
| 10 | +- Schedule tasks using cron syntax |
| 11 | +- Toggle services on/off from the menu bar |
| 12 | +- Cross-platform support (macOS, Linux, Windows) |
| 13 | +- Lightweight (<1MB) with simple configuration |
25 | 14 |
|
26 | 15 | ## Installation |
27 | 16 |
|
28 | | -### macOS (native bundle) |
29 | | - |
30 | | -Prereqs: |
31 | | -- Rust and Cargo (install via [rustup](https://rustup.rs/)) |
32 | | -- Xcode Command Line Tools |
33 | | -- cargo-bundle (`cargo install cargo-bundle`) |
| 17 | +### macOS |
34 | 18 |
|
35 | | -1. Clone the repository: |
| 19 | +**Step 1: Install Rust** (skip if already installed) |
36 | 20 | ```bash |
37 | | -git clone https://github.com/vim-zz/something_bg.git |
38 | | -cd something_bg |
| 21 | +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
| 22 | +source $HOME/.cargo/env |
39 | 23 | ``` |
40 | 24 |
|
41 | | -2. Build and bundle the macOS application (uses the macOS crate manifest so icons/identifier are applied): |
| 25 | +**Step 2: Install build tools** |
42 | 26 | ```bash |
43 | | -./scripts/bundle-macos.sh |
| 27 | +xcode-select --install |
| 28 | +cargo install cargo-bundle |
44 | 29 | ``` |
45 | 30 |
|
46 | | -3. Install or run |
| 31 | +**Step 3: Build and install** |
47 | 32 | ```bash |
48 | | -# run from build location |
49 | | -open "target/release/bundle/osx/Something in the Background.app" |
50 | | -# or install |
| 33 | +git clone https://github.com/vim-zz/something_bg.git |
| 34 | +cd something_bg |
| 35 | +./scripts/bundle-macos.sh |
51 | 36 | cp -r "target/release/bundle/osx/Something in the Background.app" /Applications/ |
52 | 37 | ``` |
53 | 38 |
|
54 | | -### Linux (tray shell) |
| 39 | +Launch from Applications or run: `open "/Applications/Something in the Background.app"` |
55 | 40 |
|
56 | | -Prereqs (Ubuntu/Debian): |
57 | | -```bash |
58 | | -sudo apt install libayatana-appindicator3-dev libgtk-3-dev |
59 | | -``` |
| 41 | +### Linux |
60 | 42 |
|
61 | | -Run the tray app: |
| 43 | +**Prerequisites** (Ubuntu/Debian): |
62 | 44 | ```bash |
63 | | -cargo run -p something_bg_linux |
| 45 | +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
| 46 | +source $HOME/.cargo/env |
| 47 | +sudo apt install libayatana-appindicator3-dev libgtk-3-dev |
64 | 48 | ``` |
65 | 49 |
|
66 | | -You’ll get a status icon in the system tray: |
67 | | -- Click tunnels to toggle them on/off (checkboxes reflect state) |
68 | | -- “Run now” under each scheduled task runs it immediately |
69 | | -- “Open config folder” opens `~/.config/something_bg/` |
70 | | -- “Quit” cleans up tunnels and stops the scheduler |
71 | | - |
72 | | -#### Run cargo check in Docker (no local GTK deps needed) |
| 50 | +**Build and run**: |
73 | 51 | ```bash |
74 | | -./scripts/linux-cargo-check.sh |
| 52 | +git clone https://github.com/vim-zz/something_bg.git |
| 53 | +cd something_bg |
| 54 | +cargo run -p something_bg_linux --release |
75 | 55 | ``` |
76 | | -The script builds an Ubuntu-based image with GTK/AppIndicator dev packages and runs `cargo check -p something_bg_linux` inside it. Pass extra cargo args after the script if needed. |
77 | 56 |
|
78 | | -### Windows (tray shell, cross-compiling from macOS/Linux) |
| 57 | +### Windows |
79 | 58 |
|
80 | | -Prereqs: Docker. |
81 | | - |
82 | | -Cross-check/build with the bundled cargo-xwin image: |
83 | | -```bash |
84 | | -./scripts/windows-cargo-check.sh |
85 | | -``` |
86 | | -This builds `something_bg_windows` for `x86_64-pc-windows-msvc` using the Windows SDK bundled in the Docker image. Pass extra cargo args after the script if needed. |
87 | | - |
88 | | -To run on Windows natively, build on Windows with a Rust toolchain and the `tray-icon` deps: |
| 59 | +**Build on Windows**: |
89 | 60 | ```powershell |
| 61 | +# Install Rust from https://rustup.rs/ |
| 62 | +git clone https://github.com/vim-zz/something_bg.git |
| 63 | +cd something_bg |
90 | 64 | cargo build -p something_bg_windows --release |
| 65 | +.\target\release\something_bg_windows.exe |
91 | 66 | ``` |
92 | | -Then launch the produced `target\release\something_bg_windows.exe`. |
93 | 67 |
|
94 | 68 | ## Configuration |
95 | 69 |
|
96 | | -The app loads all menu items from `~/.config/something_bg/config.toml`. On first run, it creates this file with example configurations. |
| 70 | +Configuration is stored in `~/.config/something_bg/config.toml` (created on first run). |
97 | 71 |
|
98 | | -### Example Configuration |
| 72 | +### Example |
99 | 73 |
|
100 | 74 | ```toml |
101 | | -# Custom PATH for command execution |
102 | 75 | path = "/bin:/usr/bin:/usr/local/bin:/opt/homebrew/bin" |
103 | 76 |
|
104 | | -[tunnels] |
105 | | - |
106 | | -# SSH tunnel with port forwarding |
107 | | -[tunnels.database-prod] |
108 | | -name = "PROD" |
| 77 | +# SSH tunnel |
| 78 | +[tunnels.database] |
| 79 | +name = "Database (PROD)" |
109 | 80 | command = "ssh" |
110 | 81 | args = ["-N", "-L", "5432:localhost:5432", "user@server.com"] |
111 | 82 | kill_command = "pkill" |
112 | 83 | kill_args = ["-f", "user@server.com"] |
113 | | -group_header = "DATABASE" # Optional: Section header |
114 | | -group_icon = "sf:cylinder.fill" # Optional: SF Symbol icon |
115 | | - |
116 | | -[tunnels.database-dev] |
117 | | -name = "DEV" |
118 | | -command = "ssh" |
119 | | -args = ["-N", "-L", "5432:localhost:5432", "dev@server.com"] |
120 | | -kill_command = "pkill" |
121 | | -kill_args = ["-f", "dev@server.com"] |
122 | | -separator_after = true # Optional: Add separator after this item |
| 84 | +group_header = "DATABASE" |
| 85 | +group_icon = "sf:cylinder.fill" |
123 | 86 |
|
124 | | -# Kubernetes port forwarding |
| 87 | +# Port forwarding |
125 | 88 | [tunnels.k8s-service] |
126 | | -name = "Service" |
| 89 | +name = "API Service" |
127 | 90 | command = "kubectl" |
128 | | -args = ["port-forward", "svc/my-service", "8080:8080"] |
| 91 | +args = ["port-forward", "svc/api", "8080:8080"] |
129 | 92 | kill_command = "pkill" |
130 | | -kill_args = ["-f", "svc/my-service"] |
| 93 | +kill_args = ["-f", "svc/api"] |
131 | 94 | group_header = "KUBERNETES" |
132 | | -group_icon = "sf:cloud.fill" |
133 | | - |
134 | | -# Development server |
135 | | -[tunnels.dev-server] |
136 | | -name = "Dev Server" |
137 | | -command = "npm" |
138 | | -args = ["run", "dev"] |
139 | | -kill_command = "pkill" |
140 | | -kill_args = ["-f", "npm.*dev"] |
141 | | -group_header = "DEVELOPMENT" |
142 | | -group_icon = "sf:hammer.fill" |
143 | 95 | separator_after = true |
144 | 96 |
|
145 | | -[schedules.daily-backup] |
146 | | -name = "Daily Backup" |
147 | | -command = "/usr/local/bin/backup.sh" |
148 | | -args = [] |
149 | | -cron_schedule = "0 6 * * *" # Every day at 6:00 AM |
150 | | -group_header = "SCHEDULED TASKS" |
151 | | -group_icon = "sf:clock.fill" |
152 | | -``` |
153 | | - |
154 | | -### Configuration Fields |
155 | | - |
156 | | -**For Tunnels:** |
157 | | -- `name`: Display name in the menu |
158 | | -- `command` + `args`: Command to start the service |
159 | | -- `kill_command` + `kill_args`: Command to stop the service |
160 | | - |
161 | | -**For Scheduled Tasks:** |
162 | | -- `name`: Display name in the menu |
163 | | -- `command` + `args`: Command to execute |
164 | | -- `cron_schedule`: Cron expression for scheduling (e.g., "0 6 * * *") |
165 | | - |
166 | | -**Optional fields (both types):** |
167 | | -- `group_header`: Section title (e.g., "DATABASE", "SCHEDULED TASKS") |
168 | | -- `group_icon`: SF Symbol name for the header (e.g., "sf:cylinder.fill", "sf:clock.fill") |
169 | | -- `separator_after`: Add a visual separator line after this item |
170 | | - |
171 | | -### Scheduled Tasks |
172 | | - |
173 | | -Schedule commands to run automatically using cron syntax. Perfect for backups, health checks, or recurring maintenance tasks. |
174 | | - |
175 | | -```toml |
176 | | -[schedules.daily-backup] |
| 97 | +# Scheduled task |
| 98 | +[schedules.backup] |
177 | 99 | name = "Daily Backup" |
178 | 100 | command = "/usr/local/bin/backup.sh" |
179 | 101 | args = [] |
180 | | -cron_schedule = "0 6 * * *" # Every day at 6:00 AM |
181 | | -group_header = "SCHEDULED TASKS" |
| 102 | +cron_schedule = "0 6 * * *" |
| 103 | +group_header = "SCHEDULED" |
182 | 104 | group_icon = "sf:clock.fill" |
183 | | - |
184 | | -[schedules.hourly-health-check] |
185 | | -name = "API Health Check" |
186 | | -command = "curl" |
187 | | -args = ["-f", "https://api.example.com/health"] |
188 | | -cron_schedule = "0 * * * *" # Every hour |
189 | | - |
190 | | -[schedules.weekly-cleanup] |
191 | | -name = "Weekly Cleanup" |
192 | | -command = "/usr/local/bin/cleanup.sh" |
193 | | -args = ["--deep"] |
194 | | -cron_schedule = "0 3 * * 0" # Every Sunday at 3:00 AM |
195 | | -separator_after = true |
196 | 105 | ``` |
197 | 106 |
|
198 | | -**Cron Schedule Format:** `minute hour day_of_month month day_of_week` |
199 | | - |
200 | | -Common examples: |
201 | | -- `0 * * * *` - Every hour |
202 | | -- `*/15 * * * *` - Every 15 minutes |
203 | | -- `0 6 * * *` - Every day at 6:00 AM |
204 | | -- `0 9 * * 1` - Every Monday at 9:00 AM |
205 | | -- `0 0 1 * *` - First day of every month at midnight |
206 | | - |
207 | | -### SF Symbols |
208 | | - |
209 | | -Group icons use SF Symbols (built-in macOS icons). Common symbols: |
210 | | -- `sf:cylinder.fill` - Database |
211 | | -- `sf:shippingbox.fill` - Cache/Redis |
212 | | -- `sf:chart.bar.fill` - Analytics |
213 | | -- `sf:cloud.fill` - Cloud/Kubernetes |
214 | | -- `sf:server.rack` - Server |
215 | | -- `sf:network` - Network |
216 | | -- `sf:clock.fill` - Scheduled tasks |
217 | | -- `sf:calendar` - Time-based operations |
| 107 | +### Fields |
| 108 | + |
| 109 | +**Tunnels** (toggleable services): |
| 110 | +- `name` — Display name |
| 111 | +- `command`, `args` — Start command |
| 112 | +- `kill_command`, `kill_args` — Stop command |
| 113 | +- `group_header` _(optional)_ — Section title |
| 114 | +- `group_icon` _(optional)_ — SF Symbol (e.g., `sf:cylinder.fill`) |
| 115 | +- `separator_after` _(optional)_ — Add separator |
| 116 | + |
| 117 | +**Schedules** (cron jobs): |
| 118 | +- `name` — Display name |
| 119 | +- `command`, `args` — Command to run |
| 120 | +- `cron_schedule` — Cron expression (`minute hour day month weekday`) |
| 121 | + |
| 122 | +**Common cron patterns**: |
| 123 | +- `0 * * * *` — Every hour |
| 124 | +- `*/15 * * * *` — Every 15 minutes |
| 125 | +- `0 6 * * *` — Daily at 6am |
| 126 | +- `0 9 * * 1` — Mondays at 9am |
| 127 | + |
| 128 | +### SF Symbols (macOS icons) |
| 129 | + |
| 130 | +Common symbols for `group_icon`: |
| 131 | +- `sf:cylinder.fill` — Database |
| 132 | +- `sf:shippingbox.fill` — Cache/Redis |
| 133 | +- `sf:cloud.fill` — Cloud/Kubernetes |
| 134 | +- `sf:server.rack` — Server |
| 135 | +- `sf:network` — Network |
| 136 | +- `sf:clock.fill` — Scheduled tasks |
| 137 | +- `sf:hammer.fill` — Development |
218 | 138 |
|
219 | 139 | Browse all symbols at [developer.apple.com/sf-symbols](https://developer.apple.com/sf-symbols/) or use the SF Symbols app. |
220 | 140 |
|
221 | | -Restart the app to pick up configuration changes. |
| 141 | +Restart the app after editing the config. |
222 | 142 |
|
223 | 143 | ## License |
224 | 144 |
|
|
0 commit comments