automating-notes
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAutomating Apple Notes (JXA-first, AppleScript discovery)
Apple Notes自动化(优先JXA,探索AppleScript)
Relationship to the macOS automation skill
与macOS自动化技能的关联
- Standalone for Notes; reuse for permissions, shell, and Objective-C/UI scripting patterns.
automating-mac-apps - PyXA Installation: To use PyXA examples in this skill, see the installation instructions in skill (PyXA Installation section).
automating-mac-apps
- 是Notes专属的独立技能;可复用技能中的权限、Shell及Objective-C/UI脚本模式。
automating-mac-apps - PyXA安装: 若要使用本技能中的PyXA示例,请查看技能中的安装说明(PyXA安装章节)。
automating-mac-apps
Core framing
核心架构
- Notes uses an AEOM hierarchy: Application → Accounts → Folders → Notes (with nested folders).
- Load: for complete specifier reference.
automating-notes/references/notes-basics.md
- Notes采用AEOM层级结构:应用→账号→文件夹→笔记(支持嵌套文件夹)。
- 参考文档加载: 完整的指定符参考请查看。
automating-notes/references/notes-basics.md
Workflow (default)
默认工作流程
- Resolve account/folder explicitly (iCloud vs On My Mac); validate existence and permissions.
- Ensure target path exists (create folders if needed); handle creation failures gracefully.
- Create notes with explicit and HTML
name; verify creation success.body - Query/update with filters; batch delete/move as needed; check counts before/after operations.
.whose - For checklists/attachments, use clipboard/Objective-C scripting if dictionary support is insufficient; test fallbacks.
- For meeting/people workflows, file notes under and
meetings/<company>/<date>-<meeting-title>; validate final structure.people/<first>-<last>/...
- 明确解析账号/文件夹(iCloud与本机Mac);验证其存在性及权限。
- 确保目标路径存在(必要时创建文件夹);优雅处理创建失败的情况。
- 创建包含明确和HTML
name的笔记;验证创建是否成功。body - 使用过滤器进行查询/更新;按需批量删除/移动笔记;操作前后检查数量。
.whose - 若字典支持不足,对于清单/附件操作,使用剪贴板/Objective-C脚本作为备选方案;测试备选方案的有效性。
- 针对会议/联系人相关工作流,将笔记归类到和
meetings/<公司>/<日期>-<会议标题>路径下;验证最终结构是否正确。people/<名>-<姓>/...
Quickstart (ensure path + create)
快速入门(确保路径存在并创建笔记)
JXA (Legacy):
javascript
const Notes = Application("Notes");
// Ensure folder path exists, creating intermediate folders as needed
function ensurePath(acc, path) {
const parts = path.split("/").filter(Boolean);
let container = acc;
parts.forEach(seg => {
let f; try {
f = container.folders.byName(seg);
f.name(); // Verify access
} catch (e) {
// Folder doesn't exist, create it
f = Notes.Folder({ name: seg });
container.folders.push(f);
}
container = f;
});
return container;
}
try {
// Get iCloud account and ensure meeting folder exists
const acc = Notes.accounts.byName("iCloud");
const folder = ensurePath(acc, "meetings/Acme/2024-07-01-Review");
// Create new note in the folder
folder.notes.push(Notes.Note({
name: "Client Review",
body: "<h1>Client Review</h1><div>Agenda...</div>"
}));
console.log("Note created successfully");
} catch (e) {
console.error("Failed to create note: " + e.message);
}PyXA (Recommended Modern Approach):
python
import PyXA
notes = PyXA.Notes()
def ensure_path(account, path):
"""Ensure folder path exists, creating intermediate folders as needed"""
parts = [p for p in path.split("/") if p] # Filter empty parts
container = account
for part in parts:
try:
# Try to find existing folder
folder = container.folders().by_name(part)
folder.name() # Verify access
except:
# Folder doesn't exist, create it
folder = notes.make("folder", {"name": part})
container.folders().push(folder)
container = folder
return container
try:
# Get iCloud account
account = notes.accounts().by_name("iCloud")
# Ensure meeting folder exists
folder = ensure_path(account, "meetings/Acme/2024-07-01-Review")
# Create new note in the folder
note = folder.notes().push({
"name": "Client Review",
"body": "<h1>Client Review</h1><div>Agenda...</div>"
})
print("Note created successfully")
except Exception as e:
print(f"Failed to create note: {e}")PyObjC with Scripting Bridge:
python
from ScriptingBridge import SBApplication
notes = SBApplication.applicationWithBundleIdentifier_("com.apple.Notes")
def ensure_path(account, path):
"""Ensure folder path exists, creating intermediate folders as needed"""
parts = [p for p in path.split("/") if p]
container = account
for part in parts:
try:
folder = container.folders().objectWithName_(part)
folder.name() # Verify access
except:
# Create new folder
folder = notes.classForScriptingClass_("folder").alloc().init()
folder.setName_(part)
container.folders().addObject_(folder)
container = folder
return container
try:
# Get iCloud account
accounts = notes.accounts()
account = None
for acc in accounts:
if acc.name() == "iCloud":
account = acc
break
if account:
# Ensure meeting folder exists
folder = ensure_path(account, "meetings/Acme/2024-07-01-Review")
# Create new note
note = notes.classForScriptingClass_("note").alloc().init()
note.setName_("Client Review")
note.setBody_("<h1>Client Review</h1><div>Agenda...</div>")
folder.notes().addObject_(note)
print("Note created successfully")
else:
print("iCloud account not found")
except Exception as e:
print(f"Failed to create note: {e}")JXA(传统版):
javascript
const Notes = Application("Notes");
// Ensure folder path exists, creating intermediate folders as needed
function ensurePath(acc, path) {
const parts = path.split("/").filter(Boolean);
let container = acc;
parts.forEach(seg => {
let f; try {
f = container.folders.byName(seg);
f.name(); // Verify access
} catch (e) {
// Folder doesn't exist, create it
f = Notes.Folder({ name: seg });
container.folders.push(f);
}
container = f;
});
return container;
}
try {
// Get iCloud account and ensure meeting folder exists
const acc = Notes.accounts.byName("iCloud");
const folder = ensurePath(acc, "meetings/Acme/2024-07-01-Review");
// Create new note in the folder
folder.notes.push(Notes.Note({
name: "Client Review",
body: "<h1>Client Review</h1><div>Agenda...</div>"
}));
console.log("Note created successfully");
} catch (e) {
console.error("Failed to create note: " + e.message);
}PyXA(推荐的现代方案):
python
import PyXA
notes = PyXA.Notes()
def ensure_path(account, path):
"""Ensure folder path exists, creating intermediate folders as needed"""
parts = [p for p in path.split("/") if p] # Filter empty parts
container = account
for part in parts:
try:
# Try to find existing folder
folder = container.folders().by_name(part)
folder.name() # Verify access
except:
# Folder doesn't exist, create it
folder = notes.make("folder", {"name": part})
container.folders().push(folder)
container = folder
return container
try:
# Get iCloud account
account = notes.accounts().by_name("iCloud")
# Ensure meeting folder exists
folder = ensure_path(account, "meetings/Acme/2024-07-01-Review")
# Create new note in the folder
note = folder.notes().push({
"name": "Client Review",
"body": "<h1>Client Review</h1><div>Agenda...</div>"
})
print("Note created successfully")
except Exception as e:
print(f"Failed to create note: {e}")PyObjC with Scripting Bridge:
python
from ScriptingBridge import SBApplication
notes = SBApplication.applicationWithBundleIdentifier_("com.apple.Notes")
def ensure_path(account, path):
"""Ensure folder path exists, creating intermediate folders as needed"""
parts = [p for p in path.split("/") if p]
container = account
for part in parts:
try:
folder = container.folders().objectWithName_(part)
folder.name() # Verify access
except:
# Create new folder
folder = notes.classForScriptingClass_("folder").alloc().init()
folder.setName_(part)
container.folders().addObject_(folder)
container = folder
return container
try:
# Get iCloud account
accounts = notes.accounts()
account = None
for acc in accounts:
if acc.name() == "iCloud":
account = acc
break
if account:
# Ensure meeting folder exists
folder = ensure_path(account, "meetings/Acme/2024-07-01-Review")
# Create new note
note = notes.classForScriptingClass_("note").alloc().init()
note.setName_("Client Review")
note.setBody_("<h1>Client Review</h1><div>Agenda...</div>")
folder.notes().addObject_(note)
print("Note created successfully")
else:
print("iCloud account not found")
except Exception as e:
print(f"Failed to create note: {e}")Validation Checklist
验证清单
- Account access works (iCloud vs On My Mac)
- Folder creation and path resolution succeeds
- Note creation with valid HTML body completes
- Note appears in Notes UI
- queries return expected results
.whose - Error handling covers missing accounts/folders
- 账号访问正常(iCloud与本机Mac)
- 文件夹创建与路径解析成功
- 包含有效HTML内容的笔记创建完成
- 笔记在Notes界面中显示
- 查询返回预期结果
.whose - 错误处理覆盖账号/文件夹缺失的情况
HTML & fallbacks
HTML与备选方案
- Allowed tags: ,
<h1>-<h3>,<b>,<i>,<u>,<ul>/<ol>/<li>,<div>/<p>/<br>.<a> - Security: Always sanitize HTML input; avoid ,
<script>, or event handlers to prevent XSS in rendered notes.<style> - Checklists/attachments: Objective-C/clipboard fallback (Cmd+Shift+L for checklist, paste image via NSPasteboard + System Events).
- Append helper: replace with extra HTML, or append when missing; validate HTML structure post-modification.
</body>
- 允许使用的标签:、
<h1>-<h3>、<b>、<i>、<u>、<ul>/<ol>/<li>、<div>/<p>/<br>。<a> - 安全提示: 始终清理HTML输入;避免使用、
<script>或事件处理程序,防止渲染笔记时出现XSS问题。<style> - 清单/附件:使用Objective-C/剪贴板作为备选方案(清单用Cmd+Shift+L,通过NSPasteboard + System Events粘贴图片)。
- 追加辅助方法:将替换为额外HTML,或在缺失时追加;修改后验证HTML结构。
</body>
When Not to Use
不适用场景
- Cross-platform note taking (use Notion API, Obsidian, or Markdown files)
- iCloud sync operations requiring status feedback (limited API support)
- Non-macOS platforms
- Rich formatting beyond supported HTML tags
- Collaborative editing workflows (no multi-user support)
- 跨平台笔记记录(建议使用Notion API、Obsidian或Markdown文件)
- 需要状态反馈的iCloud同步操作(API支持有限)
- 非macOS平台
- 超出支持HTML标签的富格式需求
- 协作编辑工作流(无多用户支持)
What to load
需加载的资源
- Basics & specifiers:
automating-notes/references/notes-basics.md - Recipes (create/move/query/ensure path/checklists):
automating-notes/references/notes-recipes.md - Advanced (HTML body rules, attachments/UI, JSON import/export, ObjC bridge):
automating-notes/references/notes-advanced.md - Dictionary/type map:
automating-notes/references/notes-dictionary.md - PyXA API Reference (complete class/method docs):
automating-notes/references/notes-pyxa-api-reference.md
- 基础与指定符:
automating-notes/references/notes-basics.md - 实用脚本(创建/移动/查询/路径确保/清单):
automating-notes/references/notes-recipes.md - 进阶内容(HTML内容规则、附件/UI、JSON导入/导出、ObjC桥接):
automating-notes/references/notes-advanced.md - 字典/类型映射:
automating-notes/references/notes-dictionary.md - PyXA API参考(完整的类/方法文档):
automating-notes/references/notes-pyxa-api-reference.md