Skip to main content

Self-contained AI config sync for Codex, Cursor, and Gemini.

Project description

AI Research Doc

A self-contained local config store for Codex, Cursor, and Gemini CLI. Define agents, skills, MCP servers, and client settings once in ~/.ai-sync/, then sync them to every client with one command.

License: PolyForm Noncommercial 1.0.0 (non-commercial use only).

Overview

This repo provides:

  • The ai-sync CLI – Manage ~/.ai-sync/ and run syncs
  • Agents – Sub-agents derived from prompts with per-client metadata
  • Skills – Agent Skills (SKILL.md) mirrored to all clients
  • MCP servers – Model Context Protocol servers with centralized config and secrets
  • Client configuration – Generic settings (subagents, mode) derived into client-specific configs
  • OAuth token portability – Manual copy of client OAuth caches across machines (automated capture/restore planned)

All syncing is idempotent: identical targets cause no writes; changed targets overwrite in place.


Install

End users (recommended)

pipx install ai-sync

Local development

pip install -e ".[dev]"

Quick start

ai-sync setup --op-account NAME
ai-sync import --repo /path/to/config-repo   # optional
ai-sync sync

Prerequisites

  • Python 3.10+
  • Codex, Cursor, and/or Gemini CLI installed
  • 1Password Desktop app (for OP_ACCOUNT) or OP_SERVICE_ACCOUNT_TOKEN for service accounts
  • For MCP stdio servers: Node.js (npx), uv (uvx for workspace-mcp), pip install mcp-server-fetch for fetch

Project structure

This repo ships the sync tool. Runtime data lives in ~/.ai-sync/.

Repo:
.
├── src/
│   └── ai_sync/               # Python: ai-sync
│       └── .client-versions.json  # Supported client versions (packaged)
├── tests/
├── pyproject.toml
└── README.md

Runtime:
~/.ai-sync/
├── config.toml                # op_account, secret_provider
├── .env.tpl                   # MCP secrets (op:// refs resolved via 1Password)
├── config/
│   ├── prompts/
│   ├── skills/
│   ├── mcp-servers/
│   └── client-settings/
└── cache/

Import repo layout:

<repo>/
├── prompts/
├── skills/
├── mcp-servers.yaml
├── client-settings.yaml
├── .env.tpl            # optional
└── rules/              # optional

ai-sync

Usage

ai-sync setup --op-account NAME
ai-sync import --repo /path/to/config-repo   # optional
ai-sync sync

Running ai-sync with no subcommand defaults to sync. Other commands: ai-sync setup, ai-sync import, ai-sync doctor.

Sync options

Option Description
(none) Full sync: agents → skills → MCP servers → client config
--force Update the packaged client version lock (dev-only), then sync
--no-interactive Skip interactive prompts
--plain Plain output (implies --no-interactive)
--override / --override-json Override manifest leaf values (e.g. /servers/context7/enabled=false)

Sync order

  1. Agents – From ~/.ai-sync/config/prompts/*.md~/.codex/agents/, ~/.cursor/agents/, ~/.gemini/agents/
  2. Skills – From ~/.ai-sync/config/skills/*/~/.codex/skills/, ~/.cursor/skills/, ~/.gemini/skills/
  3. MCP servers – From ~/.ai-sync/config/mcp-servers/servers.yaml → client MCP configs, MCP instructions
  4. Client config – From ~/.ai-sync/config/client-settings/settings.yaml → approval policy, sandbox, features

Sync strategy

  • Agents, skills, client config: Files overwritten if they exist. Untracked agents/skills (not in ~/.ai-sync/config/prompts/ or ~/.ai-sync/config/skills/) are left alone.
  • Client config: Deep-merge with existing; ai-tools keys overwrite on conflict.
  • MCP servers: Merged with existing; managed servers updated, user-added servers preserved.

Agents

Source structure

Each agent lives in ~/.ai-sync/config/prompts/:

~/.ai-sync/config/prompts/
├── <agent_name>.md           # Prompt content (required)
└── <agent_name>.metadata.yaml   # Optional metadata

Metadata schema (~/.ai-sync/config/prompts/<name>.metadata.yaml)

Metadata is generic (client-agnostic). The sync script adapts it per client.

Key Description Default
slug Agent ID (kebab-case) Derived from filename
name Display name From filename
description Short description Extracted from prompt

Untracked agents (in client but not in ~/.ai-sync/config/prompts/) are left alone.

Target layout per client

Client Target
Codex ~/.codex/agents/<slug>/prompt.md + config.toml
Cursor ~/.cursor/agents/<slug>.md (frontmatter)
Gemini ~/.gemini/agents/<slug>.md (frontmatter)

Skills

Skills are directories under ~/.ai-sync/config/skills/ with a SKILL.md file. The sync script mirrors each skill to all three clients.

Structure

~/.ai-sync/config/skills/
└── <skill-name>/
    ├── SKILL.md          # Required
    ├── reference.md      # Optional
    ├── examples.md       # Optional
    └── scripts/          # Optional; copied if present

Paths containing .venv, node_modules, __pycache__, .git, or .DS_Store are skipped. Untracked skills (in client but not in ~/.ai-sync/config/skills/) are left alone.

Targets

  • ~/.codex/skills/<skill-name>/
  • ~/.cursor/skills/<skill-name>/
  • ~/.gemini/skills/<skill-name>/

MCP servers

Manifest (~/.ai-sync/config/mcp-servers/servers.yaml)

servers:
  <server_id>:
    method: stdio | http | sse
    command: npx
    args: ["-y", "@modelcontextprotocol/server-xxx"]
    enabled: true
    clients: [codex, cursor, gemini]   # Optional; default: all
    timeout: 60s                       # Optional; startup/tool timeout
    trust: true                        # Optional; Cursor/Gemini: auto-approve tools

STDIO serverscommand, args; env vars use "${VAR}" refs resolved from ~/.ai-sync/.env.tpl.

HTTP/SSE serversurl, httpUrl; optional bearer_token_env_var for Codex.

HTTP with OAuthhttpUrl + oauth.enabled: true; clientId/clientSecret from ~/.ai-sync/.env.tpl via "${VAR}":

  google-maps-grounding-lite:
    method: http
    httpUrl: https://mapstools.googleapis.com/mcp
    oauth:
      enabled: true
      clientId: "${GOOGLE_MAPS_GROUNDING_LITE_CLIENT_ID}"
      clientSecret: "${GOOGLE_MAPS_GROUNDING_LITE_CLIENT_SECRET}"

Configured servers

Server Method Description
context7 stdio Documentation lookup (@upstash/context7-mcp)
fetch stdio URL fetch → markdown (python -m mcp_server_fetch)
playwright stdio Browser control (@playwright/mcp)
exa http Search API
google-workspace-perso stdio Gmail, Calendar, Drive (personal @gmail.com, separate OAuth)
google-workspace-pro stdio Gmail, Calendar, Drive (work @sherpas.com, separate OAuth)
google-maps-grounding-lite http Maps grounding (OAuth)

Secrets (~/.ai-sync/.env.tpl)

All MCP secrets live in ~/.ai-sync/.env.tpl. Use op:// references for 1Password:

CONTEXT7_API_KEY=op://Private/AI Tools Secrets/CONTEXT7_API_KEY
EXA_API_KEY=op://Private/AI Tools Secrets/EXA_API_KEY
GOOGLE_OAUTH_CLIENT_ID_PERSO=op://Private/AI Tools Secrets/GOOGLE_OAUTH_CLIENT_ID_PERSO
...

In servers.yaml, reference them with "${VAR_NAME}" in each server's env or oauth block. The sync script resolves these at runtime via 1Password (requires OP_ACCOUNT or OP_SERVICE_ACCOUNT_TOKEN).

Requirements: 1Password Desktop app (for OP_ACCOUNT) or OP_SERVICE_ACCOUNT_TOKEN (service account).

Client targets

Client Target Strategy
Codex ~/.codex/config.toml [mcp_servers.<id>] Merge
Codex ~/.codex/mcp.env Bearer token exports (source before running Codex)
Cursor ~/.cursor/mcp.json Overwrite mcpServers
Gemini ~/.gemini/settings.json mcpServers Deep-merge

OAuth token portability

OAuth tokens are stored per client (e.g. ~/.gemini/mcp-oauth-tokens.json). To move them between machines, copy the client token files manually via a secure channel (rsync, 1Password, etc.). Automated capture/restore is planned.


Client configuration

Single YAML definition → derived into Codex, Gemini, and Cursor.

Schema (~/.ai-sync/config/client-settings/settings.yaml)

Copy from settings.example.yaml. See that file for full schema.

Key Values Description
subagents true | false Enable multi-agents, sub-agents, child-prompts, AGENTS.md
mode ask | ask-once | full-access Approval / restriction mode
suppress_unstable_features_warning true | false Codex only. Suppress "Under-development features" warning
tools.sandbox true | false Gemini only. When false, allow MCP tools filesystem access (uvx, etc.)

Mode semantics

Mode Meaning
ask Prompt for approval every time before acting
ask-once Auto-approve safe ops, prompt for risky ones (where supported)
full-access No approval prompts, no restrictions (YOLO)

Client mapping (from official docs)

Generic Codex Gemini Cursor
subagents: true features.multi_agent, features.child_agents_md experimental.enableAgents
suppress_unstable_features_warning suppress_unstable_features_warning
tools.sandbox: false tools.sandbox
mode: ask approval_policy=on-request, sandbox_mode=workspace-write general.defaultApprovalMode=default permissions: {allow:[], deny:[]}
mode: ask-once approval_policy=untrusted, sandbox_mode=workspace-write general.defaultApprovalMode=auto_edit same as ask
mode: full-access approval_policy=never, sandbox_mode=danger-full-access general.defaultApprovalMode=yolo allow: [Shell(*), Read(*), Write(*), WebFetch(*), Mcp(*:*)]

Client targets

Client Target Strategy
Codex ~/.codex/config.toml Deep-merge with existing; ai-tools keys overwrite. No backup.
Gemini ~/.gemini/settings.json Deep-merge with existing; ai-tools keys overwrite. No backup.
Cursor ~/.cursor/cli-config.json Deep-merge with existing; ai-tools keys overwrite. No backup.

Dependencies

The sync tool is packaged from the repo root:

pip install -e .

Dependencies: pyyaml>=6.0, tomli>=2.0, tomli-w>=1.0, and others (see pyproject.toml).

Testing

pip install -e ".[dev]"
pytest

Packaging & Release

This project is published to PyPI as ai-sync.

Release checklist

  1. Update version in pyproject.toml.
  2. Update README if anything changed in CLI behavior or setup.
  3. Tag and push:
git tag vX.Y.Z
git push origin vX.Y.Z
  1. GitHub Actions runs tests, builds artifacts, publishes to PyPI, and creates a GitHub Release.

Notes

  • Use pipx install ai-sync for end users.
  • Keep ai-sync as the only supported CLI name.

.gitignore

If you maintain a separate config repo for ai-sync import, consider ignoring:

  • config/mcp-servers/servers.yaml (copy from servers.example.yaml)
  • config/client-settings/settings.yaml (copy from settings.example.yaml)
  • .env.tpl
  • knowledge-base/*
  • .env, Python bytecode, virtual envs, .pytest_cache/, node_modules/, .DS_Store, etc.

Workflow summary

New machine setup

  1. Clone repo (tooling only)
  2. pip install -e ".[dev]"
  3. ai-sync setup --op-account NAME (or set OP_SERVICE_ACCOUNT_TOKEN)
  4. ai-sync import --repo /path/to/config-repo (optional)
  5. Ensure ~/.ai-sync/.env.tpl has correct 1Password refs
  6. ai-sync sync
  7. For Codex HTTP MCP servers: source ~/.codex/mcp.env in shell profile

Adding an MCP server

  1. Edit ~/.ai-sync/config/mcp-servers/servers.yaml
  2. Add required vars to ~/.ai-sync/.env.tpl (use op:// refs for secrets)
  3. Run ai-sync sync

Adding an agent

  1. Add ~/.ai-sync/config/prompts/<name>.md
  2. (Optional) Add ~/.ai-sync/config/prompts/<name>.metadata.yaml
  3. Run ai-sync sync

Adding a skill

  1. Create ~/.ai-sync/config/skills/<skill-name>/SKILL.md
  2. Run ai-sync sync

Changing client mode

  1. Edit ~/.ai-sync/config/client-settings/settings.yaml (subagents, mode)
  2. Run ai-sync sync

References

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ai_sync-0.1.3.tar.gz (36.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ai_sync-0.1.3-py3-none-any.whl (34.0 kB view details)

Uploaded Python 3

File details

Details for the file ai_sync-0.1.3.tar.gz.

File metadata

  • Download URL: ai_sync-0.1.3.tar.gz
  • Upload date:
  • Size: 36.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ai_sync-0.1.3.tar.gz
Algorithm Hash digest
SHA256 c274e778faefa86447128ea880dfd5a180fc5b3c8443f3b2d5ced658a8f0c84e
MD5 9f1b4afc14f6ef34890be3e91e0a48a6
BLAKE2b-256 6eff4f7e8e265bd388c71ab748d06559500b28a5c440128c669280f30d2d5252

See more details on using hashes here.

Provenance

The following attestation bundles were made for ai_sync-0.1.3.tar.gz:

Publisher: release.yml on Ephasme/ai-sync

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ai_sync-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: ai_sync-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 34.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ai_sync-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 09355a96d47a34a067603b786d751882ef174860e8a4fb49fbf6cefb2b6dc05c
MD5 ea41c1b716df0c1b2f5a741586cfd372
BLAKE2b-256 9cc84e0b5a722d2e0f857f6838b15e42fd06bf8622c46c3699c3a7a1a4802b7e

See more details on using hashes here.

Provenance

The following attestation bundles were made for ai_sync-0.1.3-py3-none-any.whl:

Publisher: release.yml on Ephasme/ai-sync

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page