# hamzatekin/pergent architecture

> Architecture diagram of the GitHub repository hamzatekin/pergent, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-26). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/hamzatekin/pergent
- Repository: https://github.com/hamzatekin/pergent

## Overview

pergent runs configured research tasks through a headless Claude agent, archives each run and presents the resulting morning paper in a web reader. The main workflow is task configuration → run preparation and fetching → agent-generated paper → optional rating → persisted run → rendered reading view; scheduling and an authenticated admin dashboard support that workflow. README capabilities also include manual runs, cost/log inspection, preview images, and an installable offline-capable reader. Some source excerpts are partial, so uncertain internal call links are omitted; documented fetch and optional rating integrations are shown separately.

Main entry points: [`src/runner.ts`](https://github.com/hamzatekin/pergent/blob/main/src/runner.ts) (Task runner), [`src/server.ts`](https://github.com/hamzatekin/pergent/blob/main/src/server.ts) (HTTP server), [`src/scheduler.ts`](https://github.com/hamzatekin/pergent/blob/main/src/scheduler.ts) (Cron scheduler), [`src/admin.ts`](https://github.com/hamzatekin/pergent/blob/main/src/admin.ts) (Admin dashboard)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_task["Task inputs"]
  node_taskdefs["Task prompts and config"]
  node_fetchers["Input fetchers"]
end

subgraph group_execution["Run execution"]
  node_runner["Task runner<br/>[runner.ts]"]
  node_scheduler["Cron scheduler<br/>[scheduler.ts]"]
  node_rating["Story rating<br/>[rate.ts]"]
  node_images["Preview images<br/>[images.ts]"]
end

subgraph group_storage["Run history"]
  node_db[("SQLite run index<br/>[db.ts]")]
  node_runfiles[("Run archive files")]
end

subgraph group_web["Reader and admin"]
  node_paper["Paper parser and renderer<br/>[paper.ts]"]
  node_server["HTTP server<br/>[server.ts]"]
  node_admin["Admin dashboard<br/>[admin.ts]"]
  node_browser["Reader browser app<br/>[app.js]"]
  node_serviceworker["Offline app shell<br/>[sw.js]"]
end

node_reader(("Reader"))
node_operator(("Task operator"))
node_research(("Research sources"))
node_claude{{"Claude subscription"}}
node_typesafe{{"TypeSafe Jev"}}

node_operator -->|"starts task"| node_runner
node_operator -->|"opens dashboard"| node_server
node_reader -->|"requests paper"| node_server
node_taskdefs -->|"configures run"| node_runner
node_runner -->|"runs fetch scripts"| node_fetchers
node_fetchers -.->|"fetches inputs"| node_research
node_runner -->|"executes prompt"| node_claude
node_runner -->|"writes run files"| node_runfiles
node_runner -->|"saves run index"| node_db
node_runner -.->|"rates paper"| node_rating
node_rating -.->|"requests scores"| node_typesafe
node_runner -.->|"adds previews"| node_images
node_scheduler -->|"starts scheduled runs"| node_runner
node_scheduler -->|"reads schedules"| node_taskdefs
node_scheduler -->|"reads and writes state"| node_db
node_server -->|"loads tasks and runs"| node_runner
node_server -->|"records read state"| node_db
node_server -->|"renders paper"| node_paper
node_server -->|"mounts dashboard"| node_admin
node_admin -->|"starts and inspects runs"| node_runner
node_admin -->|"reads logs"| node_runfiles
node_browser -->|"marks paper read"| node_server
node_browser -->|"registers worker"| node_serviceworker

click node_taskdefs "https://github.com/hamzatekin/pergent/tree/main/tasks"
click node_fetchers "https://github.com/hamzatekin/pergent/tree/main/scripts"
click node_runner "https://github.com/hamzatekin/pergent/blob/main/src/runner.ts"
click node_scheduler "https://github.com/hamzatekin/pergent/blob/main/src/scheduler.ts"
click node_rating "https://github.com/hamzatekin/pergent/blob/main/src/rate.ts"
click node_images "https://github.com/hamzatekin/pergent/blob/main/src/images.ts"
click node_paper "https://github.com/hamzatekin/pergent/blob/main/src/paper.ts"
click node_server "https://github.com/hamzatekin/pergent/blob/main/src/server.ts"
click node_admin "https://github.com/hamzatekin/pergent/blob/main/src/admin.ts"
click node_browser "https://github.com/hamzatekin/pergent/blob/main/web/app.js"
click node_serviceworker "https://github.com/hamzatekin/pergent/blob/main/web/public/sw.js"
click node_db "https://github.com/hamzatekin/pergent/blob/main/src/db.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_taskdefs,node_fetchers toneBlue
class node_runner,node_scheduler,node_rating,node_images toneAmber
class node_db,node_runfiles toneMint
class node_paper,node_server,node_admin,node_browser,node_serviceworker,node_operator toneRose
class node_reader,node_research,node_claude,node_typesafe toneIndigo
```

## Components

### Task inputs

- [Task prompts and config](https://github.com/hamzatekin/pergent/tree/main/tasks): `tasks`
- [Input fetchers](https://github.com/hamzatekin/pergent/tree/main/scripts): `scripts`

### Run execution

- [Task runner](https://github.com/hamzatekin/pergent/blob/main/src/runner.ts): `src/runner.ts`
- [Cron scheduler](https://github.com/hamzatekin/pergent/blob/main/src/scheduler.ts): `src/scheduler.ts`
- [Story rating](https://github.com/hamzatekin/pergent/blob/main/src/rate.ts): `src/rate.ts`
- [Preview images](https://github.com/hamzatekin/pergent/blob/main/src/images.ts): `src/images.ts`

### Run history

- [SQLite run index](https://github.com/hamzatekin/pergent/blob/main/src/db.ts): `src/db.ts`
- **Run archive files**

### Reader and admin

- [Paper parser and renderer](https://github.com/hamzatekin/pergent/blob/main/src/paper.ts): `src/paper.ts`
- [HTTP server](https://github.com/hamzatekin/pergent/blob/main/src/server.ts): `src/server.ts`
- [Admin dashboard](https://github.com/hamzatekin/pergent/blob/main/src/admin.ts): `src/admin.ts`
- [Reader browser app](https://github.com/hamzatekin/pergent/blob/main/web/app.js): `web/app.js`
- [Offline app shell](https://github.com/hamzatekin/pergent/blob/main/web/public/sw.js): `web/public/sw.js`

### Other components

- **Reader**
- **Task operator**
- **Research sources**
- **Claude subscription**
- **TypeSafe Jev**

## Connections

- Task operator → Task runner: starts task
- Task operator → HTTP server: opens dashboard
- Reader → HTTP server: requests paper
- Task prompts and config → Task runner: configures run
- Task runner → Input fetchers: runs fetch scripts
- Input fetchers → Research sources: fetches inputs
- Task runner → Claude subscription: executes prompt
- Task runner → Run archive files: writes run files
- Task runner → SQLite run index: saves run index
- Task runner → Story rating: rates paper
- Story rating → TypeSafe Jev: requests scores
- Task runner → Preview images: adds previews
- Cron scheduler → Task runner: starts scheduled runs
- Cron scheduler → Task prompts and config: reads schedules
- Cron scheduler → SQLite run index: reads and writes state
- HTTP server → Task runner: loads tasks and runs
- HTTP server → SQLite run index: records read state
- HTTP server → Paper parser and renderer: renders paper
- HTTP server → Admin dashboard: mounts dashboard
- Admin dashboard → Task runner: starts and inspects runs
- Admin dashboard → Run archive files: reads logs
- Reader browser app → HTTP server: marks paper read
- Reader browser app → Offline app shell: registers worker
