apple-ai-reporter-agent/
agent/
__init__.py
gemini.py
main.py
moss_client.py
photo3d_job.py
supplement.py
transcribe_skill.py
scripts/
migrate_to_icloud.py
de.grasshoff.apple-ai-reporter-agent.plist
install.sh
PROJECT.yaml
README.md
requirements.txt
run.sh
[DRAFT — edit this] **iCloud-native backend for the ai-reporter ecosystem.** Inferred stage: development. Define the specific deliverable, success state, and timeline.
Success criteria:| Code | /Users/friedrichstr/ai-mac-studio/apps/apple-ai-reporter-agent |
| Check | Path | Status | Detail |
|---|---|---|---|
| code | /Users/friedrichstr/ai-mac-studio/apps/apple-ai-reporter-age | ✓ ok | 11 items, last_modified=2026-08-24 |
iCloud-native backend for the ai-reporter ecosystem.
This agent replaces the old FastAPI/uvicorn stack (ai-kanzlei, ai-desktop).
It runs as a macOS LaunchAgent, watches a single iCloud folder, and performs
only the work that cannot happen on-device: Gemini transcription and
Gemini-based supplement generation.
iCloud Drive handles every other sync detail across iPhone, Mac app, and this agent. There is no HTTP server, no DuckDB, no port to manage.
iCloud Drive
└── Apple AI Reporter/ (= ~/Library/Mobile Documents/iCloud~de~grasshoff~apple-ai-reporter/Documents/)
├── Reports/<uuid>/
│ ├── report.json
│ ├── records/<uuid>/{audio.m4a, record.json, transcript.xml, photos/, videos/, supplements/}
│ └── supplements/
├── Skills/<skill_id>/{prompt.md, skill.json, display.html}
├── Inbox/
│ ├── transcribe/<job_id>.json
│ ├── supplement/<job_id>.json
│ └── .failed/ # jobs that errored — kept for inspection
└── Outbox/<job_id>.done.json
Clients (iPhone, Mac app) write a job into Inbox/transcribe/ or
Inbox/supplement/. The agent picks it up, runs the LLM, writes the
result into the right Reports/<uuid>/.../transcript.xml (or supplement
file), updates the relevant manifest (record.json / report.json),
and removes the job.
{
"job_id": "3f7a8b21-…",
"kind": "transcribe",
"report_uuid": "8C50714E-…",
"record_uuid": "1234abcd-…",
"audio_path": "Reports/8C507…/records/1234abcd-…/audio.m4a",
"params": {
"language": "de-DE",
"diarize": true,
"instruction": null,
"model": "gemini-3.8-flash"
},
"requested_by": "iPhone:iPhonegg",
"requested_at": "2026-05-19T15:55:00Z"
}
Result: Reports/<report_uuid>/records/<record_uuid>/transcript.xml is
written; record.json gains transcript_quality: "gemini" and a
transcript_updated_at timestamp.
{
"job_id": "5a02c14e-…",
"kind": "supplement",
"report_uuid": "8C50714E-…",
"record_uuid": "1234abcd-…", // omit for report-level supplements
"skill_id": "summarize",
"params": {},
"requested_by": "iPhone:iPhonegg",
"requested_at": "2026-05-19T15:55:00Z"
}
Result: a new XML file under …/records/<record>/supplements/<job_id>.xml
(or …/<report>/supplements/<job_id>.xml for report-level). The relevant
manifest gets a supplements entry pointing at the new file.
cd /Users/friedrichstr/ai-mac-studio/apps/apple-ai-reporter-agent
# 1. Create .env with the Gemini key (re-uses the existing key)
cp .env.example .env # then edit if you want a different model
# 2. Try it in foreground first
./run.sh
# 3. Install as LaunchAgent (autostart at login)
./install.sh
# Logs land at ~/Library/Logs/apple-ai-reporter-agent.log
Inbox/.failed/<job>.json with a
sibling <job>.error.json that carries the error message. They are
kept for inspection; you can re-queue them by moving the JSON back
into Inbox/transcribe/ or Inbox/supplement/.This agent listens on no port. Clients never make HTTP calls. The filesystem under the iCloud container is the single source of truth. iCloud Drive carries every byte between devices.