McBopomofo
AGENTS.md858 starsChanged 20 months agoMITView on GitHub
McBopomofo (小麥注音輸入法) is a Traditional Chinese input method engine for macOS that enables users to input Traditional Chinese characters using the Bopomofo phonetic system (注音符號). The app also supports two Taiwanese Braille formats, Unicode and ASCII. The project is built with Swift (UI/state management), Objective-C++ (bridge layer), and C++ (core engine), using macOS Input Method Kit (IMK) framework. Runtime: macOS 10.15 (Catalina) or later Development: - macOS 14.7 or later - Xcode 15.3 or later - Python 3.9 (for dictionary…
We split this AGENTS.md into the rules it gives an agent
20 rules. About 0 are common, 10 are distinctive, and 10 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈10
Distinctive · estimate
This author's own choices. Worth a look.
10
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 59
Run in Xcode with ⌘+U or test navigator
- Distinctive: line 129
Language restriction: Use only English or Traditional Chinese.
- Very specific: line 130
Date/time format: When noting "last updated" or timestamps in documentation, always use full ISO 8601 datetime in UTC+8 timezone (e.g., …
- Distinctive: line 142
Keep descriptions concise and in present tense
- Very specific: line 147
Use Preferences static properties and property wrappers instead of direct UserDefaults access
- Very specific: line 151
Keep AppKit/IMKit work in Swift classes with private/fileprivate scope
- Very specific: line 155
Treat InputState subclasses as immutable.
- Very specific: line 163
Use std::shared_ptr when passing to C++ APIs
- Distinctive: line 166
Keep bridge methods small: forward to engine, return Foundation types
- Very specific: line 170
Follow C++17 style with std::vector, std::unordered_map, std::optional, std::string_view
- Very specific: line 171
Place code in existing namespaces: McBopomofo, Formosa::Gramambular2, Formosa::Mandarin
- Distinctive: line 173
Keep algorithms deterministic and side-effect free.
- Very specific: line 177
Swift tests: Use Swift Testing module with @Suite, @Test, #expect macros in McBopomofoTests/
- Very specific: line 178
C++ tests: Add to Source/Engine/CMakeLists.txt in McBopomofoLMLibTest target, use GoogleTest
- Very specific: line 179
Mixed tests: Use Objective-C++ (.mm) with bridging header for Swift-C++ interop
- Distinctive: line 188
Don't replace AppKit windows with SwiftUI or Combine.
- Distinctive: line 189
Don't bypass the Objective-C++ bridge to access engine from Swift directly
- Distinctive: line 190
Don't hardcode paths to user data.
- Distinctive: line 191
Don't modify large dictionary blobs unless specifically targeting them
- Distinctive: line 192
Don't add generic development practices or obvious instructions
≈ “Common” is an estimate: at least 1 in 5 of the 36,368 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
AGENTS.md
This file provides guidance to AI coding assistants when working with code in this repository.
Project Overview
McBopomofo (小麥注音輸入法) is a Traditional Chinese input method engine for macOS that enables users to input Traditional Chinese characters using the Bopomofo phonetic system (注音符號). The app also supports two Taiwanese Braille formats, Unicode and ASCII. The project is built with Swift (UI/state management), Objective-C++ (bridge layer), and C++ (core engine), using macOS Input Method Kit (IMK) framework.
System Requirements
Runtime: macOS 10.15 (Catalina) or later
Development:
- macOS 14.7 or later
- Xcode 15.3 or later
- Python 3.9 (for dictionary data generation)
Building and Running
Xcode Project Structure
The project contains these main targets:
McBopomofo: Main input method bundleMcBopomofoInstaller: Installer app (recommended for development)Data: Dictionary data generationMcBopomofoTests: Swift test suite
Build configurations: Debug, Release (default when building from command line)
Available schemes: McBopomofo, McBopomofoInstaller, Data, plus individual schemes for local packages (BopomofoBraille, CandidateUI, ChineseNumbers, FSEventStreamHelper, InputSourceHelper, NotifierUI, NSStringUtils, OpenCCBridge, SystemCharacterInfo, TooltipUI)
Primary Development Workflow
- Open
McBopomofo.xcodeprojin Xcode - Select the "McBopomofoInstaller" target
- Build (⌘+B) and run to install McBopomofo
- The installer automatically kills and restarts the input method process
Important: macOS limits how many times an input method process can be killed in a single login session. If installation stops working after multiple installs, log out and log back in.
Command-Line Build
# Build the installer
xcodebuild -project McBopomofo.xcodeproj -target McBopomofoInstaller -configuration Debug build
# Build the main input method
xcodebuild -project McBopomofo.xcodeproj -target McBopomofo -configuration Debug build
# Build dictionary data only
xcodebuild -project McBopomofo.xcodeproj -target Data -configuration Debug buildRunning Tests
Swift Tests
- Target:
McBopomofoTestsin Xcode - Framework: XCTest with Swift
Testingmodule - Run in Xcode with ⌘+U or test navigator
C++ Engine Tests
cd Source/Engine
mkdir build && cd build
cmake -DENABLE_TEST=ON ..
make
ctest
# Or run directly: ./McBopomofoLMLibTestThe C++ tests use Google Test framework and are defined in Source/Engine/CMakeLists.txt.
Dictionary Data Generation
Dictionary data must be regenerated when modifying phrase mappings or frequency data:
cd Source/Data
make all # Generate data.txt, data-plain-bpmf.txt, associated-phrases-v2.txt
make sort # Sort all data files using C locale
make check # Validate data integrity
make tidy # Clean up formattingCritical: Both BPMFMappings.txt and phrase.occ must be sorted with C locale:
LC_ALL=C sort -o BPMFMappings.txt BPMFMappings.txt
LC_ALL=C sort -o phrase.occ phrase.occFor detailed dictionary data documentation, see Source/Data/AGENTS.md which covers file formats, editing workflows, Python tools, and troubleshooting.
GitHub Copilot Configuration
GitHub Copilot uses .github/copilot-instructions.md for its custom instructions. That file references this AGENTS.md for comprehensive context but includes essential guidelines inline since Copilot cannot automatically load AGENTS.md.
For GitHub Copilot-specific configuration, see:
.github/copilot-instructions.md- Repository-wide Copilot instructions.github/instructions/Data.instructions.md- Path-specific instructions for Source/Data
Architecture Overview
McBopomofo uses a three-layer architecture (Swift/Objective-C++/C++). For detailed architecture and algorithm documentation, see:
algorithm.md: Comprehensive technical documentation (Chinese)- Wiki: 程式架構: Program architecture
- Wiki: Gramambular 演算法: Gramambular algorithm
Key Files Reference
| File | Purpose |
Source/InputMethodController.swift | Main IMK entry point, coordinates candidate menus and preferences |
Source/InputState.swift | State machine base and all state implementations |
Source/KeyHandler.mm | Objective-C++ bridge between Swift events and C++ engine |
Source/LanguageModelManager.mm | Wraps C++ language model for Swift consumption |
Source/Engine/McBopomofoLM.cpp | Core language model logic and unigram processing |
Source/Engine/Mandarin/Mandarin.cpp | Bopomofo syllable processing and keyboard layouts |
Source/Engine/gramambular2/ | Text segmentation algorithms (HMM-based) |
Source/Data/Makefile | Dictionary data build system |
Source/Data/AGENTS.md | Comprehensive dictionary data documentation |
algorithm.md | Detailed algorithm explanation (Chinese) |
McBopomofoTests/PreferencesTests.swift | Example Swift Testing suite patterns |
Development Guidelines
General
- Never use emoji in code, comments, documentation, or generated content outside
Source/Data/. Emoji are permitted only within dictionary data files inSource/Datawhere mappings include emoji. - Language restriction: Use only English or Traditional Chinese. Simplified Chinese is prohibited in all documentation, comments, and reviews.
- Date/time format: When noting "last updated" or timestamps in documentation, always use full ISO 8601 datetime in UTC+8 timezone (e.g.,
2025-10-12T14:30:00+08:00). Use thedatecommand to get the current system time and adjust to UTC+8 if needed
Conventional Commits
- MUST use Conventional Commits format for all git commits and pull requests
- Format:
type(scope): description - Common types:
feat,fix,docs,style,refactor,test,chore - Examples:
feat(input): add new keyboard layout supportfix(engine): correct syllable composition for edge casedocs(readme): update installation instructionsrefactor(state): simplify state transition logic
- Keep descriptions concise and in present tense
- See: https://www.conventionalcommits.org/
Swift & AppKit
- Use
Preferencesstatic properties and property wrappers instead of directUserDefaultsaccess - Localize all UI strings with
NSLocalizedString("…", comment: "")and update.stringsfiles inBase.lproj,en.lproj,zh-Hant.lproj - Perform UI work on main thread; use existing helpers/notifications rather than ad-hoc dispatch queues
- Interact with engine through
KeyHandler/LanguageModelManagerbridges, not directly - Keep AppKit/IMKit work in Swift classes with
private/fileprivatescope
State Machine
- Treat
InputStatesubclasses as immutable; always create new state objects on transitions - Funnel all key handling through
KeyHandlerfor consistent state transitions - Derive UI and candidate lists from state object, not scattered flags
- Extend by adding new
InputStatesubclasses with explicit transitions, not booleans
Objective-C++ Bridge
- Manage C++ object lifetimes in
.mmfiles with properinit/dealloc - Use
std::shared_ptrwhen passing to C++ APIs - Surface engine capabilities by extending bridge classes and declaring in
McBopomofo-Bridging-Header.h - Convert between
NSStringandstd::stringusingUTF8Helper/NSStringUtils, not manual conversion - Keep bridge methods small: forward to engine, return Foundation types
C++ Engine
- Follow C++17 style with
std::vector,std::unordered_map,std::optional,std::string_view - Place code in existing namespaces:
McBopomofo,Formosa::Gramambular2,Formosa::Mandarin - Reuse blob readers (
KeyValueBlobReader,ParselessPhraseDB,PhraseReplacementMap) - Keep algorithms deterministic and side-effect free; logging stays in Objective-C++ layer
Testing
- Swift tests: Use Swift
Testingmodule with@Suite,@Test,#expectmacros inMcBopomofoTests/ - C++ tests: Add to
Source/Engine/CMakeLists.txtinMcBopomofoLMLibTesttarget, use GoogleTest - Mixed tests: Use Objective-C++ (
.mm) with bridging header for Swift-C++ interop - Snapshot/restore
UserDefaultsin tests (seePreferencesTests.swift)
Dictionary Data Modifications
For dictionary data modifications, see Wiki: 詞庫開發說明 or Source/Data/AGENTS.md for detailed workflows.
Things to Avoid
- Don't replace AppKit windows with SwiftUI or Combine; runtime depends on NSWindow/XIB
- Don't bypass the Objective-C++ bridge to access engine from Swift directly
- Don't hardcode paths to user data; use preference APIs
- Don't modify large dictionary blobs unless specifically targeting them
- Don't add generic development practices or obvious instructions
Local Packages
The Packages/ directory contains local Swift Package dependencies:
BopomofoBraille: Taiwanese Braille conversion support for both Unicode and ASCII formatsCandidateUI: Candidate window renderingChineseNumbers: Chinese numeral conversionFSEventStreamHelper: File system monitoringInputSourceHelper: Input source managementNotifierUI: User notificationsNSStringUtils: String utility functionsOpenCCBridge: Traditional/Simplified Chinese conversion (wraps SwiftyOpenCC)SystemCharacterInfo: Character information lookup (uses SQLite.swift)TooltipUI: Tooltip display
These are referenced directly by Xcode project, not through Package.swift.
External Package Dependencies
The project also depends on these external Swift packages (resolved automatically by Xcode):
swift-toolchain-sqlite(1.0.4): Low-level SQLite bindings from Swift toolchainSQLite.swift(0.15.4): Swift wrapper for SQLite3SwiftyOpenCC(2.0.0-beta): Swift wrapper for OpenCC (Chinese text conversion)
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 28,693 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 repository2 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
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.

