agentleFS
openvanillaopenvanilla/McBopomofo/AGENTS.md

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
  1. Distinctive:

    Run in Xcode with ⌘+U or test navigator

    line 59
  2. Distinctive:

    Language restriction: Use only English or Traditional Chinese.

    line 129
  3. Very specific:

    Date/time format: When noting "last updated" or timestamps in documentation, always use full ISO 8601 datetime in UTC+8 timezone (e.g., …

    line 130
  4. Distinctive:

    Keep descriptions concise and in present tense

    line 142
  5. Very specific:

    Use Preferences static properties and property wrappers instead of direct UserDefaults access

    line 147
  6. Very specific:

    Keep AppKit/IMKit work in Swift classes with private/fileprivate scope

    line 151
  7. Very specific:

    Treat InputState subclasses as immutable.

    line 155
  8. Very specific:

    Use std::shared_ptr when passing to C++ APIs

    line 163
  9. Distinctive:

    Keep bridge methods small: forward to engine, return Foundation types

    line 166
  10. Very specific:

    Follow C++17 style with std::vector, std::unordered_map, std::optional, std::string_view

    line 170
  11. Very specific:

    Place code in existing namespaces: McBopomofo, Formosa::Gramambular2, Formosa::Mandarin

    line 171
  12. Distinctive:

    Keep algorithms deterministic and side-effect free.

    line 173
  13. Very specific:

    Swift tests: Use Swift Testing module with @Suite, @Test, #expect macros in McBopomofoTests/

    line 177
  14. Very specific:

    C++ tests: Add to Source/Engine/CMakeLists.txt in McBopomofoLMLibTest target, use GoogleTest

    line 178
  15. Very specific:

    Mixed tests: Use Objective-C++ (.mm) with bridging header for Swift-C++ interop

    line 179
  16. Distinctive:

    Don't replace AppKit windows with SwiftUI or Combine.

    line 188
  17. Distinctive:

    Don't bypass the Objective-C++ bridge to access engine from Swift directly

    line 189
  18. Distinctive:

    Don't hardcode paths to user data.

    line 190
  19. Distinctive:

    Don't modify large dictionary blobs unless specifically targeting them

    line 191
  20. Distinctive:

    Don't add generic development practices or obvious instructions

    line 192

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

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 bundle
  • McBopomofoInstaller: Installer app (recommended for development)
  • Data: Dictionary data generation
  • McBopomofoTests: 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

  1. Open McBopomofo.xcodeproj in Xcode
  2. Select the "McBopomofoInstaller" target
  3. Build (⌘+B) and run to install McBopomofo
  4. 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 build

Running Tests

Swift Tests

  • Target: McBopomofoTests in Xcode
  • Framework: XCTest with Swift Testing module
  • 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: ./McBopomofoLMLibTest

The 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 formatting

Critical: 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.occ

For 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:

Key Files Reference

FilePurpose
Source/InputMethodController.swiftMain IMK entry point, coordinates candidate menus and preferences
Source/InputState.swiftState machine base and all state implementations
Source/KeyHandler.mmObjective-C++ bridge between Swift events and C++ engine
Source/LanguageModelManager.mmWraps C++ language model for Swift consumption
Source/Engine/McBopomofoLM.cppCore language model logic and unigram processing
Source/Engine/Mandarin/Mandarin.cppBopomofo syllable processing and keyboard layouts
Source/Engine/gramambular2/Text segmentation algorithms (HMM-based)
Source/Data/MakefileDictionary data build system
Source/Data/AGENTS.mdComprehensive dictionary data documentation
algorithm.mdDetailed algorithm explanation (Chinese)
McBopomofoTests/PreferencesTests.swiftExample 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 in Source/Data where 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 the date command 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 support
    • fix(engine): correct syllable composition for edge case
    • docs(readme): update installation instructions
    • refactor(state): simplify state transition logic
  • Keep descriptions concise and in present tense
  • See: https://www.conventionalcommits.org/

Swift & AppKit

  • Use Preferences static properties and property wrappers instead of direct UserDefaults access
  • Localize all UI strings with NSLocalizedString("…", comment: "") and update .strings files in Base.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/LanguageModelManager bridges, not directly
  • Keep AppKit/IMKit work in Swift classes with private/fileprivate scope

State Machine

  • Treat InputState subclasses as immutable; always create new state objects on transitions
  • Funnel all key handling through KeyHandler for consistent state transitions
  • Derive UI and candidate lists from state object, not scattered flags
  • Extend by adding new InputState subclasses with explicit transitions, not booleans

Objective-C++ Bridge

  • Manage C++ object lifetimes in .mm files with proper init/dealloc
  • Use std::shared_ptr when passing to C++ APIs
  • Surface engine capabilities by extending bridge classes and declaring in McBopomofo-Bridging-Header.h
  • Convert between NSString and std::string using UTF8Helper/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 Testing module with @Suite, @Test, #expect macros in McBopomofoTests/
  • C++ tests: Add to Source/Engine/CMakeLists.txt in McBopomofoLMLibTest target, use GoogleTest
  • Mixed tests: Use Objective-C++ (.mm) with bridging header for Swift-C++ interop
  • Snapshot/restore UserDefaults in tests (see PreferencesTests.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 formats
  • CandidateUI: Candidate window rendering
  • ChineseNumbers: Chinese numeral conversion
  • FSEventStreamHelper: File system monitoring
  • InputSourceHelper: Input source management
  • NotifierUI: User notifications
  • NSStringUtils: String utility functions
  • OpenCCBridge: 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 toolchain
  • SQLite.swift (0.15.4): Swift wrapper for SQLite3
  • SwiftyOpenCC (2.0.0-beta): Swift wrapper for OpenCC (Chinese text conversion)

Download now (ZIP)

  • 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.

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.