noodle / Tools
AGENTS.md259 starsChanged 35 days agoApache-2.0View on GitHub
The tools Noodle gives its bots. Each folder here is one bundled ExtensionKit extension that Noodle discovers at launch; nothing in the app names them. Tools/Calendar and Tools/Reminders are the exceptions: they have no extension. macOS grants this access to the app a person sees and never to a background extension, which was measured before the tools were written, so their providers are ToolProviderKind.builtIn and run inside Noodle. Build a tool this way only when a permission makes an extension…
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,439 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository18 other files it gives its agents.
- AGENTS.mdAGENTS.md
- Applet/AGENTS.mdAGENTS.md
- Browser/AGENTS.mdAGENTS.md
- Computer/AGENTS.mdAGENTS.md
- docs/AGENTS.mdAGENTS.md
- Hub/AGENTS.mdAGENTS.md
- Incubator/AGENTS.mdAGENTS.md
- Mobile/AGENTS.mdAGENTS.md
- Terminal/AGENTS.mdAGENTS.md
- agents-md-symlinkSkill
- apple-history-utilitiesSkill
- helper-visibilitySkill
- mint-releaseSkill
- no-code-docsSkill
- sheet-and-settings-sizingSkill
- test-first-changesSkill
- ui-copySkill
- version-bound-cleanupSkill
The file
We split this AGENTS.md into the rules it gives an agent
6 rules. About 0 are common, 1 is distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 63
Before an action that cannot be undone, call context.authorize.
- Very specific: line 72
Create Tools/NAME in the layout above.
- Very specific: line 73
Add tool("NAME") at the end of Package.swift.
- Very specific: line 76
If it follows an assignment, publish that assignment from NoodleStore with toolAssignments.replace(KIND, with:).
- Distinctive: line 86
Write the test first and see it fail.
- Very specific: line 87
Before calling a change done, run all of swift test, then scripts/build-and-launch.sh and scripts/verify-tool-extensions.sh on the bundle.
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Tools
The tools Noodle gives its bots. Each folder here is one bundled ExtensionKit extension that Noodle discovers at launch; nothing in the app names them.
Tools/Calendar and Tools/Reminders are the exceptions: they have no extension.
macOS grants this access to the app a person sees and never to a background extension,
which was measured before the tools were written, so their providers are
ToolProviderKind.builtIn and run inside Noodle. Build a tool this way only when a
permission makes an extension impossible; the extension is the default, and the
provider contract is the same. Both share EventKitAssignments in NoodleCore and one
EventKitController in Sources/Noodle, so a third EventKit tool adds a kind, not a copy.
Tools/Applet is built in too: Noodle Applet trusts only Noodle's and Noodle Hub's
signed identities to name the bot a request is for, so its provider runs inside them
and reaches Applet through AppletController. Noodle grants it to every bot while
Applet is installed.
Tools/Browser and Tools/Computer are the bot-facing tools. The apps they
drive live in /Browser and /Computer and are separate products with their
own versions and changelogs. A change here ships with Noodle and goes in the
root CHANGELOG.md.
Layout
Tools/NAME/
Sources/NoodleNAMETools/ the provider: tools, schemas, guidance
Sources/NoodleNAMEToolsExtension/ the .appex shell, a few lines
Tests/NoodleNAMEToolsTests/
Info.plist the .appex Info.plist
Extension.entitlements what the .appex is signed with; App Sandbox alone unless there is a reasonA built-in tool has only Sources/NoodleNAMETools and Tests/NoodleNAMEToolsTests,
registered with builtInTool("NAME") in Package.swift. Its EventKit-style access to
the Mac, and the entitlement and usage string that go with it, belong to the app, and
its controller lives in Sources/Noodle like the other assignment controllers.
Where the framework is
The contract and the host are in Sources/NoodleCore, not here:
ToolProviders.swift:ToolProvider,ToolProviderManifest,ToolActivationand the schema conventions below. Read its doc comments first.ToolExtension.swift:ToolExtensionService, which an extension hands its provider to.ToolBroker.swift: every check made around a call.ToolProviderSkills.swift: writes each bot's skill from the manifest and the tool list.Sources/Noodle/ToolExtensionDiscovery.swift: finds the bundled extensions.
Bots reach every tool through messenger tool PROVIDER TOOL. There is no per-tool CLI and there must not be one.
Rules
- A provider returns MCP-shaped JSON: a
tools/listresult andtools/callresults. - The provider never authorizes. It declares, the broker enforces:
"format": "noodle-resource"with"noodle/kind"on a parameter that names a browser, computer or other assigned thing. The broker refuses values the bot was not assigned."format": "noodle-file"with"noodle/access"readorwritefor a workspace path. The provider gets an open handle, never a path.folderopens an existing folder, for an app that reads it where it is."format": "noodle-conversation"for a conversation the bot must belong to. A call that names one is withheld if the bot leaves it before the result."format": "noodle-conversation-link"for a link someone sent in that conversation. The broker refuses any other._meta["noodle/resource-list"]on a tool whose result lists resources, so the broker can remove unassigned ones._meta["noodle/post"]in a result to post into the verified conversation.- List every parameter a check depends on in the schema's
required.
- Before an action that cannot be undone, call
context.authorize. It fails if the assignment was removed while the call was running. - Activation is
.always,.whenAssigned(KIND)when the tool only makes sense with an assigned resource, or.whenGranted(KIND, id:)when the provider itself is what Noodle grants. - Everything a bot reads about a tool comes from the extension:
manifest.summary,manifest.instructionsand the tool descriptions. Do not add tool text toMessengerDocumentation,WorkspaceRepository.swiftordocs/. - An extension gets the App Sandbox only. Browser and Computer also hold their companion's app group, and only that.
scripts/verify-tool-extensions.shpins this; a new entitlement needs a change there and a reason. - Bundled extensions only. Do not add loading of third-party extensions.
- Extensions are background processes: keep
LSBackgroundOnlyinInfo.plist.
Adding a tool
- Create
Tools/NAMEin the layout above. CopyTools/Vision; it is the smallest. - Add
tool("NAME")at the end ofPackage.swift. - In
Project.swift, addtoolExtension("NAME")to the targets and a dependency on it from theNoodletarget, next to the existing three. The bundle identifier is<noodle id>.tools.NAME. scripts/verify-tool-extensions.shchecks every bundled extension and needs no change for a tool whoseExtension.entitlementsholds the sandbox alone. Anything more needs a case there.- If it follows an assignment, publish that assignment from
NoodleStorewithtoolAssignments.replace(KIND, with:).
For a built-in tool, replace steps 2–4 with builtInTool("NAME") in Package.swift, a
dependency on the provider from the Noodle target, toolProviders.register(...) in
NoodleStore, and whatever entitlement and Info.plist usage string the access needs in
Support/.
Tests
- Provider tests run without the extension, a companion app, a network or an account. They must pass in CI.
- Write the test first and see it fail.
- Before calling a change done, run all of
swift test, thenscripts/build-and-launch.shandscripts/verify-tool-extensions.shon the bundle.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

