Language Coach is a local-first Codex plugin that turns everyday writing into focused, reusable language lessons. It reviews the language in a prompt, highlights meaningful corrections and patterns, and stores only structured learning notes in a private local database.
The project includes a Codex plugin, an MCP interface, a local Node.js runtime, and a browser-based learning dashboard.
- Reviews grammar, spelling, collocations, word choice, tone, and contextual appropriateness.
- Produces natural target-language rewrites instead of literal translations.
- Captures reusable structures, phrases, and transfer examples.
- Tracks native-, target-, mixed-, and other-language usage.
- Provides progress summaries and correction-category trends.
- Includes a local dashboard for reviewing and deleting learning notes.
- Stores data locally in SQLite by default.
- Lets users opt into registration, verified-email login, and remote sync.
- Stores remote notes in Neon Postgres through Cloudflare Hyperdrive.
- Enforces account ownership in both the Worker API and Postgres row-level security policies.
- Deploys the authenticated dashboard as a Cloudflare Worker website.
- Avoids saving unrelated task context, files, or task answers.
- Open the Plugins tab.
- Click the Add button in the top-right corner of the Plugins page.
- In the Add plugin marketplace dialog, enter:
- Source:
[email protected]:jackeydou/codex-lang-coach.git - Git ref:
marketplace - Sparse paths: leave empty
- Source:
- Click Add marketplace.
- Find Language Coach in the added marketplace and install it.
Review and trust the plugin hooks after installation, then start a new Codex task so the plugin runtime is loaded.
Add the generated marketplace branch, then install the plugin:
codex plugin marketplace add jackeydou/codex-lang-coach --ref marketplace
codex plugin add language-coach@language-coachThe full Git URL works too:
codex plugin marketplace add https://github.com/jackeydou/codex-lang-coach.git --ref marketplaceAdd the generated Claude Code marketplace branch, then install the plugin:
claude plugin marketplace add jackeydou/codex-lang-coach@marketplace-cc
claude plugin install language-coach@language-coachThe marketplace-cc branch uses Claude Code's native .claude-plugin/plugin.json, .mcp.json,
and hooks/hooks.json layout. It is built separately from the native Codex and portable Agent
Plugins packages.
The generated marketplace-cursor branch contains the native Cursor plugin and marketplace
manifest. Add that repository and branch through Cursor's team marketplace or copy
plugins/language-coach into ~/.cursor/plugins/local/language-coach for local testing.
The Cursor build uses .cursor-plugin/plugin.json, mcp.json, and hooks/hooks.json. Its
sessionStart hook injects the coaching instructions, including when to save a learning note.
Download and extract the ZIP or tar.gz marketplace bundle from the latest GitHub release. Then install the extracted directory as a local marketplace:
codex plugin marketplace add /path/to/language-coach-marketplace-v0.1.3
codex plugin add language-coach@language-coachCodex cannot use the GitHub Release ZIP URL directly. It must receive the extracted local directory or the Git repository URL shown above.
- Enable plugin hooks after you install it;
- Then you can chat with your codex, now codex will correct and polish your message and save English notes into local sqlite
- Let your codex "Open the Language Coach dashboard", then you can see your English notes and your activities;
|
|
The pnpm workspace separates product source code from the assembled Codex plugin:
agent-plugin-lang-coach/
├── apps/
│ ├── dashboard/ # React and Vite dashboard
│ ├── server/ # Local Node.js runtime and HTTP API
│ └── worker/ # Remote API, Neon migration, and Cloudflare deployment
├── packages/
│ ├── core/ # Domain types, storage, and shared logic
│ ├── mcp/ # MCP schemas, tools, and handlers
│ └── plugin/ # Shared assets, skills, and compiled hooks
├── packaging/
│ ├── codex/ # Native Codex metadata, MCP config, and hooks config
│ ├── agent-plugin/ # Portable Agent Plugins 1.0.0 metadata
│ ├── claude-code/ # Native Claude Code packaging metadata
│ └── cursor/ # Native Cursor packaging metadata
├── scripts/
│ ├── build-plugin.mjs # Assembles the native Codex distribution
│ ├── build-plugin-agent.mjs # Assembles the portable Agent Plugins distribution
│ ├── build-plugin-cc.mjs # Assembles the Claude Code distribution
│ └── build-plugin-cursor.mjs # Assembles the Cursor distribution
├── dist/
│ └── language-coach/ # Generated native Codex distribution
├── dist-agent/
│ └── language-coach/ # Generated portable Agent Plugins distribution
├── dist-cc/
│ └── language-coach/ # Generated Claude Code distribution
├── dist-cursor/
│ └── language-coach/ # Generated Cursor distribution
├── package.json
├── pnpm-workspace.yaml
└── tsconfig.base.json
The package boundaries are intentional:
@language-coach/coreowns the data model, SQLite adapter, and business rules.@language-coach/mcpdefines transport-independent MCP tools and handlers.@language-coach/serverowns process startup, MCP stdio transport, the dashboard API, static assets, and graceful shutdown.@language-coach/dashboardowns the browser interface.@language-coach/workerowns the authenticated remote API and Hyperdrive connection.@language-coach/plugincontains only the source scaffold needed to assemble the plugin variants.
Generated artifacts live in dist/language-coach, dist-agent/language-coach,
dist-cc/language-coach, and dist-cursor/language-coach. Source projects must not write build
output into the plugin scaffold.
- Node.js 22.5 or newer
- pnpm 11 or newer
Install dependencies:
pnpm installRun the dashboard and API development processes:
pnpm devRun static checks and tests:
pnpm check
pnpm testBuild the complete installable plugin:
pnpm build:pluginpnpm build is an alias for the same full plugin build. Both commands assemble a clean, self-contained distribution at dist/language-coach.
Build the portable Agent Plugins 1.0.0 variant separately:
pnpm build:plugin:agentThis portable artifact contains skills and MCP configuration, but no hooks because hooks are not part of Agent Plugins 1.0.0.
Build the Claude Code variant separately:
pnpm build:plugin:ccThis assembles a clean, self-contained distribution at dist-cc/language-coach.
Build the Cursor variant separately:
pnpm build:plugin:cursorThis assembles a native Cursor distribution at dist-cursor/language-coach.
mise.toml pins Node and pnpm and provides shortcuts for the common project workflows:
mise install
mise tasks ls
mise run dev
mise run build:agent
mise run build:cc
mise run build:cursor
mise run verify
mise run worker:devMachine-specific paths and secrets belong in the gitignored mise.local.toml. Uncomment and fill in LANGUAGE_COACH_REMOTE_URL or CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE there when remote sync or local Hyperdrive access is needed.
Run the built dashboard:
pnpm dashboardThe server starts at http://localhost:43127 by default. If the port is occupied, it tries the next available port through 43146.
Set a different starting port when needed:
LANGUAGE_COACH_PORT=44000 pnpm dashboardDuring frontend development, Vite runs at http://127.0.0.1:43128 and proxies API requests to the local Node.js server.
Build the plugin before installing or refreshing it in Codex:
pnpm build:pluginThe repository marketplace at .agents/plugins/marketplace.json points to dist/language-coach. Install Language Coach from that marketplace, review and trust its hooks, then start a new Codex task so the refreshed plugin runtime is loaded.
Language Coach stores its database at:
~/.language-coach/language-coach.sqlite
Override the location with an absolute path:
LANGUAGE_COACH_DB_PATH=/absolute/path/language-coach.sqlite pnpm dashboardA learning note may contain:
- the original expression being coached;
- a polished target-language version;
- correction categories, replacements, and explanations;
- reusable grammar patterns, structures, collocations, or phrases;
- short transfer examples and their contexts;
- the detected input-language category;
- the active language pair, turn identifier, and timestamp.
The schema does not include fields for unrelated task details, files, or task answers. Language Coach saves a note only when an expression has a meaningful error, unnatural wording, a contextual problem, or a useful reusable pattern. Optional stylistic rewrites alone do not justify persistence.
Notes can be deleted through the dashboard or the MCP interface.
The hosted dashboard uses Cloudflare Workers Static Assets, Cloudflare Hyperdrive, Neon Postgres, and Neon Auth. Users can register with email and password or continue with Google or GitHub. Email/password accounts confirm their email before the hosted API returns any learning data.
Remote tables contain a user_id on every row. The Worker derives that ID from a verified Neon JWT or a hashed local-device sync token, sets it in the Postgres transaction, and row-level security enforces the same ownership rule in the database. The Hyperdrive connection must use the limited language_coach_app role rather than neondb_owner, because owner roles bypass RLS.
Local use remains account-free by default. Open Settings → Login & sync to register or sign in and upload the local notes for that account. The local device credential is stored at ~/.language-coach/remote-sync.json with owner-only permissions. Turning sync off re-authenticates, revokes the remote device tokens, and removes the local credential. Deletion tombstones prevent deleted notes from reappearing during a later merge.
- Create a Neon project and enable Neon Auth for its main branch.
- Enable email/password registration, require email verification, and add the local and deployed dashboard URLs as trusted origins.
- Enable Google and GitHub OAuth for the branch. Google can use Neon's shared credentials while developing; GitHub requires a GitHub OAuth app. For production, use your own credentials for both providers and register
{NEON_AUTH_URL}/callback/googleand{NEON_AUTH_URL}/callback/githubas their provider callback URLs. - Create a non-owner Postgres role named
language_coach_appwith a strong password. - Apply
apps/worker/migrations/0001_neon.sqlasneondb_owner. - Create a Cloudflare Hyperdrive configuration from the direct, unpooled Neon connection string for
language_coach_app. - Put the Hyperdrive configuration ID and Neon Auth URL in
apps/worker/wrangler.jsonc.
Set NEON_PRODUCTION_DATABASE_URL in the gitignored mise.local.toml to a direct, unpooled owner/admin connection string. Apply pending production migrations with:
mise run db:migrate:productionThe task asks for confirmation, verifies the limited runtime role, and records each applied file from apps/worker/migrations. Do not use the language_coach_app connection for migrations.
For local Worker development, set the documented Hyperdrive override without committing it:
export CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE='postgresql://language_coach_app:...@.../neondb?sslmode=require'
pnpm --filter @language-coach/worker devDeploy from the repository root:
pnpm deploy:cloudflareThe deployed site works at https://language-coach.pluginsfoundry.dev. The built local dashboard remains available at http://localhost:43127. Set LANGUAGE_COACH_REMOTE_URL only when the local build should discover a different deployed Worker.
The default language pair is Chinese to English. The native language, target language, and coaching status can be changed from the dashboard or through the update_language_profile MCP tool.
Disabling coaching stops prompt injection. Existing notes remain available until they are explicitly deleted.
The default build produces the native Codex artifact. Codex discovers hooks from the root
hooks/hooks.json path:
dist/language-coach/
├── .codex-plugin/plugin.json
├── .mcp.json
├── hooks/
├── skills/
├── mcp/server.mjs
└── dashboard/dist/
The portable Agent Plugins 1.0.0 build contains only the standard portable components—skills and MCP servers—and deliberately omits host-specific hooks:
dist-agent/language-coach/
├── plugin.json
├── mcp.json
├── skills/
├── mcp/server.mjs
└── dashboard/dist/
The Claude Code build produces its native layout independently:
dist-cc/language-coach/
├── .claude-plugin/plugin.json
├── .mcp.json
├── hooks/
├── skills/
├── mcp/server.mjs
└── dashboard/dist/
The Cursor build also uses a native host layout and Cursor-specific hook executables:
dist-cursor/language-coach/
├── .cursor-plugin/plugin.json
├── mcp.json
├── hooks/
│ ├── hooks.json
│ └── cursor-session-start.mjs
├── skills/
├── mcp/server.mjs
└── dashboard/dist/
The distribution must not depend on workspace imports, repository-relative source paths, TypeScript execution, or a repository-level node_modules directory. It should continue to work when copied outside this repository.
Pushing a version tag such as v0.1.3 runs the GitHub Actions release workflow. The workflow checks
and tests the workspace, builds the plugin, creates ZIP and tar.gz marketplace bundles, writes
SHA-256 checksums, publishes the files to GitHub Releases, and updates the generated marketplace
branch. The tag version must match the root package version.
The workflow can also be run manually from master to rebuild the marketplace branch without
creating another GitHub Release. The generated branch contains only the marketplace catalog and
the self-contained plugin:
.agents/plugins/marketplace.json
plugins/language-coach/
The separate Claude Code workflow uses the same tag and manual-release conditions. It packages the
Claude Code artifact and publishes this generated tree to marketplace-cc:
.claude-plugin/marketplace.json
plugins/language-coach/
The Cursor workflow follows the same release conditions and publishes its generated marketplace
to marketplace-cursor:
.cursor-plugin/marketplace.json
plugins/language-coach/
Before submitting a change, run:
pnpm install
pnpm check
pnpm test
pnpm build:plugin
pnpm build:plugin:agent
pnpm build:plugin:cc
pnpm build:plugin:cursorThe resulting plugin must:
- pass Codex plugin validation and load hooks from
hooks/hooks.json; - conform to the Agent Plugins 1.0.0 manifest and MCP schemas for the portable variant;
- pass
claude plugin validatefor the Claude Code variant; - use Cursor's native
sessionStarthook protocol for the Cursor variant; - starts its MCP server over stdio;
- starts the dashboard and serves its API;
- uses one shared database schema across hooks, MCP tools, and the dashboard;
- contains no source-only or workspace-dependent files; and
- runs after
dist/language-coachis copied outside the repository.
This project is licensed under the MIT License.


