Design and implement shadcn-style persona installs #36

Description

@willwashburn

Summary

Add a project-local persona install command inspired by shadcn: users install persona packs from npm or a local path, and the persona JSON files are copied into the current project's .agentworkforce/workforce/personas/ directory so they become editable, project-owned files.

Like shadcn, this is intentionally a copy-paste utility, not a package manager. Once copied, files are yours — there is no manifest, lockfile, or install ledger. Git tracks what you have.

Primary command shape:

agentworkforce install @agentrelay/personas
agentworkforce install @agentrelay/personas@1.2.3
agentworkforce install ./local-personas
agentworkforce install @agentrelay/personas --persona relay-orchestrator
agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer

This is distinct from sources add, which points at a live directory. install copies files into the project once, and they belong to the project.

Goals

  • Allow teams to distribute multiple personas in a single npm package or local repo.
  • Let a project install personas locally so they can be edited directly after install.
  • Avoid maintaining a separate AgentWorkforce registry. Use npm package resolution as the registry and distribution mechanism.
  • Keep persona JSON under .agentworkforce/workforce/personas/ so .agentworkforce/workforce/config.json and future workforce-level files are not scanned as personas.
  • Stay narrow: copy files, refuse to overwrite by default, support --overwrite to force. No state file, no update/uninstall/diff commands, no version tracking.

Non-goals

  • No install-state.json or any other install ledger. Once files are copied, they are project-owned and tracked by git — exactly like shadcn components.
  • No version pinning beyond what the user passes on the command line each time.
  • No update, uninstall, or diff subcommands. To update a pack, re-run install --overwrite.
  • No skill validation or skill installation at install time. Skills declared in a persona's skills[] array are resolved by the harness at agent-use time, not at persona-copy time. A broken skill reference is a bug in the persona itself, fixed at the persona's definition site.

Proposed package format

A persona package can contain many persona JSON files:

@agentrelay/personas
├── package.json
└── personas/
├── relay-orchestrator.json
├── code-reviewer.json
├── e2e-validator.json
└── posthog.json

Package metadata:

{
"name": "@agentrelay/personas",
"version": "1.2.3",
"files": ["personas"],
"keywords": ["agentworkforce-personas"],
"agentworkforce": {
"personas": "personas"
}
}

Resolution rules:

  1. Read package.json.agentworkforce.personas if present.
  2. Otherwise fall back to a top-level personas/ directory.
  3. Copy every *.json persona file from that directory.

Project layout after install

.agentworkforce/
└── workforce/
├── config.json
└── personas/
├── relay-orchestrator.json
├── code-reviewer.json
└── e2e-validator.json

Installed personas are project-owned editable files after install. Commit them to git like any other source file.

Install behavior

For npm packages, shell out to npm rather than implementing registry logic:

npm pack @agentrelay/personas --pack-destination <tmp>

Then:

  1. Unpack the tarball into a temp directory (top-level dir is package/).
  2. Read package metadata.
  3. Locate the persona directory.
  4. If --persona <id> flags were passed, filter the persona files down to those whose persona id matches. Repeating the flag selects multiple personas. If any requested id is not found in the package, exit non-zero with a clear error before copying anything.
  5. Copy persona JSON files into .agentworkforce/workforce/personas/. Filenames are flattened — the persona file is copied directly into .agentworkforce/workforce/personas/<basename>.json, regardless of any nested layout under the package's persona directory.

Benefits of using npm pack:

  • Uses npm auth and npm config automatically.
  • Works with private packages.
  • Supports version specifiers like @agentrelay/personas@1.2.3.
  • Avoids a custom registry client.

Local path installs read directly from the directory using the same package metadata rules (or the personas/ fallback if there is no package.json).

Conflict policy (shadcn-style)

Once copied, files are yours.

  • If the target file does not exist: copy it.
  • If the target file exists: skip it and report a conflict, unless --overwrite is passed.
  • --overwrite replaces the existing file unconditionally.

No hashing, no three-way merge, no edit detection. If you want to preserve a local edit, don't pass --overwrite. If you want the upstream version, pass --overwrite and read the diff in git.

Filename collisions across packages fall under the same rule. If @a/personas and @b/personas both ship code-reviewer.json, installing the second one on top of the first is treated identically to a local edit conflict — skipped by default, replaced with --overwrite. The install layer does not namespace files by package; the cascade keys by persona id, so the practical guidance is "don't ship two personas with the same filename if you also expect to be installed alongside each other."

Relationship to source directories

Keep both concepts:

  • agentworkforce sources add <dir>: point at a live directory. Good for development against a checkout or a shared directory.
  • agentworkforce install <pkg>: copy personas into this project. Good for project-owned editable personas.

Installed files participate in the existing cascade because .agentworkforce/workforce/personas/ is already the fixed cwd/project-local persona directory. install does not modify the sources config.

Acceptance criteria

  • agentworkforce install @scope/pkg copies all persona JSON files from the package's persona directory into .agentworkforce/workforce/personas/.
  • A package can contain multiple personas.
  • The package persona directory is discovered through package.json.agentworkforce.personas, with fallback to personas/.
  • The command supports npm package specs with versions (@scope/pkg@1.2.3, @scope/pkg@latest, etc.).
  • The command supports local path installs (./local-personas).
  • The command supports --persona <id> (repeatable) to install a subset of the personas in the pack. Unknown ids fail fast before any file is copied.
  • Persona filenames are flattened into .agentworkforce/workforce/personas/<basename>.json; nested layouts inside the package's persona directory are not preserved.
  • Existing persona files are not overwritten by default — the install reports conflicts and exits with a non-zero status if any target file already exists. This applies equally to filename collisions across packages.
  • --overwrite forces replacement of existing files.
  • Installed personas are visible to agentworkforce list and usable via agentworkforce agent <persona>.
  • No install ledger, lockfile, or central registry is introduced.
  • Documentation is updated in the relevant READMEs (root README.md and packages/cli/README.md at minimum) covering: the install command, version and local-path forms, --persona subset installs, --overwrite, the package format (agentworkforce.personas field and personas/ fallback), how install relates to sources, and a worked example of authoring and publishing a persona pack.

Tests to add

  • Installs multiple personas from a fixture package.
  • Reads agentworkforce.personas from package metadata.
  • Falls back to personas/ if metadata is absent.
  • Refuses to overwrite an existing persona file by default; reports the conflict.
  • --overwrite replaces existing persona files.
  • Local path installs work end-to-end.
  • --persona <id> installs only the requested persona(s); repeating the flag installs multiple; an unknown id exits non-zero before any file is copied.
  • Filenames are flattened on install (nested layouts in the package persona directory are not preserved).
  • Filename collisions across two installed packages are reported as conflicts and resolved by --overwrite.
  • Installed personas are loaded through the cwd/project cascade.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
      Skip to content

      Design and implement shadcn-style persona installs #36

      Description

      @willwashburn

      Summary

      Add a project-local persona install command inspired by shadcn: users install persona packs from npm or a local path, and the persona JSON files are copied into the current project's .agentworkforce/workforce/personas/ directory so they become editable, project-owned files.

      Like shadcn, this is intentionally a copy-paste utility, not a package manager. Once copied, files are yours — there is no manifest, lockfile, or install ledger. Git tracks what you have.

      Primary command shape:

      agentworkforce install @agentrelay/personas
      agentworkforce install @agentrelay/personas@1.2.3
      agentworkforce install ./local-personas
      agentworkforce install @agentrelay/personas --persona relay-orchestrator
      agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer

      This is distinct from sources add, which points at a live directory. install copies files into the project once, and they belong to the project.

      Goals

      • Allow teams to distribute multiple personas in a single npm package or local repo.
      • Let a project install personas locally so they can be edited directly after install.
      • Avoid maintaining a separate AgentWorkforce registry. Use npm package resolution as the registry and distribution mechanism.
      • Keep persona JSON under .agentworkforce/workforce/personas/ so .agentworkforce/workforce/config.json and future workforce-level files are not scanned as personas.
      • Stay narrow: copy files, refuse to overwrite by default, support --overwrite to force. No state file, no update/uninstall/diff commands, no version tracking.

      Non-goals

      • No install-state.json or any other install ledger. Once files are copied, they are project-owned and tracked by git — exactly like shadcn components.
      • No version pinning beyond what the user passes on the command line each time.
      • No update, uninstall, or diff subcommands. To update a pack, re-run install --overwrite.
      • No skill validation or skill installation at install time. Skills declared in a persona's skills[] array are resolved by the harness at agent-use time, not at persona-copy time. A broken skill reference is a bug in the persona itself, fixed at the persona's definition site.

      Proposed package format

      A persona package can contain many persona JSON files:

      @agentrelay/personas
      ├── package.json
      └── personas/
      ├── relay-orchestrator.json
      ├── code-reviewer.json
      ├── e2e-validator.json
      └── posthog.json
      

      Package metadata:

      {
      "name": "@agentrelay/personas",
      "version": "1.2.3",
      "files": ["personas"],
      "keywords": ["agentworkforce-personas"],
      "agentworkforce": {
      "personas": "personas"
      }
      }

      Resolution rules:

      1. Read package.json.agentworkforce.personas if present.
      2. Otherwise fall back to a top-level personas/ directory.
      3. Copy every *.json persona file from that directory.

      Project layout after install

      .agentworkforce/
      └── workforce/
      ├── config.json
      └── personas/
      ├── relay-orchestrator.json
      ├── code-reviewer.json
      └── e2e-validator.json
      

      Installed personas are project-owned editable files after install. Commit them to git like any other source file.

      Install behavior

      For npm packages, shell out to npm rather than implementing registry logic:

      npm pack @agentrelay/personas --pack-destination <tmp>

      Then:

      1. Unpack the tarball into a temp directory (top-level dir is package/).
      2. Read package metadata.
      3. Locate the persona directory.
      4. If --persona <id> flags were passed, filter the persona files down to those whose persona id matches. Repeating the flag selects multiple personas. If any requested id is not found in the package, exit non-zero with a clear error before copying anything.
      5. Copy persona JSON files into .agentworkforce/workforce/personas/. Filenames are flattened — the persona file is copied directly into .agentworkforce/workforce/personas/<basename>.json, regardless of any nested layout under the package's persona directory.

      Benefits of using npm pack:

      • Uses npm auth and npm config automatically.
      • Works with private packages.
      • Supports version specifiers like @agentrelay/personas@1.2.3.
      • Avoids a custom registry client.

      Local path installs read directly from the directory using the same package metadata rules (or the personas/ fallback if there is no package.json).

      Conflict policy (shadcn-style)

      Once copied, files are yours.

      • If the target file does not exist: copy it.
      • If the target file exists: skip it and report a conflict, unless --overwrite is passed.
      • --overwrite replaces the existing file unconditionally.

      No hashing, no three-way merge, no edit detection. If you want to preserve a local edit, don't pass --overwrite. If you want the upstream version, pass --overwrite and read the diff in git.

      Filename collisions across packages fall under the same rule. If @a/personas and @b/personas both ship code-reviewer.json, installing the second one on top of the first is treated identically to a local edit conflict — skipped by default, replaced with --overwrite. The install layer does not namespace files by package; the cascade keys by persona id, so the practical guidance is "don't ship two personas with the same filename if you also expect to be installed alongside each other."

      Relationship to source directories

      Keep both concepts:

      • agentworkforce sources add <dir>: point at a live directory. Good for development against a checkout or a shared directory.
      • agentworkforce install <pkg>: copy personas into this project. Good for project-owned editable personas.

      Installed files participate in the existing cascade because .agentworkforce/workforce/personas/ is already the fixed cwd/project-local persona directory. install does not modify the sources config.

      Acceptance criteria

      • agentworkforce install @scope/pkg copies all persona JSON files from the package's persona directory into .agentworkforce/workforce/personas/.
      • A package can contain multiple personas.
      • The package persona directory is discovered through package.json.agentworkforce.personas, with fallback to personas/.
      • The command supports npm package specs with versions (@scope/pkg@1.2.3, @scope/pkg@latest, etc.).
      • The command supports local path installs (./local-personas).
      • The command supports --persona <id> (repeatable) to install a subset of the personas in the pack. Unknown ids fail fast before any file is copied.
      • Persona filenames are flattened into .agentworkforce/workforce/personas/<basename>.json; nested layouts inside the package's persona directory are not preserved.
      • Existing persona files are not overwritten by default — the install reports conflicts and exits with a non-zero status if any target file already exists. This applies equally to filename collisions across packages.
      • --overwrite forces replacement of existing files.
      • Installed personas are visible to agentworkforce list and usable via agentworkforce agent <persona>.
      • No install ledger, lockfile, or central registry is introduced.
      • Documentation is updated in the relevant READMEs (root README.md and packages/cli/README.md at minimum) covering: the install command, version and local-path forms, --persona subset installs, --overwrite, the package format (agentworkforce.personas field and personas/ fallback), how install relates to sources, and a worked example of authoring and publishing a persona pack.

      Tests to add

      • Installs multiple personas from a fixture package.
      • Reads agentworkforce.personas from package metadata.
      • Falls back to personas/ if metadata is absent.
      • Refuses to overwrite an existing persona file by default; reports the conflict.
      • --overwrite replaces existing persona files.
      • Local path installs work end-to-end.
      • --persona <id> installs only the requested persona(s); repeating the flag installs multiple; an unknown id exits non-zero before any file is copied.
      • Filenames are flattened on install (nested layouts in the package persona directory are not preserved).
      • Filename collisions across two installed packages are reported as conflicts and resolved by --overwrite.
      • Installed personas are loaded through the cwd/project cascade.

      Activity

      Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

      Metadata

      Metadata

      Assignees

      No one assigned

        Labels

        No labels
        No labels

        Type

        No type

        Projects

        No projects

          Milestone

          No milestone

          Relationships

          None yet

          Development

          No branches or pull requests

          Issue actions

          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
          Skip to content

          Design and implement shadcn-style persona installs #36

          Description

          @willwashburn

          Summary

          Add a project-local persona install command inspired by shadcn: users install persona packs from npm or a local path, and the persona JSON files are copied into the current project's .agentworkforce/workforce/personas/ directory so they become editable, project-owned files.

          Like shadcn, this is intentionally a copy-paste utility, not a package manager. Once copied, files are yours — there is no manifest, lockfile, or install ledger. Git tracks what you have.

          Primary command shape:

          agentworkforce install @agentrelay/personas
          agentworkforce install @agentrelay/personas@1.2.3
          agentworkforce install ./local-personas
          agentworkforce install @agentrelay/personas --persona relay-orchestrator
          agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer

          This is distinct from sources add, which points at a live directory. install copies files into the project once, and they belong to the project.

          Goals

          • Allow teams to distribute multiple personas in a single npm package or local repo.
          • Let a project install personas locally so they can be edited directly after install.
          • Avoid maintaining a separate AgentWorkforce registry. Use npm package resolution as the registry and distribution mechanism.
          • Keep persona JSON under .agentworkforce/workforce/personas/ so .agentworkforce/workforce/config.json and future workforce-level files are not scanned as personas.
          • Stay narrow: copy files, refuse to overwrite by default, support --overwrite to force. No state file, no update/uninstall/diff commands, no version tracking.

          Non-goals

          • No install-state.json or any other install ledger. Once files are copied, they are project-owned and tracked by git — exactly like shadcn components.
          • No version pinning beyond what the user passes on the command line each time.
          • No update, uninstall, or diff subcommands. To update a pack, re-run install --overwrite.
          • No skill validation or skill installation at install time. Skills declared in a persona's skills[] array are resolved by the harness at agent-use time, not at persona-copy time. A broken skill reference is a bug in the persona itself, fixed at the persona's definition site.

          Proposed package format

          A persona package can contain many persona JSON files:

          @agentrelay/personas
          ├── package.json
          └── personas/
          ├── relay-orchestrator.json
          ├── code-reviewer.json
          ├── e2e-validator.json
          └── posthog.json
          

          Package metadata:

          {
          "name": "@agentrelay/personas",
          "version": "1.2.3",
          "files": ["personas"],
          "keywords": ["agentworkforce-personas"],
          "agentworkforce": {
          "personas": "personas"
          }
          }

          Resolution rules:

          1. Read package.json.agentworkforce.personas if present.
          2. Otherwise fall back to a top-level personas/ directory.
          3. Copy every *.json persona file from that directory.

          Project layout after install

          .agentworkforce/
          └── workforce/
          ├── config.json
          └── personas/
          ├── relay-orchestrator.json
          ├── code-reviewer.json
          └── e2e-validator.json
          

          Installed personas are project-owned editable files after install. Commit them to git like any other source file.

          Install behavior

          For npm packages, shell out to npm rather than implementing registry logic:

          npm pack @agentrelay/personas --pack-destination <tmp>

          Then:

          1. Unpack the tarball into a temp directory (top-level dir is package/).
          2. Read package metadata.
          3. Locate the persona directory.
          4. If --persona <id> flags were passed, filter the persona files down to those whose persona id matches. Repeating the flag selects multiple personas. If any requested id is not found in the package, exit non-zero with a clear error before copying anything.
          5. Copy persona JSON files into .agentworkforce/workforce/personas/. Filenames are flattened — the persona file is copied directly into .agentworkforce/workforce/personas/<basename>.json, regardless of any nested layout under the package's persona directory.

          Benefits of using npm pack:

          • Uses npm auth and npm config automatically.
          • Works with private packages.
          • Supports version specifiers like @agentrelay/personas@1.2.3.
          • Avoids a custom registry client.

          Local path installs read directly from the directory using the same package metadata rules (or the personas/ fallback if there is no package.json).

          Conflict policy (shadcn-style)

          Once copied, files are yours.

          • If the target file does not exist: copy it.
          • If the target file exists: skip it and report a conflict, unless --overwrite is passed.
          • --overwrite replaces the existing file unconditionally.

          No hashing, no three-way merge, no edit detection. If you want to preserve a local edit, don't pass --overwrite. If you want the upstream version, pass --overwrite and read the diff in git.

          Filename collisions across packages fall under the same rule. If @a/personas and @b/personas both ship code-reviewer.json, installing the second one on top of the first is treated identically to a local edit conflict — skipped by default, replaced with --overwrite. The install layer does not namespace files by package; the cascade keys by persona id, so the practical guidance is "don't ship two personas with the same filename if you also expect to be installed alongside each other."

          Relationship to source directories

          Keep both concepts:

          • agentworkforce sources add <dir>: point at a live directory. Good for development against a checkout or a shared directory.
          • agentworkforce install <pkg>: copy personas into this project. Good for project-owned editable personas.

          Installed files participate in the existing cascade because .agentworkforce/workforce/personas/ is already the fixed cwd/project-local persona directory. install does not modify the sources config.

          Acceptance criteria

          • agentworkforce install @scope/pkg copies all persona JSON files from the package's persona directory into .agentworkforce/workforce/personas/.
          • A package can contain multiple personas.
          • The package persona directory is discovered through package.json.agentworkforce.personas, with fallback to personas/.
          • The command supports npm package specs with versions (@scope/pkg@1.2.3, @scope/pkg@latest, etc.).
          • The command supports local path installs (./local-personas).
          • The command supports --persona <id> (repeatable) to install a subset of the personas in the pack. Unknown ids fail fast before any file is copied.
          • Persona filenames are flattened into .agentworkforce/workforce/personas/<basename>.json; nested layouts inside the package's persona directory are not preserved.
          • Existing persona files are not overwritten by default — the install reports conflicts and exits with a non-zero status if any target file already exists. This applies equally to filename collisions across packages.
          • --overwrite forces replacement of existing files.
          • Installed personas are visible to agentworkforce list and usable via agentworkforce agent <persona>.
          • No install ledger, lockfile, or central registry is introduced.
          • Documentation is updated in the relevant READMEs (root README.md and packages/cli/README.md at minimum) covering: the install command, version and local-path forms, --persona subset installs, --overwrite, the package format (agentworkforce.personas field and personas/ fallback), how install relates to sources, and a worked example of authoring and publishing a persona pack.

          Tests to add

          • Installs multiple personas from a fixture package.
          • Reads agentworkforce.personas from package metadata.
          • Falls back to personas/ if metadata is absent.
          • Refuses to overwrite an existing persona file by default; reports the conflict.
          • --overwrite replaces existing persona files.
          • Local path installs work end-to-end.
          • --persona <id> installs only the requested persona(s); repeating the flag installs multiple; an unknown id exits non-zero before any file is copied.
          • Filenames are flattened on install (nested layouts in the package persona directory are not preserved).
          • Filename collisions across two installed packages are reported as conflicts and resolved by --overwrite.
          • Installed personas are loaded through the cwd/project cascade.

          Activity

          Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

          Metadata

          Metadata

          Assignees

          No one assigned

            Labels

            No labels
            No labels

            Type

            No type

            Projects

            No projects

              Milestone

              No milestone

              Relationships

              None yet

              Development

              No branches or pull requests

              Issue actions

              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
              Skip to content

              Design and implement shadcn-style persona installs #36

              Description

              @willwashburn

              Summary

              Add a project-local persona install command inspired by shadcn: users install persona packs from npm or a local path, and the persona JSON files are copied into the current project's .agentworkforce/workforce/personas/ directory so they become editable, project-owned files.

              Like shadcn, this is intentionally a copy-paste utility, not a package manager. Once copied, files are yours — there is no manifest, lockfile, or install ledger. Git tracks what you have.

              Primary command shape:

              agentworkforce install @agentrelay/personas
              agentworkforce install @agentrelay/personas@1.2.3
              agentworkforce install ./local-personas
              agentworkforce install @agentrelay/personas --persona relay-orchestrator
              agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer

              This is distinct from sources add, which points at a live directory. install copies files into the project once, and they belong to the project.

              Goals

              • Allow teams to distribute multiple personas in a single npm package or local repo.
              • Let a project install personas locally so they can be edited directly after install.
              • Avoid maintaining a separate AgentWorkforce registry. Use npm package resolution as the registry and distribution mechanism.
              • Keep persona JSON under .agentworkforce/workforce/personas/ so .agentworkforce/workforce/config.json and future workforce-level files are not scanned as personas.
              • Stay narrow: copy files, refuse to overwrite by default, support --overwrite to force. No state file, no update/uninstall/diff commands, no version tracking.

              Non-goals

              • No install-state.json or any other install ledger. Once files are copied, they are project-owned and tracked by git — exactly like shadcn components.
              • No version pinning beyond what the user passes on the command line each time.
              • No update, uninstall, or diff subcommands. To update a pack, re-run install --overwrite.
              • No skill validation or skill installation at install time. Skills declared in a persona's skills[] array are resolved by the harness at agent-use time, not at persona-copy time. A broken skill reference is a bug in the persona itself, fixed at the persona's definition site.

              Proposed package format

              A persona package can contain many persona JSON files:

              @agentrelay/personas
              ├── package.json
              └── personas/
              ├── relay-orchestrator.json
              ├── code-reviewer.json
              ├── e2e-validator.json
              └── posthog.json
              

              Package metadata:

              {
              "name": "@agentrelay/personas",
              "version": "1.2.3",
              "files": ["personas"],
              "keywords": ["agentworkforce-personas"],
              "agentworkforce": {
              "personas": "personas"
              }
              }

              Resolution rules:

              1. Read package.json.agentworkforce.personas if present.
              2. Otherwise fall back to a top-level personas/ directory.
              3. Copy every *.json persona file from that directory.

              Project layout after install

              .agentworkforce/
              └── workforce/
              ├── config.json
              └── personas/
              ├── relay-orchestrator.json
              ├── code-reviewer.json
              └── e2e-validator.json
              

              Installed personas are project-owned editable files after install. Commit them to git like any other source file.

              Install behavior

              For npm packages, shell out to npm rather than implementing registry logic:

              npm pack @agentrelay/personas --pack-destination <tmp>

              Then:

              1. Unpack the tarball into a temp directory (top-level dir is package/).
              2. Read package metadata.
              3. Locate the persona directory.
              4. If --persona <id> flags were passed, filter the persona files down to those whose persona id matches. Repeating the flag selects multiple personas. If any requested id is not found in the package, exit non-zero with a clear error before copying anything.
              5. Copy persona JSON files into .agentworkforce/workforce/personas/. Filenames are flattened — the persona file is copied directly into .agentworkforce/workforce/personas/<basename>.json, regardless of any nested layout under the package's persona directory.

              Benefits of using npm pack:

              • Uses npm auth and npm config automatically.
              • Works with private packages.
              • Supports version specifiers like @agentrelay/personas@1.2.3.
              • Avoids a custom registry client.

              Local path installs read directly from the directory using the same package metadata rules (or the personas/ fallback if there is no package.json).

              Conflict policy (shadcn-style)

              Once copied, files are yours.

              • If the target file does not exist: copy it.
              • If the target file exists: skip it and report a conflict, unless --overwrite is passed.
              • --overwrite replaces the existing file unconditionally.

              No hashing, no three-way merge, no edit detection. If you want to preserve a local edit, don't pass --overwrite. If you want the upstream version, pass --overwrite and read the diff in git.

              Filename collisions across packages fall under the same rule. If @a/personas and @b/personas both ship code-reviewer.json, installing the second one on top of the first is treated identically to a local edit conflict — skipped by default, replaced with --overwrite. The install layer does not namespace files by package; the cascade keys by persona id, so the practical guidance is "don't ship two personas with the same filename if you also expect to be installed alongside each other."

              Relationship to source directories

              Keep both concepts:

              • agentworkforce sources add <dir>: point at a live directory. Good for development against a checkout or a shared directory.
              • agentworkforce install <pkg>: copy personas into this project. Good for project-owned editable personas.

              Installed files participate in the existing cascade because .agentworkforce/workforce/personas/ is already the fixed cwd/project-local persona directory. install does not modify the sources config.

              Acceptance criteria

              • agentworkforce install @scope/pkg copies all persona JSON files from the package's persona directory into .agentworkforce/workforce/personas/.
              • A package can contain multiple personas.
              • The package persona directory is discovered through package.json.agentworkforce.personas, with fallback to personas/.
              • The command supports npm package specs with versions (@scope/pkg@1.2.3, @scope/pkg@latest, etc.).
              • The command supports local path installs (./local-personas).
              • The command supports --persona <id> (repeatable) to install a subset of the personas in the pack. Unknown ids fail fast before any file is copied.
              • Persona filenames are flattened into .agentworkforce/workforce/personas/<basename>.json; nested layouts inside the package's persona directory are not preserved.
              • Existing persona files are not overwritten by default — the install reports conflicts and exits with a non-zero status if any target file already exists. This applies equally to filename collisions across packages.
              • --overwrite forces replacement of existing files.
              • Installed personas are visible to agentworkforce list and usable via agentworkforce agent <persona>.
              • No install ledger, lockfile, or central registry is introduced.
              • Documentation is updated in the relevant READMEs (root README.md and packages/cli/README.md at minimum) covering: the install command, version and local-path forms, --persona subset installs, --overwrite, the package format (agentworkforce.personas field and personas/ fallback), how install relates to sources, and a worked example of authoring and publishing a persona pack.

              Tests to add

              • Installs multiple personas from a fixture package.
              • Reads agentworkforce.personas from package metadata.
              • Falls back to personas/ if metadata is absent.
              • Refuses to overwrite an existing persona file by default; reports the conflict.
              • --overwrite replaces existing persona files.
              • Local path installs work end-to-end.
              • --persona <id> installs only the requested persona(s); repeating the flag installs multiple; an unknown id exits non-zero before any file is copied.
              • Filenames are flattened on install (nested layouts in the package persona directory are not preserved).
              • Filename collisions across two installed packages are reported as conflicts and resolved by --overwrite.
              • Installed personas are loaded through the cwd/project cascade.

              Activity

              Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

              Metadata

              Metadata

              Assignees

              No one assigned

                Labels

                No labels
                No labels

                Type

                No type

                Projects

                No projects

                  Milestone

                  No milestone

                  Relationships

                  None yet

                  Development

                  No branches or pull requests

                  Issue actions

                  , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
                  Skip to content

                  Design and implement shadcn-style persona installs #36

                  Description

                  @willwashburn

                  Summary

                  Add a project-local persona install command inspired by shadcn: users install persona packs from npm or a local path, and the persona JSON files are copied into the current project's .agentworkforce/workforce/personas/ directory so they become editable, project-owned files.

                  Like shadcn, this is intentionally a copy-paste utility, not a package manager. Once copied, files are yours — there is no manifest, lockfile, or install ledger. Git tracks what you have.

                  Primary command shape:

                  agentworkforce install @agentrelay/personas
                  agentworkforce install @agentrelay/personas@1.2.3
                  agentworkforce install ./local-personas
                  agentworkforce install @agentrelay/personas --persona relay-orchestrator
                  agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer

                  This is distinct from sources add, which points at a live directory. install copies files into the project once, and they belong to the project.

                  Goals

                  • Allow teams to distribute multiple personas in a single npm package or local repo.
                  • Let a project install personas locally so they can be edited directly after install.
                  • Avoid maintaining a separate AgentWorkforce registry. Use npm package resolution as the registry and distribution mechanism.
                  • Keep persona JSON under .agentworkforce/workforce/personas/ so .agentworkforce/workforce/config.json and future workforce-level files are not scanned as personas.
                  • Stay narrow: copy files, refuse to overwrite by default, support --overwrite to force. No state file, no update/uninstall/diff commands, no version tracking.

                  Non-goals

                  • No install-state.json or any other install ledger. Once files are copied, they are project-owned and tracked by git — exactly like shadcn components.
                  • No version pinning beyond what the user passes on the command line each time.
                  • No update, uninstall, or diff subcommands. To update a pack, re-run install --overwrite.
                  • No skill validation or skill installation at install time. Skills declared in a persona's skills[] array are resolved by the harness at agent-use time, not at persona-copy time. A broken skill reference is a bug in the persona itself, fixed at the persona's definition site.

                  Proposed package format

                  A persona package can contain many persona JSON files:

                  @agentrelay/personas
                  ├── package.json
                  └── personas/
                  ├── relay-orchestrator.json
                  ├── code-reviewer.json
                  ├── e2e-validator.json
                  └── posthog.json
                  

                  Package metadata:

                  {
                  "name": "@agentrelay/personas",
                  "version": "1.2.3",
                  "files": ["personas"],
                  "keywords": ["agentworkforce-personas"],
                  "agentworkforce": {
                  "personas": "personas"
                  }
                  }

                  Resolution rules:

                  1. Read package.json.agentworkforce.personas if present.
                  2. Otherwise fall back to a top-level personas/ directory.
                  3. Copy every *.json persona file from that directory.

                  Project layout after install

                  .agentworkforce/
                  └── workforce/
                  ├── config.json
                  └── personas/
                  ├── relay-orchestrator.json
                  ├── code-reviewer.json
                  └── e2e-validator.json
                  

                  Installed personas are project-owned editable files after install. Commit them to git like any other source file.

                  Install behavior

                  For npm packages, shell out to npm rather than implementing registry logic:

                  npm pack @agentrelay/personas --pack-destination <tmp>

                  Then:

                  1. Unpack the tarball into a temp directory (top-level dir is package/).
                  2. Read package metadata.
                  3. Locate the persona directory.
                  4. If --persona <id> flags were passed, filter the persona files down to those whose persona id matches. Repeating the flag selects multiple personas. If any requested id is not found in the package, exit non-zero with a clear error before copying anything.
                  5. Copy persona JSON files into .agentworkforce/workforce/personas/. Filenames are flattened — the persona file is copied directly into .agentworkforce/workforce/personas/<basename>.json, regardless of any nested layout under the package's persona directory.

                  Benefits of using npm pack:

                  • Uses npm auth and npm config automatically.
                  • Works with private packages.
                  • Supports version specifiers like @agentrelay/personas@1.2.3.
                  • Avoids a custom registry client.

                  Local path installs read directly from the directory using the same package metadata rules (or the personas/ fallback if there is no package.json).

                  Conflict policy (shadcn-style)

                  Once copied, files are yours.

                  • If the target file does not exist: copy it.
                  • If the target file exists: skip it and report a conflict, unless --overwrite is passed.
                  • --overwrite replaces the existing file unconditionally.

                  No hashing, no three-way merge, no edit detection. If you want to preserve a local edit, don't pass --overwrite. If you want the upstream version, pass --overwrite and read the diff in git.

                  Filename collisions across packages fall under the same rule. If @a/personas and @b/personas both ship code-reviewer.json, installing the second one on top of the first is treated identically to a local edit conflict — skipped by default, replaced with --overwrite. The install layer does not namespace files by package; the cascade keys by persona id, so the practical guidance is "don't ship two personas with the same filename if you also expect to be installed alongside each other."

                  Relationship to source directories

                  Keep both concepts:

                  • agentworkforce sources add <dir>: point at a live directory. Good for development against a checkout or a shared directory.
                  • agentworkforce install <pkg>: copy personas into this project. Good for project-owned editable personas.

                  Installed files participate in the existing cascade because .agentworkforce/workforce/personas/ is already the fixed cwd/project-local persona directory. install does not modify the sources config.

                  Acceptance criteria

                  • agentworkforce install @scope/pkg copies all persona JSON files from the package's persona directory into .agentworkforce/workforce/personas/.
                  • A package can contain multiple personas.
                  • The package persona directory is discovered through package.json.agentworkforce.personas, with fallback to personas/.
                  • The command supports npm package specs with versions (@scope/pkg@1.2.3, @scope/pkg@latest, etc.).
                  • The command supports local path installs (./local-personas).
                  • The command supports --persona <id> (repeatable) to install a subset of the personas in the pack. Unknown ids fail fast before any file is copied.
                  • Persona filenames are flattened into .agentworkforce/workforce/personas/<basename>.json; nested layouts inside the package's persona directory are not preserved.
                  • Existing persona files are not overwritten by default — the install reports conflicts and exits with a non-zero status if any target file already exists. This applies equally to filename collisions across packages.
                  • --overwrite forces replacement of existing files.
                  • Installed personas are visible to agentworkforce list and usable via agentworkforce agent <persona>.
                  • No install ledger, lockfile, or central registry is introduced.
                  • Documentation is updated in the relevant READMEs (root README.md and packages/cli/README.md at minimum) covering: the install command, version and local-path forms, --persona subset installs, --overwrite, the package format (agentworkforce.personas field and personas/ fallback), how install relates to sources, and a worked example of authoring and publishing a persona pack.

                  Tests to add

                  • Installs multiple personas from a fixture package.
                  • Reads agentworkforce.personas from package metadata.
                  • Falls back to personas/ if metadata is absent.
                  • Refuses to overwrite an existing persona file by default; reports the conflict.
                  • --overwrite replaces existing persona files.
                  • Local path installs work end-to-end.
                  • --persona <id> installs only the requested persona(s); repeating the flag installs multiple; an unknown id exits non-zero before any file is copied.
                  • Filenames are flattened on install (nested layouts in the package persona directory are not preserved).
                  • Filename collisions across two installed packages are reported as conflicts and resolved by --overwrite.
                  • Installed personas are loaded through the cwd/project cascade.

                  Activity

                  Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                  Metadata

                  Metadata

                  Assignees

                  No one assigned

                    Labels

                    No labels
                    No labels

                    Type

                    No type

                    Projects

                    No projects

                      Milestone

                      No milestone

                      Relationships

                      None yet

                      Development

                      No branches or pull requests

                      Issue actions

                      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                      Skip to content

                      Design and implement shadcn-style persona installs #36

                      Description

                      @willwashburn

                      Summary

                      Add a project-local persona install command inspired by shadcn: users install persona packs from npm or a local path, and the persona JSON files are copied into the current project's .agentworkforce/workforce/personas/ directory so they become editable, project-owned files.

                      Like shadcn, this is intentionally a copy-paste utility, not a package manager. Once copied, files are yours — there is no manifest, lockfile, or install ledger. Git tracks what you have.

                      Primary command shape:

                      agentworkforce install @agentrelay/personas
                      agentworkforce install @agentrelay/personas@1.2.3
                      agentworkforce install ./local-personas
                      agentworkforce install @agentrelay/personas --persona relay-orchestrator
                      agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer

                      This is distinct from sources add, which points at a live directory. install copies files into the project once, and they belong to the project.

                      Goals

                      • Allow teams to distribute multiple personas in a single npm package or local repo.
                      • Let a project install personas locally so they can be edited directly after install.
                      • Avoid maintaining a separate AgentWorkforce registry. Use npm package resolution as the registry and distribution mechanism.
                      • Keep persona JSON under .agentworkforce/workforce/personas/ so .agentworkforce/workforce/config.json and future workforce-level files are not scanned as personas.
                      • Stay narrow: copy files, refuse to overwrite by default, support --overwrite to force. No state file, no update/uninstall/diff commands, no version tracking.

                      Non-goals

                      • No install-state.json or any other install ledger. Once files are copied, they are project-owned and tracked by git — exactly like shadcn components.
                      • No version pinning beyond what the user passes on the command line each time.
                      • No update, uninstall, or diff subcommands. To update a pack, re-run install --overwrite.
                      • No skill validation or skill installation at install time. Skills declared in a persona's skills[] array are resolved by the harness at agent-use time, not at persona-copy time. A broken skill reference is a bug in the persona itself, fixed at the persona's definition site.

                      Proposed package format

                      A persona package can contain many persona JSON files:

                      @agentrelay/personas
                      ├── package.json
                      └── personas/
                      ├── relay-orchestrator.json
                      ├── code-reviewer.json
                      ├── e2e-validator.json
                      └── posthog.json
                      

                      Package metadata:

                      {
                      "name": "@agentrelay/personas",
                      "version": "1.2.3",
                      "files": ["personas"],
                      "keywords": ["agentworkforce-personas"],
                      "agentworkforce": {
                      "personas": "personas"
                      }
                      }

                      Resolution rules:

                      1. Read package.json.agentworkforce.personas if present.
                      2. Otherwise fall back to a top-level personas/ directory.
                      3. Copy every *.json persona file from that directory.

                      Project layout after install

                      .agentworkforce/
                      └── workforce/
                      ├── config.json
                      └── personas/
                      ├── relay-orchestrator.json
                      ├── code-reviewer.json
                      └── e2e-validator.json
                      

                      Installed personas are project-owned editable files after install. Commit them to git like any other source file.

                      Install behavior

                      For npm packages, shell out to npm rather than implementing registry logic:

                      npm pack @agentrelay/personas --pack-destination <tmp>

                      Then:

                      1. Unpack the tarball into a temp directory (top-level dir is package/).
                      2. Read package metadata.
                      3. Locate the persona directory.
                      4. If --persona <id> flags were passed, filter the persona files down to those whose persona id matches. Repeating the flag selects multiple personas. If any requested id is not found in the package, exit non-zero with a clear error before copying anything.
                      5. Copy persona JSON files into .agentworkforce/workforce/personas/. Filenames are flattened — the persona file is copied directly into .agentworkforce/workforce/personas/<basename>.json, regardless of any nested layout under the package's persona directory.

                      Benefits of using npm pack:

                      • Uses npm auth and npm config automatically.
                      • Works with private packages.
                      • Supports version specifiers like @agentrelay/personas@1.2.3.
                      • Avoids a custom registry client.

                      Local path installs read directly from the directory using the same package metadata rules (or the personas/ fallback if there is no package.json).

                      Conflict policy (shadcn-style)

                      Once copied, files are yours.

                      • If the target file does not exist: copy it.
                      • If the target file exists: skip it and report a conflict, unless --overwrite is passed.
                      • --overwrite replaces the existing file unconditionally.

                      No hashing, no three-way merge, no edit detection. If you want to preserve a local edit, don't pass --overwrite. If you want the upstream version, pass --overwrite and read the diff in git.

                      Filename collisions across packages fall under the same rule. If @a/personas and @b/personas both ship code-reviewer.json, installing the second one on top of the first is treated identically to a local edit conflict — skipped by default, replaced with --overwrite. The install layer does not namespace files by package; the cascade keys by persona id, so the practical guidance is "don't ship two personas with the same filename if you also expect to be installed alongside each other."

                      Relationship to source directories

                      Keep both concepts:

                      • agentworkforce sources add <dir>: point at a live directory. Good for development against a checkout or a shared directory.
                      • agentworkforce install <pkg>: copy personas into this project. Good for project-owned editable personas.

                      Installed files participate in the existing cascade because .agentworkforce/workforce/personas/ is already the fixed cwd/project-local persona directory. install does not modify the sources config.

                      Acceptance criteria

                      • agentworkforce install @scope/pkg copies all persona JSON files from the package's persona directory into .agentworkforce/workforce/personas/.
                      • A package can contain multiple personas.
                      • The package persona directory is discovered through package.json.agentworkforce.personas, with fallback to personas/.
                      • The command supports npm package specs with versions (@scope/pkg@1.2.3, @scope/pkg@latest, etc.).
                      • The command supports local path installs (./local-personas).
                      • The command supports --persona <id> (repeatable) to install a subset of the personas in the pack. Unknown ids fail fast before any file is copied.
                      • Persona filenames are flattened into .agentworkforce/workforce/personas/<basename>.json; nested layouts inside the package's persona directory are not preserved.
                      • Existing persona files are not overwritten by default — the install reports conflicts and exits with a non-zero status if any target file already exists. This applies equally to filename collisions across packages.
                      • --overwrite forces replacement of existing files.
                      • Installed personas are visible to agentworkforce list and usable via agentworkforce agent <persona>.
                      • No install ledger, lockfile, or central registry is introduced.
                      • Documentation is updated in the relevant READMEs (root README.md and packages/cli/README.md at minimum) covering: the install command, version and local-path forms, --persona subset installs, --overwrite, the package format (agentworkforce.personas field and personas/ fallback), how install relates to sources, and a worked example of authoring and publishing a persona pack.

                      Tests to add

                      • Installs multiple personas from a fixture package.
                      • Reads agentworkforce.personas from package metadata.
                      • Falls back to personas/ if metadata is absent.
                      • Refuses to overwrite an existing persona file by default; reports the conflict.
                      • --overwrite replaces existing persona files.
                      • Local path installs work end-to-end.
                      • --persona <id> installs only the requested persona(s); repeating the flag installs multiple; an unknown id exits non-zero before any file is copied.
                      • Filenames are flattened on install (nested layouts in the package persona directory are not preserved).
                      • Filename collisions across two installed packages are reported as conflicts and resolved by --overwrite.
                      • Installed personas are loaded through the cwd/project cascade.

                      Activity

                      Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                      Metadata

                      Metadata

                      Assignees

                      No one assigned

                        Labels

                        No labels
                        No labels

                        Type

                        No type

                        Projects

                        No projects

                          Milestone

                          No milestone

                          Relationships

                          None yet

                          Development

                          No branches or pull requests

                          Issue actions

                          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                          Skip to content

                          Design and implement shadcn-style persona installs #36

                          Description

                          @willwashburn

                          Summary

                          Add a project-local persona install command inspired by shadcn: users install persona packs from npm or a local path, and the persona JSON files are copied into the current project's .agentworkforce/workforce/personas/ directory so they become editable, project-owned files.

                          Like shadcn, this is intentionally a copy-paste utility, not a package manager. Once copied, files are yours — there is no manifest, lockfile, or install ledger. Git tracks what you have.

                          Primary command shape:

                          agentworkforce install @agentrelay/personas
                          agentworkforce install @agentrelay/personas@1.2.3
                          agentworkforce install ./local-personas
                          agentworkforce install @agentrelay/personas --persona relay-orchestrator
                          agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer

                          This is distinct from sources add, which points at a live directory. install copies files into the project once, and they belong to the project.

                          Goals

                          • Allow teams to distribute multiple personas in a single npm package or local repo.
                          • Let a project install personas locally so they can be edited directly after install.
                          • Avoid maintaining a separate AgentWorkforce registry. Use npm package resolution as the registry and distribution mechanism.
                          • Keep persona JSON under .agentworkforce/workforce/personas/ so .agentworkforce/workforce/config.json and future workforce-level files are not scanned as personas.
                          • Stay narrow: copy files, refuse to overwrite by default, support --overwrite to force. No state file, no update/uninstall/diff commands, no version tracking.

                          Non-goals

                          • No install-state.json or any other install ledger. Once files are copied, they are project-owned and tracked by git — exactly like shadcn components.
                          • No version pinning beyond what the user passes on the command line each time.
                          • No update, uninstall, or diff subcommands. To update a pack, re-run install --overwrite.
                          • No skill validation or skill installation at install time. Skills declared in a persona's skills[] array are resolved by the harness at agent-use time, not at persona-copy time. A broken skill reference is a bug in the persona itself, fixed at the persona's definition site.

                          Proposed package format

                          A persona package can contain many persona JSON files:

                          @agentrelay/personas
                          ├── package.json
                          └── personas/
                          ├── relay-orchestrator.json
                          ├── code-reviewer.json
                          ├── e2e-validator.json
                          └── posthog.json
                          

                          Package metadata:

                          {
                          "name": "@agentrelay/personas",
                          "version": "1.2.3",
                          "files": ["personas"],
                          "keywords": ["agentworkforce-personas"],
                          "agentworkforce": {
                          "personas": "personas"
                          }
                          }

                          Resolution rules:

                          1. Read package.json.agentworkforce.personas if present.
                          2. Otherwise fall back to a top-level personas/ directory.
                          3. Copy every *.json persona file from that directory.

                          Project layout after install

                          .agentworkforce/
                          └── workforce/
                          ├── config.json
                          └── personas/
                          ├── relay-orchestrator.json
                          ├── code-reviewer.json
                          └── e2e-validator.json
                          

                          Installed personas are project-owned editable files after install. Commit them to git like any other source file.

                          Install behavior

                          For npm packages, shell out to npm rather than implementing registry logic:

                          npm pack @agentrelay/personas --pack-destination <tmp>

                          Then:

                          1. Unpack the tarball into a temp directory (top-level dir is package/).
                          2. Read package metadata.
                          3. Locate the persona directory.
                          4. If --persona <id> flags were passed, filter the persona files down to those whose persona id matches. Repeating the flag selects multiple personas. If any requested id is not found in the package, exit non-zero with a clear error before copying anything.
                          5. Copy persona JSON files into .agentworkforce/workforce/personas/. Filenames are flattened — the persona file is copied directly into .agentworkforce/workforce/personas/<basename>.json, regardless of any nested layout under the package's persona directory.

                          Benefits of using npm pack:

                          • Uses npm auth and npm config automatically.
                          • Works with private packages.
                          • Supports version specifiers like @agentrelay/personas@1.2.3.
                          • Avoids a custom registry client.

                          Local path installs read directly from the directory using the same package metadata rules (or the personas/ fallback if there is no package.json).

                          Conflict policy (shadcn-style)

                          Once copied, files are yours.

                          • If the target file does not exist: copy it.
                          • If the target file exists: skip it and report a conflict, unless --overwrite is passed.
                          • --overwrite replaces the existing file unconditionally.

                          No hashing, no three-way merge, no edit detection. If you want to preserve a local edit, don't pass --overwrite. If you want the upstream version, pass --overwrite and read the diff in git.

                          Filename collisions across packages fall under the same rule. If @a/personas and @b/personas both ship code-reviewer.json, installing the second one on top of the first is treated identically to a local edit conflict — skipped by default, replaced with --overwrite. The install layer does not namespace files by package; the cascade keys by persona id, so the practical guidance is "don't ship two personas with the same filename if you also expect to be installed alongside each other."

                          Relationship to source directories

                          Keep both concepts:

                          • agentworkforce sources add <dir>: point at a live directory. Good for development against a checkout or a shared directory.
                          • agentworkforce install <pkg>: copy personas into this project. Good for project-owned editable personas.

                          Installed files participate in the existing cascade because .agentworkforce/workforce/personas/ is already the fixed cwd/project-local persona directory. install does not modify the sources config.

                          Acceptance criteria

                          • agentworkforce install @scope/pkg copies all persona JSON files from the package's persona directory into .agentworkforce/workforce/personas/.
                          • A package can contain multiple personas.
                          • The package persona directory is discovered through package.json.agentworkforce.personas, with fallback to personas/.
                          • The command supports npm package specs with versions (@scope/pkg@1.2.3, @scope/pkg@latest, etc.).
                          • The command supports local path installs (./local-personas).
                          • The command supports --persona <id> (repeatable) to install a subset of the personas in the pack. Unknown ids fail fast before any file is copied.
                          • Persona filenames are flattened into .agentworkforce/workforce/personas/<basename>.json; nested layouts inside the package's persona directory are not preserved.
                          • Existing persona files are not overwritten by default — the install reports conflicts and exits with a non-zero status if any target file already exists. This applies equally to filename collisions across packages.
                          • --overwrite forces replacement of existing files.
                          • Installed personas are visible to agentworkforce list and usable via agentworkforce agent <persona>.
                          • No install ledger, lockfile, or central registry is introduced.
                          • Documentation is updated in the relevant READMEs (root README.md and packages/cli/README.md at minimum) covering: the install command, version and local-path forms, --persona subset installs, --overwrite, the package format (agentworkforce.personas field and personas/ fallback), how install relates to sources, and a worked example of authoring and publishing a persona pack.

                          Tests to add

                          • Installs multiple personas from a fixture package.
                          • Reads agentworkforce.personas from package metadata.
                          • Falls back to personas/ if metadata is absent.
                          • Refuses to overwrite an existing persona file by default; reports the conflict.
                          • --overwrite replaces existing persona files.
                          • Local path installs work end-to-end.
                          • --persona <id> installs only the requested persona(s); repeating the flag installs multiple; an unknown id exits non-zero before any file is copied.
                          • Filenames are flattened on install (nested layouts in the package persona directory are not preserved).
                          • Filename collisions across two installed packages are reported as conflicts and resolved by --overwrite.
                          • Installed personas are loaded through the cwd/project cascade.

                          Activity

                          Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                          Metadata

                          Metadata

                          Assignees

                          No one assigned

                            Labels

                            No labels
                            No labels

                            Type

                            No type

                            Projects

                            No projects

                              Milestone

                              No milestone

                              Relationships

                              None yet

                              Development

                              No branches or pull requests

                              Issue actions

                              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
                              Skip to content

                              Design and implement shadcn-style persona installs #36

                              Description

                              @willwashburn

                              Summary

                              Add a project-local persona install command inspired by shadcn: users install persona packs from npm or a local path, and the persona JSON files are copied into the current project's .agentworkforce/workforce/personas/ directory so they become editable, project-owned files.

                              Like shadcn, this is intentionally a copy-paste utility, not a package manager. Once copied, files are yours — there is no manifest, lockfile, or install ledger. Git tracks what you have.

                              Primary command shape:

                              agentworkforce install @agentrelay/personas
                              agentworkforce install @agentrelay/personas@1.2.3
                              agentworkforce install ./local-personas
                              agentworkforce install @agentrelay/personas --persona relay-orchestrator
                              agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer

                              This is distinct from sources add, which points at a live directory. install copies files into the project once, and they belong to the project.

                              Goals

                              • Allow teams to distribute multiple personas in a single npm package or local repo.
                              • Let a project install personas locally so they can be edited directly after install.
                              • Avoid maintaining a separate AgentWorkforce registry. Use npm package resolution as the registry and distribution mechanism.
                              • Keep persona JSON under .agentworkforce/workforce/personas/ so .agentworkforce/workforce/config.json and future workforce-level files are not scanned as personas.
                              • Stay narrow: copy files, refuse to overwrite by default, support --overwrite to force. No state file, no update/uninstall/diff commands, no version tracking.

                              Non-goals

                              • No install-state.json or any other install ledger. Once files are copied, they are project-owned and tracked by git — exactly like shadcn components.
                              • No version pinning beyond what the user passes on the command line each time.
                              • No update, uninstall, or diff subcommands. To update a pack, re-run install --overwrite.
                              • No skill validation or skill installation at install time. Skills declared in a persona's skills[] array are resolved by the harness at agent-use time, not at persona-copy time. A broken skill reference is a bug in the persona itself, fixed at the persona's definition site.

                              Proposed package format

                              A persona package can contain many persona JSON files:

                              @agentrelay/personas
                              ├── package.json
                              └── personas/
                              ├── relay-orchestrator.json
                              ├── code-reviewer.json
                              ├── e2e-validator.json
                              └── posthog.json
                              

                              Package metadata:

                              {
                              "name": "@agentrelay/personas",
                              "version": "1.2.3",
                              "files": ["personas"],
                              "keywords": ["agentworkforce-personas"],
                              "agentworkforce": {
                              "personas": "personas"
                              }
                              }

                              Resolution rules:

                              1. Read package.json.agentworkforce.personas if present.
                              2. Otherwise fall back to a top-level personas/ directory.
                              3. Copy every *.json persona file from that directory.

                              Project layout after install

                              .agentworkforce/
                              └── workforce/
                              ├── config.json
                              └── personas/
                              ├── relay-orchestrator.json
                              ├── code-reviewer.json
                              └── e2e-validator.json
                              

                              Installed personas are project-owned editable files after install. Commit them to git like any other source file.

                              Install behavior

                              For npm packages, shell out to npm rather than implementing registry logic:

                              npm pack @agentrelay/personas --pack-destination <tmp>

                              Then:

                              1. Unpack the tarball into a temp directory (top-level dir is package/).
                              2. Read package metadata.
                              3. Locate the persona directory.
                              4. If --persona <id> flags were passed, filter the persona files down to those whose persona id matches. Repeating the flag selects multiple personas. If any requested id is not found in the package, exit non-zero with a clear error before copying anything.
                              5. Copy persona JSON files into .agentworkforce/workforce/personas/. Filenames are flattened — the persona file is copied directly into .agentworkforce/workforce/personas/<basename>.json, regardless of any nested layout under the package's persona directory.

                              Benefits of using npm pack:

                              • Uses npm auth and npm config automatically.
                              • Works with private packages.
                              • Supports version specifiers like @agentrelay/personas@1.2.3.
                              • Avoids a custom registry client.

                              Local path installs read directly from the directory using the same package metadata rules (or the personas/ fallback if there is no package.json).

                              Conflict policy (shadcn-style)

                              Once copied, files are yours.

                              • If the target file does not exist: copy it.
                              • If the target file exists: skip it and report a conflict, unless --overwrite is passed.
                              • --overwrite replaces the existing file unconditionally.

                              No hashing, no three-way merge, no edit detection. If you want to preserve a local edit, don't pass --overwrite. If you want the upstream version, pass --overwrite and read the diff in git.

                              Filename collisions across packages fall under the same rule. If @a/personas and @b/personas both ship code-reviewer.json, installing the second one on top of the first is treated identically to a local edit conflict — skipped by default, replaced with --overwrite. The install layer does not namespace files by package; the cascade keys by persona id, so the practical guidance is "don't ship two personas with the same filename if you also expect to be installed alongside each other."

                              Relationship to source directories

                              Keep both concepts:

                              • agentworkforce sources add <dir>: point at a live directory. Good for development against a checkout or a shared directory.
                              • agentworkforce install <pkg>: copy personas into this project. Good for project-owned editable personas.

                              Installed files participate in the existing cascade because .agentworkforce/workforce/personas/ is already the fixed cwd/project-local persona directory. install does not modify the sources config.

                              Acceptance criteria

                              • agentworkforce install @scope/pkg copies all persona JSON files from the package's persona directory into .agentworkforce/workforce/personas/.
                              • A package can contain multiple personas.
                              • The package persona directory is discovered through package.json.agentworkforce.personas, with fallback to personas/.
                              • The command supports npm package specs with versions (@scope/pkg@1.2.3, @scope/pkg@latest, etc.).
                              • The command supports local path installs (./local-personas).
                              • The command supports --persona <id> (repeatable) to install a subset of the personas in the pack. Unknown ids fail fast before any file is copied.
                              • Persona filenames are flattened into .agentworkforce/workforce/personas/<basename>.json; nested layouts inside the package's persona directory are not preserved.
                              • Existing persona files are not overwritten by default — the install reports conflicts and exits with a non-zero status if any target file already exists. This applies equally to filename collisions across packages.
                              • --overwrite forces replacement of existing files.
                              • Installed personas are visible to agentworkforce list and usable via agentworkforce agent <persona>.
                              • No install ledger, lockfile, or central registry is introduced.
                              • Documentation is updated in the relevant READMEs (root README.md and packages/cli/README.md at minimum) covering: the install command, version and local-path forms, --persona subset installs, --overwrite, the package format (agentworkforce.personas field and personas/ fallback), how install relates to sources, and a worked example of authoring and publishing a persona pack.

                              Tests to add

                              • Installs multiple personas from a fixture package.
                              • Reads agentworkforce.personas from package metadata.
                              • Falls back to personas/ if metadata is absent.
                              • Refuses to overwrite an existing persona file by default; reports the conflict.
                              • --overwrite replaces existing persona files.
                              • Local path installs work end-to-end.
                              • --persona <id> installs only the requested persona(s); repeating the flag installs multiple; an unknown id exits non-zero before any file is copied.
                              • Filenames are flattened on install (nested layouts in the package persona directory are not preserved).
                              • Filename collisions across two installed packages are reported as conflicts and resolved by --overwrite.
                              • Installed personas are loaded through the cwd/project cascade.

                              Activity

                              Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                              Metadata

                              Metadata

                              Assignees

                              No one assigned

                                Labels

                                No labels
                                No labels

                                Type

                                No type

                                Projects

                                No projects

                                  Milestone

                                  No milestone

                                  Relationships

                                  None yet

                                  Development

                                  No branches or pull requests

                                  Issue actions