{"code":"var Component=(()=>{var p=Object.create;var o=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var m=Object.getPrototypeOf,f=Object.prototype.hasOwnProperty;var y=(i,t)=>()=>(t||i((t={exports:{}}).exports,t),t.exports),w=(i,t)=>{for(var n in t)o(i,n,{get:t[n],enumerable:!0})},r=(i,t,n,s)=>{if(t&&typeof t==\"object\"||typeof t==\"function\")for(let a of u(t))!f.call(i,a)&&a!==n&&o(i,a,{get:()=>t[a],enumerable:!(s=g(t,a))||s.enumerable});return i};var b=(i,t,n)=>(n=i!=null?p(m(i)):{},r(t||!i||!i.__esModule?o(n,\"default\",{value:i,enumerable:!0}):n,i)),k=i=>r(o({},\"__esModule\",{value:!0}),i);var d=y((x,h)=>{h.exports=_jsx_runtime});var v={};w(v,{default:()=>l});var e=b(d());function c(i){let t={a:\"a\",blockquote:\"blockquote\",code:\"code\",em:\"em\",h2:\"h2\",h3:\"h3\",img:\"img\",li:\"li\",p:\"p\",pre:\"pre\",span:\"span\",strong:\"strong\",table:\"table\",tbody:\"tbody\",td:\"td\",th:\"th\",thead:\"thead\",tr:\"tr\",ul:\"ul\",...i.components};return(0,e.jsxs)(e.Fragment,{children:[(0,e.jsxs)(t.p,{children:[\"Your Mac is warm doing nothing. The battery estimate has halved. You open Activity Monitor, sort by CPU, and at the top is a process you have never heard of \\u2014 \",(0,e.jsx)(t.code,{children:\"peopled\"}),\" \\u2014 sitting at 70 or 80 percent and staying there. Or it is \",(0,e.jsx)(t.code,{children:\"contactsd\"}),\". Or, on the worst-affected machines, \",(0,e.jsx)(t.code,{children:\"accountsd\"}),\" at 180% with \",(0,e.jsx)(t.code,{children:\"contactsd\"}),\" and \",(0,e.jsx)(t.code,{children:\"itunescloudd\"}),\" behind it. Quitting does nothing, because you cannot quit them. Restarting helps for an hour.\"]}),`\n`,(0,e.jsx)(t.p,{children:'This has been happening to Mac users since macOS Tahoe 26.4 in March, it is still happening on 26.5 and 26.6, Apple has not acknowledged it, and the most reliable fix is not in any of the \"restart your Mac / reset NVRAM\" articles that rank for the search. It is removing a widget.'}),`\n`,(0,e.jsxs)(t.p,{children:[\"This guide explains what \",(0,e.jsx)(t.code,{children:\"peopled\"}),\" is (we looked inside it), why a widget puts it into a loop, why a quarantine flag on a folder you did not know existed is the other trigger, and the exact order in which to try the fixes.\"]}),`\n`,(0,e.jsx)(t.p,{children:(0,e.jsx)(t.img,{alt:\"peopled consuming CPU on macOS Tahoe in Activity Monitor\",src:\"/images/blog/peopled-contactsd-high-cpu-macos-tahoe-contacts-widget-callhistorydb-fix-2026/hero.webp\",width:\"1024\",height:\"541\"})}),`\n`,(0,e.jsx)(t.h2,{id:\"key-takeaways\",children:\"Key Takeaways\"}),`\n`,(0,e.jsxs)(t.ul,{children:[`\n`,(0,e.jsxs)(t.li,{children:[(0,e.jsxs)(t.strong,{children:[(0,e.jsx)(t.code,{children:\"peopled\"}),\" is the daemon behind the Contacts widget.\"]}),\" Its own binary contains classes named \",(0,e.jsx)(t.code,{children:\"WidgetSuggester\"}),\", \",(0,e.jsx)(t.code,{children:\"WidgetConfigurationReader\"}),\" and \",(0,e.jsx)(t.code,{children:\"CallHistoryFetcher\"}),\", and its sandbox profile grants it your call history database. That combination is the loop.\"]}),`\n`,(0,e.jsxs)(t.li,{children:[(0,e.jsx)(t.strong,{children:\"Fix 1: remove every Contacts widget\"}),\" \\u2014 desktop, Notification Center and Control Center \\u2014 then restart. This resolved the majority of the 54-plus confirmed reports on Apple's community forum.\"]}),`\n`,(0,e.jsxs)(t.li,{children:[(0,e.jsxs)(t.strong,{children:[\"Fix 2: clear the quarantine flag on \",(0,e.jsx)(t.code,{children:\"~/Library/Application Support/CallHistoryDB\"})]}),\" and kill \",(0,e.jsx)(t.code,{children:\"peopled\"}),\". This is the fix when there is no widget to remove; it needs Full Disk Access for Terminal.\"]}),`\n`,(0,e.jsxs)(t.li,{children:[(0,e.jsx)(t.strong,{children:\"Fix 3: disable iCloud Contacts, then re-enable it.\"}),\" Works for some, not all, and costs you sync while it is off.\"]}),`\n`,(0,e.jsxs)(t.li,{children:[(0,e.jsxs)(t.strong,{children:[(0,e.jsx)(t.code,{children:\"contactsd\"}),\" spikes with an Exchange or Google account are a different, older bug\"]}),\" with the same symptom and a different fix \\u2014 remove the account or use a third-party client.\"]}),`\n`,(0,e.jsxs)(t.li,{children:[(0,e.jsx)(t.strong,{children:\"Apple has not documented a fix.\"}),\" Nothing in the 26.4.1, 26.5, 26.6 or 26.6.x release notes mentions it, and reports on 26.5 and later continue.\"]}),`\n`]}),`\n`,(0,e.jsx)(t.h2,{id:\"which-process-exactly\",children:\"Which Process, Exactly\"}),`\n`,(0,e.jsx)(t.p,{children:\"Three daemons appear in these reports and they are not interchangeable. Sort Activity Monitor by % CPU and note which one you have.\"}),`\n`,(0,e.jsxs)(t.table,{children:[(0,e.jsx)(t.thead,{children:(0,e.jsxs)(t.tr,{children:[(0,e.jsx)(t.th,{children:\"Process\"}),(0,e.jsx)(t.th,{children:\"What it belongs to\"}),(0,e.jsx)(t.th,{children:\"Typical report\"}),(0,e.jsx)(t.th,{children:\"Most likely cause\"})]})}),(0,e.jsxs)(t.tbody,{children:[(0,e.jsxs)(t.tr,{children:[(0,e.jsx)(t.td,{children:(0,e.jsx)(t.code,{children:\"peopled\"})}),(0,e.jsx)(t.td,{children:\"People framework \\u2014 widget suggestions, Family, Screen Time, status\"}),(0,e.jsx)(t.td,{children:\"70\\u201380% sustained since 26.4\"}),(0,e.jsx)(t.td,{children:\"Contacts widget + unreadable CallHistoryDB\"})]}),(0,e.jsxs)(t.tr,{children:[(0,e.jsx)(t.td,{children:(0,e.jsx)(t.code,{children:\"contactsd\"})}),(0,e.jsx)(t.td,{children:\"Contacts framework \\u2014 the address book database and sync\"}),(0,e.jsx)(t.td,{children:\"Spikes to 80% every 60\\u201390 s, or sustained\"}),(0,e.jsx)(t.td,{children:\"iCloud/Exchange/Google contacts sync loop\"})]}),(0,e.jsxs)(t.tr,{children:[(0,e.jsx)(t.td,{children:(0,e.jsx)(t.code,{children:\"accountsd\"})}),(0,e.jsx)(t.td,{children:\"Accounts framework \\u2014 every signed-in account\"}),(0,e.jsxs)(t.td,{children:[\"180% alongside \",(0,e.jsx)(t.code,{children:\"contactsd\"}),\" and \",(0,e.jsx)(t.code,{children:\"itunescloudd\"})]}),(0,e.jsx)(t.td,{children:\"Account authentication loop; sign-out fix often fails\"})]})]})]}),`\n`,(0,e.jsxs)(t.p,{children:[\"If it is \",(0,e.jsx)(t.code,{children:\"peopled\"}),\", start with the widget section. If it is \",(0,e.jsx)(t.code,{children:\"contactsd\"}),\" alone, jump to the sync-account section. If it is all three with \",(0,e.jsx)(t.code,{children:\"accountsd\"}),\" on top, you are in the least-understood variant and the section on that is honest about how little is known.\"]}),`\n`,(0,e.jsxs)(t.h2,{id:\"what-peopled-actually-does\",children:[\"What \",(0,e.jsx)(t.code,{children:\"peopled\"}),\" Actually Does\"]}),`\n`,(0,e.jsx)(t.p,{children:'The name suggests contacts, and the guides that mention it at all describe it as \"manages contact data.\" That is roughly right and specifically wrong, and the difference is why the fix is a widget rather than an address-book repair.'}),`\n`,(0,e.jsxs)(t.p,{children:[\"We looked at the daemon on a Mac running 26.5.2. It lives at \",(0,e.jsx)(t.code,{children:\"/System/Library/PrivateFrameworks/People.framework/peopled\"}),\", and its launchd job (\",(0,e.jsx)(t.code,{children:\"/System/Library/LaunchAgents/com.apple.peopled.plist\"}),\") tells you what wakes it up. It is not loaded at login \\u2014 \",(0,e.jsx)(t.code,{children:\"RunAtLoad\"}),\" is false. It is started by events:\"]}),`\n`,(0,e.jsxs)(t.ul,{children:[`\n`,(0,e.jsxs)(t.li,{children:[\"Biome streams for \",(0,e.jsx)(t.code,{children:\"missedCall\"}),\", \",(0,e.jsx)(t.code,{children:\"unreadMessage\"}),\", \",(0,e.jsx)(t.code,{children:\"readMessage\"}),\", \",(0,e.jsx)(t.code,{children:\"location\"}),\", \",(0,e.jsx)(t.code,{children:\"dndAvailability\"}),\", \",(0,e.jsx)(t.code,{children:\"screenTimeRequest\"}),\", \",(0,e.jsx)(t.code,{children:\"askToBuyRequest\"}),\" and \",(0,e.jsx)(t.code,{children:\"childState\"})]}),`\n`,(0,e.jsxs)(t.li,{children:[\"Two system notifications: \",(0,e.jsx)(t.code,{children:\"__ABDataBaseChangedByOtherProcessNotification\"}),\" (the address book changed) and \",(0,e.jsx)(t.code,{children:\"_CalDatabaseChangedNotification\"}),\" (the calendar changed)\"]}),`\n`]}),`\n`,(0,e.jsxs)(t.p,{children:[\"So every missed call, every message, every contact edit and every calendar change wakes \",(0,e.jsx)(t.code,{children:\"peopled\"}),\". And what does it do when woken? The strings in its binary answer that directly. Among the Swift class names:\"]}),`\n`,(0,e.jsx)(e.Fragment,{children:(0,e.jsx)(t.pre,{className:\"shiki shiki-themes github-light github-dark\",style:{\"--shiki-light\":\"#24292e\",\"--shiki-dark\":\"#e1e4e8\",\"--shiki-light-bg\":\"#fff\",\"--shiki-dark-bg\":\"#24292e\"},tabIndex:\"0\",icon:'<svg viewBox=\"0 0 24 24\"><path d=\"M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z\" fill=\"currentColor\" /></svg>',children:(0,e.jsxs)(t.code,{children:[(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:\"_TtC7peopled15WidgetSuggester\"})}),`\n`,(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:\"_TtC7peopled18CallHistoryFetcher\"})}),`\n`,(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:\"_TtC7peopled25WidgetConfigurationReader\"})})]})})}),`\n`,(0,e.jsx)(t.p,{children:\"and among its log message templates:\"}),`\n`,(0,e.jsx)(e.Fragment,{children:(0,e.jsx)(t.pre,{className:\"shiki shiki-themes github-light github-dark\",style:{\"--shiki-light\":\"#24292e\",\"--shiki-dark\":\"#e1e4e8\",\"--shiki-light-bg\":\"#fff\",\"--shiki-dark-bg\":\"#24292e\"},tabIndex:\"0\",icon:'<svg viewBox=\"0 0 24 24\"><path d=\"M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z\" fill=\"currentColor\" /></svg>',children:(0,e.jsxs)(t.code,{children:[(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:\"Event triggered widget refresh: %{private}s, %s\"})}),`\n`,(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:\"Last widget suggestion date is older 24 hours, suggest widgets\"})}),`\n`,(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:\"Last widget suggestion date is within 24 hours, do not suggest widgets\"})}),`\n`,(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:\"error reading widgets configurations: %s\"})}),`\n`,(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:\"Failed to suggest widgets with error: %s\"})})]})})}),`\n`,(0,e.jsx)(t.p,{children:\"It links the Contacts framework, the CallHistory framework and two Biome frameworks. Its purpose, as far as its own code describes it, is to decide which people to surface in the Contacts widget and in people-related suggestions, using your recent calls and messages as the signal.\"}),`\n`,(0,e.jsx)(t.p,{children:\"That is what makes the failure mode make sense: a daemon that is woken by every call and message, whose job is to refresh a widget, and which needs to read the call history to do it.\"}),`\n`,(0,e.jsx)(t.p,{children:(0,e.jsx)(t.img,{alt:\"Inside the peopled daemon on macOS Tahoe\",src:\"/images/blog/peopled-contactsd-high-cpu-macos-tahoe-contacts-widget-callhistorydb-fix-2026/content-1.webp\",width:\"1024\",height:\"572\"})}),`\n`,(0,e.jsx)(t.h2,{id:\"why-it-loops\",children:\"Why It Loops\"}),`\n`,(0,e.jsx)(t.p,{children:\"Put the pieces from the community thread next to what the binary says.\"}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.code,{children:\"peopled\"}),\" runs inside a sandbox. Its profile, at \",(0,e.jsx)(t.code,{children:\"/System/Library/Sandbox/Profiles/com.apple.peopled.sb\"}),\", starts with \",(0,e.jsx)(t.code,{children:\"(deny default)\"}),\" and then opens specific doors. Two of them:\"]}),`\n`,(0,e.jsx)(e.Fragment,{children:(0,e.jsx)(t.pre,{className:\"shiki shiki-themes github-light github-dark\",style:{\"--shiki-light\":\"#24292e\",\"--shiki-dark\":\"#e1e4e8\",\"--shiki-light-bg\":\"#fff\",\"--shiki-dark-bg\":\"#24292e\"},tabIndex:\"0\",icon:'<svg viewBox=\"0 0 24 24\"><path d=\"M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z\" fill=\"currentColor\" /></svg>',children:(0,e.jsxs)(t.code,{children:[(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:'(home-subpath \"/Library/CallHistoryDB/\")'})}),`\n`,(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:'(home-subpath \"/Library/Logs/CallHistory\")'})})]})})}),`\n`,(0,e.jsxs)(t.p,{children:[\"So it is allowed to read \",(0,e.jsx)(t.code,{children:\"~/Library/Application Support/CallHistoryDB/\"}),\", where macOS keeps the database of calls made and received through your iPhone via Continuity. That folder is also protected by TCC \\u2014 on our Mac, \",(0,e.jsx)(t.code,{children:\"ls\"}),\" on it from Terminal returns \",(0,e.jsx)(t.code,{children:\"Operation not permitted\"}),\" until Terminal has Full Disk Access \\u2014 which is why the fixes below need that permission.\"]}),`\n`,(0,e.jsxs)(t.p,{children:[\"Now the reports. On 21 April a user on \",(0,e.jsx)(t.a,{href:\"https://discussions.apple.com/thread/256271160\",children:\"Apple's community thread\"}),\" quoted the kernel message they found in Console while \",(0,e.jsx)(t.code,{children:\"peopled\"}),\" was spinning:\"]}),`\n`,(0,e.jsxs)(t.blockquote,{children:[`\n`,(0,e.jsx)(t.p,{children:\"Sandbox: peopled \\u2026 deny(1) file-read-data ~/Library/Application Support/CallHistoryDB\"}),`\n`]}),`\n`,(0,e.jsx)(t.p,{children:\"And on 20 May another quoted:\"}),`\n`,(0,e.jsxs)(t.blockquote,{children:[`\n`,(0,e.jsx)(t.p,{children:\"failed to open /Users/[user]/Library/Application Support/CallHistoryDB: 1 (Operation not permitted)\"}),`\n`]}),`\n`,(0,e.jsxs)(t.p,{children:[\"The reading that fits all of this: a Contacts widget is installed, so \",(0,e.jsx)(t.code,{children:\"peopled\"}),\" is asked to refresh it; refreshing means fetching call history; the fetch is denied \\u2014 because the folder has acquired a \",(0,e.jsx)(t.code,{children:\"com.apple.quarantine\"}),\" attribute, or for some other permission reason the reports have not pinned down \\u2014 the refresh fails, and the next event (or the retry) triggers it again. A daemon that should run for milliseconds after a missed call instead runs continuously.\"]}),`\n`,(0,e.jsx)(t.p,{children:'We want to be precise about what is and is not established here. The class names, the sandbox rules and the log messages are directly observable; we read them. That the loop is \"widget refresh, denied read, retry\" is an inference that fits every report we have seen and both fixes that work. Apple has not confirmed the mechanism, and there may be a second trigger \\u2014 one user reports the loop starting after reorganising Control Center with no Contacts widget present at all.'}),`\n`,(0,e.jsx)(t.h2,{id:\"confirm-it-before-you-change-anything\",children:\"Confirm It Before You Change Anything\"}),`\n`,(0,e.jsx)(t.p,{children:\"Two minutes of looking saves an hour of guessing, and the pattern of the CPU use tells you which fix to reach for.\"}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.strong,{children:\"Watch the shape of it.\"}),\" In Activity Monitor, select the process and look at the CPU history in the window's footer, or from Terminal:\"]}),`\n`,(0,e.jsx)(e.Fragment,{children:(0,e.jsx)(t.pre,{className:\"shiki shiki-themes github-light github-dark\",style:{\"--shiki-light\":\"#24292e\",\"--shiki-dark\":\"#e1e4e8\",\"--shiki-light-bg\":\"#fff\",\"--shiki-dark-bg\":\"#24292e\"},tabIndex:\"0\",icon:'<svg viewBox=\"0 0 24 24\"><path d=\"M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z\" fill=\"currentColor\" /></svg>',children:(0,e.jsx)(t.code,{children:(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:\"top -stats pid,command,cpu,time -o cpu -n 5\"})})})})}),`\n`,(0,e.jsxs)(t.p,{children:[\"A \",(0,e.jsx)(t.code,{children:\"peopled\"}),\" that sits at a flat 70\\u201380% is the widget loop. A \",(0,e.jsx)(t.code,{children:\"contactsd\"}),\" that spikes, drops to zero, and spikes again a minute later is the sync loop. Sustained CPU on all three daemons at once is the account variant.\"]}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.strong,{children:\"Check how long it has been running.\"}),\" \",(0,e.jsx)(t.code,{children:\"peopled\"}),\" normally lives for seconds. On our (healthy) Mac it has been resident for 41 days at 0.0% CPU \\u2014 resident but idle is fine. What you are looking for is resident \",(0,e.jsx)(t.em,{children:\"and\"}),\" busy:\"]}),`\n`,(0,e.jsx)(e.Fragment,{children:(0,e.jsx)(t.pre,{className:\"shiki shiki-themes github-light github-dark\",style:{\"--shiki-light\":\"#24292e\",\"--shiki-dark\":\"#e1e4e8\",\"--shiki-light-bg\":\"#fff\",\"--shiki-dark-bg\":\"#24292e\"},tabIndex:\"0\",icon:'<svg viewBox=\"0 0 24 24\"><path d=\"M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z\" fill=\"currentColor\" /></svg>',children:(0,e.jsx)(t.code,{children:(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:'ps -axo pid,etime,pcpu,comm | grep -E \"peopled|contactsd|accountsd\"'})})})})}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.strong,{children:\"Look for the denial.\"}),\" This is the decisive test. Open a second Terminal window and stream the daemon's log while it is spinning:\"]}),`\n`,(0,e.jsx)(e.Fragment,{children:(0,e.jsx)(t.pre,{className:\"shiki shiki-themes github-light github-dark\",style:{\"--shiki-light\":\"#24292e\",\"--shiki-dark\":\"#e1e4e8\",\"--shiki-light-bg\":\"#fff\",\"--shiki-dark-bg\":\"#24292e\"},tabIndex:\"0\",icon:'<svg viewBox=\"0 0 24 24\"><path d=\"M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z\" fill=\"currentColor\" /></svg>',children:(0,e.jsx)(t.code,{children:(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:`log stream --predicate 'process == \"peopled\"' --info`})})})})}),`\n`,(0,e.jsx)(t.p,{children:\"and, in the first window, search the last few minutes for the sandbox line that the community reports quote:\"}),`\n`,(0,e.jsx)(e.Fragment,{children:(0,e.jsx)(t.pre,{className:\"shiki shiki-themes github-light github-dark\",style:{\"--shiki-light\":\"#24292e\",\"--shiki-dark\":\"#e1e4e8\",\"--shiki-light-bg\":\"#fff\",\"--shiki-dark-bg\":\"#24292e\"},tabIndex:\"0\",icon:'<svg viewBox=\"0 0 24 24\"><path d=\"M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z\" fill=\"currentColor\" /></svg>',children:(0,e.jsx)(t.code,{children:(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:`log show --last 10m --predicate 'eventMessage CONTAINS \"Sandbox: peopled\"'`})})})})}),`\n`,(0,e.jsxs)(t.p,{children:[\"If you see \",(0,e.jsx)(t.code,{children:\"deny(1) file-read-data\"}),\" against \",(0,e.jsx)(t.code,{children:\"CallHistoryDB\"}),\", you have the CallHistoryDB variant and Fix 2 is the one that will work. If you see \",(0,e.jsx)(t.code,{children:\"Event triggered widget refresh\"}),\" repeating without a denial, start with Fix 1. If the log is quiet and the CPU is high, the loop is in code that does not log at the default level; try the fixes in order anyway.\"]}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.strong,{children:\"Watch the file system, if you want certainty.\"}),\" \",(0,e.jsx)(t.code,{children:\"fs_usage\"}),\" shows every file operation a process attempts, including the ones that fail:\"]}),`\n`,(0,e.jsx)(e.Fragment,{children:(0,e.jsx)(t.pre,{className:\"shiki shiki-themes github-light github-dark\",style:{\"--shiki-light\":\"#24292e\",\"--shiki-dark\":\"#e1e4e8\",\"--shiki-light-bg\":\"#fff\",\"--shiki-dark-bg\":\"#24292e\"},tabIndex:\"0\",icon:'<svg viewBox=\"0 0 24 24\"><path d=\"M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z\" fill=\"currentColor\" /></svg>',children:(0,e.jsx)(t.code,{children:(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:\"sudo fs_usage -w -f filesys peopled\"})})})})}),`\n`,(0,e.jsxs)(t.p,{children:[\"A screen full of attempts on \",(0,e.jsx)(t.code,{children:\"CallHistoryDB\"}),\" returning errors is the loop, visible in real time.\"]}),`\n`,(0,e.jsx)(t.h2,{id:\"fix-1-remove-the-contacts-widget\",children:\"Fix 1: Remove the Contacts Widget\"}),`\n`,(0,e.jsx)(t.p,{children:\"This is the fix with the most confirmations, and it is the one to try first because it is reversible and needs no Terminal.\"}),`\n`,(0,e.jsx)(t.p,{children:\"The catch is that there are three places a widget can live on a Tahoe Mac, and it has to be gone from all of them.\"}),`\n`,(0,e.jsx)(t.h3,{id:\"desktop\",children:\"Desktop\"}),`\n`,(0,e.jsxs)(t.p,{children:[\"Control-click the wallpaper and choose \",(0,e.jsx)(t.strong,{children:\"Edit Widgets\"}),\". Any Contacts widget on the desktop shows a remove button (the minus in the corner) while editing; click it. Alternatively Control-click the widget itself and choose \",(0,e.jsx)(t.strong,{children:\"Remove Widget\"}),\". Click \",(0,e.jsx)(t.strong,{children:\"Done\"}),\".\"]}),`\n`,(0,e.jsx)(t.h3,{id:\"notification-center\",children:\"Notification Center\"}),`\n`,(0,e.jsxs)(t.p,{children:[\"Click the date and time in the menu bar to open Notification Center, scroll to the bottom, click \",(0,e.jsx)(t.strong,{children:\"Edit Widgets\"}),\". Remove any Contacts widget there the same way \\u2014 Control-click and \",(0,e.jsx)(t.strong,{children:\"Remove Widget\"}),\", or Option-click its remove button.\"]}),`\n`,(0,e.jsx)(t.h3,{id:\"control-center\",children:\"Control Center\"}),`\n`,(0,e.jsxs)(t.p,{children:[\"This is the one people miss, because Tahoe moved widgets into Control Center and the customisation is not in System Settings. Click the Control Center icon in the menu bar, choose \",(0,e.jsx)(t.strong,{children:\"Edit Controls\"}),\", and drag any Contacts item out of Control Center. Click \",(0,e.jsx)(t.strong,{children:\"Done\"}),\".\"]}),`\n`,(0,e.jsxs)(t.p,{children:[\"Then \",(0,e.jsx)(t.strong,{children:\"restart\"}),\" \\u2014 not just log out. Several confirmed fixes on the thread note that the CPU dropped only after a full restart.\"]}),`\n`,(0,e.jsx)(t.p,{children:\"One further caution from the same thread, reported on 31 July: for some users the loop came back after they opened the widget gallery again, even without adding the Contacts widget. If you have had this problem, treat the widget editor as something to avoid until Apple fixes the daemon.\"}),`\n`,(0,e.jsx)(t.h2,{id:\"fix-2-clear-the-quarantine-flag-on-callhistorydb\",children:\"Fix 2: Clear the Quarantine Flag on CallHistoryDB\"}),`\n`,(0,e.jsx)(t.p,{children:'For Macs with no Contacts widget anywhere, or where removing it did not help, this is the fix that the most technically detailed report on the thread arrived at on 20 May, and that at least two other users confirmed (\"peopled process is now in 0% in CPU consumption,\" one wrote on 26 June).'}),`\n`,(0,e.jsx)(t.h3,{id:\"step-1-give-terminal-full-disk-access\",children:\"Step 1: give Terminal Full Disk Access\"}),`\n`,(0,e.jsxs)(t.p,{children:['System Settings > Privacy & Security > Full Disk Access, add Terminal, and toggle it on. Without this, every command below fails with \"Operation not permitted\" \\u2014 which, as it happens, is the same error ',(0,e.jsx)(t.code,{children:\"peopled\"}),\" is hitting. Restart Terminal after granting.\"]}),`\n`,(0,e.jsx)(t.h3,{id:\"step-2-look-at-the-folder\",children:\"Step 2: look at the folder\"}),`\n`,(0,e.jsx)(e.Fragment,{children:(0,e.jsx)(t.pre,{className:\"shiki shiki-themes github-light github-dark\",style:{\"--shiki-light\":\"#24292e\",\"--shiki-dark\":\"#e1e4e8\",\"--shiki-light-bg\":\"#fff\",\"--shiki-dark-bg\":\"#24292e\"},tabIndex:\"0\",icon:'<svg viewBox=\"0 0 24 24\"><path d=\"M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z\" fill=\"currentColor\" /></svg>',children:(0,e.jsx)(t.code,{children:(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:'ls -lan@ \"$HOME/Library/Application Support/CallHistoryDB\"'})})})})}),`\n`,(0,e.jsxs)(t.p,{children:[\"The \",(0,e.jsx)(t.code,{children:\"@\"}),\" flag shows extended attributes. What you are looking for is \",(0,e.jsx)(t.code,{children:\"com.apple.quarantine\"}),\" on the folder or on the \",(0,e.jsx)(t.code,{children:\"CallHistory.storedata\"}),\" files inside it. Quarantine is the flag macOS puts on downloaded files; it has no business being on a system database, and how it gets there is not known \\u2014 a restore from backup and a migration from another Mac are the two plausible routes.\"]}),`\n`,(0,e.jsx)(t.h3,{id:\"step-3-remove-it\",children:\"Step 3: remove it\"}),`\n`,(0,e.jsx)(e.Fragment,{children:(0,e.jsx)(t.pre,{className:\"shiki shiki-themes github-light github-dark\",style:{\"--shiki-light\":\"#24292e\",\"--shiki-dark\":\"#e1e4e8\",\"--shiki-light-bg\":\"#fff\",\"--shiki-dark-bg\":\"#24292e\"},tabIndex:\"0\",icon:'<svg viewBox=\"0 0 24 24\"><path d=\"M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z\" fill=\"currentColor\" /></svg>',children:(0,e.jsx)(t.code,{children:(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:'xattr -dr com.apple.quarantine \"$HOME/Library/Application Support/CallHistoryDB\"'})})})})}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.code,{children:\"-d\"}),\" deletes the attribute, \",(0,e.jsx)(t.code,{children:\"-r\"}),\" recurses into the folder.\"]}),`\n`,(0,e.jsx)(t.h3,{id:\"step-4-restart-the-daemons\",children:\"Step 4: restart the daemons\"}),`\n`,(0,e.jsx)(e.Fragment,{children:(0,e.jsx)(t.pre,{className:\"shiki shiki-themes github-light github-dark\",style:{\"--shiki-light\":\"#24292e\",\"--shiki-dark\":\"#e1e4e8\",\"--shiki-light-bg\":\"#fff\",\"--shiki-dark-bg\":\"#24292e\"},tabIndex:\"0\",icon:'<svg viewBox=\"0 0 24 24\"><path d=\"M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z\" fill=\"currentColor\" /></svg>',children:(0,e.jsx)(t.code,{children:(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:\"sudo killall -9 peopled CallHistorySyncHelper\"})})})})}),`\n`,(0,e.jsx)(t.p,{children:\"Both will be relaunched on demand. Watch Activity Monitor for a few minutes.\"}),`\n`,(0,e.jsx)(t.h3,{id:\"if-the-flag-comes-back\",children:\"If the flag comes back\"}),`\n`,(0,e.jsx)(t.p,{children:`One user on the thread reported on 17 July that the fix worked and the quarantine flag \"reappeared\" overnight. If that happens to you, something is re-quarantining the folder, and the candidates are a backup or sync tool that treats it as new data. Check what runs at night. Alternatively, and more bluntly, another user's approach was to delete the database and let macOS recreate it:`}),`\n`,(0,e.jsx)(e.Fragment,{children:(0,e.jsx)(t.pre,{className:\"shiki shiki-themes github-light github-dark\",style:{\"--shiki-light\":\"#24292e\",\"--shiki-dark\":\"#e1e4e8\",\"--shiki-light-bg\":\"#fff\",\"--shiki-dark-bg\":\"#24292e\"},tabIndex:\"0\",icon:'<svg viewBox=\"0 0 24 24\"><path d=\"M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z\" fill=\"currentColor\" /></svg>',children:(0,e.jsx)(t.code,{children:(0,e.jsx)(t.span,{className:\"line\",children:(0,e.jsx)(t.span,{children:\"rm -rf ~/Library/Application\\\\ Support/CallHistoryDB\"})})})})}),`\n`,(0,e.jsx)(t.p,{children:\"You lose the Mac's copy of your call history. It repopulates from the iPhone over Continuity. This is a bigger hammer than removing an attribute and we would try the attribute first.\"}),`\n`,(0,e.jsx)(t.h2,{id:\"fix-3-toggle-icloud-contacts\",children:\"Fix 3: Toggle iCloud Contacts\"}),`\n`,(0,e.jsx)(t.p,{children:\"System Settings > [your name] > iCloud > Saved to iCloud > Contacts, off. Wait a minute, watch the CPU. If it drops, turn it back on and see whether it stays down.\"}),`\n`,(0,e.jsxs)(t.p,{children:[\"This works for a subset of users and is the standard advice on the thread's older siblings going back years. It also has a failure mode that one user hit on 11 May: the toggle would not turn off at all. If that happens, sign out of iCloud entirely (keeping a copy of data when asked), restart, sign back in. Note that the V2EX reporter with the \",(0,e.jsx)(t.code,{children:\"accountsd\"}),\" variant tried exactly this and the CPU came straight back after signing in.\"]}),`\n`,(0,e.jsx)(t.p,{children:(0,e.jsx)(t.img,{alt:\"Removing the Contacts widget and clearing CallHistoryDB quarantine on macOS Tahoe\",src:\"/images/blog/peopled-contactsd-high-cpu-macos-tahoe-contacts-widget-callhistorydb-fix-2026/content-2.webp\",width:\"1024\",height:\"572\"})}),`\n`,(0,e.jsxs)(t.h2,{id:\"if-it-is-contactsd-and-you-have-an-exchange-or-google-account\",children:[\"If It Is \",(0,e.jsx)(t.code,{children:\"contactsd\"}),\" and You Have an Exchange or Google Account\"]}),`\n`,(0,e.jsx)(t.p,{children:\"This one predates Tahoe and has a cleaner mechanism.\"}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.code,{children:\"contactsd\"}),\" is the Contacts framework's daemon: it owns the address book database and reconciles it with every account that syncs contacts. It also does housekeeping on a schedule \\u2014 its launchd job registers a daily \",(0,e.jsx)(t.code,{children:\"validate-cache\"}),\" task that runs only on external power when you are inactive, and a repeating \",(0,e.jsx)(t.code,{children:\"accounts.cleanup\"}),\" activity. Occasional brief CPU from \",(0,e.jsx)(t.code,{children:\"contactsd\"}),\" is normal.\"]}),`\n`,(0,e.jsxs)(t.p,{children:[\"What is not normal is a spike every minute or so. A developer \",(0,e.jsx)(t.a,{href:\"https://developer.apple.com/forums/thread/809986\",children:\"documented exactly this\"}),\" on the Apple Developer Forums in December 2025: on an M1 Max on Tahoe 26.1, an Office 365 account with Contacts enabled sent \",(0,e.jsx)(t.code,{children:\"AddressBookManager\"}),\" to 81% and \",(0,e.jsx)(t.code,{children:\"contactsd\"}),\" to 22\\u201359% in a repeating pattern every 60\\u201390 seconds \\u2014 even with the Exchange contacts folder emptied on the server, and reproducible on a clean install. The same account and data did not do it on an M4 Mac or on iOS. Nobody from Apple replied.\"]}),`\n`,(0,e.jsxs)(t.p,{children:[\"His workaround is the one that works: remove the Exchange account from System Settings > Internet Accounts, and if you need it, use Outlook, which does not go through the Contacts framework. A February report on the community forum with \",(0,e.jsx)(t.code,{children:\"contactsd\"}),\" on a 2024 MacBook Pro on 26.3 got the equivalent advice \\u2014 stop syncing contacts from Exchange and Google and test \\u2014 and if you have both iCloud and a Google account syncing contacts, try dropping Google first.\"]}),`\n`,(0,e.jsxs)(t.h2,{id:\"the-accountsd-variant\",children:[\"The \",(0,e.jsx)(t.code,{children:\"accountsd\"}),\" Variant\"]}),`\n`,(0,e.jsxs)(t.p,{children:[\"The most severe reports \\u2014 \",(0,e.jsx)(t.code,{children:\"accountsd\"}),\" at 180% with \",(0,e.jsx)(t.code,{children:\"contactsd\"}),\" and \",(0,e.jsx)(t.code,{children:\"itunescloudd\"}),\" in tow, on an M5 MacBook Air on 26.5.2, \",(0,e.jsx)(t.a,{href:\"https://www.v2ex.com/t/1226043\",children:\"described on V2EX in July\"}),\" \\u2014 do not have a confirmed fix. The reporter noted it started at the same time each morning, which points at a scheduled task rather than a widget event. Signing out and back in did not help.\"]}),`\n`,(0,e.jsxs)(t.p,{children:[\"What we can add: \",(0,e.jsx)(t.code,{children:\"accountsd\"}),\" is the Accounts framework daemon and is invoked whenever anything needs a credential for a signed-in account, and \",(0,e.jsx)(t.code,{children:\"itunescloudd\"}),\" is the iTunes Cloud (Apple Music / Store) library daemon. All three at once means something is repeatedly asking for account credentials and failing. If you have this variant, the fixes above are still worth trying in order, and if none of them work, it is worth checking whether a single account \\u2014 an old Google or Exchange login, an expired app-specific password \\u2014 is failing authentication in System Settings > Internet Accounts. Remove anything showing a warning badge.\"]}),`\n`,(0,e.jsx)(t.h2,{id:\"why-tahoe-and-why-a-widget\",children:\"Why Tahoe, and Why a Widget\"}),`\n`,(0,e.jsx)(t.p,{children:\"Widgets have existed on the Mac for years, so it is fair to ask why this began with 26.4. Two things changed together.\"}),`\n`,(0,e.jsx)(t.p,{children:`The first is where widgets live. Tahoe put widgets into Control Center alongside the desktop and Notification Center, and a Contacts widget in Control Center is refreshed on a different cadence from one sitting on the desktop \\u2014 the daemon's own log templates distinguish a daily \"suggest widgets\" pass (\"Last widget suggestion date is older 24 hours\") from event-triggered refreshes (\"Event triggered widget refresh\"). More surfaces, more refresh requests, more chances for a failing one to be retried.`}),`\n`,(0,e.jsx)(t.p,{children:\"The second is that the daemon's error handling appears to retry rather than back off. That is our inference from the behaviour, not something we can read in the binary, and it is the actual bug: a denied read should be logged once and the refresh abandoned until the next genuine event. Instead it is attempted again, and the events keep coming.\"}),`\n`,(0,e.jsx)(t.p,{children:\"Neither of these is something you can change. What you can change is whether the widget exists and whether the read is denied, which is what the three fixes do.\"}),`\n`,(0,e.jsx)(t.h2,{id:\"after-it-is-fixed\",children:\"After It Is Fixed\"}),`\n`,(0,e.jsx)(t.p,{children:\"A few things keep it fixed.\"}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.strong,{children:\"Leave Terminal's Full Disk Access in place\"}),\" if you used Fix 2, or revoke it deliberately \\u2014 either is fine, but know which you did, because Terminal with Full Disk Access is a broad grant.\"]}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.strong,{children:\"Avoid the widget gallery\"}),\" for a while. The 31 July report on the thread is specific that opening it \\u2014 not adding anything \\u2014 restarted the loop. If you want to add other widgets, do it, then check Activity Monitor afterwards.\"]}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.strong,{children:\"After the next macOS update, check again.\"}),\" Point updates have re-added default Control Center items for some users, and a Contacts widget quietly returning is the most likely reason the problem comes back.\"]}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.strong,{children:\"File the report.\"}),\" Feedback Assistant, category macOS, attach a sysdiagnose taken while the CPU is high (\",(0,e.jsx)(t.code,{children:\"sudo sysdiagnose\"}),\" from Terminal, or Shift-Control-Option-Command-Period), and paste the sandbox denial line. Five months of forum threads have not moved this; a few hundred Feedback reports with the same log line might.\"]}),`\n`,(0,e.jsx)(t.h2,{id:\"is-it-fixed-yet\",children:\"Is It Fixed Yet?\"}),`\n`,(0,e.jsxs)(t.p,{children:[\"No, as far as anyone can tell. We checked Apple's \",(0,e.jsx)(t.a,{href:\"https://support.apple.com/en-us/122868\",children:\"update notes for Tahoe\"}),': 26.4.1 \"provides bug fixes,\" 26.5 \"includes enhancements, bug fixes, and security updates,\" 26.6 optimises the Spotlight index, and 26.6.1 and 26.6.2 are security releases. None mentions Contacts, widgets or CPU. On the community thread, reports continue on 26.5 (\"The issue still exists in Tahoe 26.5. Apple needs to fix this asap,\" on 15 May) and into July. We have not seen a report either way for 26.6.2, which shipped 17 August.']}),`\n`,(0,e.jsxs)(t.p,{children:[\"If you are on macOS 27 beta and have or have not seen this, the \",(0,e.jsx)(t.a,{href:\"/blog/should-you-install-macos-27-golden-gate-developer-beta-known-issues-2026\",children:\"beta known-issues roundup\"}),\" is where we track it.\"]}),`\n`,(0,e.jsx)(t.h2,{id:\"what-not-to-bother-with\",children:\"What Not to Bother With\"}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.strong,{children:\"Resetting NVRAM or SMC.\"}),\" Neither has anything to do with a user-space daemon's file permissions. Skip.\"]}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsxs)(t.strong,{children:[(0,e.jsx)(t.code,{children:\"tccutil reset All\"}),\".\"]}),\" One user tried it; it did not help, and it strips every privacy permission from every app on the Mac, which you then spend an afternoon re-granting. There is no reason to think TCC is the layer at fault \\u2014 the denial in the logs is the sandbox, not TCC.\"]}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.strong,{children:\"Safe Mode.\"}),\" Booting into Safe Mode and back clears some caches and gave a few users temporary relief. It is a restart with extra steps and does not address the cause.\"]}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsxs)(t.strong,{children:[\"Disabling \",(0,e.jsx)(t.code,{children:\"peopled\"}),\" with \",(0,e.jsx)(t.code,{children:\"launchctl\"}),\".\"]}),\" You can \",(0,e.jsx)(t.code,{children:\"launchctl disable\"}),` the agent, and it will stop consuming CPU because it will stop running. It will also stop the Contacts widget, people suggestions, Screen Time's \"ask to buy\" plumbing and whatever else depends on it, and on a system-integrity-protected Mac the change may not survive an update. Not recommended except as a last-resort diagnostic.`]}),`\n`,(0,e.jsx)(t.h2,{id:\"troubleshooting-common-issues\",children:\"Troubleshooting Common Issues\"}),`\n`,(0,e.jsxs)(t.h3,{id:\"activity-monitor-shows-twenty-copies-of-contactsd\",children:[\"Activity Monitor shows twenty copies of \",(0,e.jsx)(t.code,{children:\"contactsd\"})]}),`\n`,(0,e.jsxs)(t.p,{children:[\"We saw this ourselves while writing: a burst of twenty \",(0,e.jsx)(t.code,{children:\"contactsd\"}),\" processes with consecutive PIDs, all children of launchd, all at 0% CPU, gone within a minute. That is launchd spawning per-client instances on demand, and it is not the bug. The bug is one process at high CPU that stays.\"]}),`\n`,(0,e.jsxs)(t.h3,{id:\"the-contacts-widget-is-gone-but-peopled-is-still-at-80\",children:[\"The Contacts widget is gone but \",(0,e.jsx)(t.code,{children:\"peopled\"}),\" is still at 80%\"]}),`\n`,(0,e.jsx)(t.p,{children:\"Check all three locations \\u2014 desktop, Notification Center, Control Center \\u2014 and then move to Fix 2. If you never had a Contacts widget, go straight to Fix 2.\"}),`\n`,(0,e.jsxs)(t.h3,{id:\"xattr-says-no-such-xattr-comapplequarantine\",children:[(0,e.jsx)(t.code,{children:\"xattr\"}),' says \"No such xattr: com.apple.quarantine\"']}),`\n`,(0,e.jsx)(t.p,{children:\"The folder is not quarantined, so that is not your trigger. Try Fix 3, and check whether you have an Exchange or Google account syncing contacts.\"}),`\n`,(0,e.jsxs)(t.h3,{id:\"ls-on-callhistorydb-says-operation-not-permitted-even-with-sudo\",children:[(0,e.jsx)(t.code,{children:\"ls\"}),' on CallHistoryDB says \"Operation not permitted\" even with sudo']}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.code,{children:\"sudo\"}),\" does not bypass TCC. Terminal itself needs Full Disk Access, granted in System Settings, and then relaunched.\"]}),`\n`,(0,e.jsx)(t.h3,{id:\"it-came-back-after-a-macos-update\",children:\"It came back after a macOS update\"}),`\n`,(0,e.jsx)(t.p,{children:\"Updates can re-add the widget to Control Center's default layout. Check the three locations again.\"}),`\n`,(0,e.jsx)(t.h2,{id:\"faq\",children:\"FAQ\"}),`\n`,(0,e.jsxs)(t.h3,{id:\"is-peopled-malware\",children:[\"Is \",(0,e.jsx)(t.code,{children:\"peopled\"}),\" malware?\"]}),`\n`,(0,e.jsxs)(t.p,{children:[\"No. It is a signed Apple daemon at \",(0,e.jsx)(t.code,{children:\"/System/Library/PrivateFrameworks/People.framework/peopled\"}),\" on the sealed system volume. A process with that name running from anywhere else would be worth investigating; this one is Apple's.\"]}),`\n`,(0,e.jsx)(t.h3,{id:\"can-i-just-kill-it\",children:\"Can I just kill it?\"}),`\n`,(0,e.jsxs)(t.p,{children:[(0,e.jsx)(t.code,{children:\"sudo killall peopled\"}),\" stops it until the next event wakes it, which on a busy Mac is seconds. It is useful as a diagnostic \\u2014 if the CPU stays low after a kill, the trigger is gone \\u2014 not as a fix.\"]}),`\n`,(0,e.jsx)(t.h3,{id:\"does-removing-the-widget-lose-anything\",children:\"Does removing the widget lose anything?\"}),`\n`,(0,e.jsxs)(t.p,{children:[\"Only the widget. Contacts, call history and suggestions in Spotlight and Messages all still work; \",(0,e.jsx)(t.code,{children:\"peopled\"}),\" still runs when needed. It just stops being asked to refresh something it cannot refresh.\"]}),`\n`,(0,e.jsx)(t.h3,{id:\"why-does-the-callhistorydb-folder-need-full-disk-access-to-read\",children:\"Why does the CallHistoryDB folder need Full Disk Access to read?\"}),`\n`,(0,e.jsx)(t.p,{children:\"It contains your call log, which macOS treats as sensitive personal data and protects with TCC like Messages and Mail. That protection is why Terminal needs the grant, and it is also why an unexpected quarantine flag on it is so disruptive: the daemon has one narrow, sandboxed path to the data, and anything that blocks that path blocks it entirely.\"}),`\n`,(0,e.jsx)(t.h3,{id:\"will-macos-27-fix-this\",children:\"Will macOS 27 fix this?\"}),`\n`,(0,e.jsx)(t.p,{children:\"Unknown. Apple has not acknowledged the problem, and there is nothing in the beta release notes about it. If the mechanism is what the evidence suggests, the fix is a small one \\u2014 fail once and stop retrying \\u2014 and it could arrive in any point release without being mentioned.\"}),`\n`,(0,e.jsx)(t.h2,{id:\"conclusion\",children:\"Conclusion\"}),`\n`,(0,e.jsx)(t.p,{children:\"A Mac that runs hot doing nothing almost always has one process in a loop, and the loop almost always has a mundane cause. This one is a daemon whose job is to keep a widget fresh, that is woken by every call and message, and that cannot read the one database it needs. Remove the widget and the requests stop; fix the folder's permissions and the reads succeed. Either breaks the loop.\"}),`\n`,(0,e.jsxs)(t.p,{children:[\"If you have \",(0,e.jsx)(t.code,{children:\"peopled\"}),\" at the top of Activity Monitor, work through the three fixes in order and restart between them. If it is \",(0,e.jsx)(t.code,{children:\"contactsd\"}),\" with an Exchange or Google account, remove the account. And if it is all three with \",(0,e.jsx)(t.code,{children:\"accountsd\"}),\" in front, try everything above, remove any account showing a warning, and \\u2014 because Apple has been silent on this for five months \\u2014 file the Feedback report, with the sandbox log line, that might finally get it fixed.\"]}),`\n`,(0,e.jsx)(t.p,{children:(0,e.jsxs)(t.em,{children:[\"Related reading: \",(0,e.jsx)(t.a,{href:\"/blog/mac-hot-battery-drain-after-macos-26-6-spotlight-siri-index-rebuild-fix-2026\",children:\"Mac hot and draining after macOS 26.6\"}),\", \",(0,e.jsx)(t.a,{href:\"/blog/windowserver-high-cpu-macos-tahoe-26-5-liquid-glass-multi-display-fix-2026\",children:\"WindowServer CPU on 26.5 with Liquid Glass\"}),\", \",(0,e.jsx)(t.a,{href:\"/blog/contacts-app-not-working-macos-tahoe-ghost-numbers-crashes-wont-save-fix-2026\",children:\"the Contacts app not working on Tahoe\"}),\", \",(0,e.jsx)(t.a,{href:\"/blog/mac-activity-monitor-complete-guide-2025\",children:\"Activity Monitor from the ground up\"}),\", and \",(0,e.jsx)(t.a,{href:\"/blog/macos-tahoe-widgets-customization-complete-guide-2025\",children:\"customising widgets on Tahoe\"}),\".\"]})})]})}function l(i={}){let{wrapper:t}=i.components||{};return t?(0,e.jsx)(t,{...i,children:(0,e.jsx)(c,{...i})}):c(i)}return k(v);})();\n;return Component;","toc":[{"title":"Key Takeaways","url":"#key-takeaways","depth":2},{"title":"Which Process, Exactly","url":"#which-process-exactly","depth":2},{"title":"What peopled Actually Does","url":"#what-peopled-actually-does","depth":2},{"title":"Why It Loops","url":"#why-it-loops","depth":2},{"title":"Confirm It Before You Change Anything","url":"#confirm-it-before-you-change-anything","depth":2},{"title":"Fix 1: Remove the Contacts Widget","url":"#fix-1-remove-the-contacts-widget","depth":2},{"title":"Desktop","url":"#desktop","depth":3},{"title":"Notification Center","url":"#notification-center","depth":3},{"title":"Control Center","url":"#control-center","depth":3},{"title":"Fix 2: Clear the Quarantine Flag on CallHistoryDB","url":"#fix-2-clear-the-quarantine-flag-on-callhistorydb","depth":2},{"title":"Step 1: give Terminal Full Disk Access","url":"#step-1-give-terminal-full-disk-access","depth":3},{"title":"Step 2: look at the folder","url":"#step-2-look-at-the-folder","depth":3},{"title":"Step 3: remove it","url":"#step-3-remove-it","depth":3},{"title":"Step 4: restart the daemons","url":"#step-4-restart-the-daemons","depth":3},{"title":"If the flag comes back","url":"#if-the-flag-comes-back","depth":3},{"title":"Fix 3: Toggle iCloud Contacts","url":"#fix-3-toggle-icloud-contacts","depth":2},{"title":"If It Is contactsd and You Have an Exchange or Google Account","url":"#if-it-is-contactsd-and-you-have-an-exchange-or-google-account","depth":2},{"title":"The accountsd Variant","url":"#the-accountsd-variant","depth":2},{"title":"Why Tahoe, and Why a Widget","url":"#why-tahoe-and-why-a-widget","depth":2},{"title":"After It Is Fixed","url":"#after-it-is-fixed","depth":2},{"title":"Is It Fixed Yet?","url":"#is-it-fixed-yet","depth":2},{"title":"What Not to Bother With","url":"#what-not-to-bother-with","depth":2},{"title":"Troubleshooting Common Issues","url":"#troubleshooting-common-issues","depth":2},{"title":"Activity Monitor shows twenty copies of contactsd","url":"#activity-monitor-shows-twenty-copies-of-contactsd","depth":3},{"title":"The Contacts widget is gone but peopled is still at 80%","url":"#the-contacts-widget-is-gone-but-peopled-is-still-at-80","depth":3},{"title":"xattr says \"No such xattr: com.apple.quarantine\"","url":"#xattr-says-no-such-xattr-comapplequarantine","depth":3},{"title":"ls on CallHistoryDB says \"Operation not permitted\" even with sudo","url":"#ls-on-callhistorydb-says-operation-not-permitted-even-with-sudo","depth":3},{"title":"It came back after a macOS update","url":"#it-came-back-after-a-macos-update","depth":3},{"title":"FAQ","url":"#faq","depth":2},{"title":"Is peopled malware?","url":"#is-peopled-malware","depth":3},{"title":"Can I just kill it?","url":"#can-i-just-kill-it","depth":3},{"title":"Does removing the widget lose anything?","url":"#does-removing-the-widget-lose-anything","depth":3},{"title":"Why does the CallHistoryDB folder need Full Disk Access to read?","url":"#why-does-the-callhistorydb-folder-need-full-disk-access-to-read","depth":3},{"title":"Will macOS 27 fix this?","url":"#will-macos-27-fix-this","depth":3},{"title":"Conclusion","url":"#conclusion","depth":2}],"estimatedTime":20}