@aitne-sh/aitne 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/README.md +218 -161
  2. package/agent-assets/agent-profiles/_safety.md +3 -3
  3. package/agent-assets/agent-profiles/browser-task.md +108 -0
  4. package/agent-assets/agent-profiles/conversational.md +3 -3
  5. package/agent-assets/agent-profiles/profile-importer.md +2 -2
  6. package/agent-assets/agent-profiles/routine-fetch-window.md +30 -19
  7. package/agent-assets/agents/context-index-reconcile/agent.md +52 -0
  8. package/agent-assets/agents/evening-review/agent.md +53 -0
  9. package/agent-assets/agents/hourly-check/agent.md +62 -0
  10. package/agent-assets/agents/monthly-review/agent.md +55 -0
  11. package/agent-assets/agents/morning-routine/agent.md +78 -0
  12. package/agent-assets/agents/roadmap-maintenance/agent.md +52 -0
  13. package/agent-assets/agents/skill-curation/agent.md +52 -0
  14. package/agent-assets/agents/user-profile-sweep-evening/agent.md +48 -0
  15. package/agent-assets/agents/user-profile-sweep-morning/agent.md +53 -0
  16. package/agent-assets/agents/weekly-review/agent.md +51 -0
  17. package/agent-assets/docs/concepts/agent-day.md +13 -11
  18. package/agent-assets/docs/concepts/auth-health.md +47 -10
  19. package/agent-assets/docs/concepts/backends-and-tiers.md +66 -31
  20. package/agent-assets/docs/concepts/costs-and-quotas.md +50 -15
  21. package/agent-assets/docs/concepts/delegated-mode.md +52 -13
  22. package/agent-assets/docs/concepts/memory-model.md +72 -32
  23. package/agent-assets/docs/concepts/observations.md +49 -11
  24. package/agent-assets/docs/concepts/process-keys.md +56 -22
  25. package/agent-assets/docs/concepts/routines.md +60 -33
  26. package/agent-assets/docs/concepts/safety-and-execution.md +50 -21
  27. package/agent-assets/docs/concepts/safety-model.md +42 -34
  28. package/agent-assets/docs/concepts/skills.md +33 -17
  29. package/agent-assets/docs/features/integrations/browser-history.md +195 -0
  30. package/agent-assets/docs/features/integrations/calendar.md +39 -29
  31. package/agent-assets/docs/features/integrations/git.md +18 -7
  32. package/agent-assets/docs/features/integrations/github.md +84 -33
  33. package/agent-assets/docs/features/integrations/mail.md +59 -16
  34. package/agent-assets/docs/features/integrations/notion.md +18 -6
  35. package/agent-assets/docs/features/integrations/obsidian.md +28 -5
  36. package/agent-assets/docs/features/lifestyle/git.md +42 -38
  37. package/agent-assets/docs/features/lifestyle/reading.md +50 -22
  38. package/agent-assets/docs/features/lifestyle/receipts.md +51 -21
  39. package/agent-assets/docs/features/lifestyle/travel-bookings.md +76 -14
  40. package/agent-assets/docs/features/memory-files/agent-journal.md +111 -50
  41. package/agent-assets/docs/features/memory-files/projects.md +71 -17
  42. package/agent-assets/docs/features/memory-files/roadmap.md +50 -10
  43. package/agent-assets/docs/features/memory-files/schedule.md +113 -70
  44. package/agent-assets/docs/features/memory-files/today.md +46 -21
  45. package/agent-assets/docs/features/memory-files/user-profile.md +63 -33
  46. package/agent-assets/docs/features/messaging/bang-commands.md +113 -36
  47. package/agent-assets/docs/features/messaging/dashboard-chat.md +43 -21
  48. package/agent-assets/docs/features/messaging/discord.md +35 -4
  49. package/agent-assets/docs/features/messaging/overview.md +37 -19
  50. package/agent-assets/docs/features/messaging/pairing-and-magic-phrase.md +94 -27
  51. package/agent-assets/docs/features/messaging/slack.md +67 -14
  52. package/agent-assets/docs/features/messaging/telegram.md +18 -5
  53. package/agent-assets/docs/features/messaging/whatsapp.md +71 -17
  54. package/agent-assets/docs/features/operations/activity-and-conversations.md +44 -15
  55. package/agent-assets/docs/features/operations/approvals.md +48 -16
  56. package/agent-assets/docs/features/operations/backend-routing.md +68 -16
  57. package/agent-assets/docs/features/operations/cost-tracking.md +84 -17
  58. package/agent-assets/docs/features/operations/managed-chromium.md +221 -0
  59. package/agent-assets/docs/features/operations/notifications.md +52 -11
  60. package/agent-assets/docs/features/operations/quiet-hours.md +63 -40
  61. package/agent-assets/docs/features/operations/schedule-approaching.md +54 -24
  62. package/agent-assets/docs/features/routines/custom-routines.md +88 -20
  63. package/agent-assets/docs/features/routines/evening-review.md +74 -21
  64. package/agent-assets/docs/features/routines/hourly-check.md +149 -29
  65. package/agent-assets/docs/features/routines/morning-routine.md +53 -35
  66. package/agent-assets/docs/features/routines/weekly-review.md +40 -21
  67. package/agent-assets/docs/features/wiki/commands.md +26 -16
  68. package/agent-assets/docs/features/wiki/cost-and-approval.md +240 -0
  69. package/agent-assets/docs/features/wiki/dashboard.md +255 -0
  70. package/agent-assets/docs/features/wiki/overview.md +68 -10
  71. package/agent-assets/docs/features/wiki/search.md +248 -0
  72. package/agent-assets/docs/features/wiki/workspaces.md +254 -0
  73. package/agent-assets/docs/getting-started/01-what-is-this.md +34 -23
  74. package/agent-assets/docs/getting-started/02-first-steps.md +13 -8
  75. package/agent-assets/docs/getting-started/03-what-can-this-do.md +25 -14
  76. package/agent-assets/docs/getting-started/04-first-day.md +38 -20
  77. package/agent-assets/docs/glossary.md +235 -24
  78. package/agent-assets/docs/guides/add-a-custom-routine.md +63 -23
  79. package/agent-assets/docs/guides/backup-and-restore.md +80 -16
  80. package/agent-assets/docs/guides/budget-and-cost-for-wiki.md +56 -25
  81. package/agent-assets/docs/guides/build-your-wiki.md +22 -9
  82. package/agent-assets/docs/guides/change-which-model-handles-x.md +64 -10
  83. package/agent-assets/docs/guides/connect-a-new-mail-account.md +64 -15
  84. package/agent-assets/docs/guides/explore-with-trace-and-connect.md +28 -11
  85. package/agent-assets/docs/guides/import-knowledge-file.md +50 -40
  86. package/agent-assets/docs/guides/install-and-run.md +48 -19
  87. package/agent-assets/docs/guides/maintain-wiki-health.md +35 -10
  88. package/agent-assets/docs/guides/migrate-machines.md +74 -18
  89. package/agent-assets/docs/guides/multiple-wikis-for-multiple-domains.md +111 -60
  90. package/agent-assets/docs/guides/pause-the-agent.md +65 -24
  91. package/agent-assets/docs/guides/reinstall-cleanly.md +88 -18
  92. package/agent-assets/docs/guides/setup-wizard.md +113 -54
  93. package/agent-assets/docs/guides/switch-default-backend.md +62 -16
  94. package/agent-assets/docs/guides/use-an-existing-obsidian-vault.md +26 -10
  95. package/agent-assets/docs/reference/api.md +143 -32
  96. package/agent-assets/docs/reference/cli-commands.md +38 -17
  97. package/agent-assets/docs/reference/config.md +224 -49
  98. package/agent-assets/docs/reference/disallowed-tools.md +29 -10
  99. package/agent-assets/docs/reference/keyboard-shortcuts.md +34 -10
  100. package/agent-assets/docs/reference/knowledge-layout.md +620 -0
  101. package/agent-assets/docs/reference/process-keys.md +61 -5
  102. package/agent-assets/docs/reference/skills.md +38 -12
  103. package/agent-assets/docs/troubleshooting/auth-failed.md +48 -19
  104. package/agent-assets/docs/troubleshooting/dashboard-shows-degraded.md +90 -28
  105. package/agent-assets/docs/troubleshooting/fallback-keeps-firing.md +86 -22
  106. package/agent-assets/docs/troubleshooting/messaging-not-pairing.md +68 -24
  107. package/agent-assets/docs/troubleshooting/morning-routine-didnt-run.md +80 -20
  108. package/agent-assets/docs/troubleshooting/observation-not-detected.md +73 -21
  109. package/agent-assets/docs/troubleshooting/quota-exhausted.md +29 -5
  110. package/agent-assets/docs/troubleshooting/wiki-ingest-full-blocked.md +126 -54
  111. package/agent-assets/docs/troubleshooting/wiki-write-failed.md +29 -12
  112. package/agent-assets/optimizer-skills/drift-analysis/SKILL.md +1 -1
  113. package/agent-assets/optimizer-skills/knowledge-map/SKILL.md +1 -1
  114. package/agent-assets/optimizer-skills/skill-curation/SKILL.md +1 -1
  115. package/agent-assets/sandbox/linux/aitne-chromium.apparmor +91 -0
  116. package/agent-assets/sandbox/macos/aitne-chromium.sb +156 -0
  117. package/agent-assets/skills/agent-actions/SKILL.md +2 -2
  118. package/agent-assets/skills/agent-create/SKILL.md +149 -0
  119. package/agent-assets/skills/attach/SKILL.md +2 -2
  120. package/agent-assets/skills/browser-history/SKILL.md +198 -0
  121. package/agent-assets/skills/browser-history-respond/SKILL.md +106 -0
  122. package/agent-assets/skills/browser-task/SKILL.md +169 -0
  123. package/agent-assets/skills/context/SKILL.md +12 -12
  124. package/agent-assets/skills/context/curation.json +2 -2
  125. package/agent-assets/skills/context/references/api.md +43 -31
  126. package/agent-assets/skills/context/references/required-frontmatter.md +3 -3
  127. package/agent-assets/skills/context/references/snapshot-files.md +6 -6
  128. package/agent-assets/skills/context/seeds/file-responsibilities.seed.json +3 -3
  129. package/agent-assets/skills/docs-search/SKILL.md +4 -3
  130. package/agent-assets/skills/external-services/SKILL.delegated.claude.md +11 -21
  131. package/agent-assets/skills/external-services/SKILL.delegated.codex.md +11 -21
  132. package/agent-assets/skills/external-services/SKILL.delegated.gemini.md +11 -21
  133. package/agent-assets/skills/external-services/SKILL.md +3 -3
  134. package/agent-assets/skills/external-services/SKILL.native.claude.md +5 -5
  135. package/agent-assets/skills/external-services/SKILL.native.codex.md +7 -7
  136. package/agent-assets/skills/external-services/SKILL.native.gemini.md +4 -4
  137. package/agent-assets/skills/external-services/references/calendar-apple.md +2 -2
  138. package/agent-assets/skills/external-services/references/calendar-outlook.md +1 -1
  139. package/agent-assets/skills/external-services/references/obsidian.md +2 -2
  140. package/agent-assets/skills/gmail-lifestyle/SKILL.md +9 -82
  141. package/agent-assets/skills/mail/SKILL.delegated.claude.md +14 -5
  142. package/agent-assets/skills/mail/SKILL.delegated.codex.md +8 -4
  143. package/agent-assets/skills/mail/SKILL.delegated.gemini.md +8 -4
  144. package/agent-assets/skills/mail/references/api.md +4 -2
  145. package/agent-assets/skills/mail/references/providers.md +1 -1
  146. package/agent-assets/skills/managed-tasks/SKILL.md +9 -9
  147. package/agent-assets/skills/managed-tasks/references/errors.md +9 -6
  148. package/agent-assets/skills/managed-tasks/references/recurrence-rule.md +1 -1
  149. package/agent-assets/skills/management-policy/SKILL.md +32 -31
  150. package/agent-assets/skills/management-policy/curation.json +1 -1
  151. package/agent-assets/skills/management-policy/references/policy-workflow.md +9 -9
  152. package/agent-assets/skills/management-policy/seeds/policy-file-shape.seed.json +1 -1
  153. package/agent-assets/skills/notify/SKILL.md +4 -4
  154. package/agent-assets/skills/notify/references/priority.md +9 -4
  155. package/agent-assets/skills/notion/SKILL.delegated.claude.md +1 -1
  156. package/agent-assets/skills/notion/SKILL.delegated.codex.md +1 -1
  157. package/agent-assets/skills/notion/SKILL.delegated.gemini.md +1 -1
  158. package/agent-assets/skills/notion/SKILL.native.claude.md +10 -6
  159. package/agent-assets/skills/notion/SKILL.native.codex.md +9 -4
  160. package/agent-assets/skills/notion/SKILL.native.gemini.md +9 -4
  161. package/agent-assets/skills/observations/SKILL.md +24 -8
  162. package/agent-assets/skills/project-doc/SKILL.md +1 -1
  163. package/agent-assets/skills/project-doc/curation.json +3 -3
  164. package/agent-assets/skills/project-doc/seeds/project-shape.seed.json +7 -4
  165. package/agent-assets/skills/project-doc/seeds/slug-grammar.seed.json +3 -3
  166. package/agent-assets/skills/reading/SKILL.md +10 -0
  167. package/agent-assets/skills/reading/references/reading-taste.md +2 -2
  168. package/agent-assets/skills/roadmap/SKILL.md +5 -5
  169. package/agent-assets/skills/roadmap/curation.json +1 -1
  170. package/agent-assets/skills/roadmap/references/api.md +7 -7
  171. package/agent-assets/skills/roadmap/references/cross-check.md +15 -8
  172. package/agent-assets/skills/roadmap/references/migration.md +4 -4
  173. package/agent-assets/skills/roadmap/seeds/entry-types.seed.json +1 -1
  174. package/agent-assets/skills/schedule/SKILL.md +42 -34
  175. package/agent-assets/skills/schedule/references/batch.md +2 -2
  176. package/agent-assets/skills/schedule/references/errors.md +7 -4
  177. package/agent-assets/skills/schedule/references/model-selection.md +3 -3
  178. package/agent-assets/skills/schedule/references/recurrence-rule.md +1 -1
  179. package/agent-assets/skills/scheduled-managed-task/SKILL.md +46 -36
  180. package/agent-assets/skills/today/SKILL.md +9 -9
  181. package/agent-assets/skills/today/curation.json +3 -3
  182. package/agent-assets/skills/today/references/agent-plan-lifecycle.md +6 -5
  183. package/agent-assets/skills/today/seeds/section-shape.seed.json +1 -1
  184. package/agent-assets/skills/user-interview/SKILL.md +12 -9
  185. package/agent-assets/skills/user-interview/references/op-briefing.md +2 -2
  186. package/agent-assets/skills/user-interview/references/sweep-and-fallback.md +8 -0
  187. package/agent-assets/skills/user-profile/SKILL.md +17 -17
  188. package/agent-assets/skills/user-profile/curation.json +2 -2
  189. package/agent-assets/skills/user-profile/references/character-preferences.md +2 -2
  190. package/agent-assets/skills/user-profile/seeds/routing-table.seed.json +8 -8
  191. package/agent-assets/skills/user-profile/seeds/topic-files.seed.json +6 -6
  192. package/agent-assets/skills/wiki/wiki-compile/SKILL.md +4 -4
  193. package/agent-assets/system-prompts/routine-fetch-window.md +22 -12
  194. package/agent-assets/task-flows/_partials/calendar-acquire.google_calendar.md +4 -2
  195. package/agent-assets/task-flows/_partials/calendar-acquire.outlook_calendar.md +4 -2
  196. package/agent-assets/task-flows/_partials/capture-user-info.md +2 -2
  197. package/agent-assets/task-flows/_partials/dm-intent.long-horizon.md +1 -1
  198. package/agent-assets/task-flows/_partials/dm-intent.project.md +9 -9
  199. package/agent-assets/task-flows/_partials/mail-acquire.outlook_mail.md +3 -2
  200. package/agent-assets/task-flows/_partials/notion-acquire.notion.md +10 -5
  201. package/agent-assets/task-flows/browser_task.md +84 -0
  202. package/agent-assets/task-flows/github.assigned.md +1 -1
  203. package/agent-assets/task-flows/github.pull_request.review_requested.md +2 -2
  204. package/agent-assets/task-flows/github.workflow_run.failed.md +2 -2
  205. package/agent-assets/task-flows/knowledge.import.md +14 -14
  206. package/agent-assets/task-flows/message.received.dm.md +9 -4
  207. package/agent-assets/task-flows/message.received.dm_first.md +3 -3
  208. package/agent-assets/task-flows/routine.custom.md +3 -3
  209. package/agent-assets/task-flows/routine.evening_review.md +8 -8
  210. package/agent-assets/task-flows/routine.fetch_window.md +2 -2
  211. package/agent-assets/task-flows/routine.hourly_check.md +16 -12
  212. package/agent-assets/task-flows/routine.monthly_review.md +21 -21
  213. package/agent-assets/task-flows/routine.morning_routine_journal.md +119 -97
  214. package/agent-assets/task-flows/routine.morning_routine_today.md +43 -43
  215. package/agent-assets/task-flows/routine.research_cluster_update.md +35 -0
  216. package/agent-assets/task-flows/routine.research_dispatch.md +38 -0
  217. package/agent-assets/task-flows/routine.research_offer_dm.md +125 -0
  218. package/agent-assets/task-flows/routine.research_wiki_summary.md +53 -0
  219. package/agent-assets/task-flows/routine.roadmap_refresh.md +10 -10
  220. package/agent-assets/task-flows/routine.today_refresh.md +4 -4
  221. package/agent-assets/task-flows/routine.user_profile_sweep.md +10 -10
  222. package/agent-assets/task-flows/routine.weekly_review.md +93 -24
  223. package/agent-assets/task-flows/schedule.approaching.md +0 -1
  224. package/agent-assets/task-flows/scheduled.dm.md +5 -5
  225. package/agent-assets/task-flows/scheduled.task.md +4 -4
  226. package/agent-assets/task-flows/setup.initial.md +21 -21
  227. package/agent-assets/task-flows/setup.update.md +2 -2
  228. package/agent-assets/templates/README.md +27 -20
  229. package/agent-assets/templates/_index.md +42 -26
  230. package/agent-assets/templates/_manifest.json +34 -99
  231. package/agent-assets/templates/{user → identity}/_index.md +1 -1
  232. package/agent-assets/templates/{user → identity}/profile.md +2 -2
  233. package/agent-assets/templates/{dossiers → knowledge/dossiers}/_index.md +1 -1
  234. package/agent-assets/templates/{projects → plans/projects}/_active.base +1 -1
  235. package/agent-assets/templates/policies/_index.md +21 -0
  236. package/agent-assets/templates/{rules → policies}/journal-export.md +1 -1
  237. package/agent-assets/templates/{rules → policies}/journal-format.md +5 -5
  238. package/agent-assets/templates/{rules/policies → policies/management-captures}/_index.md +2 -2
  239. package/agent-assets/templates/{rules → policies}/management.md +3 -3
  240. package/agent-assets/templates/{rules → policies}/mcp.md +1 -1
  241. package/agent-assets/templates/{rules → policies}/redaction.md +1 -1
  242. package/agent-assets/templates/{routines → policies/routines}/_index.md +1 -1
  243. package/agent-assets/templates/{routines → policies/routines}/evening.md +2 -2
  244. package/agent-assets/templates/{routines → policies/routines}/hourly.md +1 -1
  245. package/agent-assets/templates/{routines → policies/routines}/monthly.md +2 -2
  246. package/bin/aitne.mjs +13 -4
  247. package/package.json +5 -4
  248. package/scripts/commands/doctor.mjs +14 -8
  249. package/scripts/commands/run-now.mjs +6 -21
  250. package/scripts/lib/ports.d.mts +27 -0
  251. package/scripts/lib/ports.mjs +36 -0
  252. package/scripts/lib/read-api-token.mjs +176 -0
  253. package/scripts/start.mjs +2 -1
  254. package/agent-assets/docs/features/lifestyle/travel-time.md +0 -58
  255. package/agent-assets/skills/gmail-lifestyle/references/travel-time-api.md +0 -59
  256. package/agent-assets/skills/schedule/references/recurring.md +0 -185
  257. package/agent-assets/templates/context-index.md +0 -42
  258. package/agent-assets/templates/rules/_index.md +0 -19
  259. /package/agent-assets/templates/{user → identity}/expertise.md +0 -0
  260. /package/agent-assets/templates/{user → identity}/goals.md +0 -0
  261. /package/agent-assets/templates/{user → identity}/people.md +0 -0
  262. /package/agent-assets/templates/{user → identity}/personal.md +0 -0
  263. /package/agent-assets/templates/{user → identity}/work.md +0 -0
  264. /package/agent-assets/templates/{agent/journal.md → journal/agent.md} +0 -0
  265. /package/agent-assets/templates/{dossiers → knowledge/dossiers}/evening.md +0 -0
  266. /package/agent-assets/templates/{dossiers → knowledge/dossiers}/hourly.md +0 -0
  267. /package/agent-assets/templates/{dossiers → knowledge/dossiers}/monthly.md +0 -0
  268. /package/agent-assets/templates/{dossiers → knowledge/dossiers}/morning.md +0 -0
  269. /package/agent-assets/templates/{dossiers → knowledge/dossiers}/roadmap.md +0 -0
  270. /package/agent-assets/templates/{dossiers → knowledge/dossiers}/weekly.md +0 -0
  271. /package/agent-assets/templates/{projects → plans/projects}/_index.md +0 -0
  272. /package/agent-assets/templates/{roadmap.md → plans/roadmap.md} +0 -0
  273. /package/agent-assets/templates/{routines → policies/routines}/morning.md +0 -0
  274. /package/agent-assets/templates/{routines → policies/routines}/weekly.md +0 -0
  275. /package/agent-assets/templates/{agent → state}/profile-questions.md +0 -0
  276. /package/agent-assets/templates/{today.md → state/today.md} +0 -0
@@ -32,15 +32,15 @@ or the dashboard's Settings → Management page._
32
32
  ## C. Active Policies
33
33
 
34
34
  Auto-maintained by the daemon (do not edit). Source files live under
35
- `rules/policies/<slug>.md`; capture new policies via the
36
- `management-policy` skill. Full index: [[rules/policies/_index.md]]
35
+ `policies/management-captures/<slug>.md`; capture new policies via the
36
+ `management-policy` skill. Full index: [[policies/management-captures/_index.md]]
37
37
 
38
38
  _No active policies yet._
39
39
 
40
40
  ## Notes
41
41
 
42
42
  - The agent cannot use `Edit` / `Write` tools on this file — writes go
43
- through `/api/context/rules/management` (locked + snapshotted) or the
43
+ through `/api/context/policies/management` (locked + snapshotted) or the
44
44
  managed-tasks / sot-bindings API surfaces.
45
45
  - This file is injected into every flow via `policy-files.ts`. Keep it
46
46
  concise so prompt assembly stays cheap.
@@ -16,7 +16,7 @@ This file governs how the agent uses attached Model Context Protocol
16
16
  the target with me via DM when the change is visible to others (a new
17
17
  issue, a posted message, an edited doc).
18
18
  - Failures are loggable events. On repeated MCP call failures, the agent
19
- appends to `agent/journal.md` and surfaces the pattern at the next
19
+ appends to `journal/agent.md` and surfaces the pattern at the next
20
20
  hourly check.
21
21
  - Scope to the active task. MCP calls unrelated to the current flow's
22
22
  stated goal are skipped.
@@ -22,7 +22,7 @@ redaction is performed in code by `packages/shared/src/secret-redaction.ts`.
22
22
  ## Context-specific (journal export)
23
23
 
24
24
  When exporting `daily/*.md` to an external vault (B-005), additional
25
- user-defined rules in `rules/journal-export.md` are applied on top.
25
+ user-defined rules in `policies/journal-export.md` are applied on top.
26
26
 
27
27
  ## Appearance in logs
28
28
 
@@ -17,4 +17,4 @@ I've added later via DM). All checks are treated equally.
17
17
  | `evening.md` | evening | `routine.evening_review` |
18
18
  | `weekly.md` | Friday | `routine.weekly_review` |
19
19
  | `monthly.md` | month-end | `routine.monthly_review` |
20
- | custom/<slug>.md | user-defined cron in `routines/custom/` | `routine.custom.<slug>` |
20
+ | custom/<slug>.md | user-defined cron in `policies/routines/custom/` | `routine.custom.<slug>` |
@@ -10,7 +10,7 @@ template_version: 1
10
10
  ## Checks
11
11
 
12
12
  ### Today → Handoff
13
- - **Action**: scan `today.md` for open items and summarize them into
13
+ - **Action**: scan `state/today.md` for open items and summarize them into
14
14
  `## Handoff` so tomorrow's morning routine can pick them up
15
15
 
16
16
  ### Tomorrow preview
@@ -18,5 +18,5 @@ template_version: 1
18
18
  deadlines into `## Handoff`
19
19
 
20
20
  ### Journal tail
21
- - **Action**: append a 1–2 sentence note to `agent/journal.md` describing
21
+ - **Action**: append a 1–2 sentence note to `journal/agent.md` describing
22
22
  anything surprising the agent observed today
@@ -21,7 +21,7 @@ skipping any whose preconditions are not met.
21
21
 
22
22
  ### Upcoming schedule
23
23
  - **Precondition**: always
24
- - **Action**: scan `today.md` `## Agent Plan` for items in the next 60
24
+ - **Action**: scan `state/today.md` `## Agent Plan` for items in the next 60
25
25
  min; ensure each has a `scheduled.task` row.
26
26
 
27
27
  ## Skip conditions (applied before any check)
@@ -17,9 +17,9 @@ Fires on the last calendar day of the month. Output target:
17
17
  `daily/*.md` items
18
18
 
19
19
  ### Roadmap delta
20
- - **Action**: compare current `roadmap.md` against the month's progress;
20
+ - **Action**: compare current `plans/roadmap.md` against the month's progress;
21
21
  highlight completed + delayed items
22
22
 
23
23
  ### Habit + health snapshot
24
- - **Action**: if the user logged health/habit data in `user/personal.md`,
24
+ - **Action**: if the user logged health/habit data in `identity/personal.md`,
25
25
  surface month-over-month changes (opt-in only)
package/bin/aitne.mjs CHANGED
@@ -8,6 +8,15 @@ import process from "node:process";
8
8
  import { fileURLToPath } from "node:url";
9
9
  import { ensureBuild } from "../scripts/run-node.mjs";
10
10
  import { fetchHttpOk, openBrowser } from "../scripts/browser.mjs";
11
+ // Port defaults live in this plain-ESM module (NOT @aitne/shared, per the
12
+ // pre-build constraint noted below). scripts/lib/ ships in the published
13
+ // `files` list, so this import works in global installs too.
14
+ import {
15
+ DEFAULT_API_PORT,
16
+ DEFAULT_DASHBOARD_PORT,
17
+ resolveApiPort,
18
+ resolveDashboardPort,
19
+ } from "../scripts/lib/ports.mjs";
11
20
 
12
21
  const IS_WINDOWS = process.platform === "win32";
13
22
 
@@ -55,8 +64,8 @@ const DAEMON_PID_FILE = path.join(PIDS_DIR, "daemon.pid");
55
64
  const DASHBOARD_PID_FILE = path.join(PIDS_DIR, "dashboard.pid");
56
65
  const DAEMON_LOG_FILE = path.join(DATA_DIR, "logs", "daemon.log");
57
66
  const DASHBOARD_LOG_FILE = path.join(DATA_DIR, "logs", "dashboard.log");
58
- const DAEMON_PORT = parseInt(process.env.PA_API_PORT || "8321", 10);
59
- const DASHBOARD_PORT = parseInt(process.env.PA_DASHBOARD_PORT || "3000", 10);
67
+ const DAEMON_PORT = resolveApiPort();
68
+ const DASHBOARD_PORT = resolveDashboardPort();
60
69
 
61
70
  const VERSION = JSON.parse(
62
71
  fs.readFileSync(path.join(PROJECT_ROOT, "package.json"), "utf8"),
@@ -1004,8 +1013,8 @@ Options:
1004
1013
 
1005
1014
  Environment:
1006
1015
  PA_DATA_DIR Data directory (default: ~/.personal-agent)
1007
- PA_API_PORT Daemon port (default: 8321)
1008
- PA_DASHBOARD_PORT Dashboard port (default: 3000)
1016
+ PA_API_PORT Daemon port (default: ${DEFAULT_API_PORT})
1017
+ PA_DASHBOARD_PORT Dashboard port (default: ${DEFAULT_DASHBOARD_PORT})
1009
1018
 
1010
1019
  Examples:
1011
1020
  aitne start Launch in background
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aitne-sh/aitne",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Aitne — a local-first, proactive personal AI agent. A long-running TypeScript daemon is the nervous system; Claude Code (or Codex / Gemini CLI) is the brain. All persistent memory lives in local Markdown files.",
5
5
  "keywords": [
6
6
  "ai",
@@ -43,9 +43,9 @@
43
43
  "README.md"
44
44
  ],
45
45
  "dependencies": {
46
- "@aitne/daemon": "0.1.8",
47
- "@aitne/dashboard": "0.1.8",
48
- "@aitne/shared": "0.1.8"
46
+ "@aitne/daemon": "0.1.9",
47
+ "@aitne/dashboard": "0.1.9",
48
+ "@aitne/shared": "0.1.9"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@typescript-eslint/eslint-plugin": "^8.58.1",
@@ -75,6 +75,7 @@
75
75
  "test": "node scripts/check-redaction-coverage.mjs && vitest run --coverage",
76
76
  "test:watch": "vitest",
77
77
  "check:redaction": "node scripts/check-redaction-coverage.mjs",
78
+ "check:vault-paths": "node scripts/check-vault-path-drift.mjs",
78
79
  "lint": "turbo run lint",
79
80
  "typecheck:tests": "turbo run typecheck:tests",
80
81
  "clean": "turbo run clean && node scripts/rm-paths.mjs node_modules .buildstamp"
@@ -38,7 +38,7 @@ Exit code:
38
38
  await checkSecretStore(ctx),
39
39
  await checkBackendCli(),
40
40
  await checkProcessProbe(),
41
- await checkBrowserOpener(),
41
+ await checkBrowserOpener(ctx.DASHBOARD_PORT),
42
42
  await checkDataDirWritable(ctx.DATA_DIR),
43
43
  await checkBetterSqlite3(ctx.PROJECT_ROOT),
44
44
  await checkAgentAssets(ctx.PROJECT_ROOT),
@@ -127,8 +127,8 @@ async function checkPort(label, port, pidFile, getRunningPid) {
127
127
  label,
128
128
  detail: `${port} in use by another process`,
129
129
  hint: label.startsWith("Daemon")
130
- ? `Set PA_API_PORT to an open port (e.g. PA_API_PORT=8322 aitne start), or stop the conflicting process.`
131
- : `Set PA_DASHBOARD_PORT to an open port (e.g. PA_DASHBOARD_PORT=3001 aitne start), or stop the conflicting process.`,
130
+ ? `Set PA_API_PORT to an open port (e.g. PA_API_PORT=8331 aitne start), or stop the conflicting process.`
131
+ : `Set PA_DASHBOARD_PORT to an open port (e.g. PA_DASHBOARD_PORT=8333 aitne start), or stop the conflicting process.`,
132
132
  };
133
133
  }
134
134
 
@@ -182,11 +182,17 @@ async function checkSecretStore(ctx) {
182
182
  }
183
183
  }
184
184
  if (platform === "win32") {
185
- const psBinary = whichSync("powershell.exe") ? "powershell.exe" : "pwsh.exe";
185
+ // Match the factory's terminal fallback (secret-client-factory.ts:37-41): prefer
186
+ // in-box powershell.exe, else pwsh.exe, else default to powershell.exe — the exact
187
+ // binary the daemon will exec — so a both-missing FAIL names the right binary.
188
+ const psBinary = whichSync("powershell.exe") ? "powershell.exe" : (whichSync("pwsh.exe") ? "pwsh.exe" : "powershell.exe");
186
189
  try {
190
+ // Mirror WindowsDpapiSecretClient's real encrypt path: ConvertTo/From-SecureString
191
+ // (no -Key => DPAPI). Works on both powershell.exe (5.1) and pwsh.exe (7+); the prior
192
+ // [ProtectedData] type check false-fails on PowerShell-Core-only hosts that work fine.
187
193
  execFileSync(psBinary, [
188
- "-NoProfile", "-Command",
189
- "[System.Security.Cryptography.ProtectedData] | Out-Null; exit 0",
194
+ "-NoProfile", "-NonInteractive", "-Command",
195
+ "$s = ConvertTo-SecureString 'probe' -AsPlainText -Force; $e = ConvertFrom-SecureString $s; if (-not $e) { exit 1 }; exit 0",
190
196
  ], { stdio: "pipe", timeout: 5000 });
191
197
  return { status: "pass", label: "Secret store", detail: `Windows DPAPI via ${psBinary} reachable` };
192
198
  } catch (err) {
@@ -253,7 +259,7 @@ async function checkProcessProbe() {
253
259
  * Warn-only: nothing in the daemon depends on this; users can navigate to
254
260
  * the dashboard URL by hand if missing.
255
261
  */
256
- async function checkBrowserOpener() {
262
+ async function checkBrowserOpener(dashboardPort) {
257
263
  const platform = process.platform;
258
264
  const tool =
259
265
  platform === "darwin" ? "open"
@@ -268,7 +274,7 @@ async function checkBrowserOpener() {
268
274
  detail: `${tool} not on PATH`,
269
275
  hint:
270
276
  platform === "linux"
271
- ? "apt install xdg-utils · or open http://localhost:3000 manually after `aitne start`."
277
+ ? `apt install xdg-utils · or open http://localhost:${dashboardPort} manually after \`aitne start\`.`
272
278
  : "Auto-open is a convenience; the dashboard URL works in any browser.",
273
279
  };
274
280
  }
@@ -9,8 +9,10 @@
9
9
  * `docs/design/appendices/evening-review-slimdown.md` §2.2.
10
10
  *
11
11
  * Implementation:
12
- * - Reads the daemon's apiToken from the macOS Keychain (the same
13
- * entry the dashboard proxy uses). Bearer-auth required because
12
+ * - Reads the daemon's apiToken from the OS secret store (macOS
13
+ * Keychain, Windows DPAPI, Linux libsecret, or the encrypted file
14
+ * fallback) via the shared cross-platform reader — the same entry
15
+ * the dashboard proxy uses. Bearer-auth required because
14
16
  * `POST /api/agent/run-now/*` routes are Approve-tier in the
15
17
  * `risk-classifier`.
16
18
  * - POSTs to `http://127.0.0.1:<PA_API_PORT>/api/agent/run-now/<job>`.
@@ -23,7 +25,7 @@
23
25
  * - 3 daemon not running, not reachable, or 5xx
24
26
  * - 4 result.status === "failed" — the job reported errors[]
25
27
  */
26
- import { execFileSync } from "node:child_process";
28
+ import { readApiToken } from "../lib/read-api-token.mjs";
27
29
 
28
30
  const SUPPORTED_JOBS = new Set(["roadmap_maintenance"]);
29
31
 
@@ -53,7 +55,7 @@ export async function run(args, ctx) {
53
55
  const token = readApiToken();
54
56
  if (!token) {
55
57
  process.stderr.write(
56
- "Failed to read daemon API token from the macOS Keychain.\n" +
58
+ "Failed to read the daemon API token from the OS secret store.\n" +
57
59
  "Is the daemon initialized? Run `aitne start` once first.\n",
58
60
  );
59
61
  process.exit(3);
@@ -125,23 +127,6 @@ function parseArgs(args) {
125
127
  return opts;
126
128
  }
127
129
 
128
- function readApiToken() {
129
- try {
130
- return execFileSync(
131
- "security",
132
- [
133
- "find-generic-password",
134
- "-s",
135
- "com.personal-agent.secret.apiToken",
136
- "-w",
137
- ],
138
- { encoding: "utf-8" },
139
- ).trim();
140
- } catch {
141
- return null;
142
- }
143
- }
144
-
145
130
  function printSummary(job, result) {
146
131
  if (job === "roadmap_maintenance") {
147
132
  if (!result || typeof result !== "object") {
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Type declarations for the plain-ESM launcher mirror `ports.mjs`.
3
+ *
4
+ * `ports.mjs` is hand-written JavaScript (it must run before the TypeScript
5
+ * build), so it carries no inferred types. This sidecar lets TypeScript
6
+ * consumers — notably the `packages/shared/src/ports.test.ts` drift guard,
7
+ * which imports this module to assert it stays in lockstep with the TS
8
+ * source-of-truth `packages/shared/src/ports.ts` — typecheck the import under
9
+ * `strict`. Keep these signatures identical to `ports.ts`'s exports (minus
10
+ * `loopbackOrigins`, which is TS-only and not mirrored here).
11
+ */
12
+
13
+ /** Daemon HTTP API port. Overridable via `PA_API_PORT`. */
14
+ export const DEFAULT_API_PORT: number;
15
+
16
+ /** Dashboard (Next.js) port. Overridable via `PA_DASHBOARD_PORT`. */
17
+ export const DEFAULT_DASHBOARD_PORT: number;
18
+
19
+ /** Resolve the daemon API port from env, falling back to DEFAULT_API_PORT. */
20
+ export function resolveApiPort(
21
+ env?: Record<string, string | undefined>,
22
+ ): number;
23
+
24
+ /** Resolve the dashboard port from env, falling back to DEFAULT_DASHBOARD_PORT. */
25
+ export function resolveDashboardPort(
26
+ env?: Record<string, string | undefined>,
27
+ ): number;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Default network ports for the Aitne daemon API and dashboard.
3
+ *
4
+ * SINGLE SOURCE OF TRUTH (launcher / plain-ESM side). `bin/aitne.mjs` and the
5
+ * `scripts/**` launchers cannot import `@aitne/shared`: they run *before* the
6
+ * TypeScript build that produces it (running `aitne start` is what triggers
7
+ * that build), and the published package ships only `bin` + `scripts/*.mjs` +
8
+ * `agent-assets`, never `packages/`. So the defaults are mirrored here in a
9
+ * build-independent module that lives under the published `scripts/lib/`.
10
+ *
11
+ * The TypeScript mirror lives in `packages/shared/src/ports.ts`. The two are
12
+ * pinned together by `packages/shared/src/ports.test.ts`, which fails CI if
13
+ * the values ever drift. Change a default in BOTH or the test goes red.
14
+ */
15
+
16
+ /** Daemon HTTP API port. Overridable via `PA_API_PORT`. */
17
+ export const DEFAULT_API_PORT = 8321;
18
+
19
+ /** Dashboard (Next.js) port. Overridable via `PA_DASHBOARD_PORT`. Not 3000 — that collides with most dev servers. */
20
+ export const DEFAULT_DASHBOARD_PORT = 8322;
21
+
22
+ function parsePort(raw) {
23
+ if (raw == null || raw === "") return null;
24
+ const n = Number.parseInt(raw, 10);
25
+ return Number.isFinite(n) && n > 0 ? n : null;
26
+ }
27
+
28
+ /** Resolve the daemon API port from env, falling back to DEFAULT_API_PORT. */
29
+ export function resolveApiPort(env = process.env) {
30
+ return parsePort(env.PA_API_PORT) ?? DEFAULT_API_PORT;
31
+ }
32
+
33
+ /** Resolve the dashboard port from env, falling back to DEFAULT_DASHBOARD_PORT. */
34
+ export function resolveDashboardPort(env = process.env) {
35
+ return parsePort(env.PA_DASHBOARD_PORT) ?? DEFAULT_DASHBOARD_PORT;
36
+ }
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Cross-platform reader for the daemon's `apiToken` secret.
3
+ *
4
+ * CLI scripts (`run-now`, `remint-roadmap-ids`) need the daemon's apiToken to
5
+ * call Approve-tier `/api/...` routes, but they intentionally must run WITHOUT
6
+ * a successful `@aitne/shared` build (which only ships `./dist/*.js`). So this
7
+ * helper re-implements the per-OS read inline, mirroring the secret clients in
8
+ * `packages/shared/src/`:
9
+ *
10
+ * - darwin → macOS Keychain via `security` (service com.personal-agent.secret.apiToken)
11
+ * - win32 → DPAPI: decrypt ~/.personal-agent/secrets/apiToken.dpapi via PowerShell
12
+ * - linux → libsecret (`secret-tool lookup`), else the AES-256-GCM file store
13
+ * - WSL / other → the AES-256-GCM file store
14
+ *
15
+ * The file-store format/params and the DPAPI script are copied verbatim from
16
+ * `secret-client-file.ts` / `secret-client-windows.ts` — keep them in sync if
17
+ * those change. The secret clients hardcode `~/.personal-agent/secrets` (they
18
+ * do NOT honor PA_DATA_DIR), so this helper uses the same homedir-relative
19
+ * location to find what the daemon actually wrote.
20
+ *
21
+ * Returns the token string, or null when it cannot be read; the caller decides
22
+ * how to message the failure. Best-effort: never throws (so a CLI never dies
23
+ * with a raw stack trace on a misconfigured secret store).
24
+ */
25
+ import { execFileSync } from "node:child_process";
26
+ import { existsSync, readFileSync, statSync } from "node:fs";
27
+ import { homedir } from "node:os";
28
+ import { join } from "node:path";
29
+ import { createDecipheriv, scryptSync } from "node:crypto";
30
+
31
+ const SECRET_NAME = "apiToken";
32
+ const KEYCHAIN_SERVICE = "com.personal-agent.secret.apiToken";
33
+
34
+ function secretsDir() {
35
+ return join(homedir(), ".personal-agent", "secrets");
36
+ }
37
+
38
+ /** @returns {string | null} the daemon apiToken, or null if unreadable. */
39
+ export function readApiToken() {
40
+ const platform = process.platform;
41
+ if (platform === "darwin") return readDarwin();
42
+ if (platform === "win32") return readWindows();
43
+ if (platform === "linux") {
44
+ if (!isWsl() && whichSync("secret-tool")) {
45
+ const fromKeyring = readSecretTool();
46
+ if (fromKeyring) return fromKeyring;
47
+ }
48
+ return readFileStore();
49
+ }
50
+ return readFileStore();
51
+ }
52
+
53
+ function readDarwin() {
54
+ // Byte-identical to the historical `security` read so macOS cannot regress.
55
+ try {
56
+ return execFileSync(
57
+ "security",
58
+ ["find-generic-password", "-s", KEYCHAIN_SERVICE, "-w"],
59
+ { encoding: "utf-8" },
60
+ ).trim();
61
+ } catch {
62
+ return null;
63
+ }
64
+ }
65
+
66
+ /** Cross-platform `which`, returning the resolved path or null. */
67
+ function whichSync(cmd) {
68
+ const tool = process.platform === "win32" ? "where" : "which";
69
+ try {
70
+ const out = execFileSync(tool, [cmd], {
71
+ stdio: ["ignore", "pipe", "ignore"],
72
+ timeout: 2_000,
73
+ });
74
+ return out.toString().split(/\r?\n/)[0]?.trim() || null;
75
+ } catch {
76
+ return null;
77
+ }
78
+ }
79
+
80
+ function readWindows() {
81
+ const path = join(secretsDir(), `${SECRET_NAME}.dpapi`);
82
+ if (!existsSync(path)) return null;
83
+ const encrypted = readFileSync(path, "utf-8").trim();
84
+ // Prefer in-box Windows PowerShell 5.1, fall back to PowerShell 7+ (pwsh),
85
+ // matching the daemon's secret-client-factory resolution order.
86
+ const psBinary = whichSync("powershell.exe")
87
+ ? "powershell.exe"
88
+ : whichSync("pwsh.exe")
89
+ ? "pwsh.exe"
90
+ : "powershell.exe";
91
+ // Mirrors WindowsDpapiSecretClient.get(): DPAPI-decrypt via
92
+ // ConvertTo-SecureString and marshal back to plaintext. The ciphertext is
93
+ // passed via stdin, never interpolated into the script, to avoid injection.
94
+ const script = [
95
+ "$enc = [System.Console]::In.ReadToEnd().Trim()",
96
+ "$ss = ConvertTo-SecureString $enc",
97
+ "$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($ss)",
98
+ "try { [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr) }",
99
+ "finally { [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) }",
100
+ ].join("; ");
101
+ try {
102
+ const out = execFileSync(
103
+ psBinary,
104
+ ["-NoProfile", "-NonInteractive", "-Command", script],
105
+ { input: encrypted, encoding: "utf-8", timeout: 10_000 },
106
+ );
107
+ return out.trimEnd() || null;
108
+ } catch {
109
+ return null;
110
+ }
111
+ }
112
+
113
+ function readSecretTool() {
114
+ try {
115
+ const out = execFileSync(
116
+ "secret-tool",
117
+ ["lookup", "service", "personal-agent", "key", SECRET_NAME],
118
+ { encoding: "utf-8", timeout: 5_000 },
119
+ );
120
+ return out.replace(/\n$/, "") || null;
121
+ } catch {
122
+ return null;
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Detect WSL. WSL reports platform "linux" but cannot use `secret-tool`
128
+ * (D-Bus / GNOME Keyring typically unavailable), so it uses the file store.
129
+ */
130
+ function isWsl() {
131
+ try {
132
+ return /microsoft|wsl/i.test(readFileSync("/proc/version", "utf-8"));
133
+ } catch {
134
+ return false;
135
+ }
136
+ }
137
+
138
+ // ── AES-256-GCM file store (mirrors secret-client-file.ts) ────────────────
139
+ const FILE_ALGORITHM = "aes-256-gcm";
140
+ const FILE_KEY_LENGTH = 32; // 256 bits
141
+ const FILE_SCRYPT = { N: 16384, r: 8, p: 1 };
142
+
143
+ /** Resolve the file-store master password (env, then key file); null if none. */
144
+ function resolveMasterPassword() {
145
+ if (process.env.PA_MASTER_PASSWORD) return process.env.PA_MASTER_PASSWORD;
146
+ const keyFilePath = join(secretsDir(), ".master-key");
147
+ if (!existsSync(keyFilePath)) return null;
148
+ // Refuse to read a key file with insecure permissions (mirrors the daemon's
149
+ // 0600/0400 gate); degrade to null rather than risk exposing it.
150
+ const mode = statSync(keyFilePath).mode & 0o777;
151
+ if (mode !== 0o600 && mode !== 0o400) return null;
152
+ return readFileSync(keyFilePath, "utf-8").trim();
153
+ }
154
+
155
+ function readFileStore() {
156
+ const path = join(secretsDir(), `${SECRET_NAME}.enc`);
157
+ if (!existsSync(path)) return null;
158
+ try {
159
+ const password = resolveMasterPassword();
160
+ if (!password) return null;
161
+ const stored = JSON.parse(readFileSync(path, "utf-8"));
162
+ const salt = Buffer.from(stored.salt, "hex");
163
+ const iv = Buffer.from(stored.iv, "hex");
164
+ const authTag = Buffer.from(stored.authTag, "hex");
165
+ const ciphertext = Buffer.from(stored.ciphertext, "hex");
166
+ const key = scryptSync(password, salt, FILE_KEY_LENGTH, FILE_SCRYPT);
167
+ const decipher = createDecipheriv(FILE_ALGORITHM, key, iv);
168
+ decipher.setAuthTag(authTag);
169
+ return Buffer.concat([
170
+ decipher.update(ciphertext),
171
+ decipher.final(),
172
+ ]).toString("utf-8");
173
+ } catch {
174
+ return null;
175
+ }
176
+ }
package/scripts/start.mjs CHANGED
@@ -6,6 +6,7 @@ import path from "node:path";
6
6
  import process from "node:process";
7
7
  import { ensureBuild, log } from "./run-node.mjs";
8
8
  import { openBrowser, waitForHttpReady } from "./browser.mjs";
9
+ import { resolveDashboardPort } from "./lib/ports.mjs";
9
10
 
10
11
  const IS_WINDOWS = process.platform === "win32";
11
12
  const requireFromScript = createRequire(import.meta.url);
@@ -57,7 +58,7 @@ function nextSpawnArgs(dashboardDir, nextBin, userArgs) {
57
58
  * 5. Ctrl+C stops both
58
59
  */
59
60
 
60
- const DASHBOARD_PORT = parseInt(process.env.PA_DASHBOARD_PORT || "3000", 10);
61
+ const DASHBOARD_PORT = resolveDashboardPort();
61
62
  const noOpen = process.argv.slice(2).includes("--no-open");
62
63
  const children = [];
63
64
  let shuttingDown = false;
@@ -1,58 +0,0 @@
1
- ---
2
- schema_version: 1
3
- slug: features/lifestyle/travel-time
4
- title: Travel Time
5
- id: travel-time
6
- aliases:
7
- - door to door
8
- - eta
9
- category: features
10
- summary: |
11
- A skill that estimates door-to-door travel time given an origin
12
- and destination — used by schedule-approaching reminders for
13
- events with location.
14
- section: lifestyle
15
- tags:
16
- - lifestyle
17
- - travel
18
- - skills
19
- status: stable
20
- ask_examples:
21
- - How long will it take me to get to the airport?
22
- - Does the agent know about traffic?
23
- locale: en-US
24
- created: 2026-04-25
25
- updated: 2026-04-25
26
- keywords:
27
- - travel time
28
- - departure time
29
- - google maps
30
- - commute
31
- - ETA
32
- related:
33
- - features/lifestyle/travel-bookings
34
- - features/operations/schedule-approaching
35
- ---
36
-
37
- # Travel Time
38
-
39
- ## In One Sentence
40
-
41
- A skill the agent calls to estimate door-to-door travel time before
42
- a calendar event with a location.
43
-
44
- ## What It Does
45
-
46
- - Reads origin (current location, configured home/work) and
47
- destination (event location).
48
- - Returns a typical-time estimate with mode (drive, transit, walk).
49
- - Used by `schedule-approaching` reminders to lead-time the alert.
50
-
51
- ## Where in the Dashboard
52
-
53
- There is no operator surface for the travel-time data itself; the
54
- estimates appear inline in event reminders and morning routines.
55
-
56
- ## Related
57
-
58
- - [Schedule Approaching](../operations/schedule-approaching.md)
@@ -1,59 +0,0 @@
1
- ---
2
- kind: reference
3
- name: travel-time-api
4
- description: /api/travel-time reference — Google Maps Directions wrapper. Estimate door-to-door duration and compute departure time for a calendar event with location.
5
- ---
6
-
7
- # `/api/travel-time` reference
8
-
9
- Uses the Google Maps Directions API. Prerequisite: `googleMapsApiKey`
10
- configured in the daemon's secret store, with the Directions API
11
- enabled.
12
-
13
- ## GET /api/travel-time
14
-
15
- Estimate travel time between two locations.
16
-
17
- ```bash
18
- # Transit (default)
19
- curl -s "http://localhost:8321/api/travel-time?origin=Grand+Central&destination=Times+Square"
20
-
21
- # Driving with arrival time
22
- curl -s "http://localhost:8321/api/travel-time?origin=Brooklyn&destination=Newark&mode=driving&arrival=2026-04-12T14:00:00-04:00"
23
- ```
24
-
25
- | Param | Type | Default | Description |
26
- |-------|------|---------|-------------|
27
- | `origin` | string | (required) | Origin address or place name |
28
- | `destination` | string | (required) | Destination address or place name |
29
- | `mode` | string | transit | driving, transit, walking, bicycling |
30
- | `arrival` | ISO 8601 | — | Desired arrival time (computes departure time) |
31
-
32
- Response:
33
-
34
- ```json
35
- {
36
- "origin": "Grand Central Terminal, NY",
37
- "destination": "Times Square, NY",
38
- "mode": "transit",
39
- "durationSeconds": 1380,
40
- "durationText": "23 mins",
41
- "distanceMeters": 8500,
42
- "distanceText": "8.5 km",
43
- "departBy": "2026-04-12T13:34:00.000Z"
44
- }
45
- ```
46
-
47
- ## GET /api/travel-time/for-event/:eventId
48
-
49
- ```bash
50
- curl -s "http://localhost:8321/api/travel-time/for-event/abc123?origin=Home&mode=transit"
51
- ```
52
-
53
- | Param | Type | Default | Description |
54
- |-------|------|---------|-------------|
55
- | `origin` | string | (required) | Your starting location |
56
- | `mode` | string | transit | Travel mode |
57
-
58
- Response includes both `event` and `travelTime` blocks; see the route
59
- implementation for full shape.