Normal view

There are new articles available, click to refresh the page.
Before yesterdayMain stream

Inside the Unified Log 4: Log entries

By: hoakley
6 October 2025 at 14:30

For many years, I believed what the log command told me, that log entries could contain any of the 26 or more fields available, although they didn’t. It was only as I was developing utilities like LogUI that I discovered that log entries come in (at least) four types, each with its own format and set of fields. This article is a guide to those, and how they are displayed in LogUI.

Entry fields

Those available in the OSLog API are fewer in number than appear in log command output, and include some of limited interest. Those not exposed in LogUI include:

  • store category, which is invariably disk storage here.
  • format string, that used to format the contents of messages. This was introduced following serious security leaks in High Sierra.
  • components, linking in with the format string.

LogUI displays each entry using the same order of fields and colour-coding. Although they can’t all be seen together in any single log entry, the overall sequence is:

Standard levels are given as text, and chosen from one of the following: fault, error, notice, info, debug, undefined. These are only used with Regular log entries, not other types. LogUI always includes debug level entries when they’re available.

The four types of entry are:

  1. Regular
  2. Activity
  3. Boundary
  4. Signpost.

Regular entries

These are normally by far the most common, and are seen throughout the processes and subsystems writing log entries. They normally contain up to the following fields:
datestamp, [1], activity ID, category, level, sender, process, process ID, subsystem, thread ID, message

These examples include:
datestamp, 1, activity ID, category, level, sender, process, process ID, subsystem, thread ID, message
which is fairly normal.

Activities

These mark specific activities, and vary according to the process and subsystem. Some are valuable waypoints, and all are recognisably shorter than most regular entries, containing only the following fields:
datestamp, [2], activity ID, parent activity ID, sender, process, process ID, thread ID, message

These are examples of one of the most valuable activities reported, indicating a mouse-click or tap. They’re also complete, as they consist of:
datestamp, 2, activity ID, parent activity ID, sender, process, process ID, thread ID, message

Boundaries

These are rare but instantly recognisable because of their brevity. They consist of just three fields:
datestamp,[3], message

Two of the most important are the announcement of the start of kernel boot:

and adjustment of the internal clock:

These are also easy to search for, as their message contains the distinctive === string.

Signposts

By default, LogUI extracts omit Signposts, but if you tick the Show Signposts box before loading log entries, they will also be displayed. In parts, they can outnumber regular entries, and are unlikely to provide you with meaningful information unless you know internal details of their process. Each Signpost adds three type-specific fields, shown after the process ID:
datestamp, [4], activity ID, category, sender, process, process ID, signpost ID, signpost name, signpost type, subsystem, thread ID

These examples come from the most prolific user of Signposts, SkyLight for WindowServer, and contain
datestamp, 4, activity ID, category, sender, process, process ID, signpost ID, signpost name, signpost type, subsystem, thread ID
Note there’s no message field, as their meaning is determined by the signpost fields.

Datestamps and times

The OSLog API doesn’t currently give access to Mach times, only to opaque Date variables. From those, LogUI’s datestamps give:
year–month–day hour:minute:second.microsecond+timezone

All times and time zones given are those current when LogUI obtains that extract, not when that entry was written. This can become extremely confusing when clocks change to and from {summer time, daylight time, daylight saving time, daylight savings time, DST}, and when passing through time zones, and great care is required when reading logs containing such corrections. LogUI tries to make this easier, but care is still required.

If you have used the log command, you may be aware that can return Mach times as ticks, offering precision down to the nanosecond. This currently isn’t possible when using the OSLog API, but given the relatively slow clock of Apple silicon Macs, it’s no longer as useful as it used to be with Intel’s nanosecond Mach ticks.

Censorship

By default, all data in message fields is censored to protect the privacy of the user. This replaces chunks of text with the dreaded <private>, and can render many entries devoid of any useful information. In recent versions of macOS log privacy can be removed by installing a profile. However, that doesn’t apply retrospectively, only to log entries collected after the profile has been installed.

Removing privacy also increases the size in storage of log entries, and may reveal sensitive information. As soon as you have completed acquisition of the logs you need with privacy removed, you should therefore remove the profile, to allow normal censorship to resume.

A suitably signed profile is here: enablelogprivatedata

To install the profile, unzip the archive into a convenient folder and double-click it. You’ll be informed by a notification that you need to review the profile to install it. Open System Settings and select Device Management in its View menu, or search for it. Follow the instructions given there to install and activate it.

Sadly, this doesn’t cover all censorship. Some systems require additional configuration changes, for example CFNetwork diagnostic logging. Jeff Johnson explained how to enable that, but Apple has since blocked that, and I don’t know of a practical alternative. In some cases, additional detail can be obtained by adjusting log settings.

Summary

A short practical summary of LogUI’s log entries is provided in its Help book.

LogUI 1.0 build 74 adds a Diagnostics Tool for your logs

By: hoakley
1 October 2025 at 14:30

As promised earlier this week, I’m delighted to offer a new version of my log browser LogUI that provides a Diagnostics Tool to help you understand log folders and discover any problems with them.

Open its window using the Diagnostics Tool command in the Window menu, and you’re offered four tools at the top.

The first, Get Info, performs a simple analysis on the files in the selected diagnostics folder. By default, that’s your current live log, in the path /private/var/db/diagnostics, in your Data volume. After telling you how many log files there are in each of its three main folders, and the number of timesync files, it reports the date and time of the oldest Persist log file, marking the start of the continuous log record, in this case nearly 4 days ago.

You can use these tools on any diagnostics folder you can access through its dialog. This includes Time Machine backups, external boot disks, and other bootable systems. Don’t click on the Open button, though, until you’ve selected the diagnostics folder in the view above.

Locating the diagnostics folder in a Time Machine backup can be interesting, but once you’ve found it, LogUI will happily check it for you.

The Catalogue tool lists all the tracev3 log files in the folders inside diagnostics, starting with those in Persist. It gives each file’s creation and modification timestamps, indicating the range for log entries within them, their size in bytes, and an estimate of the period that file covers.

The Analyse tool extracts information from each of logd‘s statistics files, with the number of log entries broken down in frequency order. If you tick the CSV checkbox, they will be delivered in CSV format, ready to import into other software such as a spreadsheet.

The last of the tools, Save Text, saves the contents of the window to a text file for your records.

Further information about locations used for log files is in this article.

LogUI 1.0 build 74 is now available from here: logui174
from Downloads above, and from its Product Page.

Enjoy!

Inside the Unified Log 3: Log storage and attrition

By: hoakley
29 September 2025 at 14:30

By far the most common problem experienced with the Unified log isn’t its large number of entries, but a lack of entries. You go to check your Mac’s security using SilentKnight, or Skint runs its automatic daily check, and they can’t find any log entries recording XProtect Remediator scans. Since those are obtained by analysing the log for the previous 36 hours, when your Mac’s logs only go back 8-12 hours, entries for the last set of scans are likely to be missing. This article looks at why that happens, and how macOS maintains its log.

Traditional Unix-style logs are maintained according to their age. Every 24 hours, routine housekeeping procedures delete log files over a certain age, typically five days, in the process of rolling the log. Because the Unified log could over that five-day period have swallowed many GB of storage, its maintenance service logd deletes log records according to multiple criteria including the space they occupy, their age, and the type of entry. This is considerably more complex, and occurs in three phases, according to where the entry is stored.

Ephemeral entries

Log entries are initially written to memory, before logd writes most of them to permanent storage on disk.

mul102LogdFlow

The first substantial purging of entries thus occurs when logd decides which are ephemeral and won’t be written to disk. This can be seen by following the number of entries in a short period of high activity in the log, over time, and is shown in the chart below for a sample period of 3 seconds.

When fetched from the log within a minute of the entries being written, a total of 22,783 entries were recovered. Five minutes later there were only 82% (18,655) of those remaining. Attrition of entries then continued more slowly, leaving 80% (18,309) after 8 hours. Analysis suggests that over this period in which there were about 6,100 log entries per second written to disk, approximately 1,700 log entries per second were only kept in memory and never written to disk. That suggests about 22% were ephemeral, a proportion that’s likely to vary according to the origin and nature of log entries.

Persist entries

The great majority of log entries that survive to be written to permanent storage are kept in the tracev3 files in /private/var/db/diagnostics/Persist, where logd maintains them according to the total size of that folder, with a target of 520-530 MB. As each tracev3 file is up to 10.5 MB in size, that results in logd retaining about 50 files in that folder, although some are smaller than the maximum.

Two of my apps currently provide the datestamp of the start of the current collection of Persist log files as an indicator of the oldest log entry available from them: XProCheck, and Mints with its Logs button. This is a feature I intend adding shortly to LogUI.

However, not all log entries are stored in those Persist files. Looking back in time at total log entries available for a set ten minute period each day, you might see totals like:

  • 1 day old 33,827 in 10 minutes
  • 2 days old 98,534
  • 3 days old 59,296
  • 4 days old 10
  • 5 days old 1
  • 6 days old 40
  • 7 days old 0
  • 8 days old 358
  • 9 days old 1.

Those for the last 3 days are almost all Persist entries, but older entries are those retained in tracev3 files in the Special folder.

Special entries

Fault and Error log entries are normally written to the tracev3 files in the Special folder, and may contain additional message content kept in the warren of folders and files inside /private/var/db/uuidtext. logd purges entries from Special files separately, and apparently on the basis of their type and content rather than size. As a result, the Special folder can contain many tracev3 files of sizes ranging from over 2 MB to just a few KB, with their size tending to reduce with age. Any log entries recovered from dates before the oldest Persist file thus must have come from Special files.

Although files stored in the uuidtext folder are small, there can be a great many of them, and total size of that folder can exceed 1 GB. Those too are maintained by logd.

Other folders and files

tracev3 files stored in the Signpost folder contain only Signpost log entries used for performance assessment, and are purged at a slower rate than Persist files, but not retained as long as Special files. The High Volume folder appears seldom if ever used. The timesync folder contains time synchronisation data, small files that normally cover the whole period of Special files.

The /private/var/db/diagnostics folder contains several other files, including the logs of logd and logd_helper, and most significantly pairs of statistical summaries written during log maintenance, named logdata.statistics.[n] where n is a number starting from 0, in both .txt and .jsonl (JSON) format.

Each time logd performs maintenance on a tracev3 file, or on associated uuidtext files, it records data about the files in the current logdata.statistics files, both as plain text and in JSON format. The most useful of these records occurs when a Persist tracev3 file is rotated from being the file into which new log entries are written, to being retained without further additions. That entry records:

  • the name of the tracev3 file;
  • the time of rotation, thus the time immediately following the last log entry to be made to that file;
  • the total number of log entries in that file, for example 42,365,476;
  • for the top 20 processes that wrote entries in that period, the number of entries, the percentage of total entries, and the path to the process, listed in order of number of entries.

For example, in that tracev3 file containing a total of 42,365,476 entries, the kernel might have written 13,095,296 entries, 30.9%, and be top of the list, while runningboardd might only have written 1,223,157 or 2.9%. These statistics can be valuable in drawing attention to periods when there were problems, and for discovering which entries are limiting the coverage of Persist files, making it impossible for apps to recover entries for XProtect Remediator scans, for example.

Statistics entries for memory rollovers can also be useful, as are those for Special file rotation, although the latter contain fewer entries than Persist files.

Extending the period of log coverage

Currently, there doesn’t appear to be any way to set logd‘s size allowance for Persist files. When the Unified log was first introduced, it wasn’t unusual for that setting to preserve full log records covering a period of up to 20 days. As more processes now write copious entries in the log, a Mac that’s left awake and running at all times may only retain the last 20 hours of Persist entries, or even less.

Macs that don’t need to be awake and running at all times can extend their log coverage by sleeping or being shut down, when of course no entries can be written. If that isn’t possible, you can write your own XML property lists to /Library/Preferences/Logging to limit the retention of specific categories of entry. However, experience shows that only achieves small extensions to time coverage. It’s also worth bearing in mind that disabling privacy protection in the log will increase the size taken by most log entries, so shortening time covered by the retained logs.

Perhaps the wisest and most effective way to extend the time coverage of logs is to discover the causes of excess entries and address those, although that’s inevitably the most difficult solution.

One little-used technique is to turn log records in backups into logarchives, enabling old log entries to be accessed days or even years after they have been written. As an example of what can be achieved, the log entries below were written eight years ago, on 26 September 2017, saved in a logarchive, and browsed using LogUI on 26 September 2025.

I will explain how to do this in a future article in this series.

Summary

  • Log maintenance is a sophisticated managed process that discards log messages for several reasons, most generally to keep total log file size within limits, rather than removing entries purely on the basis of age.
  • A fifth of log entries are likely to be ephemeral, and lost from the log within the first minutes after they’re written. If you want the fullest entries possible, obtain the log excerpt as soon as possible after its entries have been written.
  • Most retained log entries are written in Persist logs, where tracev3 files are removed by age to keep their total size to just over 500 MB. Those should preserve log entries for hours or days after they’re written.
  • Entries for Faults and Errors are stored in Special logs, where they’re kept for longer, sometimes for weeks.
  • logdata.statistics files provide detailed statistics for log files as they’re rotated, and can tell you which processes wrote most entries.
  • As logs aren’t written during sleep, or when shut down, allowing sleep and shutting down will extend the duration of log records.
  • Time Machine and other backups can be used to recover old logs as logarchives.

Inside the Unified Log 2: Why browse the log?

By: hoakley
25 September 2025 at 14:30

Following the introduction of the Unified Log, a surprising number of folk you would expect to use it have stopped. Some experienced developers and those providing advice in Apple Support Communities seemingly take pride in their lack of log literacy, claiming that the log is now impossible to use, and only accessible to Apple’s engineers. While it does present obstacles, pretending that the log isn’t a vital tool in diagnosis and understanding is burying your head in the sand. This article shows why.

Why the log?

The log provides support for several purposes. It’s widely used to investigate events such as bugs and unexpected behaviours, to establish their cause before working out how to fix them, in diagnosis and troubleshooting. It’s also used to discover how subsystems within macOS work, and what they do. Examples of those include LaunchServices, DAS-CTS scheduling and dispatching, and RunningBoard, all of which are nearly invisible to other methods, but write copious and explicit entries in the log. With its precise time recording and special Signpost log entries, it’s also invaluable for measuring performance, hence in optimising code.

Concentrating on the log’s use in diagnosis, log entries can be used to answer most of the key questions:

  • What happened?
  • When did it happen?
  • Who made it happen?
  • How did it happen?
  • Why did it happen?
  • What can I do about it?

Diagnose a mystery update

To illustrate those in practice, I’ll use an example that happens to be fresh in my mind, the silent updating of XProtect data last week. The only two clues available outside the log were the fact that XProtect had been updated, and that had occurred at 06:46:43 GMT on the morning of 17 September. There was no record of this event anywhere else that might have given any better information on how it had occurred.

Browsing the log from one second earlier confirmed what and when that had happened. I quickly discovered who made it happen when I found the log entry
2025-09-17 06:46:42.615072 com.apple.duetactivityscheduler REQUESTING START: 0:com.apple.security.syspolicy.xprotect-update:7874AD
revealing that update had been accomplished by a background check scheduled and dispatched by DAS-CTS, and performed by an update service com.apple.security.syspolicy.xprotect-update.

That in turn fired up XProtectUpdateService, which recorded that it promptly completed and activated the update:
2025-09-17 06:46:42.695517 com.apple.xprotect Connecting to XProtectUpdateService
2025-09-17 06:46:42.744182 com.apple.security.XProtectFramework.XProtectUpdateService XProtectUpdateService booting
2025-09-17 06:46:43.157255 com.apple.security.XProtectFramework.XProtectUpdateService Attempting to apply update: [private]
2025-09-17 06:46:43.191178 com.apple.security.XProtectFramework.XProtectUpdateService Update completed. Activated update [private]

XProtectUpdateService initiated a connection to the iCloud service now used to update XProtect in Sequoia and later, but log entries didn’t show the update being downloaded from that source. Instead, there was an error reported in the entry
2025-09-17 06:46:43.193159 com.apple.syspolicy.activities Finished Xprotect update in 496.4100122451782 ms: Error Domain=XProtectUpdateError Code=2 "Activated update LocalUpdate[5315]" UserInfo={NSLocalizedDescription=Activated update LocalUpdate[5315]}

Although the messages in many of these log entries are opaque, that entry makes it clear that XProtectUpdateService hadn’t downloaded the new version from iCloud, but had activated a local update, which we know from experience means the copy already downloaded to the traditional XProtect location had been used to install that update in its new location. That used to be available to the user through the xprotect update command, but is no longer. Thus, the only way that update could have been installed was the result of com.apple.security.syspolicy.xprotect-update being run routinely.

If we can’t intervene and force the update manually, the final piece of information we need is how often com.apple.security.syspolicy.xprotect-update is run, and that’s revealed into a later log entry:
2025-09-17 06:46:43.202474 com.apple.duetactivityscheduler Submitted: 0:com.apple.security.syspolicy.xprotect-update:58B6CE at priority 5 with interval 86400 (Wed Sep 17 22:58:51 2025 - Thu Sep 18 18:58:51 2025)
i.e. every 86,400 seconds, or 24 hours.

Procedure

How difficult was that to discover? Even with minimal prior knowledge, consummately easy, and it only took a couple of minutes.

My starting point was the timestamp reported for the update by xprotect version, of 06:46:43 GMT. I therefore set LogUI to display 5 seconds of log starting from one second before that. In the screenshots below, times are shown in BST, one hour in advance of GMT.

This returned a total of 7,174 log entries, far too many to browse. Knowing that I was looking for entries concerning XProtect, I then typed that into the search box and pressed Return, to display only those entries whose message contained the text xprotect.

That narrowed down the number of entries to just 65, starting with the scoring and dispatch of com.apple.security.syspolicy.xprotect-update by DAS-CTS at 42.608967 seconds, and containing all the entries quoted above. Just to be certain that I hadn’t missed anything relevant, I then cleared the search box and pressed Return to display all log entries again, scrolled down to 42.608967 seconds, and checked through those for the period to 43.19315 seconds, when the update had completed.

Of course, not all log investigations are as simple or successful, but many are just as straightforward. The main limitation isn’t the excessive number of log entries, but those from subsystems that make very few entries, as occurs in Spotlight indexing and search. There’s always a way to filter out unwanted entries, but you can’t magic in entries that were never made in the first place.

Conclusions

Browsing the log might appear daunting, even overwhelming or terrifying at first, but as you become more familiar with it you appreciate the rich information it can provide. Log literacy is one of the basic skills required for anyone who wants or needs to dig deeper into their Mac or Apple device. Without it diagnosis, research and performance measurement are like trying to paint a landscape while wearing a blindfold.

Inside the Unified Log 1: Goals and architecture

By: hoakley
23 September 2025 at 14:30

The introduction of Mac OS X in 2000-01 brought conventional text-based logging to the Mac, with standard logs including system.log and console.log.

console2005

With the release of macOS 10.12 Sierra in 2016, those were almost completely replaced by the Unified Log, which has continued evolving since. Intended to provide a single efficient logging mechanism for user and kernel modes, its design goals are:

  • to maximise information collection with minimum observer effect;
  • as much logging on as much of the time as possible;
  • compression of log data for efficient use of space;
  • a managed log message lifecycle;
  • designed-in privacy protection;
  • to be common across all Apple’s operating systems;
  • all legacy APIs (NSLog, asl_log_message, syslog, etc.) to be redirected into the single log;
  • to support debugging, but not system administration or audit.

To achieve this, log entries are written using the OSLog API (or Logger from Swift), handled by the logd daemon and compressed into a buffer. From there entries are either retained in memory if intended to be ephemeral, or written out to a file. Log entries are only made from the start of kernel boot; earlier phases of the boot process instead save breadcrumbs that are largely inaccessible and unintelligible.

mul102LogdFlow

Performance of writing log entries is excellent, with a single process able to write sequential entries every 400 ns from a code loop, a rate of 2.5 million entries per second, although that rate is unlikely to be sustainable for long.

Log storage

There are two main groups of files that store log entries: those kept in /var/db/diagnostics/Persist/ in the form of tracev3 files containing regular log entries, and further tracev3 files in /var/db/diagnostics/Special/ containing additional shorter-life entries. Additional and lengthier log data can instead be stored in files named by UUID in /var/db/uuidtext/, and there’s also support for special Signpost entries intended for performance measurement, and scope for high-volume collection.

tracev3 files use a proprietary compressed binary format that remains undocumented to this day, but has been largely reversed. Apple’s APIs don’t give direct access to their contents, only through closed-source utilities such as the log command tool and programmatically through the OSLog API. Where users want a more portable format, Apple recommends conversion to a logarchive package, although that’s also undocumented and only directly accessible using log, the Console app and some third-party utilities. Logarchives still store all log entries in tracev3 files.

Collection and retention of entries from different subsystems is configured in logging profiles, XML property lists stored in /System/Library/Preferences/Logging (read-only, in the System volume) and /Library/Preferences/Logging, which the user controls. You can create your own custom profiles, or modify them on the fly using the log command.

The logd service maintains tracev3 files and their ancillaries, weeding them to remove time-expired entries. It does so to constrain the total size of log files in the system, rather than rolling them to retain all entries for a specified period. Most ephemeral entries are weeded within 5 minutes of being written to the log, leaving persistent entries to remain for the following days, depending on the volume of new entries being written. For example, in a 3 second period of collection, when all entries were obtained within a minute of being written, 22,783 entries were found. Five minutes after they had been written, only 82% of those remained, and over 8 hours later that had fallen to 80%, or 18,309.

Log content

In contrast to traditional text-based logs, entries in the macOS log contain structured data in set fields, such as the datestamp, subsystem and log message. The number of fields available from the log command has risen from 16 to over 25, but entries are constrained in which fields are available, according to their type. Currently there are four types, Regular, Activity, Boundary and Signpost.

Some log entries, notably those written to /var/db/uuidtext/, can have very long message fields, extending to dozens of lines. Among the most verbose is the com.apple.runningboard subsystem, which not infrequently writes the whole of its records for an app into the message field of a single log entry.

Privacy

Privacy protection censors content of log entries when they’re written, replacing sections of the message field with <private> in accordance with the formatting string for that message. This protection can be disabled, but as entries are censored when they’re written, that only affects those written after censorship has been removed, and can’t be applied retrospectively.

One significant change in macOS 26 Tahoe is that the message contents of all log entries written using the old NSLog interface are replaced with <private>, rendering them essentially useless. Since macOS 10.12.4, all access to log entries has required admin privileges.

Access

macOS provides users with two means of accessing entries in the log: the log command tool, and Console app. In common use, log generates text output, so losing the original data fields, one of the major advantages of the Unified Log. Console offers two methods of access: a live stream of entries, or browsing past entries in a saved logarchive.

I have four main tools that provide extensive log access:

  • LogUI, using the OSLog API and displaying entries as formatted SwiftUI Lists;
  • Mints, offering special-purpose browsers for Time Machine, APFS, and other domains;
  • Ulbow, using the log tool and displaying entries as formatted Rich Text using AppKit;
  • Consolation, using the log tool and displaying entries as formatted Rich Text using AppKit.

These are available from their product page, and here for Mints.

Which cores does Visual Look Up use?

By: hoakley
16 September 2025 at 14:30

A couple of weeks ago I estimated how much power and energy were used when performing Visual Look Up (VLU) on an Apple silicon Mac, and was surprised to discover how little that was, concluding that “it’s not actually that demanding on the capability of the hardware”. This article returns to those measurements and looks in more detail at what the CPU cores and GPU were doing.

That previous article gives full details of what I did. In brief, this was performed on a Mac mini M4 Pro running macOS Sequoia 15.6.1, using an image of cattle in a field, opened in Preview. powermetrics collected samples in periods of 100 ms throughout, and a full log extract was obtained to relate time to logged events.

Power use by CPU cores, GPU and neural engine (ANE) are shown in this chart from that article. This tallies against log records for the main work in VLU being performed in samples 10-24, representing a time interval of approximately 1.0-2.4 seconds after the start. There were also briefer periods of activity around 3.2 seconds on the GPU, 4.2 seconds on the CPU, and 6.6-7.1 seconds on the CPU. The latter correlated with online access to Apple’s SMOOT service to populate and display the VLU window.

To gain further detail, powermetrics measurements of CPU core cluster frequencies, active residencies of each core, and GPU frequency and active residency, were analysed for the first 80 collection periods.

Frequency and active residency

Cluster frequencies in MHz are shown in the chart above for the one E and two P clusters, and the GPU. These show:

  • The E cores (black) ran at a baseline of 1200-1300 MHz for much of the time, reaching their maximum frequency of 2592 MHz during the main VLU period at 1.0-2.4 seconds.
  • The first P cluster (blue), P0, was active in short bursts over the first 1.5 seconds, and again between 6.3-7.0 seconds. For the remainder of the period the cluster was shut down.
  • The second P cluster (red), P1, was most active during the three periods of high power use, although it didn’t quite reach its maximum frequency of 4512 MHz. When there was little core activity, it was left to idle at 1260 MHz but wasn’t shut down.
  • The GPU (yellow) ran at 338 MHz or was shut down for almost all the time, with one brief peak at 927 MHz.

This chart shows the total active residencies for each of the three CPU clusters, obtained by adding their % measurements. Thus the maximum for the E cluster is 400%, and 500% for each of the two P clusters, and 1,400% in all. These are broadly equivalent to the CPU % shown in Activity Monitor, and take no account of frequency. These show:

  • The E cores (pale blue) had the highest active residency throughout, ranging from as little as 30% when almost idle around 5 seconds, to just over 300% during the main VLU phase at 1.4 seconds.
  • The first P cluster (purple) remained almost inactive throughout.
  • The second P cluster (red) was only active during the periods of highest work, particularly between 1.0-2.4 seconds and again at 6.4-7.1 seconds. For much of the rest of the test it had close to zero active residency.

Taken together, these show that a substantial proportion of the processing undertaken in VLU was performed by the E cores, with shorter peaks of activity in some of the cores in the second P cluster. For much of the time, though, all ten P cores were either idle or shut down.

Load

Combining frequency and active residency into a single value is difficult for the two types of CPU core. To provide a rough metric, I have calculated ‘cluster load’ as
total cluster active residency x (cluster frequency / maximum core frequency)
where the maximum frequency of these E cores is taken as 2592 MHz, and the P cores as 4512 MHz. For example, in the sample period at 2.2 seconds, the P1 cluster frequency was 4449 MHz, and the total active residency for the five cores was 122%. Thus the P1 cluster load was 122 x (4449/4512) = 120.3%. Maximum load for that cluster would have been 500%.

The chart above shows load values for:

  • The E cluster (black) riseing to 150-260% during the peak of VLU activity, from a baseline of 20-30%.
  • The P0 cluster (blue) which never reached 10% after the initial sample at 0 seconds.
  • The P1 cluster (red) spiking at 90-150% during the three most active phases, otherwise remaining below 10%.

Caution is required when comparing E with P cores on this measurement, as not only is E core maximum frequency only 57% that of P cores, but it’s generally assumed that their maximum processing capacity is roughly half that of P cores. Even with that reservation, it’s clear that a substantial proportion of the processing performed in this VLU was on the E cores, with just one cluster of P cores active in short spikes.

Finally, it’s possible to examine the correlation between total P cluster load and total CPU power.

This chart shows calculated total P load and reported total CPU power use. The linear regression shown is
CPU power = 4.1 + (42.2 x total load)
giving a power use of 4,200 mW for a load of 100%, equating to a single P core running at maximum frequency.

Conclusions

  • Cluster frequencies and active residencies measured in CPU cores followed the same phases as seen in CPU power, with most of the processing load of VLU in the the early stage, between 1.0-2.4 seconds, a shorter peak at 6.6-7.1 seconds correlating with online lookup, and a small peak at about 4.2 seconds.
  • A substantial proportion of the processing performed for VLU was run on E rather than P cores, with P cores only being used for brief periods.
  • Visual Look Up used remarkably little of the capability of an M4 Pro chip.

How much power does Visual Look Up use?

By: hoakley
2 September 2025 at 14:30

Look in the log, and Visual Look Up (VLU) on an Apple silicon Mac apparently involves a great deal of work, in both CPU cores and the neural engine (ANE). This article reports a first attempt to estimate power and energy use for a single VLU on an image.

To estimate this, I measured CPU, GPU and ANE power in sampling periods of 100 ms using powermetrics, and correlated events seen there with those recorded in a log extract over the same period, obtained using LogUI. The test was performed on a Mac mini M4 Pro running macOS 15.6.1, using Preview to perform the VLU on a single image showing a small group of cattle in an upland field. Power measurements were collected from a moment immediately before opening the image, and ceased several seconds after VLU was complete.

When used like this, powermetrics imposes remarkably little overhead on the CPU cores, but its sampling periods are neither exact nor identical. This makes it difficult to correlate log entries and their precise timestamps with sampling periods. While powermetrics gives power use in mW, those measurements aren’t calibrated and making assumptions about their accuracy is hazardous. Nevertheless, they remain the best estimates available.

Log narrative

The first step in log analysis was to identify the starting time of powermetrics sampling periods. Although execution of that command left no trace in its entries, as it has to be run with elevated privileges using sudo, its approval was obvious in entries concluding
30.677182 com.apple.opendirectoryd ODRecordVerifyPassword completed
A subsequent entry at 30.688828 seconds was thus chosen as the start time for sampling periods, and all times given below as given in seconds after that time zero.

The following relevant events were identified in the log extract at elapsed times given in seconds:

  • 1.3 com.apple.VisionKit Signpost Begin: “VisionKit MAD Parse Request”
  • 1.3 com.apple.mediaanalysis Running task VCPMADServiceImageProcessingTask
  • 1.4 ANE started and an ObjectDetectionModel run for 0.2 s
  • 1.6 ANE activity and a NatureWorldModel run for 0.25 s
  • 2.0 ANE activity for 0.15 s
  • 2.4 ANE activity for 0.1 s
  • 8.1 ANE activity and a UnifiedModel run for 0.01 s
  • 8.1 PegasusKit queried Apple’s SMOOT service, the external connection used to populate the VLU window.

Thus, the ANE was run almost continuously from 1.4-2.2 seconds after the start of sampling, otherwise was used little over the total period of about 9 seconds. Over that period of activity, an initial model used to detect objects was succeeded by a later model to identify objects in a ‘nature world’.

Power and energy estimates

From the log record, it was deduced that the VLU was started in powermetrics sample 10 (1.0 seconds elapsed), and essentially complete by sample 75 (7.5 seconds elapsed), a period of approximately 6.5 seconds, following which power use was low until the end of the sampling periods. All subsequent calculations refer to that series of samples and period of time.

Sums, averages and maxima of power measurements for that period of 6.5 seconds are:

  • CPU 64,289 mW total, 989 mW average, 7,083 mW maximum (10 P cores)
  • GPU 3,151 mW total, 48 mW average, 960 mW maximum (20 cores)
  • ANE 1,551 mW total, 24 mW average, 671 mW maximum
  • total 68,991 mW total, 1,061 mW average, 7,083 mW maximum.

Thus for the whole VLU, 93% of power was used by the CPU, 4.6% by the GPU, and only 2.2% by the ANE.

For comparison, in the M4 Pro chip running maximal in-core loads, each P core can use 1.3 W running floating point code, and 3 W running NEON code. The chip’s 20-core GPU was previously measured as using a steady maximum power of 20 W, with peaks at 25 W.

As each power sample covers 0.1 seconds, energy used during each sampling period is power/0.1, thus the total energy used over the 6.5 second period of VLU is:

  • CPU 6.4 J
  • GPU 0.3 J
  • ANE 0.2 J
  • total 6.9 J.

Those are small compared to the test threads used previously, which cost 3-8 J for each P core used.

Power over time

Power used in each 100 ms sampling period varied considerably over the whole 10 seconds. The chart below shows total power for the CPU.

Highest power was recorded between samples 10-25, corresponding to 1.0-2.5 seconds elapsed since the start of measurements, and most events identified in the log. Later bursts of power use occurred at about 4.2 seconds, and between 6.6-7.1 seconds, which most probably corresponded to opening the info window and performing the selected look-up.

Almost all power use by the neural engine occurred between 1.5-2.1 seconds, correlating well with the period in which substantial models were being run.

Peak GPU power use occurred around 1.0-1.5 seconds when the image was first displayed, at 3.1-3.2 seconds, and between 6.5-7.4 seconds. It’s not known whether any of those were the result of image processing for VLU as GPU-related log entries are unusual.

Composite total power use demonstrates how small and infrequent ANE and GPU use was in comparison to that of the CPU.

Conclusions

Given the limitations of this single set of measurements, I suggest that, on Apple silicon Macs

  • power and energy cost of VLU is remarkably low;
  • the great majority of work done in VLU is performed in the CPU;
  • although use of the neural engine may result in substantial performance improvements, VLU doesn’t make heavy demands on the neural engine in terms of power or energy use;
  • VLU may appear impressive, but it’s not actually that demanding on the capability of the hardware.

What happens during startup?

By: hoakley
29 August 2025 at 14:30

With careful observation and a little knowledge of the startup sequence of an Apple silicon Mac, you can learn a lot about what can and can’t happen during that sequence. This article explains how, with examples from the log of a Mac mini M4 Pro.

In broad terms, startup of an Apple silicon Mac consists of the following sequence of events:

  • Boot ROM, which ends in DFU mode if there’s a problem, otherwise it hands on to
  • the Low-Level Bootloader (LLB) and iBoot (Stage 2), the firmware, that should end in validating and running
  • the kernel, which initially runs on a single CPU core before starting others up and launching launchd, and later
  • unlocking and accessing the Data volume, and progressing to
  • userspace.

The opening entry in the log is the boot announcement of
=== system boot:
followed by the boot UUID. There’s then a gap of 5 seconds or more before the next entry, which marks the start of kernel boot. Those seconds are the silent phase during which the LLB and iBoot are doing their thing. They don’t write to the Unified log, but leave fragments of cryptic information known as breadcrumbs, which you can’t make use of. The kernel then writes its usual welcome of
kprintf initialized
and the following four seconds or so are filled by log entries from the kernel.

Wallclock adjustment

During this phase, the system clock is synchronised, and wallclock time adjusted, usually twice in rapid succession. This is obvious by step changes in timestamp, usually putting the clock back by several seconds in the first sync, then putting it forward slightly in the second. These play havoc with the timestamps, as you can have two or even more instances of the same time being recorded in the log. Beware of the entries
=== system wallclock time adjusted

Early during the kernel phase, it starts up all the other CPU cores in the chip, and records that in the log. Entries become progressively more varied after launchd is loaded, and this first userspace boot (without Data volume access).

Data volume unlock

With FileVault enabled, by this stage macOS still doesn’t have access to the Data volume. That means all the code run so far, and almost all the data, are immutable, locked in the firmware or the Signed System Volume (SSV). The firmware does access LocalPolicy from another container in the internal SSD, and there’s always the NVRAM, but there’s no access to anything in /Library, including the many property lists there. This also means that processes running before the Data volume is unlocked and mounted can’t write to storage.

Around 10-15 seconds after the start of booting, the login window is displayed, ready for the user to enter their password. Once that has been entered, there’s a watershed moment:
30.845097 com.apple.loginwindow Attempting to unlock the data volume <LFVolume: 0x6000001b8e40: [UUID]: Data>
30.883172 "AppleSEPKeyStore":3814:0: Sending notification for volume [UUID] unlocked (action 1, handle -842987934)
30.885459 com.apple.login volume <LFVolume: 0x6000001b8e40: [UUID]: Data> was unlocked
30.886129 com.apple.loginwindow Unlocked data volume <LFVolume: 0x6000001b8e40: [UUID]: Data>
30.886154 com.apple.loginwindow FileVault volume unlocked, allow authorization
30.887562 com.apple.loginwindowLite -[LWLSystemUnlock unlockSystem]:439: Authorization was successful
30.887587 com.apple.loginwindowLite -[LWLSystemUnlock unlockSystem]:447: logging in user hoakley

The times on those entries were deliberately delayed, as I pressed the Return key for password entry after 30 seconds had elapsed, a good 10 seconds later than I could have done so.

Shortly after that, the kernel manager shuts down, a great many kernel space processes are handed over to continue in userspace, and you’ll then see the kernel report
userspace boot

Before the Data volume is unlocked, log entries are frequent, but hardly a torrent, at around 1,000 per second, and more than 25% of them are written by the kernel. Once the kernel has booted userspace and the Data volume is accessible, log entries are written far more frequently, at an average rate of 5,000 per second, often even higher, with less than 10% of them coming from the kernel.

Phase summary

  • Boot ROM, entering DFU mode or handing over to
  • Low-Level Bootloader (LLB) and iBoot (Stage 2) firmware, without log entries, handing over to
  • the kernel, with wallclock adjustments, until
  • Data volume unlocking, then into
  • userspace and access to /Library and user files.

What is a SEP panic?

By: hoakley
26 August 2025 at 14:30

In the last few months I have had reports from several whose Macs have experienced a “SEP Panic” rather than a regular kernel panic. Although the immediate effects are the same, and my previous advice on how to deal with a kernel panic still applies, this article looks in more detail at what should be exceedingly rare events.

Essentials

If your Mac restarts or shuts down spontaneously, or ‘freezes’ for you to force it to shut down, chances are that was a kernel panic. When it starts up again, look out for the dialog inviting you to send a report to Apple. Expand that so you can see the panic log, copy and paste that into a text document, and save it. That’s the only record you have of that report, and that provides valuable clues as to what went wrong and how you might go about fixing it.

Apple will not contact you in response to sending the panic log. If you want advice or assistance about your Mac, contact Apple Support, and ensure you have your copy of the panic log ready, as they’ll need to see it.

Secure enclave

No matter how secure you try to make an operating system, if its most precious secrets are being processed by the main CPU cores, an attacker will find a way to access them. The proven solution to this is to build in a separate part of the chip with its own processor, and isolate that from everything else – a secure enclave, with its own secure enclave processor, SEP, as patented by Apple 13 years ago.

Two Mac architectures have secure enclaves and SEPs: Intel Macs with T2 (and T1) chips, where the SEP is in the T2/T1, and Apple silicon Macs, where the SEP is an integral part of the chip. These handle several different security features, including biometrics in Touch ID, management of secure encryption keys including those for FileVault, and performing encryption and decryption for the internal SSD.

The SEP runs its own operating system, sepOS, thought to be a derivative of L4, and communicates with the rest of the chip using mailboxes. When the CPU needs something from the SEP, it posts a message in the SEP mailbox, then retrieves the response when the SEP has processed that request.

What could possibly go wrong?

Like all processors, the SEP can hit problems that it can only manage by a reset, and those will result in it panicking, which in turn provokes the kernel running on the CPU to panic. Those problems can result from anything from a hardware fault to a bug in sepOS.

The SEP in a T2 chip is also known to be vulnerable to some exploits including blackbird, which can be used to ‘jailbreak’ a device using checkra1n or with malicious intent.

Reading the SEP panic log

When a kernel panic is the result of a SEP panic, the panic log is different from normal, and contains considerable detail about the SEP and what went wrong with it. As usual, though, much of that information is cryptic to say the least.

The first line in the panic log confirms that the panic originated in the SEP
panic(cpu 1 caller 0xfffffe001f55e344): SEP Panic: […]

You’re then given the version of sepOS
Root task vers: AppleSEPOS-2772.140.4

Unfortunately, further down it disclaims knowledge of that
Firmware type: UNKNOWN SEPOS

The status of the SEP’s mailboxes are given
Mailbox status:
IDLE_STATUS: 0x00000008
INBOX0_CTRL: 0x00105601
OUTBOX0_CTRL: 0x00023301

and
Mailbox entries:
Unavailable
Mailbox queue pointers: […]

This is confirmed as a panic
Debugger message: panic

The version of macOS is given by build number, with details of the kernel running on the CPU
OS version: 24G90
Kernel version: Darwin Kernel Version 24.6.0: Mon Jul 14 11:30:29 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T6000

For a T2 chip, the kernel version given should be for a T8010
root:xnu-11417.140.69~1/RELEASE_ARM64_T8010

Apple silicon Macs should then confirm their iBoot versions, first the LLB (Stage 1) then iBoot Stage 2, and whether Secure Boot was used
iBoot version: iBoot-11881.140.96
iBoot Stage 2 version: iBoot-11881.140.96
secure boot?: YES

T2 SEPs don’t normally give an iBoot Stage 2 version, but provide information about the Intel (x86) host
iBoot Stage 2 version:
secure boot?: YES
roots installed: 0
x86 EFI Boot State: 0xe
x86 System State: 0x0
x86 Power State: 0x0
x86 Shutdown Cause: 0x5
x86 Previous Power Transitions: 0x20002000200
PCIeUp link state: 0x94721611

Information is provided about the task running on the CPU, which should normally be the kernel
Panicked task 0xfffffe1fb0037248: 0 pages, 654 threads: pid 0: kernel_task

Towards the end of the panic log are details about kernel extensions. In SEP panics, that includes the SEP Manager
Kernel Extensions in backtrace:
com.apple.driver.AppleSEPManager(1.0.1)[UUID]@0xfffffe001f5366e0->0xfffffe001f566a63

and
last started kext at 242997189818: com.apple.iokit.SCSITaskUserClient 500.120.2 (addr 0xfffffe001ce0f6a0, size 2206)
loaded kexts:

In the list of loaded kernel extensions that follows, ensure there are no third-party entries, unless your Mac is expected to load them.

Actions

Although you should take a SEP panic seriously, there’s no need to panic yourself. This doesn’t mean that your Mac’s SEP has died, has been attacked by malware, or has released all the secrets it protects. A single panic in isolation could well just be chance, and not indicative of anything serious.

Provided that your Mac starts up correctly and then runs normally, your only essential task is to ensure that you capture and keep a copy of the panic log. If you wish, you can run hardware Diagnostics, but I doubt whether that performs any specific test intended to detect problems in the SEP. If you have potentially problematic peripherals, or any third-party kernel extensions, then you should take the hint and try to eliminate them.

If your Mac suffers any further kernel panics, capture their panic logs, and contact Apple Support with those to hand. Alternatively, book your Mac into an Apple store or authorised service provider for them to check it out for you.

Summary

  • SEP panics are exceedingly rare, but are readily identified from the first line of the panic log.
  • Ensure you copy and save a copy of the panic log.
  • Much of the panic log will appear meaningless, but there is some information about version numbers and kernel extensions that may be helpful.
  • Follow the normal recommendations, considering hardware diagnostics, and updating/removing potentially troublesome peripherals and third-party kernel extensions.
  • If there are any further panics, capture those and obtain support from Apple.

References

How to deal with a kernel panic (this blog)
Apple, Platform Security Guide
Manu Gulati, Michael J Smith and Shu-Yi Yu, US Patent 8,832,465 B2, Security enclave processor for a system on a chip, filed 25 September 2012, granted 9 September 2014.
Tarjei Mandt, Mathew Soling and David Wang (2016), Demystifying the Secure Enclave Processor, Black Hat USA 16 (PDF)
Blackbird SEP exploit, Apple Wiki.

I’m very grateful to Joe, Marc and another for sharing their SEP panic logs.

How to check if your Apple silicon Mac is booting securely

By: hoakley
21 August 2025 at 14:30

There are so many controls in macOS that sometimes you can’t see the wood for the trees. This can leave uncertainty over essentials, such as whether your Apple silicon Mac really is properly secure, or maybe there’s something sinister going on with it? This is a question I’m asked not infrequently, usually when someone has been spreading disinformation or FUD (fear, uncertainty, doubt). So how can you check that your Mac is properly locked down and boots securely?

Quick checks

There are two quick checks that cover the essentials. First, open System Information and select the Controller section in Hardware.

This provides a brief summary of your Mac’s boot security, which should read as shown above. If you still need to use a kernel extension or similar, your Mac might show Reduced Security with Allow All Kernel Extensions enabled, but you should do everything you can to avoid that.

Secure Boot is controlled using Startup Security Utility in Recovery mode, and if you care to start up in that mode, you can confirm or correct its settings there.

bootsec2

Back in normal user mode, open Privacy & Security settings and ensure you have FileVault enabled there.

filevault3

SilentKnight also checks that XProtect/Gatekeeper checks are enabled, and that security data are up to date, giving you complete confidence.

Details

Although those should be sufficient for most, some want to go further and verify that their Mac’s boot process and security systems are also working correctly. To do that, shut your Mac down, wait ten seconds or so, and start up normally with the startup chime sounding at a known time. Enter your password, wait a few seconds for the Finder to get set up and running, and open LogUI. Set its time to that of the startup chime, and get the first 10 seconds or 10,000 log entries. You may need to adjust the seconds to capture the full boot sequence. When you have, look through the log and identify the following waypoints.

In each of these log entries, I have emboldened a word or two that you can copy from here and paste into LogUI’s Search box, then press Return. That will display the log entry, and sometimes others you might find relevant. Times are given here in seconds, with the startup chime occurring at about 37 seconds. Version numbers shown are those for macOS 15.6.

The start of boot is recorded as
37.562774 === system boot: [UUID]
and a little while after that, the kernel declares its version details
42.759300 Darwin Kernel Version 24.6.0: Mon Jul 14 11:30:40 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T6041
for macOS 15.6.

Further down you’ll come across more information about key security components, including the Trusted Execution Monitor
43.060422 [Log]: Code Signing Monitor Image4 Module Version 7.0.0: Fri Jul 11 16:51:29 PDT 2025; root:AppleImage4_txm-320.100.22~1090
43.060447 [Log]: build variant: txm.macosx.release.TrustedExecutionMonitor_Guarded-135.100.37

Then the iBoot firmware version
43.061758 iBoot version: iBoot-11881.140.96
43.061760 iBoot Stage 2 version: iBoot-11881.140.96

CoreCrypto support is vital, and another Image4 extension
43.137635 FIPSPOST_KEXT [133796636] fipspost_post:154: [FIPSPOST][Module-ID] Apple corecrypto Module v18.3 [Apple silicon, Kernel, Software, SL1]
43.242334 Darwin Image4 Extension Version 7.0.0: Mon Jul 14 11:23:46 PDT 2025; root:AppleImage4-320.100.22~2585/AppleImage4/RELEASE_ARM64E

You should see entries reporting the loading of security policy components
43.242343 Security policy loaded: AppleImage4 hooks (AppleImage4)
43.242961 Security policy loaded: Apple Mobile File Integrity (AMFI)
43.243092 Security policy loaded: Seatbelt sandbox policy (Sandbox)

The Secure Enclave Processor or SEP is another key component that has to be started up
43.264594 "AppleSEPKeyStore":326:0: starting (BUILT: Jul 14 2025 23:34:10) ("normal" variant 🌽 , 1827.120.2)
43.264639 "AppleSEPKeyStore":471:0: _sep_enabled = 1

Apple System Policy should follow a bit later
43.760156 Security policy loaded: Apple System Policy (ASP)
43.760188 AppleSystemPolicy has been successfully started

The root of the file system is then identified in two entries whose origins go right back to the start of Mac OS X
43.940643 BSD root: disk3s1
43.940644 , major 1, minor 13

And APFS mounts the root file system, using the SSV snapshot
43.941048 apfs_vfsop_mountroot:2984: apfs: mountroot called!
44.034685 apfs_vfsop_mount:2763: disk3s1 Rooting from snapshot with xid 1724240.

One of the most important entries comes shortly after that, where successful validation of the SSV’s root hash is reported
44.038830 authenticate_root_hash:642: disk3s1 successfully validated on-disk root hash

It’s now time to start user space processes, and for that launchd must be loaded so it can launch everything else
44.103761 load_init_program: attempting to load /sbin/launchd

How Secure Boot works

Apple silicon Macs have a small ROM to support DFU mode in case a full Restore is required, and to check and load the first stage of the ‘firmware’, the Low-Level Bootloader or LLB. Only if that matches its signature will the ROM firmware hand over to it and proceed with the boot process. The LLB in turn performs the same checks on the second stage ‘firmware’, iBoot proper. That goes on to check the kernel, before loading that and handing over for kernel boot to take over.

iBoot ‘firmware’ doesn’t write anything in the log, but once the kernel takes over its log entries provide a detailed account of its progress. The great majority of its log entries are unintelligible to anyone outside Apple, but the waypoints I have given above identify some of the most important steps it takes. When it’s ready, the kernel validates the root hash for the SSV snapshot, as noted above, enabling the boot process to proceed to load and run other parts of macOS. The remaining hash checking of the SSV, to confirm that it’s exactly as Apple intends, proceeds in a ‘lazy’ fashion, as access is needed to its contents.

This chain of validation before loading the next stage ensures that nothing in the boot process can be tampered with or changed, and the boot is secure throughout. Apple provides further details in its Platform Security Guide.

What does RunningBoard do? 5 Log insights

By: hoakley
7 August 2025 at 14:30

If RunningBoard’s copious log entries record the life cycle of apps, can we use them to our advantage? To test this out, I’ve analysed a section of log using waypoints and information provided in RunningBoard’s entries.

Waypoints, or landmarks if you prefer, are essential for navigating the log. In an ideal world we would always know when any significant event occurred, timed to the millisecond. In practice we may only be able to estimate to the nearest few seconds or minutes. Without some means of discovering exactly when to obtain log extracts, you can waste many hours trying to pin down when something happened, and in many cases will be forced to abandon the hunt.

Methods

My aim was to separate RunningBoard log entries into those handling its assertions, which should represent life-cycle events, and job descriptions giving details of apps launched. To try this yourself, open LogUI and set the Start date and time to the start of the period of interest. Set the Period to at least 100 seconds, and Max entries to 2,000 or more. Then set the Predicate popup menu to read subsystem, and type in com.apple.runningboard so that LogUI only gets entries from that subsystem. Click on the Get Log tool in the toolbar, and check you get at least 1,000 entries.

Click on the Save JSON tool to save the whole of this excerpt. To view all the RunningBoard assertions acquired over that excerpt, type acquiring assertion in the search box at the top right, and press Enter.

The window name then changes to append the text from the search box.

To save this limited selection of entries, first click on the Reduce tool to discard all the others, then click on the Save JSON tool again and save the entries using a different filename. Repeat that using each of three search terms:

  • acquiring assertion to see RunningBoard’s outline of life cycle events,
  • constructed job to see job descriptions for newly launched apps,
  • extension overlay to see similar information for appexes and similar extensions.

In my case, I analysed a period of 4 minutes of user activity on a Mac mini M4 Pro running macOS 15.6, during which there were 6,580 RunningBoard entries, suggesting that the whole log would have had well over 50,000 entries in that time, far too many to attempt any more detailed analysis. My search terms found 305 assertions acquired, 3 job descriptions constructed, and 20 extension overlays submitted.

Job descriptions

The three captured represented the three apps I had launched over those four minutes, Cormorant, DelightEd and Consolation 3. Each of them has a platform ID of 1, as notarized macOS apps. I also noticed that one was run in app translocation, although this was long after its first run. Recent versions of macOS, Sequoia in particular, appear prone to this, when an app that should have cleared quarantine gets stuck in perpetual app translocation.

Extension overlays

While I had expected to find those three app launches, I didn’t expect to see any appexes being run over this period. Those encountered consisted of three widgets, none of which had ever been opened, and five QuickLook thumbnail extensions. Most of these were run multiple times, with ScappleThumbnail appearing on six occasions. All were platform 1, except for the widgets, all three of which are bundled in macOS, for the FindMy widget and NewsToday2. They were platform 6, and subject to RunningBoard’s resource controls.

RunningBoard’s log entries here give potentially valuable insights that might otherwise be missed.

Assertions

It’s straightforward to construct a narrative of the key events that took place over that period of 4 minutes using a selection of assertions acquired. Rather than reproduce the whole of each of those waypoints, here they are laid out in more readable form.

11:40:50.424950 Acquiring assertion targeting app application.co.eclecticlight.Cormorant.10809046.10809052(501)
description "LS launch co.eclecticlight.Cormorant" ID:424-620-716
target: application.co.eclecticlight.Cormorant.10809046.10809052(501)
attributes: domain:"com.apple.launchservicesd" name:"LaunchRoleUserInteractive" sourceEnvironment:"(null)"

This marks the start of the launch process for Cormorant, handled in the normal way through LaunchServices and RunningBoard.

11:41:18.304367 Acquiring assertion targeting app application.co.eclecticlight.DelightEd.10206240.10206246(501)
description "LS launch co.eclecticlight.DelightEd" ID:424-620-756
target: application.co.eclecticlight.DelightEd.10206240.10206246(501)
attributes: domain:"com.apple.launchservicesd" name:"LaunchRoleUserInteractive" sourceEnvironment:"(null)"

This is the same for DelightEd.

11:41:20.050166 Acquiring assertion targeting [xpcservice com.apple.appkit.xpc.openAndSavePanelService([app application.co.eclecticlight.DelightEd.10206240.10206246(501) :1553])(501) 1576:1576]
description "viewBridge:1576" ID:424-391-769
target: 1576
attributes: domain:"com.apple.launchservicesd" name:"RoleViewBridge" sourceEnvironment:"(null)"

DelightEd is here being used to open a document using the openAndSavePanelService, a separate process.

11:41:44.171636 Acquiring assertion targeting app application.co.eclecticlight.Consolation3.430650.430692(501)
description "LS launch co.eclecticlight.Consolation3" ID:424-620-788
target: application.co.eclecticlight.Consolation3.430650.430692(501)
attributes: domain:"com.apple.launchservicesd" name:"LaunchRoleUserInteractive" sourceEnvironment:"(null)"

This is the launch of Consolation 3, a user error on this occasion!

Two long runs of assertions were discovered, both involving syncing the address book for Contacts.

11:41:57.462118 Acquiring assertion targeting [osservice com.apple.AddressBook.SourceSync(501):1610]
description "App is holding power assertion" ID:424-362-811
target: 1610
attributes: domain:"com.apple.appnap" name:"PowerAssertion" sourceEnvironment:"(null)", RBSAcquisitionCompletionAttribute policy:AfterApplication

The first of these was to sync the Address Book with its source in iCloud, and lasted 12.181 seconds.

11:42:11.840349 Acquiring assertion targeting [osservice com.apple.AddressBook.abd(501):1625]
description "Contacts shared filesystem lock" ID:424-1625-857
target: 1625
attributes: domain:"com.apple.common" name:"FinishTaskUninterruptable" sourceEnvironment:"(null)", RBSAcquisitionCompletionAttribute policy:AfterApplication

Shortly after that completed, synced data was updated by a service abd (Address Book Daemon?) that I had been unaware of. This only lasted 2.238 seconds.

RunningBoard’s assertions seldom appear for single-shot shell commands, and most commonly handle executable bundles rather than bare Mach-O binaries. They also don’t appear to provide clear information recording when apps are quit normally.

Conclusions

  • RunningBoard entries can readily provide accurate waypoints for many events in the log.
  • Establishing waypoints on the strength of RunningBoard log entries is straightforward in LogUI.
  • Job descriptions are readily found, and provide useful information on apps launched.
  • Extension overlays provide details of appexes that might otherwise be overlooked.
  • Acquisition of assertions identify various events in the app life cycle.
  • Once RunningBoard entries have provided precise times of events, attention can be focussed on obtaining more detail using short log extracts.

Last Week on My Mac: Search and you’ll find

By: hoakley
3 August 2025 at 15:00

One thing we humans are good at is searching. It’s a task we engage in from a few moments after birth until the time we slip away in death, we search everything around us. Locating and identifying that bird of prey wheeling high, finding the house keys, and that book we mislaid some time last week, meeting the perfect partner, discovering the right job, choosing the best education, looking through a Where’s Wally? or Where’s Waldo? book, and so on. Searching has transformed some into explorers like Christopher Columbus, and was the purpose of the chivalric quest. It’s what researchers in every field do, and thanks to Douglas Adams can be answered by the number 42.

Last week my searching took two new turns.

Spotlight

The first was more of a meta-search, in trying to discover more about the internals of Spotlight. Following the example of Maynard Handley, who has used them so successfully in understanding how M-series CPUs work, I looked through patents that have been awarded to Apple for the work of its search engineers. Yesterday’s slightly fuller history of Spotlight search is one result, and there are more to come in the future as I digest those patents concerned with performing search.

There’s a tinge of irony here, as many of my searches have been conducted using Google Patents, alongside Google Scholar one of the remaining search engines that doesn’t yet use AI and attempt to provide its own answers.

Logs

The other marks a new phase in my quest to get more information from the Unified log. Looking back to my first comment here, I realise how wildly over-optimistic I was when I wrote that it “should make my life a lot easier”, and that “a new version of Console will provide improved features to help us wade through logs.” Nine years later, I look wistfully at what remains of Console and realise how wrong I was on both counts.

When RunningBoard arrived in macOS Catalina, I soon noticed how “its log entries are profuse, detailed, and largely uncensored for privacy.” Since then it has proved garrulous to the point where its apparently ceaseless log chatter is a distraction, and can overwhelm attempts to read other log entries. I suspect it has contributed significantly to those advanced Mac users who now refuse to even try to make sense of the log.

One answer might be to tweak log preferences to shut out this noise, but given the purpose of RunningBoard in monitoring the life cycle of apps, why not try to use the information it provides? To do that, it’s first necessary to understand RunningBoard’s idiosyncratic language of assertions, and its protocols under which they’re acquired. The only way to do that without documentation is by observation: catalogue over 30 of those assertions for an interesting example like Apple’s Developer app, and see what they reveal.

By far the most informative entries from RunningBoard are those announcing that it’s acquiring an assertion, such as
Acquiring assertion targeting [app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946] from originator [osservice<com.apple.uikitsystemapp(501)>:748] with description <RBSAssertionDescriptor| "com.apple.frontboard.after-life.subordinate" ID:424-748-2228 target:2946 attributes:[
<RBSDomainAttribute| domain:"com.apple.frontboard" name:"AfterLife-Subordinate" sourceEnvironment:"(null)">
]>

In a log often censored to the point of being unintelligible, this contains frank and explicit detail. The app is identified clearly, with the user ID of 501 and process ID of 2946. The originator is similarly identified as com.apple.uikitsystemapp with its PID of 748, which is confirmed in the middle digits in the Assertion ID. This is explicitly related to FrontBoard and an attribute named AfterLife-Subordinate. There’s not a single <private> to blight this entry, although further knowledge is needed to decode it fully.

Normally to get such information from a running process would require its source code to be instrumented with calls to write log entries, many of which would be lost to <private>, yet RunningBoard seems happy, for the moment, to provide that information freely. You can see what I mean by applying the predicate
subsystem == "com.apple.runningboard" AND message CONTAINS "Acquiring assertion t"
in LogUI, to obtain a running commentary on active apps and processes. Once you’ve identified a relevant assertion, you can focus attention on other log entries immediately prior to that. I will be following this up in the coming week, with fuller instructions and some demonstrations.

Although neither patents nor assertions have the significance of the number 42, in their own ways they show how the art and science of search aren’t dead yet, nor have they succumbed to AI.

What does RunningBoard do? 4 Assertions

By: hoakley
31 July 2025 at 14:30

This week’s dive into RunningBoard tackles one of the central questions: this subsystem repeatedly uses the term assertion, but what are these assertions, and how does RunningBoard handle them?

In computing, assertions may have their origin in hardware verification languages like Verilog, where they’re used to state required conditions in declarative form. They appear to have entered macOS through the background service assertiond, which made a name for itself as a killer of processes and apps. Power assertions have been noted in the log and elsewhere for at least the last decade, and are mentioned in IOPMLib, part of IOKit. Since macOS Catalina, assertions have been at the centre of RunningBoard, which remains essentially undocumented.

Developer app

To get a better idea of how assertions are used, I launched Apple’s Developer app on a Mac mini M4 Pro running macOS 15.5, and followed log entries for a period of over 14 seconds from the start of the launch process. Although RunningBoard’s job description records this app’s platform as 6, typical of a Catalyst app, in other log entries it’s claimed not to be a Catalyst app.

At an arbitrary start time of 01.126 seconds, LaunchServices decided to launch this app initially through CoreServicesUIAgent, which 0.04 seconds later requested RunningBoard to execute the launch request. This eventually led to a connection being initialised to FrontBoard Scene Manager, where the app was registered as a new scene, and activated.

Example assertion

FrontBoard set the process visibility to Foreground:
01.593239 com.apple.FrontBoard [app<application.developer.apple.wwdc-Release.9312198.9312203~>:2946] Setting process visibility to: Foreground

RunningBoard then announced it was acquiring a new assertion, giving its descriptor and the PID of the target process
01.593248 com.apple.runningboard Acquiring assertion: <RBSAssertionDescriptor| "com.apple.frontboard.after-life.subordinate" ID:(null) target:2946>
01.593288 com.apple.runningboard PERF: Received request from [osservice<com.apple.uikitsystemapp(501)>:748] (euid 501, auid 501) (persona (null)): acquireAssertionWithDescriptor:error:
01.593289 runningboardd acquireAssertionWithDescriptor

A fuller description followed, including the RunningBoard ID, and the attributes of the assertion
01.593324 com.apple.runningboard Acquiring assertion targeting [app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946] from originator [osservice<com.apple.uikitsystemapp(501)>:748] with description <RBSAssertionDescriptor| "com.apple.frontboard.after-life.subordinate" ID:424-748-2228 target:2946 attributes:[
<RBSDomainAttribute| domain:"com.apple.frontboard" name:"AfterLife-Subordinate" sourceEnvironment:"(null)">
]>

This assertion was made active, and RunningBoard stated how many assertions were currently targeting that process
01.593343 com.apple.runningboard Assertion 424-748-2228 (target:[app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946]) will be created as active
01.593389 com.apple.runningboard app<application.developer.apple.wwdc-Release.9312198.9312203(501)> is now targeted by 11 assertions

That triggered a state update for the process
01.593400 runningboardd state update

In this case, RunningBoard couldn’t do anything, so left the process’s assertions as they were
01.593461 com.apple.runningboard _checkForSuspendableAssertionCycle for app<application.developer.apple.wwdc-Release.9312198.9312203(501)> bailing out since it's not holding a suspendable assertion
01.593466 com.apple.runningboard Removing 0 assertions

This did, though, alter the inheritance of existing assertions
01.593556 com.apple.runningboard Process: [app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946] has changes in inheritances: {(
<RBSInheritance| environment:(none) name:com.apple.launchservices.userfacing origID:424-391-2215 0>,
<RBSInheritance| environment:(none) name:com.apple.launchservices.userfacing origID:424-391-2215 0>,
<RBSInheritance| environment:(none) name:com.apple.launchservices.userfacing origID:424-391-2214 0>,
<RBSInheritance| environment:(none) name:com.apple.frontboard.visibility origID:424-420-2216 0>
)}

This completed the acquisition of this assertion, and the process’s new state was calculated
01.593564 com.apple.runningboard Finished acquiring assertion 424-748-2228 (target:[app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946])
01.593741 com.apple.runningboard Calculated state for app<application.developer.apple.wwdc-Release.9312198.9312203(501)>: running-active (role: UserInteractiveFocal) (endowments: <private>)

This was all accomplished in around 0.0005 seconds. FrontBoard then continued processing the app’s scene
01.593743 com.apple.FrontBoard Ingesting properties from UIApplicationSceneSettings...

RunningBoard assertion numbers are of the form 424-748-2228, where the second group 748 is the PID of the source of the assertion, and the third group 2228 is a sequential number.

Assertions recorded

  • Assertion 424-620-2211 for LaunchServices to launch the app. For this, RunningBoard created its job description with its process ID of 2946, assigned it memory limits, stated the process will be managed, and stated it was running-active with a role of UserInteractive.
  • Assertion 424-424-2212 RunningBoard Underlying Assertion. RunningBoard stated the process will be created as active, calculated its processStartTime, created a new RunningBoard Coalition with an ID of 4460, set its Jetsam priority to 0 (the lowest priority over memory use), and set its Darwin GPU to “deny”. Its state was given as running-interactive-NotVisible with a taskState of 4.
  • Assertion 424-391-2213 foregroundApp 2946. This changed its role to UserInteractiveNonFocal, and was repeated in assertion 424-391-2214.
  • Assertion 424-391-2215 frontmost 2946. RunningBoard changed it to running-active-NotVisible, with a Jetsam priority of 100 (extremely unlikely to be killed to free memory), and Darwin GPU to “allow”.
  • Assertion 424-391-2217 LaunchServices notification. It was changed to running-active with a role of UserInteractiveFocal, handshaking took place with the process, and the launch request was recorded. Slightly later, RunningBoard announced it had started “death monitoring” of the process, in case its launch request was denied and the process was killed.
  • Assertion 424-748-2218 FrontBoard Bootstrap Background. Following this, the process acquired its first power assertion ID 34241, outside of RunningBoard.
  • Assertion 424-2946-2219 Shared Background Assertion
  • Assertion 424-655-2220 File Coordination Claim, the first of a series of five similar assertions. For each, RunningBoard recorded Prevent Task Suspend, Prevent Task Throttle Down. After the last it checked for a Suspendable Assertion Cycle, then removed several assertions held for the process.
  • Assertion 424-2946-2227 App Nap adapter assertion. RunningBoard then enabled and configured AppNap for the process, and set the AppNap state.
  • Assertion 424-748-2228 FrontBoard AfterLife-Subordinate. This is the assertion detailed above.
  • Assertion 424-748-2229 FrontBoard Visibility Workspace Foreground Focal. With this, RunningBoard set the process to running-active-Visible with taskState 4.
  • Assertion 424-420-2230 App Drawing. Following that, storekitagent was running as PID 2947, accompanying the Developer app.
  • Assertion 424-2946-2232 CFNetwork StorageDB.
  • Assertion 424-2946-2233 System Animation Fence.
  • Assertion 424-420-2234 App Visible. Following that, uikitsystemapp was drawing, presumably for the Developer app.
  • Assertion 424-420-2236 FuseBoard Process Window State Visible.
  • Assertion 424-2946-2238 system animation fence, which was repeated a total of five times.
  • Assertion 424-2946-2244 Shared Background Assertion 1, following which were two more assertions for system animation fence.
  • Assertion 424-2946-2247 com.apple.CFNetwork.StorageDB again.
  • Assertion 424-655-2248 File coordination claim, repeated in Assertion 424-655-2250.

All these assertions were completed in 14 seconds.

Reading RunningBoard

As shown in the series of assertions recorded in the log for the Developer app, RunningBoard provides a detailed account of milestones through the launch and early running of this app, covering much other than its security and TCC activity.

This starts with a job description containing a great deal of useful information about the app, when it’s neither visible nor focal. At that stage it’s given a minimal Jetsam priority, putting it in the front line to be forcibly quit if memory was short, and it’s denied access to the GPU. As launch proceeds, its Jetsam priority is raised to 100 and it’s allowed GPU access. Its role is then changed to UserInteractiveFocal, its window management is handled by FrontBoard and it becomes visible, and able to undergo AppNap. Two supporting services are engaged, storekitagent to handle its data, and uikitsystemapp to draw its interface.

Once the novelty of RunningBoard had worn off, I had come to consider its incessant chatter in the log as a distraction. However, a log extract obtained with the subsystem set to com.apple.runningboard provides a detailed account of events during an app’s life cycle, without the nuisance of privacy censorship, or the app having to make its own log entries.

Key points for close reading of the log

  • Set a predicate for obtaining log entries for the com.apple.runningboard subsystem, and initially filter entries on Acquiring assertion in the Messages field.
  • Identify the Process ID of interest.
  • Track assertion descriptions, giving the reason for each assertion.
  • Note assertion IDs, and interpret them with the aid of the PID given in their second number field.
  • Follow assertions for linked processes through their PIDs.

Updates for file integrity (Dintch/Fintch), compression (Cormorant) and LogUI build 70

By: hoakley
14 July 2025 at 14:30

This is the last batch of ‘simple’ updates to my free apps to bring them up to the expectations of macOS 26 Tahoe. With them comes a minor update to my log browser LogUI, which is recommended for all using Tahoe, as it fixes an annoying if fundamentally cosmetic bug.

Preparing these updates for release was a little troublesome, as I attempted this using developer beta 3 of Tahoe and Xcode 26 beta 3. Little did I realise when I got all four rebuilt, tested and notarized, that this combination had stripped their shiny new Tahoe-compliant app icons. That made these new versions unusable in Sequoia and earlier, as they each displayed there with the generic app icon, despite working fine in Tahoe.

Eventually I discovered that I could build fully functional versions using Xcode 26 beta 2 in Sequoia 15.5, so that’s how they have been produced.

File integrity

Five years ago I build a suite of two apps and a command tool to enable checking the integrity of file data wherever it might be stored. This uses SHA256 hashes stored with each checked file as an extended attribute. At that time, the only alternative saved hashes to a file in the enclosing folder, which I considered to be suboptimal, as it required additional maintenance whenever files were moved or copied to another location. It made more sense to ensure that the hash travels with the file whose data integrity it verifies.

The three are Fintch, intended for use with single files and small collections, Dintch, for larger directories or whole volumes, and cintch, a command tool ideal for calling from your own scripts. As the latter has no interface beyond its options, it continues to work fine in macOS 26.

Since then other products have recognised the benefits of saving hashes as extended attributes, although some may now use SHA512 rather than SHA256 hashes. What may not be apparent is the disadvantage of that choice.

Checking the integrity of thousands of files and hundreds of GB of data is computationally intensive and takes a lot of time, even on fast M4 chips. It’s therefore essential to make that as efficient as possible. Although checksums would be much quicker than SHA256 hashes, they aren’t reliable enough to detect some changes in data. SHA algorithms have the valuable property of amplifying even small differences in data: changing a single bit in a 10 GB file results in a huge change in its SHA256 hash.

At the same time, the chances of ‘collisions’, in which two different files share the same hash, are extremely low. For SHA256, the probability that two arbitrary byte sequences share the same hash is one in 2^256, roughly one in 1.2 x 10^77. Using SHA512 changes that to one in 2^512, which is even more remote.

However, there ain’t no such thing as a free lunch, as going from SHA256 to SHA512 brings a substantial increase in the computational burden. When run on a Mac mini M4 Pro, using its internal SSD, SHA256 hashes are computed from files on disk at a speed of around 3 GB/s, but that falls to 1.8 GB/s when using SHA512 hashes instead.

dintchcheck14

Dintch provides two controls to optimise its performance: you can tune the size of its buffer to cope best with the combination of CPU and storage, and you can set it to run at one of three different QoS values. At its highest QoS, it will run preferentially on Apple silicon P cores for a best speed of 3 GB/s, while run at its lowest QoS it will be confined to the E cores for best energy economy, and a speed of around 0.6 GB/s for running long jobs unobtrusively in the background.

The two apps and cintch are mutually compatible, and with their earlier versions going back to macOS El Capitan. In more recent versions of macOS they use Apple’s CryptoKit for optimum performance.

Dintch version 1.8 is now available from here: dintch18
Fintch version 1.4 is now available from here: fintch14
and from their Product Page, from where you can also download cintch. Although they do use the auto-update mechanism, I fear that changes in WordPress locations may not allow this to work with earlier versions.

Compression/decompression

Although I recommend Keka as a general compression and decompression utility, I also have a simple little app that I use with folders and files I transfer using FileVault. This only uses AppleArchive LZFSE, and strips any quarantine extended attributes when decompressing. It’s one of my testbeds for examining core allocation in Apple silicon Macs, so has extensive controls over QoS and performance, and offers manual settings as well as three presets.

Cormorant version 1.6 is now available from here: cormorant16
and from its Product Page. Although it does use the auto-update mechanism, I fear that changes in WordPress locations may not allow this to work with version 1.5 and earlier.

LogUI

Those using this new lightweight log browser in Tahoe will have discovered that, despite SwiftUI automatically laying out its controls, their changed sizes in Tahoe makes a mess of the seconds setting for times. This new version corrects that, and should be easier to use.

LogUI version 1 build 70 is now available from here: logui170

There will now be a pause in updates for macOS Tahoe until Apple has restored backward compatibility of app icons, hopefully in the next beta-releases.

一个 INJT 的工作室里有什么?

By: Steven
27 April 2025 at 20:40

这期视频,是我的工作室 Roomtour。

第一部分,介绍了空间内的四个大件;

第二部分,向观众交待近半年的情况;

第三部分,聊了正在开展的艺术项目。

视频的最后,给设计师观众们留下了一个问题。

🎥 观看视频:https://www.bilibili.com/video/BV1XEjAzREam/

🎥 观看视频:https://youtu.be/ZieOsQ1dFeI

误入 Autumn leaves 音乐现场的观众(C调)vlog.74

By: Steven
24 February 2025 at 20:07

【曲目】Autumn leaves

【场地】一方音乐·深圳龙岗

【鼓手】阿吉

【吉他】筱烨、秋夏

【键盘】菜菜

【贝斯】苏志斌

点击这里跳转到 BiliBli 观看:https://www.bilibili.com/video/BV1ZYAReSEv4

点击这里跳转到 Youtube 观看:https://youtu.be/W5ytb1LRvhM

在 github 架设 hugo blog(纯浏览器操作)

By: fivestone
11 November 2024 at 21:12

我其实对 Hugo 不熟,不知道这算不算重新发明了一遍轮子。但我搜索「如何在 github 上,用 hugo 架设自己的 blog?」时,搜到的教程,都需要用户在自己的电脑上,安装运行各种 git 和 hugo 的相关命令,感觉对新手并不友好。所以,我试着写了一个流程,让新人完全只需要在网页浏览器上操作,就能快速生成自己的 blog 网站。

所有操作都在 Github 这个项目上进行:
https://github.com/fivestone/hugo-papermod-beginning

这个项目本质上,就是搭了一个空白的 hugo 网站,让用户 fork 到自己的账户下,设置一下就能直接使用。对功能和界面有什么额外要求的话,请自行学习 hugo 的进阶教程。——然后你们就不是需要用这个项目的新人啦~

  • 本项目基于 hugo 博客引擎,和流行的 PaperMod 主题
  • 在 github 上建立的 blog,在墙内是不能直接访问的,需注意

1. 创建 github 账号

首先,注册自己的 github 账号,过程略。注册过程中,你设置的账户名 username,通常就是最终的网站地址 username.github.io,当然以后也可以把自己的域名映射到上面。

2. 架设自己的 blog 项目

注意,这一步,有两种方法

  • 第一种方法:你建一个全新的项目,下载我提供的 .zip 文件,解压后,再手动上传到你的项目。和第二种相比,稍微繁琐一点。但还是希望大家,有条件的话,使用这种方法。
  • 第二种方法,把我的这个项目,fork 到你的项目。这种方法对新人更简便,完全不需要在本地操作文件,只用手机或 pad 就可以完成。但这种 fork 在一起的项目,在进行自动发布 blog 的操作时,是共享同一个操作额度的。如果 fork 的人数非常多,未来可能会被 Github 限制。——要达到这种规模,大概要几千人同时用吧……所以也不需要很在意。
2.1. 第一种方法

注册并登入账号后,新建自己的项目(Repository)。

项目的名称,决定了最终 blog 的网址。假设你的 github 用户名为 username

  • 如果把项目命名为 username.github.io ,则最终的网站地址为
    https://username.github.io/
  • 如果把项目设置成其它名字,如 new-name,则最终的网站地址为
    https://username.github.io/new-name

确认项目为 Public。其它设置都不需要更改,点击绿色按钮创建。

创建项目后,点击「上传已有的文件」

我的 github 项目,下载已经设置好的 hugo 文件包,在本地解压缩 .zip 文件。然后,把里面的所有文件,拖拽上传到你的项目里。

等到 80 多个文件都被上传后,别忘了点击页面底部的 Commit changes 提交。

2.2. 第二种方法

注册并登入账号后,进入项目:
https://github.com/fivestone/hugo-papermod-beginning
点击 Fork,将这个模板复制到你自己的账号下。

和第一种方法一样,这里需要设置你自己的项目名称,假设你的 github 用户名为 username

  • 如果把项目命名为 username.github.io ,则最终的网站地址为
    https://username.github.io/
  • 如果把项目设置成其它名字,如 new-name,则最终的网站地址为
    https://username.github.io/new-name

然后点击 Create fork 创建项目。


3. 配置自动发布 blog

创建新项目后,进入项目的 Settings – Pages 页面,把 Build and deployment – Source,改为 GitHub Actions。

把 Source 从 Deploy from a branch,改为 GitHub Actions 后,进入上方的 Actions 页面。

初次进入 Actions 页面后,会显示 Github 预设的各种配置方案,通过搜索框找到 hugo,然后点击 hugo 方案中的 Configure

系统会自动生成配置文件,不需要做任何改动,点击绿色的 Commit changes 提交。

此时自动发布的 action / workflow 就已经开始运行了,大约 1~2 分钟后,就可以在
https://username.github.io 看到 blog 最初的页面了。

以后,每次对项目里文章或配置文件的更改,都会触发这个 action / workflow,重新生成一遍网站。可以在 Actions 页面,查看 workflow 每次运行的情况。


4. 更改网站基本信息

在 Code 页面,点击编辑 config.yml 页面,把一些预设的网站信息,改成你自己的信息。

对新人来说,需要在 config.yml 文件里更改的,大概有以下几项:

baseURL: https://username.github.io/ # 改成你自己的网址
title: 网站名称
params:
  author: somebody # 作者的署名

  homeInfoParams:
    Title: 网站标题,只显示在首页上
    Content: >
      显示在首页标题下方的一些文字。</br>
      支持一些简单的 html 和 markdown。

更改后,点击绿色的 Commit Changes… 在弹出的页面中,再一次点击绿色的 Commit Changes,保存文件后 1~2 分钟,就可以在 blog 页面上,看到更改后的内容了。


5. 添加、管理文章

所有的 blog 文章,都在 content / posts 目录中。在 Code 页面,进入 content / posts 目录。点击右上角,创建新文件。

所有的文章,均为 .md 结尾的 markdown 文件。文件名对应着这篇文章的网址,譬如,post-20241111.md 文章链接,就是
https://username.github.io/posts/post-20241111/

在文件的开头,如图所示,写入用 — 隔开的,文章的标题和发布日期。

---
title: "新文章的标题"
date: "2024-11-11"
---
然后开始写正文,markdown 格式。

同样,点击绿色的 Commit changes… 保存提交。1~2 分钟后,就可以在 blog 页面上看到新文章了。

content / posts 目录里的所有文件,都可以随意地新增、删除、修改、重命名文件。对应着 blog 文章的增删改、和改变 url 链接。

文章内嵌的图片,建议放在 static 目录下,然后在文章中用 markdown 格式引用。譬如 static / aa.jpg 文件,相应地在 markdown 文件中插入的代码为:

![](https://username.github.io/aa.jpg)

有经验的用户,也可以使用其它更有效的组织方式。


6. 其它注意事项

  • 生成的 blog 对应的 rss 订阅地址为
https://username.github.io/index.xml
  • 如果是用第二种方法,直接 fork 的项目,以后在这个 blog 项目里,会一直看到,图片里这样的消息,提示要把你对项目的更改,反馈给原本的我的项目。——不用理会就是了。

十三岁的唱片制作人!敏锐的设计洞察力来自街头?设由心声:序 Vol.0

By: Steven
28 July 2023 at 19:05

🎥 点击跳转至 B站 播放视频:https://www.bilibili.com/video/BV1SN411a72T/

🎥 点击跳转至 YouTube 播放视频:https://youtu.be/o3XL_woaCUs

这是新企划的设计师视频系列《设由心声》的序章。在这期视频里,你将会看到设计意识自我觉醒的过程,以及不可遏制的创作冲动是如何生长的。

这是想重启很久的一个全新大坑:设计师访谈 + 产品与设计背后的内幕信息。

这一条是今年三月份去上海参观《拍照的人》线下展的时候,和 akira 在前台做的采访。你将会看到一个设计师自我觉醒的过程,和他的学习方法。

因为原本就有重新开启这个新企划的打算,于是借机做了这一期访谈,作为整个系列的开篇。 这个系列应该都会是这种类型的类似纪录片的形式,来展现设计和产品的业内信息和观察。为什么说是「重启」呢?因为很多年前做过一个设计师访谈的专栏,因为各种原因只做了七期就终止了,现在想用视频的形式复活这个企划。

早年的设计师采访文章见:

输出是一种排泄

By: Steven
20 May 2024 at 21:13

在不同的平台上时不常的都能看到一些内容创作者他们会有疑问,说我的东西明明很有深度,准备得也很充分,制作也很用心,但是为什么没有获得很好的流量,或者其他的回报?这种时候要么就是真的有疑问,要么就是想通过这种疑问的方式,来表达对于这种流量的不满或者鄙视。

每次看到他们说这种话的时候,我就会代入到自己。我也有很多内容是花了很多心思很认真做的,但就是没有什么人看,没有什么人听。前几年确实会有疑惑,但现在我很坦诚地接受自己就是不擅长做那种大众流量欢迎的内容。

这里并没有鄙视大众流量的意思,我是真的发自内心的不懂,哈哈哈哈哈~

因为我做内容 99% 的动机,都只是为了把脑袋里的东西腾出来,它只是我的一个思考过程的外化。有人获得共鸣和启发,那就最好,没有那也无所谓。因此我确实没有真的花过心思在研究怎么样制作大家都喜欢的那种类型的内容,因为我也确实没有发自真心地想把自媒体作为自己的一条所谓职业赛道来看待。

因此,没有获得那样的流量,是很正常,也应该的。

一张封面引发的内核更换

By: Steven
28 April 2024 at 18:29

我把博客的模版换了,更简洁,但更好用了。

事情要从「播客封面的输出事故」开始。

我在播客后台上传的一张 1600×1600 的封面图,在通过 RSS Feed 分别同步到小宇宙和 Apple Podcast 的时候,出现了不显示或被识别成「未提供」的状态。小宇宙的后台能看见,这张图是抓到了的,但在播放页没显示;而在 Apple Podcast Connect 的后台就直接识别为「未提供」。同样的源我也尝试给到 YouTube,能抓到,能显示,但非常模糊。

第一时间我就认为是博客那头的设置问题,但具体是什么原因呢?实在是太多年没有折腾过博客的模版设计了。每个菜单我挨个检查了一遍,发现确实有个「摘录」的开关打开了,它会限制 Feed 分享出去的是完整的一篇还是只有局部的内容。这确实有影响,它导致小宇宙没抓到全文,在单集详情页里只显示了第一段话,后面还跟一个无法点击的跳转的纯文字「阅读更多」。关掉这个开关之后,小宇宙也马上就更新,能显示全文了,但封面依然没有显示出来;Apple Podcast 那边完全没动静,别说更新了,就是搜索都还搜不出来,但明明已经发布了。

我实在想不出是哪里的设置不对,就上即刻问了一下。很幸运的是,小宇宙的小伙伴立刻就开始帮我找原因。在几经周折后,最终联系上了小宇宙的技术同学,他给我看说托管源输出的图片尺寸只有 180×200 px。这就很明确了!

https://suithink.files.wordpress.com/2024/04/vol-0000.jpg?w=180&amp;h=200&amp;crop=1

但我依然不知道为什么,因为翻遍了整个后台,都不存在一个设置 RSS Feed 输出封面尺寸的地方。别的朋友也都没遇到过这样的事。况且,一张正方形的图,就算是缩略图也应该是正方形的,比例变了又是为什么呢?

于是我意识到一件事:

这是一个行业内的标准做法,那就应该是通用的,如果别人的播客都没有这个问题,而博客后台又不存在可设置和调整的界面,那最有可能的原因大概就是,我博客使用的模板太过于老旧了。

为什么我会想到这个角度呢?

因为我博客目前用的模板,是 2013 年开始启用的,这十一年来,只在 2022 年时调整过一次,但技术内核还是原本的那套东西。然而事实上,我博客后台切换到区块编辑器已经好几年了,我还在用的这个老模板其实已经下架很多很多年了,只是因为我一直没有更换它,还在生效而已。

为了验证这件事,我先是研究了一下朋友托管播客的网站结构,确定了「封面图」在通用模版中的形式,再在我的博客后台巡了几圈,选定一些结构相似的、我也喜欢的模板,把它们套用在我的播客日志上,看看是什么表现。最后,我在区块编辑器里找到这些页面,看看它们是怎么表达和处理这张「封面图」的,有哪些可以设置的项。

至此,我锁定,问题的根源就在于,这个多年前就早已下架不再维护的老版本软件的模版,它在技术层面和现行的技术之间的差异,导致输出的封面图变成了一个比例错误的缩略图。我只需要换上一个新模版,就可以解决了。

但「换模版」这件事,其实我已经考虑好长时间了。

在这次「封面图事故」之前,我就有换新的的想法了。一方面确实是,在日常写作和新增一些页面时会明显感觉到这种技术上的代际差,只是自己懒得动,能用就不改。我相信大部分程序员也是这么想的,代码屎山不就是这么回事嘛。但如果只是换个模版,其实不用想那么久,所以另一方面更核心的是,我在同时考虑把博客的套餐升级到 Explorer 版,还想提前买下后面几年的域名使用权,因此,在我心里,模版的更新、升级、域名这三件事是合并在一起考虑的。

这次小事故,倒像是上天推了我一把。

于是乎,我下了决心,升档、域名、模版,一次性全部处理好了。我现在的博客,是一个更为简练、但更好用的全新状态。播客源的抓取也回归正常了。

20132022 到今天,眼看着我的博客越改越简练,但内容越来越充盈,我心中是欢喜的。这就是我这些年的状态,越发充盈,越不需要装饰,所有形式都让位于内容。我只要一件舒适的 T 恤就够了。年轻时喜欢说的个性,那不是通过页面、手机壳、衣裤鞋来体现的,个性是行动做派,不需要是任何视觉化的呈现。

这就是另一种「我变秃了,但更强了」。

在博客上做播客,再因为做播客而全面更新了博客,再把这个过程记录在博客上,我如果不写出来,这事儿说给人听都会觉得我有神经病哈!不过 Blog 和 Podcast 这俩完全不相关的事物,在简体中文里的说法竟然像绕口令一般相似,也是有意思。

兔子王国里的外星人_0.ylog

By: Steven
26 April 2024 at 00:52

欢迎收听荒野楼阁 WildloG,这里是设计师苏志斌的个人播客。作为第 0 期,我会与你分享一下做这个播客的动机、这个播客的主题会是什么、起这个名字的缘由、本期封面和播客 Logo 的设计想法,以及后续的节目计划。

在这一期,你会听到:

—- 我是谁?从我家的动物园,工作和话剧的经历,聊到我二十多年的写作习惯。

—- 我对于视频内容的态度?为什么那么久没更新《设以观复》系列?

—- 原本并不想做播客,为什么转变想法呢?动机是什么?

—- 这个播客的主题:一个外星人

—- 荒野楼阁 WildloG 这个名字是什么意思?因为生机勃勃啊!

—- Why not 和 WildloG

—- 封面设计:隐秘的荒野和兔子王国

—- 以两类节目为主:一个人捡树枝,两人以上一起捡树枝

—- 要停更视频?

|登场人物|

苏志斌:工业设计师,车联网智能硬件产品经理/联创,《设以观复》作者

|相关链接|

若你所使用的播客客户端未能完整显示插图,或遇网络问题未能正常播放,请访问:

荒野楼阁 WildloG 的地址:https://suithink.me/zlink/podcast/

阅读设计相关的各类文章:https://suithink.me/zlink/idea/

|其他社交网络媒体|

苏志斌 @ 知乎|SUiTHiNK @ 即刻 / 微博

苏志斌SUiTHiNK @ Bilibili / YouTube / 小红书

|联络邮箱|

suithink.su@gmail.com

欢迎在 小宇宙、Spotify、YouTube、Apple Podcast 收听本节目,期待你的留言。

💾

分类法

By: fivestone
10 April 2024 at 21:16

把 blog 的文章分类整理一下。

这项任务已经拖延了超过十年,早就没意义了。blog 页面上,已经很多年没有放置分类列表。曾经企图把所有文章归入 uncategorized,然后用 tag 来做分类,——幸好没有,不然又是个半途而废的坑。

还是先把分类的框架搭出来吧。即使有了框架,从前的旧帖子,也还没有妥善归置到各个分类里,继续拖着吧。


yy – /yy

也就是「意淫」,初代互联网口头语之一。某种意义上,整个 blog 的所有文章,都是在 yy,所以从这个网站初建,这就是分类之一。内容偏向于各种奇怪的,未必和情欲相关的幻想。也经常觉得 yy 这个词渐渐不合时宜、甚至有些男性油腻,想换个更高大上的(譬如 P.Bourdieu 的 illusio…);但,还是先这么放着吧。

日子流 – /current

流水账。早年 blog 大兴的时候,一大群人的文章风格,都是今天吃了什么玩了什么买了什么。我也想学着这么接地气一些,但最终还是没写太多。网址的英文名,出自卡佛的《水流》。

nowhere man – /nowhere

旅行相关,或者日常生活中偏向旅行气质的片段。出处是 Beatles。

norwegian wood – /wood

情感相关。出处是村上春树当然也是 Beatles。

不正经的 – /funny

纯搞笑段子。

偶知道 – /seriously

一些比较认真的思考吧。「偶知道」既是偶然知道,也是我知道,——(偶 = 我)仍然是上古网络用语,尴尬到脚抠地。

他们 – /ille

偏向于对他人的描述,有网络引用的,也有实际访谈的。ille 是第三人称自指。关于他者的描述,终归还是要映照自身。

无政府主义审美 – /aesthetic

最初是时政方面的吐槽。后来也包括从无政府主义视角,对同温层内部的一些不同的观感。然而并不会努力地,专注于用这个 blog 向人普及反贼言论,所以最终还是轻轻地立足于「审美」两个字,说些只是看着不爽的东西。

love me do – /tech

和人文情感无关;一些在各种兴趣领域的技术攻略:攀岩、射箭、外语、IT……

拍拍 – /photography

作为童年爱好,这个 blog 曾经把「摄影」作为一个二层分类的顶端,下面包括很多细微的分类:拍的照片、心得、理论讨论……甚至还有过一个摄影 blog,后来停掉了,也没有合并过来。这边还多多少少留了些,就先堆在这里。——所以心中还是对此有爱的吧。要知道,连 IT 类原创都没资格独占一个分类,而是胡乱塞进 /tech /fyi /misc 里面……

FYI – /fyi

For Your Information,感觉会对很多人有用的资源。和 /tech 类似,但兴趣方面的含量就低了很多,只是当作工具来整理,也未必是原创。

misc – /misc

杂项。

把日常阅读的网页,用 RSS 推荐给好友

By: fivestone
8 March 2024 at 22:10

虽然大家写 blog 的频率都没那么勤了,但是,RSS 还是有其它可以玩的方式的!

很多人都有用各种 read it later、或者书签类工具,把有意思的网页保存下来。在这些工具里,可以通过某些手法,把一些想要分享的网页,生成 rss。其他好友订阅这个 rss 地址,就可以自动刷新,看到你推荐的文章啦!

下面介绍一些,常见的书签网站,生成 rss 的方式。但首先——

  • 这些生成的 rss 地址里,大多都内嵌着网站的验证码,容易泄密,也冗长而不简洁。强烈建议:得到 rss 后,先用 Feedburner 之类的网站,转成新的 rss,再分享出来,可以去掉原先网址里的隐私信息。
  • 很多网站,并没有专门用来 share 的分类,只能通过曲线手段,把已经 archive 或者 star 的类别分享出来。这可能会影响你原本的使用习惯。
  • 一些网站生成的 rss,并没有全文,甚至只有标题和链接地址。没关系,能看到大家的推荐,就已经很好了,自己点开就可以啦。
  • 大多数 rss 订阅工具里,也都有发送给 read it later 的功能,可以辗转着,把自己订阅的文章分享给他人。

我的 RSS 分享地址是:

https://feed.fivest.one/readings
或者
https://feeds.feedburner.com/fivestone/readings

有兴趣和我分享的,欢迎留言或私信交换!!


Instapaper 免费版

感觉 Instapaper 生成 RSS 的功能是最好用的,可以把特定的文件夹设为公开,直接得到它的 rss,形如:

https://instapaper.com/folder/1234567/rss/123456/Vciysdfsd7mod9B
  • 在左边栏创建新的 Folder,存放想要分享的文章;
  • 进入这个 Folder,在页面上方选择 Edit,设置成 Public;
  • 点击页面右上角的下拉菜单,选择 Download;
  • 下载为 RSS Feed,就得到 RSS 地址了。

Pocket 免费版

好像 Pocket 的免费用户,内容都只能是公开的(无语…),只要知道了用户名,就可以通过 RSS 查看全部的内容(所以生成的 rss 需要转录才安全)。而且不能自定义分类,只有默认的:

https://getpocket.com/users/USERNAME/feed/all
https://getpocket.com/users/USERNAME/feed/unread
https://getpocket.com/users/USERNAME/feed/read

最后一条 …/read 会返回所有 Archived 了的文章,可以勉强用它作为分类的手段。

Readwise

这个只有收费版,我就不去试了。有它家的用户,可以帮忙把生成 rss 的方法分享一下?

Wallabag

我在用 Wallabag,可以自建,也有收费的服务可用。生成的 rss 是全文输出,效果很好。在 Config – Feed 里,生成一个 token,然后点开任何一个 tag,点击列表上方的 rss 图标,就可以得到这个 tag 的 rss 订阅(生成的地址里带着统一的 token,所以需要转录才安全):

https://wallabag.your.domain/feed/USERNAME/asdfghjkl/tags/t:share

運動無國界,嗎?

By: Steven
21 February 2024 at 21:35

🎥 點擊封面播放視頻

由一個提問開始,我從設計師與創作的角度,談論體育運動中的民族主義,警惕「分類」思維對思考過程的影響。

今日戶外步行運動記錄:開發了一條四分馬的路線!

🎥 B站播放地址:https://www.bilibili.com/video/BV1yv421k7Mg/

🎥 YouTube 播放地址:https://youtu.be/w2KQoic8LAg

這是春節過後的第一條視頻,主要是起個頭跟大家聊聊天。如果你有任何想法,歡迎在視頻中的彈幕或評論區里和其他人一起理性討論。

读完一本不好看的书,但心里很舒坦

By: Steven
13 February 2024 at 19:04

在西西弗里偶遇这本书,随手翻了一下,被设定吸引了,就一下看了前九章。

二十三天后回到书店里把余下的二十二章看完了,满足的同时又觉得很失望。

满足的是,这个下午是我近一年来完整读完了一本书的时刻;失望的是,前半截一直吊着我胃口的摆渡世界的故事,最后居然演变成了俗气的爱情故事和死而复生的怪诞情节。我不喜欢这样的收尾。

但是,迪伦凭着自己的信念从死亡的世界回到人间这段路,这一路的勇气,是我愿意把第三颗星打上来的原因。书里的男女角色我都不怎么喜欢,无辜枉死的三十六岁女士也很莫名其妙,但对于此刻低气压的我而言,我喜欢迪伦一路冲过去的那份勇气和冒险的决心。

对多数人而言,读这本书是浪费时间。但我之所以感觉还行,是因为我太久没有体会到「完成」一件事时「结束」的那一刻了。哪怕这一刻并不欢欣鼓舞,但我完成了。

相对应的,前两天看完的两部片子,让我感到心里非常的舒坦。一个是贾玲的新电影《热辣滚烫YOLO》,另外一个是 Casey 最新的一条 vlog《Sisyphus and the Impossible Dream》。

一方面惊叹于贾玲真的一年瘦下来一百斤,练成了可以和职业拳击运动员打几下的状态;二来佩服于她为了实现这个目标所做的一切努力,一切向生活挥拳而做的事情。她不是瘦了,而是变了一个人,瘦下来只是一个副产品。

Casey 的 vlog 时间跨度长达 17 年。从大腿骨折,到跑进三小时以内,从二十来岁到四十多,一切的付出,就像西西弗斯一次次推石头上山,不仅过程令我震动,结果更是让我感受到了希望!

他俩是我 2024 年初的第一束光。

❌
❌