Showing posts with label development. Show all posts
Showing posts with label development. Show all posts

Thursday, July 02, 2026

Using Apple Notes Note in place of a Reminders note field - the Shortcut workaround

Update 

In practice this has been much more useful than I imagined, particularly once I became aware that Apple Reminder subtasks are toxic sludge. 

For a more complex task my Reminder names are simply [project name: ] & [next step]. All the history, context, external links, status, change log and so on simply live in the macOS Notes.app Note. I reserve the feeble internal Reminder Note for optional details. the macOS Note is a useful project summary.

One note can be used by multiple Reminders. The note creation timestamp used to generate the UID doesn't have to match any of the linked notes. It's just a convenient unique identifier.

Sharing Reminders doesn't share access to the Note. Recipient would have to be given access and the shortcut for resolving the link to a Note has to be present on their machine.

Original

I recently switched from using Microsoft's To Do app to Apple Reminders. I have since found reasons [1] to doubt the wisdom of this choice, but I'm staying with it for now.

One of my frustrations is the Reminders note field.  It's only suited for 1-2 line notes and even those clutter up list display. (A better UI would truncate notes at one line, click reminder to see, etc. etc). I rely on notes to document work on a Reminder task.

So for anything longer than a 1-2 line note I'd prefer to use something like Apple Notes.app to hold a Reminder note.

Apple does support the use case of creating a Reminder about an already existing Note using the Share Sheet. It's a bit ugly but is said to more or less work on macOS and iOS. The Reminder will have a kind of link to the Note. But the use case is truly only for being reminded about a Note. For example, there's nothing in the Note to show it has an associated Reminder. 

A same workaround to this would be to just do it all manually. Create a Note, copy/paste the Note title into the Reminder note field. Put these kinds of Notes into a folder. This is 95% of the result with 10% of the effort.

An insane approach is to try to automate this. Which is what I did.

I had an extensive discussion with Sonnet about workarounds. It was a difficult discussion thanks to Apple's miserable documentation and the usual versioning/release confusions but after pounding on it, and reviewing and reinventing failed workarounds others have developed over years, we settled on an approach that uses Apple Shortcuts. A Perplexity search on found 4 instances of people redeveloping this same workaround; Fable and I did our own versions. (Why Fable?! [2]).

It works like this:

  1. I'm working on a Reminder.
  2. I run the Shortcut "CreateNoteLink". It creates a Note in my ReminderNotes folder from a plaintext template; then uses the Note timestamp as a unique identifier (key) in the title of the Note. It puts a URL on the clipboard that includes that timestamp as a search key.
  3. I paste the clipboard contents into the Reminder URL field. I can now use the Notes.app Note instead of the native Reminder note field.
From the Reminder clicking on the URL opens the note. The URL is a shortcut:// URL that passes the timestamp key to the OpenLinkedNote Shortcut.  On both iOS and macOS this find the reminder-Note and opens it in Notes.app

If you want to try something like this below are the Shortcut Share Links (there's no way to share a bloody Shortcut other than by iCloud Link -- which are easy to break but we all hate Apple so we're not surprised). Or give the Fable build doc to an ai, give it control of Shortcuts, and let the ai build it. If you do that, consider using this Claude Skill (I saved it).

CreateNoteLink: create the note and create the link stored in Reminder URL field (manual paste into reminder)

OpenLinkedNote: accepts a parameter from the Reminder URL and finds the correct note

The plaintext template (screenshot) - it lives in iCloud Shortcuts folder. I can edit this as I like. (Fable warned that trying to use a Notes based template was a recipe for more pain).

In the absence of any better way to $#@$ share a Shortcut, some screenshots. Click to enlarge.


If you really want this and need some more advice you can email me at jgordon@kateva.org.

- fn -

[1] Subtask implementation is so badly done that subtasks should be avoided. (Search results do not allow navigation from result to a view that shows task/subtask. Sadly Apple did it less badly in Smart Lists, but clearly ran out of time to finish the work and, of course, never got back to it.) The calendar date picker was stolen from Windows 3.1. The Reminder notes field is awful. Too small, hard to read/type into, messes up display of tasks and lists.

[2] I used Fable because Opus couldn't deal with the sheer horror of Apple Shortcuts. There's no code to look at, it's only in iCloud or GUI screenshots. It's amazing Fable was able to guide me and it took a lot of screenshots and corrections. I was doing it wrong of course, I should have given Opus control over the macOS Shortcuts app so it could iterate there. As it was there were a lot of corrections needed including errors in Apple documentation and version changes.

Thursday, June 18, 2026

My macOS ai coding projects to date

This is a reference post - mostly for my own use. Over the past few months I've used ai coding tools to create several personal solutions. I don't think the results are appropriate to share on github - it's probably easier/faster to have an ai recreate from general descriptions. In future I'll give projects a separate post in case anyone wants to the code, and if I remember I'll add them to this list and link to a project specific post.

  • PDF highlight exporter: I did this for my Old Person UMN courses. All our readings are PDF now. In Apple Preview I highlight text of interest, then drop PDF on a Python applet that creates a citation-friendly plaintext file I can use in studying, writing, and import into MindNode.
  • Windows slideshow from macOS Photos. Creates an 800x600 floating window and displays specified album photos in a slideshow window that behaves like any other Finder window.
  • Web scraper of all articles by a specific journalist - a single use script that created a citation-friendly plaintext of all articles by them.
  • Folder search in Photos.app. It's banana-pants that Photos does not search folder names. I have hundreds of folders. The script creates a plaintext file I can search using a text editor. It's easy to then browse to the folder in macOS Photos
  • A web app that reformats an unreadable public Google Sheet into a mobile/desktop friendly view of CrossFit Minneapolis-St Paul workouts. This is one of my faves; I use it several times a week and it's the only app so far that other people use.
  • A data reformatting app that takes several standard CSV files from SportsEngine and turns them into a useful worksheet.
  • A data reformatting app that lets me download a class list and turn it into names I can put into Apple Notes.
  • Shortcuts to work around the defective Reminders.app note field
For context I have extensive (decades) of work experience as a product manager and in technical domains too esoteric to describe. I last coded for money around 1981 (FORTRAN), did a shareware C app in the 90s that had one paying customer, and I can more or less read/edit Python. I would never have done these projects without ai coding but I do have serious development experience.

Thursday, April 02, 2026

My new favorite utility - a Claude-built python app for turning macOS Preview PDF highlights into a plaintext list

I've asked Claude to build me a few tools, but my new favorite is a macOS droplet that turns macOS Preview PDF highlighted text into a plaintext document like this:


It's written in Python. I used Google Antigravity -- there wasn't much of a prompt. By accident I prematurely submitted something like 'turn every contiguous highlighted text string into a quotes with page number'. It went through some minor revision cycles that simplified the citation reference and added a descriptive header with available metadata. I even made some small changes by hand. (Antigravity burned my free Claude Thinking credits so I started doing more things manually.)

Claude made me a bash script that lets the Python code run as a droplet.

If I open the text file and copy all, then paste into MindNode, I get one quote per node.

I used Claude Thinking with Google Antigravity. I tried Gemini a bit but it is far behind Claude.

I thought about sharing the code for this, but it's ai generated. You could just tell the ai what you want using the above as an example. (The "con-stitutive" is a hard-for-Claude edge case with text wrapping in PDFs.)

Anyway, if anyone wants the code just leave a comment below and I'll put it on my personal web site and add a link here.

Monday, March 18, 2024

Visual Studio Code Jupyter Python Extension line wrap in output cell - how to set notebook.output.wordWrap

My Visual Studio Code (Mac) Jupyter extension (plug-in) output was not line wrapped. It was a single unreadable output string. I had to either copy and paste into a markdown cell (where VSC line wrap config is followed) or I had to come up with Python output formatting solutions.

Then I saw a video in which the developer's cell block output was wrapping. So I went looking again. This turned out to be a lot harder than it was, say, 10 years ago. I spent at least 40 minutes, and probably more, digging through obscure corners of the internet

At last I got a hint. There is something called "notebook.output.wordWrap" that defaults to false but can be set true. If you can figure out how to set it.

I couldn't figure out how to set this value for the Jupyter Notebook extension on my Mac however. I got some hints from Microsoft's documentation on editing settings.json even though it's not correct about how to navigate to preferences. I used the ⌘, shortcut. From there I searched for "wordwrap"

You can see the result below. I needed to set Notebook > Output > Word Wrap to true. The copied JSON version of this is "notebook.output.wordWrap": true. You can see the setting in the screen shot below (click for full size).

I set this value for User and Workspace both, I assume Workspace wins but I don't know. Now my output wraps so I can read it.

There's also supposed be a metadata tag that causes a Jupyter notebook cell to scroll output but I couldn't get I too work and it felt too obscure to rely on.

Saturday, January 06, 2024

Rendering ChatGPT output in readable form in a Juypter Notebook

Update: This post is still useful, but there's also a way to enable line wrap in Visual Studio Code's Jupyter extension. You can also use the Python Print function instead of the Display example in my original post. For example:

output = client.completions.create(
    model="gpt-3.5-turbo-instruct",
    prompt="List the days of the week: ",
    max_tokens=100,
    stop = "Saturday", #put this in for fun
)
print(output.choices[0].text)

Note these print parameters are specific to this particular object's structure. (I think JSON but I'm a newbie.)

Original below
--------

This was a bit of a revelation. I don't know Python but I've been working through a ChatGPT / LLM tutorial using Visual Studio Code and a Juypter Notebook on macOS. In a Jupyter cell the output renders below the cell and it looks like this:

Completion(id='cmpl-....', choices=[CompletionChoice(finish_reason='stop', index=0, logprobs=None, text='1...

All in one unreadable line with \n as a paragraph deliver and no line wrap.

I asked ChatGPT 4 to help. Over a series of interactions I tried different things and got various error messages I passed to ChatGPT 4. In turn it analyzed my error message and suggested fixes.

This is what I ended up with in about 15 minutes, here added to a cell that ran a simple prompt query

from IPython.display import display, HTML

output = client.completions.create(

    model="gpt-3.5-turbo-instruct",

    prompt="write me a poem",

    max_tokens=100,

    n=3

)

text_content = output.choices[0].text if output.choices else ""

html_output = text_content.replace('\n', '<br>')

display(HTML(html_output))

This is what the output looks like now (the poetry is greeting card quality and mildly painful):

A poem, a weave of words and rhyme

A tapestry of thoughts and time

A magic spell from the poet's pen

A story of love, of loss, of when


The stars above, they guide my hand

As I write of distant lands

Of fiery sunsets and ocean tides

Of moments we hold and let slip by ...   

[Adolescent poetry truncated] 

This screenshot shows it best ...


We are in a new world.

Sunday, October 16, 2022

AppleScripts to speed Java compile and execute with BBEdit

Students are often asked not to use an IDE (I like Visual Studio Java) for their Java projects. Instead they need to use BBEdit without an IDE. BBEdit does not appear to natively support facilitated compile/execute but it does run AppleScrips that can speed things a bit.

The davalign.com site has some scripts written for TextWranger. If you rename them to BBEdit they work well.

Reproducing them here in case that site vanishes. I didn't see much like this. Note if you open and save in macOS Script Editor they will be compiled. I like that the first action is to save the document, it's easy to forget to save before a compile.

Compile java.scpt

tell application "BBEdit"
save text document 1
set the_file to file of text document 1
end tell

set AppleScript's text item delimiters to ":"
set source_file to the last text item of (the_file as string)

tell application "Finder"
set the_folder to container of file the_file
end tell

tell application "Terminal"
activate
set p to POSIX path of (the_folder as string)
set shell_script to "cd " & (quoted form of p) & ¬
"; javac " & source_file
if (count windows) is 0 then
do script shell_script
else
do script shell_script in the front window
end if
end tell

Run java.scpt

tell application "BBEdit"
set the_file to file of text document 1
end tell

set AppleScript's text item delimiters to ":"
set source_file to the last text item of (the_file as string)
set compiled_file to text 1 thru -6 of source_file

tell application "Finder"
set the_folder to container of file the_file
end tell

tell application "Terminal"
activate
set p to POSIX path of (the_folder as string)
set shell_script to "cd " & (quoted form of p) & ¬
"; java " & compiled_file
if (count windows) is 0 then
do script shell_script
else
do script shell_script in the front window
end if
end tell

Friday, July 22, 2022

Getting Outlook to export Exchange contacts as vCards (vcf) with proper email addresses for use in macOS

In 2009 I wrote about how it was getting harder to move contact information out of Outlook into something else (like macOS Contacts). I wrote about some options, but that's not what I do now.

Here's what I do (tested in Mojave, which I'm still using because Aperture):

  1. Create a simple list Contacts view. I usually only want people so I sort by last name. In a few cases last name of people is blank so I fix that.
  2. Now create an empty email. Drag Contacts from Outlook's view into the email body. It has to be to the email, dragging to desktop creates a .msg file. It might fail if you do too many so I distribute 300-400 contacts across 4 separate emails. Outlook creates a vCard file as an attachment. It resolves the email too, so instead of an Outlook x400 (?) you get a proper email address.
  3. Send the email to your Mac
  4. On the Mac download all attachments. They show as VCF files and macOS renders them quite well.  If they have photos the photos show within the card icon. Spotlight indexes them all. You don't even need to bother with dropping them into Contacts (though that's easy to do, you can drop them into your Contacts Groups (folders)).
It's pretty easy if you know the trick. I've not seen it described anywhere else but I'm sure others know it.

Wednesday, June 24, 2020

Python macOS environments for learners in 2020

My daughter is auditing Coursera's Intro to Python class. It's pretty standard stuff, but I was surprised by the development environment. For macOS there's a non-trivial Python install that requires some unix knowledge, use of the Homebrew package manager, dealing with admin vs non-admin user issues, consideration of pyenv, editing the path, and finally installing Python.

That's a long way from the ease of, say, TurboPascal circa 1983.

I figured there had to be a better way, but Google only found me some pro-level IDEs. It fell to Twitter to clue me in to the modern scene. The 4 good modern options turn out to be:
  • Google Colab: absolute easiest and least painful. I believe the Python code executes in the browser, so it's substantially slower than execution directly in macOS.
  • Microsoft Visual Studio Code for macOS: this does require the traditional Python install with Homebrew, but it's a very beginner friendly environment. The Python plugin provides Jupyter support.
  • Homebrew Jupyter: similar to Colab but like Visual Studio is part of the Homebrew/Python path.
  • Azure does Jupyter Notebooks (via @jhovland) at notebooks.azure.com.
Years ago I ran into iPython as a novice environment; turns out it morphed into Juypter.

It's a sign of the times that Google search didn't turn up a blog post with these options. (It won't find this one either, I'm way off Google's radar now.) Once I'd identified the above options however I could do a Google search to find an educational resource that did mention then:

There are many ways to write and execute Python code:

Python tutor (online, visual debugger)
Python interpreter (command line)
Visual Studio Code (editor, good debugger)
Jupyter (notebook)
Google Colab (online, collaborative)
 
During this lab we see all of them and familiarize with the exercises format. For now ignore the exercises zip and proceed reading.

That site is the University of Trento's data science lab course, updated 2019/2020.  The U of Trento was founded in 1962. Reading the wikipedia page it seems to have started out focusing on sociology (and, given the era, was likely a wee bit Left) but now seems to be very tech.

The course material is presumably translated from Italian. It's quite readable though it would benefit from a native speaker updating the GitHub content. Judging by my little test it may be one of the best resources of its kind.

See also:

I came back to Python for course on working with the OpenAI ChatGPT LLM. This time around I used Visual Studio Code with the Jupyter support. I use the default Python PIP package manager but I think Microsoft favors Conda. As of 2024 CoPilot is an option but it is not free.

Monday, September 30, 2013

Micro-Frameworks for web app development

A developer colleague (M.A) sent me a brief list of micro-frameworks organized by language. His list is in the same vein as Microjs: Fantastic Micro-Frameworks and Micro-Libraries for Fun and Profit but quite a bit shorter.

For my own future reference, here's his list organized by server-side language
  • Java – Spark or perhaps something old fashion like Tomcat or Spring MVC in Tomcat
  • Groovy – Grails or Ratpack
  • Javascript – node.js or Meteor
  • Ruby – Sinatra
  • PHP – PHP
  • Python – Django or Bottle
For my own amusement (and perhaps my 14yo) I'd be inclined towards either Django (Python and packaged on DreamHost, my longtime hosting service) or Meteor (he likes).

PS. Clearly the world needs an AppleScript micro-framework. (ok, sick joke)