Commit graph

54 commits

Author SHA1 Message Date
b46d6b24d4 Add .gitignore for .claude/ session data
All checks were successful
CI / shellcheck (push) Successful in 16s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 02:10:26 -07:00
1c50738ebc updated tapes
All checks were successful
CI / shellcheck (push) Successful in 18s
2026-03-02 02:08:07 -07:00
6e2aaf99f6 Fix VHS quoting and make tape test runner Hide-aware
Sequential cleanup commands fixed the VHS parse error but exposed
a deeper issue: the test runner was blind to Hide/Show blocks,
so cleanup commands ran as tests and could delete jobs mid-sequence.

- test-tapes.sh now reads tapes line-by-line tracking Hide/Show state;
  only Type lines in visible (Show) blocks are executed as tests
- Pre-clean named jobs from each tape at start of run_tape to handle
  leftovers from previously failed runs (mirrors what the Hide cleanup
  does when VHS records the tape)
- 19 tape commands tested (cleanup commands correctly excluded)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 01:58:25 -07:00
4413f2229d Add justfile task runner
Recipes: check (lint+test+tape-test), lint, test, tape-test, record.
`just` with no args lists all recipes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 01:46:14 -07:00
b72a95f4ed Refresh demo tapes: retire editmode, update commands, improve quickstart
- Remove editmode.tape; quickstart now takes the editmode.png screenshot
  and demonstrates adding a new job in edit mode (new:n=diskcheck_home)
- healthcheck_home uses 'uptime', monitor_home uses 'ping -c 1 localhost'
- all-features one-time reminder gains -i (desktop notification example)
- 19 tape commands total (was 24)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 01:34:20 -07:00
530a2162bf Add -R restart operation for timer and service jobs
Resets the countdown for timer jobs and restarts the process for
service jobs. Disabled jobs are refused with a clear error message.
Accepts hex ID or name like all other management operations.

- restartJob() function with disabled-job guard
- getopts R:, manage_count, mutual-exclusion error messages updated
- 9 new tests in test.sh (112 total), 1 new tape command (24 total)
- README options table, names prose, and future-ideas checklist updated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 01:17:12 -07:00
8e45f7917c Add -X delete operation, demo tape tests, and consolidate demos
- Add -X <id|name> to stop, disable, and remove a job's unit files;
  mutually exclusive with all other management options; 13 new tests
- Add demo/test-tapes.sh to verify all VHS tape commands run cleanly;
  wired into pre-commit hook alongside test.sh (combined badge count)
- Rename demo job names to *_home variants to avoid clashing with real
  user jobs; add per-tape preflight cleanup via -X
- Consolidate four demo GIFs into quickstart + all-features + editmode
  screenshot; remove notifications/services tapes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 01:02:13 -07:00
16404fb596 moving edit mode up and adding service example
All checks were successful
CI / shellcheck (push) Successful in 16s
2026-03-01 00:38:39 -07:00
3ebe0cf5bf correct edit-mode example
All checks were successful
CI / shellcheck (push) Successful in 20s
2026-03-01 00:24:30 -07:00
87b13d590d add codeberg mirror and future ideas
All checks were successful
CI / shellcheck (push) Successful in 18s
2026-03-01 00:15:01 -07:00
0943a639cc Add -l tests, update editmode tape, fix service schedule pattern
All checks were successful
CI / shellcheck (push) Successful in 20s
5 new tests for -l: service job presence, timer job presence, pipe
alignment, and mutual exclusivity checks. Fix | service | pattern in
edit mode test to handle alignment padding. Add -l demo step to
editmode.tape before opening the editor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 01:45:44 -07:00
8368f1dcf7 Add -l option and align pipe separators in edit mode
Extract printCrontabContent() shared by both -e and new -l, collecting
job data into arrays first so column widths can be computed for aligned
pipe separators. -l prints the same crontab format to stdout without
opening an editor, useful for scripting and quick inspection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 00:26:40 -07:00
57d2c38d3c Fix badge cache purge by using GitHub API instead of scraping page HTML
All checks were successful
CI / shellcheck (push) Successful in 16s
GitHub's repository page is JS-rendered, so curl gets a skeleton without
README images. Use the rendered README API endpoint instead, which returns
actual HTML including camo-proxied image URLs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 23:08:29 -07:00
28170d02d0 remove some examples and add a banner
All checks were successful
CI / shellcheck (push) Successful in 18s
2026-02-24 21:17:25 -07:00
041f893242 Rename all functions to camelCase
All checks were successful
CI / shellcheck (push) Successful in 17s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 20:22:20 -07:00
b71ef735af Update README to document name display in notifications
All checks were successful
CI / shellcheck (push) Successful in 16s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 19:45:15 -07:00
6ea5b7f849 Show job name in notifications via dynamic runtime lookup
All checks were successful
CI / shellcheck (push) Successful in 17s
Instead of embedding the name as a literal string at job creation time,
ExecStopPost now greps # SYSTAB_NAME= from the service file at runtime.
This ensures notifications always show the current name even for jobs
created without a name or renamed after their ExecStopPost was written.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 19:33:50 -07:00
90f188491d Fix CI badge cache purge failing when no camo URLs found
All checks were successful
CI / shellcheck (push) Successful in 18s
With pipefail enabled, grep exiting 1 on no matches fails the step.
Add xargs -r and || true so the purge is best-effort only.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 17:54:41 -07:00
fe272eb0b0 cleanup and optimizations
Some checks failed
CI / shellcheck (push) Failing after 17s
2026-02-24 17:25:50 -07:00
c69d857966 Update CLAUDE.md for service job support
Some checks failed
CI / shellcheck (push) Failing after 17s
Document the -s flag, SYSTAB_TYPE=service marker, service vs timer
branching in _write_unit_files, get_managed_service_jobs,
is_job_service, daemon-reload ordering, ActiveState/SubState status
display, the 's' flag in parse_flags/build_flags_string, and the
updated test count (81).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 01:16:44 -07:00
e407597d2b Update README for service job support
Some checks failed
CI / shellcheck (push) Failing after 18s
Document the new -s flag, add services demo GIF to the demo table,
add quick start and usage examples for persistent services, update
edit mode docs with the new:s syntax, and clarify how it works for
both timer and service job types.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 01:12:55 -07:00
164087ab22 Add persistent service jobs (-s flag)
Some checks failed
CI / shellcheck (push) Failing after 19s
Introduces a new job type for long-running systemd user services alongside
the existing timer-based jobs. Services use Type=simple with Restart=on-failure
and WantedBy=default.target — no .timer unit is created.

- New -s flag creates a service job; mutually exclusive with -t/-i/-m/-o
- Service jobs tagged with # SYSTAB_TYPE=service in their unit file
- enable/disable (-E/-D) start/stop the service in addition to toggling
  the enabled state, mirroring timer behaviour
- -S status shows ActiveState/SubState from systemd directly (avoids
  false "Inactive" for services in activating state)
- -L logs, -e edit mode, -D/-E disable/enable all handle service jobs
- Edit mode represents service jobs with 'service' as the schedule column
  (e.g. new:s,n=name | service | /path/to/cmd)
- daemon-reload runs before enable/start during service creation so
  systemd registers the new unit file first
- 22 new tests covering unit file contents, active state, disable/enable,
  named services, edit mode representation, and flag conflict errors
- New demo/services.tape and regenerated demo GIFs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 01:00:07 -07:00
2b75547726 a note on thhe crontab format
Some checks failed
CI / shellcheck (push) Failing after 16s
2026-02-17 14:02:48 -07:00
1655a64ab3 Add emoji icons to feature list and fix typos in README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 13:57:34 -07:00
8a3939bf11 purge github mirror badge
Some checks failed
CI / shellcheck (push) Failing after 16s
2026-02-16 20:36:13 -07:00
f393941a37 try image with node
All checks were successful
CI / shellcheck (push) Successful in 14s
2026-02-16 09:20:45 -07:00
972178ad1c used forgejo checkout
Some checks failed
CI / shellcheck (push) Failing after 2s
2026-02-16 09:13:34 -07:00
be47247da7 Fix test cleanup destroying user jobs, consolidate code
Some checks failed
CI / shellcheck (push) Failing after 2s
- Test cleanup now only removes jobs it created (tracked via
  test_job_ids array) instead of nuking all systab_* units.
  Fixes bug where running tests would delete real user jobs.
- Fix extract_id subshell issue: array appends in $() don't
  propagate to parent, so use _extracted_id variable instead.
- Merge disable_job_by_id/enable_job_by_id into toggle_job_by_id.
- Update usage text: -D/-E/-L/-S now show <id|name> consistently.
- Fix pre-commit hook sed regex that only captured last digit of
  multi-digit numbers; replaced with grep -oP.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 21:55:09 -07:00
96d7d6179a adding demo gifs
Some checks failed
CI / shellcheck (push) Failing after 2s
2026-02-15 12:32:16 -07:00
f4cb6c77f6 adding tests
Some checks are pending
CI / shellcheck (push) Waiting to run
2026-02-15 12:10:09 -07:00
3aa7f9e722 adding badges
Some checks are pending
CI / shellcheck (push) Waiting to run
2026-02-15 11:26:27 -07:00
7673787736 adding license 2026-02-15 10:39:38 -07:00
19ccb76235 fixing timesting examples and stripping "at" 2026-02-15 10:15:52 -07:00
f32bf5495b adding name option 2026-02-15 10:11:26 -07:00
308f9e6b11 adding FAQ with -f/-c 2026-02-15 01:21:27 -07:00
558d4046cd adding demo gifs 2026-02-15 00:58:11 -07:00
8319924139 Rename pause/resume to disable/enable to align with systemd terminology
-P/-R flags become -D/-E, -E (edit) becomes -e. Functions renamed to
disable_job_by_id/enable_job_by_id. Output messages, docs, tests, and
demo tapes updated accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:41:21 -07:00
e636ea323c Add gum-styled annotations and less paging to VHS demo tapes
Annotations use demo/note.sh (gum style with clear) wrapped in
Hide/Show so only the styled box appears. Long output commands
pipe through less with search to highlight key fields.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:12:42 -07:00
d19709dc1f Add automated test suite for systab
44 tests covering job creation, status, logs, pause/resume,
notifications, time format parsing, error cases, and cleanup.
Tests run against real systemd user timers with automatic cleanup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 22:50:17 -07:00
32ac2c3d5f Fix "in N minutes" parsing and VHS tape errors
- Strip "in " prefix before passing to date -d (was always broken)
- Fix quickstart tape: -B3 → -B4 for resume grep (Job: is 4 lines back)
- Fix notifications tape: -f ~/backup.sh → -c (file doesn't exist)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 22:24:06 -07:00
8781ac9f2f Refactor: deduplicate notifications, fix timer parsing, -o optional arg
- Extract build_job_list helper (shared by show_status/list_logs)
- clean_jobs now calls remove_job instead of inline stop/disable/rm
- Extract status preamble in write_notify_lines (icon_pre/status_pre)
- Replace fragile list-timers tail/awk with systemctl show properties
- Combine consecutive sed -i calls into single invocations
- Simplify is_manage_mode check to use existing manage_count
- Make -o accept optional line count arg (-o 20 or just -o for default 10)
- Fix %%s escaping in unit files and document in CLAUDE.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 21:49:18 -07:00
67528374cd Add -o flag to include job output in notifications
Fetches the last N lines of journal output (default 10) via
journalctl and includes them in desktop/email notification bodies.
Supports CLI (-o 5) and edit mode (o or o=5 flag syntax).

Also fixes systemd %s specifier expansion in email printf format
strings (must use %%s so systemd passes %s through to the shell).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 16:35:52 -07:00
c3c534f7ce Auto-detect sendmail/msmtp for email notifications
Resolve the mailer binary at job creation time and bake the full path
into the service file, so it works regardless of PATH in the systemd
service environment. Warns and skips if neither is found.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 15:51:31 -07:00
98b180a912 Refactor: deduplicate and simplify systab
Merge get_managed_services/get_managed_timers into get_managed_units
with a type parameter, drop unnecessary seen array. Extract shared
_write_unit_files core from create_job and create_job_from_edit. Add
get_job_command helper to replace triple-sed command extraction (3
call sites). Deduplicate list-timers call in show_status. Replace
rg/grep pipe in list_logs with journalctl --grep. Remove redundant
-h pre-scan loop in main. Net -97 lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 15:45:28 -07:00
ef442d464c Add status-aware notifications, edit mode flags, job ID filtering
Notifications now use ExecStopPost (fires on success and failure) with
status-aware icons/messages instead of ExecStartPost (success only).
Desktop uses dialog-information/dialog-error, email uses sendmail.
Flags (i, e=addr) are persisted as # SYSTAB_FLAGS= comments in service
files and exposed in edit mode via ID:flags syntax. Edit mode validates
schedules before applying (re-edit loop like crontab -e). -S and -L
accept an optional job ID to filter to a single job. Extract trim()
helper to replace inline whitespace-stripping idiom.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 14:43:06 -07:00
37efa43d0a first functional commit 2026-02-14 11:34:00 -07:00
5e961d70f4 Use short ID as unit filename instead of timestamp
Unit files are now named systab_<6-char-hex> (e.g., systab_a1b2c3),
so the ID is derived from the filename — no more SYSTAB_ID comments
in unit files, no id-to-jobname mappings in edit mode. Removes
generate_job_name, get_job_id, get_job_by_id, ensure_job_id.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 00:22:51 -07:00
b7e6a77ef5 Accept spaces or tabs as field separators in edit mode
Parse crontab lines by splitting on the first two whitespace
boundaries via regex, so both spaces and tabs work as delimiters.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 00:02:20 -07:00
661baf6c16 Add schedule format examples to edit mode header
Shows common OnCalendar patterns (hourly, every 15 min, specific
times, day-of-week) so users know what formats are available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 23:25:11 -07:00
a231bc63e9 Fix edit mode job creation and unique name generation
- Handle multiple "new" lines in edit mode by collecting them in an
  array instead of an associative array (which collapsed duplicates)
- Use random hex suffix in job names instead of PID, avoiding
  collisions when multiple jobs are created in the same second
- Fix trap variable scoping in edit_jobs()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 23:22:08 -07:00