Skip to content

Repository files navigation

ship.md tray inventory watcher

ship cover

ship.md is the macOS menu bar app name and routing document name for this project. It watches a root folder called ship (recommended: ~/ship) and routes inventory files based on ship.md documents.

The interface is intentionally agent-native: places are folders, things are files, and moving a file expresses the intent to move its physical counterpart. That means an agent does not need a proprietary logistics protocol—it can use the filesystem operations it already understands.

What it does:

  • Watches a root folder called ship.
  • Prompts for location and email when a new direct child folder is created.
  • Treats any ship.md inside watched folders as routing context.
  • Reads inventory filenames and contacts from ship.md.
  • When a .zip file is dropped into a watched folder, it unzips it, inspects filenames, and moves matching inventory files.
  • When images are dropped, it sends the image plus all ship.md context to the Nous inference API.
  • If a text file says quantities like we have 10 apples, those quantities are indexed in SQLite and move with the file.
  • Uses tool-style movement actions: mv, sendUberDelivery, sendWhatsapp, sendEmail, makeCall, showToast.
  • Detects filesystem moves done by Finder or command line.
  • Writes audit trails to JSON.
  • Logs each configured email, WhatsApp, and call webhook as correlated webhook_attempted, webhook_succeeded, or webhook_failed audit events.
  • Indexes ## Webhook definitions from every ship.md in SQLite. Live file events invoke applicable webhooks from the root down to the nearest folder; startup backfills only index them.

Recommended paths:

  • Watched root: ~/ship (set SHIP_ROOT_PATH=~/ship; the legacy compatibility with CP_ROOT_PATH remains available)
  • Support/config: ~/ship/.ship/
  • Config, audit trail, inventory, and webhook index: ~/ship/.ship/inventory.db

On first launch, the app copies any missing demo files into ~/ship, then builds the SQLite config, inventory, and webhook tables from those files without firing webhooks. The audit table stays empty until activity happens after initialization. Every stored row is stamped with the same version as the installed macOS app.

Ask Codex to move a thing

After bootstrapping the demo, you can ask Codex in plain language:

Move the Spanish jersey to the office.

Codex can find the seeded clothes/spanish-jersey.png inventory file and perform the corresponding auditable move:

python3 -m ship mv ~/ship/clothes/spanish-jersey.png ~/ship/clothes/office/ \
  --message "Move the Spanish jersey to the office"

And it will. ship.md records the move, resolves the nearest manifests, updates inventory state, and invokes any delivery or notification actions configured for the route. The same workflow can start from Codex, Finder, a shell mv, or another program that manipulates the watched filesystem.

How Codex & GPT-5.6 were used

ship.md was designed and implemented with Codex powered by GPT-5.6. It was used throughout the project as both a coding collaborator and an operator:

  • Turning the filesystem-as-logistics idea into an implementation plan.
  • Inspecting and modifying the Python service, watcher, manifests, webhooks, and admin UI.
  • Writing regression tests and running them after changes.
  • Debugging the macOS app, PKG, DMG, uninstall, and reinstall flows.
  • Reviewing diffs and keeping the README aligned with the behavior of the app.
  • Operating ship.md directly—for example, moving the Spanish jersey to the office from a natural-language request.

The repeatable development workflow was treated as a Codex skill:

  1. Uninstall the currently installed macOS app.
  2. Build and reinstall the latest local version.
  3. Exercise the app and run its automated tests.
  4. Inspect the diff and draft a logical commit plan.
  5. Create the commits and push the branch.

This is also the product thesis in miniature: give an agent understandable files, clear Markdown context, and ordinary tools, and it can operate a useful real-world workflow without a bespoke UI.

ship.md format

Example:

# Warehouse ship.md

## Inventory
- laptop
- monitor
- contract

## Contacts
- email: ops@example.com
- whatsapp: +15551234567
- call: +15557654321

If an arriving file name matches one of the inventory items, ship.md can move it into that folder and notify contacts.

Webhook definitions may use ${ENV_VAR} for secrets and {{ context.* }}, {{ event.* }}, or {{ inventory }} templates. Authorization headers are redacted from audit logs.

Setup

cd ship
export SHIP_ROOT_PATH=~/ship
python3 -m pip install -r requirements.txt
python3 -m ship bootstrap
python3 -m ship location-endpoint warehouse-a   --email-endpoint https://example.com/email   --whatsapp-endpoint https://example.com/whatsapp   --call-endpoint https://example.com/call
python3 -m ship add-subscriber warehouse-a   --email ops@example.com   --whatsapp +15551234567   --phone +15557654321
python3 -m ship run

Build macOS installer

cd ship
make build

Useful targets:

make clean
make build
make reinstall

Artifacts:

  • dist/ship.md.app
  • dist/ship-md-installer.pkg
  • dist/ship-md-installer.dmg
  • dist/Uninstall ship.md.command

make reinstall will uninstall the current system app, install the freshly built package, and launch ship.md.

To distribute a disk image installer:

  • run make build
  • open dist/ship-md-installer.dmg
  • inside the mounted image, use Open Installer.command for a one-click install/reinstall
  • or double-click ship-md-installer.pkg directly
  • README.txt inside the mounted image explains install, reinstall, legacy receipt cleanup, and uninstall flow
  • scripts/reinstall-ship-md.command now prefers the DMG helper when dist/ship-md-installer.dmg is available

Commands

  • python3 -m ship bootstrap
  • python3 -m ship run
  • python3 -m ship headless
  • python3 -m ship show-config
  • python3 -m ship show-audit
  • python3 -m ship admin --host 127.0.0.1 --port 8765
  • python3 -m ship location-endpoint <location> --email-endpoint URL --whatsapp-endpoint URL --call-endpoint URL
  • python3 -m ship add-subscriber <location> --email you@example.com --whatsapp +1555... --phone +1555...
  • python3 -m ship mv <from> <to> --message "operator requested move"

Environment

  • HERMES_PORTAL_API_KEY for image recognition and movement-planning inference.
  • SHIP_ROOT_PATH to set the watched root (for example ~/ship). Legacy CP_ROOT_PATH is also still supported.
  • SHIP_SUPPORT_DIR or CP_SUPPORT_DIR to override config storage. By default, state is stored in .ship/ under the watched root.
  • SHIP_EMAIL_ENDPOINT / CP_EMAIL_ENDPOINT
  • SHIP_WHATSAPP_ENDPOINT / CP_WHATSAPP_ENDPOINT
  • SHIP_CALL_ENDPOINT / CP_CALL_ENDPOINT
  • SHIP_VISION_MODEL / CP_VISION_MODEL

Audit trail

The audit JSON includes events like:

  • folder_registered
  • ship_updated
  • zip_extracted
  • file_observed
  • movement_executed
  • service_started
  • service_stopped

Admin portal

The project includes a lightweight admin portal for operators to inspect runtime state.

Run it with:

python3 -m ship admin --host 127.0.0.1 --port 8765

Then open http://127.0.0.1:8765 in a browser.

Views:

  • Dashboard with summary counts and recent activity
  • Inventory table backed by inventory.db
  • Audit log viewer backed by the SQLite audit_events table
  • Config viewer backed by SQLite configuration tables

JSON endpoints:

  • /api/summary
  • /api/inventory
  • /api/logs
  • /api/config

Icons

The macOS app bundle and installer use:

  • ship/assets/ship-icon.icns as the app icon
  • ship/assets/ship-icon.png as the source render
  • ship/assets/trayTemplate.png as the monochrome menu bar icon

The tray icon is configured as a macOS template image so it adapts to light/dark menu bar appearances.

Uninstall

The macOS installer also ships an uninstaller:

  • /Applications/Uninstall ship.md.command
  • dist/Uninstall ship.md.command

Double-clicking it will:

  • prompt for confirmation
  • stop the running ship.md app if needed
  • remove /Applications/ship.md.app
  • forget the installer receipt com.boskykode.shipmd.pkg

It intentionally leaves support data in:

  • ~/ship/.ship/

That keeps audit logs and local state unless you remove them manually.

About

Move things in the real-world as easy as dropping files

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages