Skip to content

feat(sync): implement skills sync upload and apply commands with support for ignore patterns#144

Merged
crimx merged 2 commits into
mainfrom
skill-sync
May 6, 2026
Merged

feat(sync): implement skills sync upload and apply commands with support for ignore patterns#144
crimx merged 2 commits into
mainfrom
skill-sync

Conversation

@crimx
Copy link
Copy Markdown
Contributor

@crimx crimx commented May 6, 2026

Registry-Only Skills Sync

closes #138

Summary

  • Add oo skills sync upload and oo skills sync apply.
  • apply also supports aliases: download and install.
  • Both commands accept --source registry, default to registry, and reject other sources.

Key Changes

  • Add a sync child under oo skills with:
    • upload
    • apply aliases: download, install
  • upload scans installed oo-managed registry skills only, then PUT https://cli-api.<endpoint>/v1/skills with:
    { packageName: string; version: string; skillName: string }[]
  • apply / download / install reads GET https://cli-api.<endpoint>/v1/skills and installs those registry skills into supported local agent directories.
  • Extend registry install internals to support an explicit package version, so sync restores uploaded versions instead of always installing latest.
  • Add -i, --ignore <patterns...> to upload; repeated flags and comma-separated values are accepted, matched via the existing ignore package against packageName or skillName.

User-Facing Behavior

  • Supported forms:
    • oo skills sync upload
    • oo skills sync upload --source registry
    • oo skills sync apply
    • oo skills sync download
    • oo skills sync install
  • upload overwrites the remote registry-skill manifest, including uploading [] when none are installed.
  • Reverse-sync commands install/apply the cloud registry-skill manifest; local and bundled skills are never synced.

Tests

  • Test API request URLs, methods, headers, payload validation, and invalid-response errors.
  • Test upload excludes bundled/local skills, deduplicates registry installs, and honors --ignore.
  • Test apply, download, and install aliases all install exact versions from the remote manifest.
  • Test --source default and invalid source errors.
  • Update docs/commands.md and docs/commands.zh-CN.md.
  • Run bun run lint:fix, bun run ts-check, and bun run test.

Assumptions

  • /v1/skills is served at https://cli-api.<account.endpoint>/v1/skills.
  • Server auth should use the current account Authorization header.
  • apply remains the canonical documented verb; download and install are aliases for discoverability.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Summary by CodeRabbit

  • New Features

    • Added oo skills sync upload command to upload registry-managed skills to a sync service.
    • Added oo skills sync apply command to download and apply registry skills from the sync service locally.
    • Enabled version-specific installation of registry skills.
  • Documentation

    • Added comprehensive command documentation for skills synchronization in English and Chinese with options, behavior, and output details.

Walkthrough

This pull request introduces a skills synchronization command (oo skills sync) with two subcommands: upload and apply. The upload subcommand collects registry-managed skills from local canonical and host paths, filters and deduplicates them by ignore patterns, and uploads them to a sync service. The apply subcommand downloads synchronized skill records and installs them into local skill directories. The change also adds shared comma-separated value parsing, propagates packageVersion through registry install flows, adds docs and i18n entries, and adds tests for the new behavior.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI as CLI Client
    participant Filesystem as Local Filesystem
    participant SyncService as Sync Service

    User->>CLI: oo skills sync upload
    activate CLI
    CLI->>Filesystem: Read canonical & host registry skills
    Filesystem-->>CLI: Skill files/metadata
    CLI->>CLI: Filter by ignore patterns\nDeduplicate records
    CLI->>SyncService: PUT /sync (skill records)
    activate SyncService
    SyncService-->>CLI: 200 OK (success)
    deactivate SyncService
    CLI->>User: Print success message
    deactivate CLI
Loading
sequenceDiagram
    actor User
    participant CLI as CLI Client
    participant SyncService as Sync Service
    participant Filesystem as Local Filesystem

    User->>CLI: oo skills sync apply
    activate CLI
    CLI->>SyncService: GET /sync (request records)
    activate SyncService
    SyncService-->>CLI: 200 OK (skill records JSON)
    deactivate SyncService
    CLI->>CLI: Parse and filter records
    CLI->>Filesystem: Install skills to local directories
    Filesystem-->>CLI: Installation results
    CLI->>User: Print success or no-results message
    deactivate CLI
Loading

Possibly related PRs

  • oomol-lab/oo-cli#140: Modifies skills command wiring and related docs/i18n to extend skills subcommands — overlaps with adding skillsSyncCommand.
  • oomol-lab/oo-cli#41: Related registry-based skills work; both touch registry skill install/source modules and tests, and this PR extends that with packageVersion and sync commands.
  • oomol-lab/oo-cli#47: Overlaps on skills command surface and registry skill installation flow; both PRs modify the same files and installation-related logic.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the required format with type and scope, is clear and descriptive, and directly relates to the main change in the changeset.
Description check ✅ Passed The PR description is comprehensive and clearly related to the changeset, detailing the sync upload/apply commands, key changes, user-facing behavior, and testing requirements.
Linked Issues check ✅ Passed All coding requirements from issue #138 are met: sync command added for oo-managed skills, handles only oo-managed skills, preserves versions instead of upgrading to latest, and appropriate tests are included.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the skills sync functionality; no unrelated modifications detected beyond the scope of issue #138.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch skill-sync

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/application/commands/skills/sync.ts (1)

150-161: ⚖️ Poor tradeoff

Consider parallelizing independent skill installations.

The for...of loop installs records sequentially. If installations are independent, Promise.all() would improve performance. However, sequential execution may be intentional for rate limiting or consistent output ordering.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/application/commands/skills/sync.ts` around lines 150 - 161, The loop in
sync.ts iterates records sequentially calling installRegistrySkills for each
record, causing slow installs; replace the for...of with parallel execution by
mapping records to promises that call installRegistrySkills(record, context) and
await Promise.all(...) so independent installs run concurrently, or if
rate-limiting/ordering is required use a bounded concurrency utility (e.g.,
p-map) to limit simultaneous calls while still improving throughput; ensure you
reference the existing installRegistrySkills function, the records array, and
the context parameter when implementing the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/application/commands/skills/sync.ts`:
- Around line 171-173: The createSkillSyncRequestUrl function builds URLs with
the wrong host prefix; change the host from "cli-api" to "api" so it returns new
URL(`https://api.${endpoint}/v1/skills`) instead of using "cli-api" — update the
createSkillSyncRequestUrl function accordingly (tests referencing sync.test.ts
and index.test.ts expect the "api" prefix).

---

Nitpick comments:
In `@src/application/commands/skills/sync.ts`:
- Around line 150-161: The loop in sync.ts iterates records sequentially calling
installRegistrySkills for each record, causing slow installs; replace the
for...of with parallel execution by mapping records to promises that call
installRegistrySkills(record, context) and await Promise.all(...) so independent
installs run concurrently, or if rate-limiting/ordering is required use a
bounded concurrency utility (e.g., p-map) to limit simultaneous calls while
still improving throughput; ensure you reference the existing
installRegistrySkills function, the records array, and the context parameter
when implementing the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 49e2d219-739b-45f4-8d08-08654cea46ea

📥 Commits

Reviewing files that changed from the base of the PR and between 4eed4cc and b587481.

📒 Files selected for processing (11)
  • docs/commands.md
  • docs/commands.zh-CN.md
  • src/application/commands/shared/keywords.ts
  • src/application/commands/shared/list-parsing.ts
  • src/application/commands/skills/index.test.ts
  • src/application/commands/skills/index.ts
  • src/application/commands/skills/registry-skill-install.ts
  • src/application/commands/skills/registry-skill-source.ts
  • src/application/commands/skills/sync.test.ts
  • src/application/commands/skills/sync.ts
  • src/i18n/catalog.ts

Comment thread src/application/commands/skills/sync.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/application/commands/skills/index.test.ts (1)

1823-1910: ⚡ Quick win

Extract repeated sync test setup into a local factory helper.

The request-capture + fetcher scaffolding is duplicated across these new sync tests. A small local helper would reduce drift and make future sync cases easier to add.

♻️ Example extraction
+function createJsonEchoFetcher(
+  requests: Array<{
+    authorization: string | null;
+    method: string;
+    url: string;
+    body: unknown;
+  }>,
+) {
+  return async (input: RequestInfo | URL, init?: RequestInit) => {
+    const request = toRequest(input, init);
+    const body = await request.json();
+    requests.push({
+      authorization: request.headers.get("Authorization"),
+      method: request.method,
+      url: request.url,
+      body,
+    });
+    return new Response(JSON.stringify(body));
+  };
+}

As per coding guidelines, **/*.test.{ts,tsx}: “Extract repeated setup (mocks, stubs, setup objects) into local factory functions in test files; avoid copy-pasting test setup.”

Also applies to: 1957-2080

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/application/commands/skills/index.test.ts` around lines 1823 - 1910,
Several sync upload tests repeat sandbox setup, directory/file creation, auth
writing and a fetcher that captures requests; extract that repeated scaffolding
into a local factory helper (e.g., makeSyncUploadTest or createSyncTestFixture)
inside the test file and call it from the tests. The helper should perform
createCliSandbox(), compute codexHomeDirectory, create skill directories
(chatSkillDirectoryPath, captionSkillDirectoryPath), writeAuthFile, write
managed metadata files via resolveManagedSkillMetadataFilePath and
renderSkillMetadataJson, and return the sandbox, paths, and a requests array
plus a fetcher function suitable for passing to sandbox.run; then replace the
duplicated blocks in the tests (the setup around createCliSandbox, mkdir,
Bun.write, requests array and the inline fetcher) with calls to that helper and
use the returned fetcher when invoking sandbox.run.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/application/commands/skills/index.test.ts`:
- Around line 1823-1910: Several sync upload tests repeat sandbox setup,
directory/file creation, auth writing and a fetcher that captures requests;
extract that repeated scaffolding into a local factory helper (e.g.,
makeSyncUploadTest or createSyncTestFixture) inside the test file and call it
from the tests. The helper should perform createCliSandbox(), compute
codexHomeDirectory, create skill directories (chatSkillDirectoryPath,
captionSkillDirectoryPath), writeAuthFile, write managed metadata files via
resolveManagedSkillMetadataFilePath and renderSkillMetadataJson, and return the
sandbox, paths, and a requests array plus a fetcher function suitable for
passing to sandbox.run; then replace the duplicated blocks in the tests (the
setup around createCliSandbox, mkdir, Bun.write, requests array and the inline
fetcher) with calls to that helper and use the returned fetcher when invoking
sandbox.run.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 25394225-0283-4f91-884b-15dd9809c54e

📥 Commits

Reviewing files that changed from the base of the PR and between b587481 and 6cb589e.

📒 Files selected for processing (2)
  • src/application/commands/skills/index.test.ts
  • src/application/commands/skills/sync.test.ts

@crimx crimx merged commit 4142f3a into main May 6, 2026
5 checks passed
@crimx crimx deleted the skill-sync branch May 6, 2026 13:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add skills sync command for oo-managed skills

1 participant