Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,6 +56,7 @@ corepack pnpm --filter agentworkforce link --global
```
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -74,6 +75,10 @@ agentworkforce harness check
intent. Flags: `--all`, `--json`, `--filter-rating <tier>`,
`--filter-harness <harness>`, `--no-display-description`. See
**[packages/cli/README.md](./packages/cli/README.md#list)** for details.
- `install` — copy persona JSON files from an npm package or local package
directory into `./.agentworkforce/workforce/personas/`. Installed files are
project-owned and editable. There is no install manifest, lockfile, update
command, or registry beyond the npm package spec you pass.
- `sources` — list, add, or remove configured persona source directories.
This is how you include personas installed into another checkout or repo.
See **[packages/cli/README.md](./packages/cli/README.md#sources)**.
Expand All@@ -96,6 +101,70 @@ export POSTHOG_API_KEY=phx_…
agentworkforce agent posthog@best
```

### Persona pack installs

Install a persona pack into the current project:

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

The command copies matching `*.json` persona files into
`./.agentworkforce/workforce/personas/`, flattening nested package paths to
plain filenames. Existing files are skipped and reported as conflicts by
default; pass `--overwrite` to replace them:

```bash
agentworkforce install @agentrelay/personas --overwrite
```

Persona packs use npm as the distribution mechanism. A package can point at
its persona directory with `package.json` metadata, or fall back to a top-level
`personas/` directory:

```json
{
"name": "@acme/personas",
"version": "1.0.0",
"files": ["personas"],
"keywords": ["agentworkforce-personas"],
"agentworkforce": {
"personas": "personas"
}
}
```

```text
@acme/personas/
├── package.json
└── personas/
├── reviewer.json
└── release-runner.json
```

`install` is a copy utility. Use it when a project should own and edit its
persona files. `sources add <dir>` is separate: it points the cascade at a live
directory and does not copy files.

Worked authoring flow:

```bash
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
git add .agentworkforce/workforce/personas/reviewer.json
```

### Local persona override

Project-local `./.agentworkforce/workforce/personas/my-posthog.json`:
Expand Down
152 changes: 152 additions & 0 deletions packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ source.
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce show <persona>[@<tier>]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -17,6 +18,8 @@ agentworkforce harness check
- `list` — print the persona catalog as a table (or JSON). See
[`## List`](#list) below for every flag.
- `show` — print the resolved spec for one persona.
- `install` — copy persona JSON files from an npm or local persona pack into
the current project's fixed cwd source directory.
- `sources` — list, add, or remove persona source directories.
- `harness check` — probe which harnesses (`claude`, `codex`, `opencode`)
are installed. See [`## Harness check`](#harness-check) below.
Expand DownExpand Up@@ -68,6 +71,150 @@ agentworkforce agent posthog@best
agentworkforce agent my-posthog@best
```

## Install persona packs

```text
agentworkforce install <pkg|path> [--persona <id> ...] [--overwrite]
```

`install` is a shadcn-style copy utility for persona JSON. It copies persona
files into the current project's fixed cwd layer:
`<cwd>/.agentworkforce/workforce/personas/`.

Once copied, files are project-owned. Edit them directly and commit them to
git. The CLI does not create an install ledger, lockfile, manifest, update
command, uninstall command, diff command, or central AgentWorkforce registry.

### Package and path forms

Npm package specs are resolved with `npm pack`, so npm auth, npm config,
private packages, tags, and versions work the same way they do for npm:

```sh
agentworkforce install @agentrelay/personas
agentworkforce install @agentrelay/personas@1.2.3
agentworkforce install @agentrelay/personas@latest
```

Local path installs read directly from the directory:

```sh
agentworkforce install ./local-personas
agentworkforce install /absolute/path/to/local-personas
```

### Selecting personas

By default, every `*.json` file in the pack's persona directory is copied.
Use repeated `--persona <id>` flags to install a subset by persona `id`:

```sh
agentworkforce install @agentrelay/personas --persona relay-orchestrator
agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer
```

If any requested id is missing, the command exits non-zero before copying
anything.

### Conflicts and overwrite

Target filenames are flattened into the cwd persona directory:

```text
package/personas/nested/code-reviewer.json
-> .agentworkforce/workforce/personas/code-reviewer.json
```

If the target file already exists, the installer reports a conflict, skips
that file, and exits non-zero. Non-conflicting files from the same run may
still be copied. Pass `--overwrite` to replace existing files unconditionally:

```sh
agentworkforce install @agentrelay/personas --overwrite
```

Filename collisions across packages use the same rule. The install layer does
not namespace files by package; avoid shipping two pack files with the same
basename if they are expected to be installed together.

### Persona pack format

A pack can contain multiple personas:

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

`package.json` may declare the persona directory:

```json
{
"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 use a top-level `personas/` directory.
3. Recursively copy every `*.json` file from that directory, flattening to
`<cwd>/.agentworkforce/workforce/personas/<basename>.json`.

Local path installs use the same metadata rules.

### Relationship to sources

Use `install` when this project should receive editable copies:

```sh
agentworkforce install @acme/personas
git add .agentworkforce/workforce/personas
```

Use `sources add` when you want the cascade to point at a live directory
without copying:

```sh
agentworkforce sources add ~/src/acme-personas/personas
```

Both feed the same cascade. `install` writes to the fixed cwd layer, while
`sources` changes the configured source directories in
`~/.agentworkforce/workforce/config.json`.

### Author and publish a persona pack

```sh
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
```

Then install it in a project:

```sh
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
agentworkforce list --filter-tag review
agentworkforce agent reviewer@best-value
```

## List

```
Expand DownExpand Up@@ -296,6 +443,11 @@ changes — `systemPrompt`, `harness`, and `harnessSettings` still come from the
base. Use top-level `systemPrompt` if you want to replace the prompt
uniformly across all tiers.

To define a standalone local persona that does not inherit from a lower layer,
include `intent` and a complete `tiers` object for `best`, `best-value`, and
`minimum`. This is the shape persona packs usually ship before `install`
copies them into the cwd layer.

## Env references & secrets

Any `env` value or `mcpServers.*.{headers,env,args,url,command}` value can be
Expand Down
19 changes: 19 additions & 0 deletions packages/cli/src/cli.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ import {
configureGitForMount,
decideCleanMode,
parseAgentArgs,
parseInstallArgs,
resolveSystemPromptPlaceholders,
stripAgentFlag
} from './cli.js';
Expand DownExpand Up@@ -94,6 +95,24 @@ test('parseAgentArgs: -- stops flag parsing, positional args after are preserved
assert.deepEqual(positional, ['--install-in-repo', 'posthog']);
});

test('parseInstallArgs: accepts package specs, repeatable persona flags, and overwrite', () => {
assert.deepEqual(
parseInstallArgs([
'@scope/pkg@1.2.3',
'--persona',
'relay-orchestrator',
'--persona',
'code-reviewer',
'--overwrite'
]),
{
source: '@scope/pkg@1.2.3',
personaIds: ['relay-orchestrator', 'code-reviewer'],
overwrite: true
}
);
});

test('decideCleanMode: claude defaults to mount (parity with opencode)', () => {
// claude and opencode both default to the sandbox mount; the includeGit
// path in relayfile 0.6 keeps `.git` in the mount so git operations work
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,6 +56,7 @@ corepack pnpm --filter agentworkforce link --global
```
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -74,6 +75,10 @@ agentworkforce harness check
intent. Flags: `--all`, `--json`, `--filter-rating <tier>`,
`--filter-harness <harness>`, `--no-display-description`. See
**[packages/cli/README.md](./packages/cli/README.md#list)** for details.
- `install` — copy persona JSON files from an npm package or local package
directory into `./.agentworkforce/workforce/personas/`. Installed files are
project-owned and editable. There is no install manifest, lockfile, update
command, or registry beyond the npm package spec you pass.
- `sources` — list, add, or remove configured persona source directories.
This is how you include personas installed into another checkout or repo.
See **[packages/cli/README.md](./packages/cli/README.md#sources)**.
Expand All@@ -96,6 +101,70 @@ export POSTHOG_API_KEY=phx_…
agentworkforce agent posthog@best
```

### Persona pack installs

Install a persona pack into the current project:

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

The command copies matching `*.json` persona files into
`./.agentworkforce/workforce/personas/`, flattening nested package paths to
plain filenames. Existing files are skipped and reported as conflicts by
default; pass `--overwrite` to replace them:

```bash
agentworkforce install @agentrelay/personas --overwrite
```

Persona packs use npm as the distribution mechanism. A package can point at
its persona directory with `package.json` metadata, or fall back to a top-level
`personas/` directory:

```json
{
"name": "@acme/personas",
"version": "1.0.0",
"files": ["personas"],
"keywords": ["agentworkforce-personas"],
"agentworkforce": {
"personas": "personas"
}
}
```

```text
@acme/personas/
├── package.json
└── personas/
├── reviewer.json
└── release-runner.json
```

`install` is a copy utility. Use it when a project should own and edit its
persona files. `sources add <dir>` is separate: it points the cascade at a live
directory and does not copy files.

Worked authoring flow:

```bash
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
git add .agentworkforce/workforce/personas/reviewer.json
```

### Local persona override

Project-local `./.agentworkforce/workforce/personas/my-posthog.json`:
Expand Down
152 changes: 152 additions & 0 deletions packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ source.
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce show <persona>[@<tier>]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -17,6 +18,8 @@ agentworkforce harness check
- `list` — print the persona catalog as a table (or JSON). See
[`## List`](#list) below for every flag.
- `show` — print the resolved spec for one persona.
- `install` — copy persona JSON files from an npm or local persona pack into
the current project's fixed cwd source directory.
- `sources` — list, add, or remove persona source directories.
- `harness check` — probe which harnesses (`claude`, `codex`, `opencode`)
are installed. See [`## Harness check`](#harness-check) below.
Expand DownExpand Up@@ -68,6 +71,150 @@ agentworkforce agent posthog@best
agentworkforce agent my-posthog@best
```

## Install persona packs

```text
agentworkforce install <pkg|path> [--persona <id> ...] [--overwrite]
```

`install` is a shadcn-style copy utility for persona JSON. It copies persona
files into the current project's fixed cwd layer:
`<cwd>/.agentworkforce/workforce/personas/`.

Once copied, files are project-owned. Edit them directly and commit them to
git. The CLI does not create an install ledger, lockfile, manifest, update
command, uninstall command, diff command, or central AgentWorkforce registry.

### Package and path forms

Npm package specs are resolved with `npm pack`, so npm auth, npm config,
private packages, tags, and versions work the same way they do for npm:

```sh
agentworkforce install @agentrelay/personas
agentworkforce install @agentrelay/personas@1.2.3
agentworkforce install @agentrelay/personas@latest
```

Local path installs read directly from the directory:

```sh
agentworkforce install ./local-personas
agentworkforce install /absolute/path/to/local-personas
```

### Selecting personas

By default, every `*.json` file in the pack's persona directory is copied.
Use repeated `--persona <id>` flags to install a subset by persona `id`:

```sh
agentworkforce install @agentrelay/personas --persona relay-orchestrator
agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer
```

If any requested id is missing, the command exits non-zero before copying
anything.

### Conflicts and overwrite

Target filenames are flattened into the cwd persona directory:

```text
package/personas/nested/code-reviewer.json
-> .agentworkforce/workforce/personas/code-reviewer.json
```

If the target file already exists, the installer reports a conflict, skips
that file, and exits non-zero. Non-conflicting files from the same run may
still be copied. Pass `--overwrite` to replace existing files unconditionally:

```sh
agentworkforce install @agentrelay/personas --overwrite
```

Filename collisions across packages use the same rule. The install layer does
not namespace files by package; avoid shipping two pack files with the same
basename if they are expected to be installed together.

### Persona pack format

A pack can contain multiple personas:

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

`package.json` may declare the persona directory:

```json
{
"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 use a top-level `personas/` directory.
3. Recursively copy every `*.json` file from that directory, flattening to
`<cwd>/.agentworkforce/workforce/personas/<basename>.json`.

Local path installs use the same metadata rules.

### Relationship to sources

Use `install` when this project should receive editable copies:

```sh
agentworkforce install @acme/personas
git add .agentworkforce/workforce/personas
```

Use `sources add` when you want the cascade to point at a live directory
without copying:

```sh
agentworkforce sources add ~/src/acme-personas/personas
```

Both feed the same cascade. `install` writes to the fixed cwd layer, while
`sources` changes the configured source directories in
`~/.agentworkforce/workforce/config.json`.

### Author and publish a persona pack

```sh
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
```

Then install it in a project:

```sh
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
agentworkforce list --filter-tag review
agentworkforce agent reviewer@best-value
```

## List

```
Expand DownExpand Up@@ -296,6 +443,11 @@ changes — `systemPrompt`, `harness`, and `harnessSettings` still come from the
base. Use top-level `systemPrompt` if you want to replace the prompt
uniformly across all tiers.

To define a standalone local persona that does not inherit from a lower layer,
include `intent` and a complete `tiers` object for `best`, `best-value`, and
`minimum`. This is the shape persona packs usually ship before `install`
copies them into the cwd layer.

## Env references & secrets

Any `env` value or `mcpServers.*.{headers,env,args,url,command}` value can be
Expand Down
19 changes: 19 additions & 0 deletions packages/cli/src/cli.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ import {
configureGitForMount,
decideCleanMode,
parseAgentArgs,
parseInstallArgs,
resolveSystemPromptPlaceholders,
stripAgentFlag
} from './cli.js';
Expand DownExpand Up@@ -94,6 +95,24 @@ test('parseAgentArgs: -- stops flag parsing, positional args after are preserved
assert.deepEqual(positional, ['--install-in-repo', 'posthog']);
});

test('parseInstallArgs: accepts package specs, repeatable persona flags, and overwrite', () => {
assert.deepEqual(
parseInstallArgs([
'@scope/pkg@1.2.3',
'--persona',
'relay-orchestrator',
'--persona',
'code-reviewer',
'--overwrite'
]),
{
source: '@scope/pkg@1.2.3',
personaIds: ['relay-orchestrator', 'code-reviewer'],
overwrite: true
}
);
});

test('decideCleanMode: claude defaults to mount (parity with opencode)', () => {
// claude and opencode both default to the sandbox mount; the includeGit
// path in relayfile 0.6 keeps `.git` in the mount so git operations work
Expand Down
Loading
Loading
, '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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,6 +56,7 @@ corepack pnpm --filter agentworkforce link --global
```
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -74,6 +75,10 @@ agentworkforce harness check
intent. Flags: `--all`, `--json`, `--filter-rating <tier>`,
`--filter-harness <harness>`, `--no-display-description`. See
**[packages/cli/README.md](./packages/cli/README.md#list)** for details.
- `install` — copy persona JSON files from an npm package or local package
directory into `./.agentworkforce/workforce/personas/`. Installed files are
project-owned and editable. There is no install manifest, lockfile, update
command, or registry beyond the npm package spec you pass.
- `sources` — list, add, or remove configured persona source directories.
This is how you include personas installed into another checkout or repo.
See **[packages/cli/README.md](./packages/cli/README.md#sources)**.
Expand All@@ -96,6 +101,70 @@ export POSTHOG_API_KEY=phx_…
agentworkforce agent posthog@best
```

### Persona pack installs

Install a persona pack into the current project:

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

The command copies matching `*.json` persona files into
`./.agentworkforce/workforce/personas/`, flattening nested package paths to
plain filenames. Existing files are skipped and reported as conflicts by
default; pass `--overwrite` to replace them:

```bash
agentworkforce install @agentrelay/personas --overwrite
```

Persona packs use npm as the distribution mechanism. A package can point at
its persona directory with `package.json` metadata, or fall back to a top-level
`personas/` directory:

```json
{
"name": "@acme/personas",
"version": "1.0.0",
"files": ["personas"],
"keywords": ["agentworkforce-personas"],
"agentworkforce": {
"personas": "personas"
}
}
```

```text
@acme/personas/
├── package.json
└── personas/
├── reviewer.json
└── release-runner.json
```

`install` is a copy utility. Use it when a project should own and edit its
persona files. `sources add <dir>` is separate: it points the cascade at a live
directory and does not copy files.

Worked authoring flow:

```bash
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
git add .agentworkforce/workforce/personas/reviewer.json
```

### Local persona override

Project-local `./.agentworkforce/workforce/personas/my-posthog.json`:
Expand Down
152 changes: 152 additions & 0 deletions packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ source.
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce show <persona>[@<tier>]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -17,6 +18,8 @@ agentworkforce harness check
- `list` — print the persona catalog as a table (or JSON). See
[`## List`](#list) below for every flag.
- `show` — print the resolved spec for one persona.
- `install` — copy persona JSON files from an npm or local persona pack into
the current project's fixed cwd source directory.
- `sources` — list, add, or remove persona source directories.
- `harness check` — probe which harnesses (`claude`, `codex`, `opencode`)
are installed. See [`## Harness check`](#harness-check) below.
Expand DownExpand Up@@ -68,6 +71,150 @@ agentworkforce agent posthog@best
agentworkforce agent my-posthog@best
```

## Install persona packs

```text
agentworkforce install <pkg|path> [--persona <id> ...] [--overwrite]
```

`install` is a shadcn-style copy utility for persona JSON. It copies persona
files into the current project's fixed cwd layer:
`<cwd>/.agentworkforce/workforce/personas/`.

Once copied, files are project-owned. Edit them directly and commit them to
git. The CLI does not create an install ledger, lockfile, manifest, update
command, uninstall command, diff command, or central AgentWorkforce registry.

### Package and path forms

Npm package specs are resolved with `npm pack`, so npm auth, npm config,
private packages, tags, and versions work the same way they do for npm:

```sh
agentworkforce install @agentrelay/personas
agentworkforce install @agentrelay/personas@1.2.3
agentworkforce install @agentrelay/personas@latest
```

Local path installs read directly from the directory:

```sh
agentworkforce install ./local-personas
agentworkforce install /absolute/path/to/local-personas
```

### Selecting personas

By default, every `*.json` file in the pack's persona directory is copied.
Use repeated `--persona <id>` flags to install a subset by persona `id`:

```sh
agentworkforce install @agentrelay/personas --persona relay-orchestrator
agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer
```

If any requested id is missing, the command exits non-zero before copying
anything.

### Conflicts and overwrite

Target filenames are flattened into the cwd persona directory:

```text
package/personas/nested/code-reviewer.json
-> .agentworkforce/workforce/personas/code-reviewer.json
```

If the target file already exists, the installer reports a conflict, skips
that file, and exits non-zero. Non-conflicting files from the same run may
still be copied. Pass `--overwrite` to replace existing files unconditionally:

```sh
agentworkforce install @agentrelay/personas --overwrite
```

Filename collisions across packages use the same rule. The install layer does
not namespace files by package; avoid shipping two pack files with the same
basename if they are expected to be installed together.

### Persona pack format

A pack can contain multiple personas:

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

`package.json` may declare the persona directory:

```json
{
"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 use a top-level `personas/` directory.
3. Recursively copy every `*.json` file from that directory, flattening to
`<cwd>/.agentworkforce/workforce/personas/<basename>.json`.

Local path installs use the same metadata rules.

### Relationship to sources

Use `install` when this project should receive editable copies:

```sh
agentworkforce install @acme/personas
git add .agentworkforce/workforce/personas
```

Use `sources add` when you want the cascade to point at a live directory
without copying:

```sh
agentworkforce sources add ~/src/acme-personas/personas
```

Both feed the same cascade. `install` writes to the fixed cwd layer, while
`sources` changes the configured source directories in
`~/.agentworkforce/workforce/config.json`.

### Author and publish a persona pack

```sh
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
```

Then install it in a project:

```sh
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
agentworkforce list --filter-tag review
agentworkforce agent reviewer@best-value
```

## List

```
Expand DownExpand Up@@ -296,6 +443,11 @@ changes — `systemPrompt`, `harness`, and `harnessSettings` still come from the
base. Use top-level `systemPrompt` if you want to replace the prompt
uniformly across all tiers.

To define a standalone local persona that does not inherit from a lower layer,
include `intent` and a complete `tiers` object for `best`, `best-value`, and
`minimum`. This is the shape persona packs usually ship before `install`
copies them into the cwd layer.

## Env references & secrets

Any `env` value or `mcpServers.*.{headers,env,args,url,command}` value can be
Expand Down
19 changes: 19 additions & 0 deletions packages/cli/src/cli.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ import {
configureGitForMount,
decideCleanMode,
parseAgentArgs,
parseInstallArgs,
resolveSystemPromptPlaceholders,
stripAgentFlag
} from './cli.js';
Expand DownExpand Up@@ -94,6 +95,24 @@ test('parseAgentArgs: -- stops flag parsing, positional args after are preserved
assert.deepEqual(positional, ['--install-in-repo', 'posthog']);
});

test('parseInstallArgs: accepts package specs, repeatable persona flags, and overwrite', () => {
assert.deepEqual(
parseInstallArgs([
'@scope/pkg@1.2.3',
'--persona',
'relay-orchestrator',
'--persona',
'code-reviewer',
'--overwrite'
]),
{
source: '@scope/pkg@1.2.3',
personaIds: ['relay-orchestrator', 'code-reviewer'],
overwrite: true
}
);
});

test('decideCleanMode: claude defaults to mount (parity with opencode)', () => {
// claude and opencode both default to the sandbox mount; the includeGit
// path in relayfile 0.6 keeps `.git` in the mount so git operations work
Expand Down
Loading
Loading
, '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 > 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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,6 +56,7 @@ corepack pnpm --filter agentworkforce link --global
```
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -74,6 +75,10 @@ agentworkforce harness check
intent. Flags: `--all`, `--json`, `--filter-rating <tier>`,
`--filter-harness <harness>`, `--no-display-description`. See
**[packages/cli/README.md](./packages/cli/README.md#list)** for details.
- `install` — copy persona JSON files from an npm package or local package
directory into `./.agentworkforce/workforce/personas/`. Installed files are
project-owned and editable. There is no install manifest, lockfile, update
command, or registry beyond the npm package spec you pass.
- `sources` — list, add, or remove configured persona source directories.
This is how you include personas installed into another checkout or repo.
See **[packages/cli/README.md](./packages/cli/README.md#sources)**.
Expand All@@ -96,6 +101,70 @@ export POSTHOG_API_KEY=phx_…
agentworkforce agent posthog@best
```

### Persona pack installs

Install a persona pack into the current project:

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

The command copies matching `*.json` persona files into
`./.agentworkforce/workforce/personas/`, flattening nested package paths to
plain filenames. Existing files are skipped and reported as conflicts by
default; pass `--overwrite` to replace them:

```bash
agentworkforce install @agentrelay/personas --overwrite
```

Persona packs use npm as the distribution mechanism. A package can point at
its persona directory with `package.json` metadata, or fall back to a top-level
`personas/` directory:

```json
{
"name": "@acme/personas",
"version": "1.0.0",
"files": ["personas"],
"keywords": ["agentworkforce-personas"],
"agentworkforce": {
"personas": "personas"
}
}
```

```text
@acme/personas/
├── package.json
└── personas/
├── reviewer.json
└── release-runner.json
```

`install` is a copy utility. Use it when a project should own and edit its
persona files. `sources add <dir>` is separate: it points the cascade at a live
directory and does not copy files.

Worked authoring flow:

```bash
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
git add .agentworkforce/workforce/personas/reviewer.json
```

### Local persona override

Project-local `./.agentworkforce/workforce/personas/my-posthog.json`:
Expand Down
152 changes: 152 additions & 0 deletions packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ source.
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce show <persona>[@<tier>]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -17,6 +18,8 @@ agentworkforce harness check
- `list` — print the persona catalog as a table (or JSON). See
[`## List`](#list) below for every flag.
- `show` — print the resolved spec for one persona.
- `install` — copy persona JSON files from an npm or local persona pack into
the current project's fixed cwd source directory.
- `sources` — list, add, or remove persona source directories.
- `harness check` — probe which harnesses (`claude`, `codex`, `opencode`)
are installed. See [`## Harness check`](#harness-check) below.
Expand DownExpand Up@@ -68,6 +71,150 @@ agentworkforce agent posthog@best
agentworkforce agent my-posthog@best
```

## Install persona packs

```text
agentworkforce install <pkg|path> [--persona <id> ...] [--overwrite]
```

`install` is a shadcn-style copy utility for persona JSON. It copies persona
files into the current project's fixed cwd layer:
`<cwd>/.agentworkforce/workforce/personas/`.

Once copied, files are project-owned. Edit them directly and commit them to
git. The CLI does not create an install ledger, lockfile, manifest, update
command, uninstall command, diff command, or central AgentWorkforce registry.

### Package and path forms

Npm package specs are resolved with `npm pack`, so npm auth, npm config,
private packages, tags, and versions work the same way they do for npm:

```sh
agentworkforce install @agentrelay/personas
agentworkforce install @agentrelay/personas@1.2.3
agentworkforce install @agentrelay/personas@latest
```

Local path installs read directly from the directory:

```sh
agentworkforce install ./local-personas
agentworkforce install /absolute/path/to/local-personas
```

### Selecting personas

By default, every `*.json` file in the pack's persona directory is copied.
Use repeated `--persona <id>` flags to install a subset by persona `id`:

```sh
agentworkforce install @agentrelay/personas --persona relay-orchestrator
agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer
```

If any requested id is missing, the command exits non-zero before copying
anything.

### Conflicts and overwrite

Target filenames are flattened into the cwd persona directory:

```text
package/personas/nested/code-reviewer.json
-> .agentworkforce/workforce/personas/code-reviewer.json
```

If the target file already exists, the installer reports a conflict, skips
that file, and exits non-zero. Non-conflicting files from the same run may
still be copied. Pass `--overwrite` to replace existing files unconditionally:

```sh
agentworkforce install @agentrelay/personas --overwrite
```

Filename collisions across packages use the same rule. The install layer does
not namespace files by package; avoid shipping two pack files with the same
basename if they are expected to be installed together.

### Persona pack format

A pack can contain multiple personas:

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

`package.json` may declare the persona directory:

```json
{
"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 use a top-level `personas/` directory.
3. Recursively copy every `*.json` file from that directory, flattening to
`<cwd>/.agentworkforce/workforce/personas/<basename>.json`.

Local path installs use the same metadata rules.

### Relationship to sources

Use `install` when this project should receive editable copies:

```sh
agentworkforce install @acme/personas
git add .agentworkforce/workforce/personas
```

Use `sources add` when you want the cascade to point at a live directory
without copying:

```sh
agentworkforce sources add ~/src/acme-personas/personas
```

Both feed the same cascade. `install` writes to the fixed cwd layer, while
`sources` changes the configured source directories in
`~/.agentworkforce/workforce/config.json`.

### Author and publish a persona pack

```sh
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
```

Then install it in a project:

```sh
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
agentworkforce list --filter-tag review
agentworkforce agent reviewer@best-value
```

## List

```
Expand DownExpand Up@@ -296,6 +443,11 @@ changes — `systemPrompt`, `harness`, and `harnessSettings` still come from the
base. Use top-level `systemPrompt` if you want to replace the prompt
uniformly across all tiers.

To define a standalone local persona that does not inherit from a lower layer,
include `intent` and a complete `tiers` object for `best`, `best-value`, and
`minimum`. This is the shape persona packs usually ship before `install`
copies them into the cwd layer.

## Env references & secrets

Any `env` value or `mcpServers.*.{headers,env,args,url,command}` value can be
Expand Down
19 changes: 19 additions & 0 deletions packages/cli/src/cli.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ import {
configureGitForMount,
decideCleanMode,
parseAgentArgs,
parseInstallArgs,
resolveSystemPromptPlaceholders,
stripAgentFlag
} from './cli.js';
Expand DownExpand Up@@ -94,6 +95,24 @@ test('parseAgentArgs: -- stops flag parsing, positional args after are preserved
assert.deepEqual(positional, ['--install-in-repo', 'posthog']);
});

test('parseInstallArgs: accepts package specs, repeatable persona flags, and overwrite', () => {
assert.deepEqual(
parseInstallArgs([
'@scope/pkg@1.2.3',
'--persona',
'relay-orchestrator',
'--persona',
'code-reviewer',
'--overwrite'
]),
{
source: '@scope/pkg@1.2.3',
personaIds: ['relay-orchestrator', 'code-reviewer'],
overwrite: true
}
);
});

test('decideCleanMode: claude defaults to mount (parity with opencode)', () => {
// claude and opencode both default to the sandbox mount; the includeGit
// path in relayfile 0.6 keeps `.git` in the mount so git operations work
Expand Down
Loading
Loading
, '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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,6 +56,7 @@ corepack pnpm --filter agentworkforce link --global
```
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -74,6 +75,10 @@ agentworkforce harness check
intent. Flags: `--all`, `--json`, `--filter-rating <tier>`,
`--filter-harness <harness>`, `--no-display-description`. See
**[packages/cli/README.md](./packages/cli/README.md#list)** for details.
- `install` — copy persona JSON files from an npm package or local package
directory into `./.agentworkforce/workforce/personas/`. Installed files are
project-owned and editable. There is no install manifest, lockfile, update
command, or registry beyond the npm package spec you pass.
- `sources` — list, add, or remove configured persona source directories.
This is how you include personas installed into another checkout or repo.
See **[packages/cli/README.md](./packages/cli/README.md#sources)**.
Expand All@@ -96,6 +101,70 @@ export POSTHOG_API_KEY=phx_…
agentworkforce agent posthog@best
```

### Persona pack installs

Install a persona pack into the current project:

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

The command copies matching `*.json` persona files into
`./.agentworkforce/workforce/personas/`, flattening nested package paths to
plain filenames. Existing files are skipped and reported as conflicts by
default; pass `--overwrite` to replace them:

```bash
agentworkforce install @agentrelay/personas --overwrite
```

Persona packs use npm as the distribution mechanism. A package can point at
its persona directory with `package.json` metadata, or fall back to a top-level
`personas/` directory:

```json
{
"name": "@acme/personas",
"version": "1.0.0",
"files": ["personas"],
"keywords": ["agentworkforce-personas"],
"agentworkforce": {
"personas": "personas"
}
}
```

```text
@acme/personas/
├── package.json
└── personas/
├── reviewer.json
└── release-runner.json
```

`install` is a copy utility. Use it when a project should own and edit its
persona files. `sources add <dir>` is separate: it points the cascade at a live
directory and does not copy files.

Worked authoring flow:

```bash
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
git add .agentworkforce/workforce/personas/reviewer.json
```

### Local persona override

Project-local `./.agentworkforce/workforce/personas/my-posthog.json`:
Expand Down
152 changes: 152 additions & 0 deletions packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ source.
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce show <persona>[@<tier>]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -17,6 +18,8 @@ agentworkforce harness check
- `list` — print the persona catalog as a table (or JSON). See
[`## List`](#list) below for every flag.
- `show` — print the resolved spec for one persona.
- `install` — copy persona JSON files from an npm or local persona pack into
the current project's fixed cwd source directory.
- `sources` — list, add, or remove persona source directories.
- `harness check` — probe which harnesses (`claude`, `codex`, `opencode`)
are installed. See [`## Harness check`](#harness-check) below.
Expand DownExpand Up@@ -68,6 +71,150 @@ agentworkforce agent posthog@best
agentworkforce agent my-posthog@best
```

## Install persona packs

```text
agentworkforce install <pkg|path> [--persona <id> ...] [--overwrite]
```

`install` is a shadcn-style copy utility for persona JSON. It copies persona
files into the current project's fixed cwd layer:
`<cwd>/.agentworkforce/workforce/personas/`.

Once copied, files are project-owned. Edit them directly and commit them to
git. The CLI does not create an install ledger, lockfile, manifest, update
command, uninstall command, diff command, or central AgentWorkforce registry.

### Package and path forms

Npm package specs are resolved with `npm pack`, so npm auth, npm config,
private packages, tags, and versions work the same way they do for npm:

```sh
agentworkforce install @agentrelay/personas
agentworkforce install @agentrelay/personas@1.2.3
agentworkforce install @agentrelay/personas@latest
```

Local path installs read directly from the directory:

```sh
agentworkforce install ./local-personas
agentworkforce install /absolute/path/to/local-personas
```

### Selecting personas

By default, every `*.json` file in the pack's persona directory is copied.
Use repeated `--persona <id>` flags to install a subset by persona `id`:

```sh
agentworkforce install @agentrelay/personas --persona relay-orchestrator
agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer
```

If any requested id is missing, the command exits non-zero before copying
anything.

### Conflicts and overwrite

Target filenames are flattened into the cwd persona directory:

```text
package/personas/nested/code-reviewer.json
-> .agentworkforce/workforce/personas/code-reviewer.json
```

If the target file already exists, the installer reports a conflict, skips
that file, and exits non-zero. Non-conflicting files from the same run may
still be copied. Pass `--overwrite` to replace existing files unconditionally:

```sh
agentworkforce install @agentrelay/personas --overwrite
```

Filename collisions across packages use the same rule. The install layer does
not namespace files by package; avoid shipping two pack files with the same
basename if they are expected to be installed together.

### Persona pack format

A pack can contain multiple personas:

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

`package.json` may declare the persona directory:

```json
{
"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 use a top-level `personas/` directory.
3. Recursively copy every `*.json` file from that directory, flattening to
`<cwd>/.agentworkforce/workforce/personas/<basename>.json`.

Local path installs use the same metadata rules.

### Relationship to sources

Use `install` when this project should receive editable copies:

```sh
agentworkforce install @acme/personas
git add .agentworkforce/workforce/personas
```

Use `sources add` when you want the cascade to point at a live directory
without copying:

```sh
agentworkforce sources add ~/src/acme-personas/personas
```

Both feed the same cascade. `install` writes to the fixed cwd layer, while
`sources` changes the configured source directories in
`~/.agentworkforce/workforce/config.json`.

### Author and publish a persona pack

```sh
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
```

Then install it in a project:

```sh
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
agentworkforce list --filter-tag review
agentworkforce agent reviewer@best-value
```

## List

```
Expand DownExpand Up@@ -296,6 +443,11 @@ changes — `systemPrompt`, `harness`, and `harnessSettings` still come from the
base. Use top-level `systemPrompt` if you want to replace the prompt
uniformly across all tiers.

To define a standalone local persona that does not inherit from a lower layer,
include `intent` and a complete `tiers` object for `best`, `best-value`, and
`minimum`. This is the shape persona packs usually ship before `install`
copies them into the cwd layer.

## Env references & secrets

Any `env` value or `mcpServers.*.{headers,env,args,url,command}` value can be
Expand Down
19 changes: 19 additions & 0 deletions packages/cli/src/cli.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ import {
configureGitForMount,
decideCleanMode,
parseAgentArgs,
parseInstallArgs,
resolveSystemPromptPlaceholders,
stripAgentFlag
} from './cli.js';
Expand DownExpand Up@@ -94,6 +95,24 @@ test('parseAgentArgs: -- stops flag parsing, positional args after are preserved
assert.deepEqual(positional, ['--install-in-repo', 'posthog']);
});

test('parseInstallArgs: accepts package specs, repeatable persona flags, and overwrite', () => {
assert.deepEqual(
parseInstallArgs([
'@scope/pkg@1.2.3',
'--persona',
'relay-orchestrator',
'--persona',
'code-reviewer',
'--overwrite'
]),
{
source: '@scope/pkg@1.2.3',
personaIds: ['relay-orchestrator', 'code-reviewer'],
overwrite: true
}
);
});

test('decideCleanMode: claude defaults to mount (parity with opencode)', () => {
// claude and opencode both default to the sandbox mount; the includeGit
// path in relayfile 0.6 keeps `.git` in the mount so git operations work
Expand Down
Loading
Loading
, '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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,6 +56,7 @@ corepack pnpm --filter agentworkforce link --global
```
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -74,6 +75,10 @@ agentworkforce harness check
intent. Flags: `--all`, `--json`, `--filter-rating <tier>`,
`--filter-harness <harness>`, `--no-display-description`. See
**[packages/cli/README.md](./packages/cli/README.md#list)** for details.
- `install` — copy persona JSON files from an npm package or local package
directory into `./.agentworkforce/workforce/personas/`. Installed files are
project-owned and editable. There is no install manifest, lockfile, update
command, or registry beyond the npm package spec you pass.
- `sources` — list, add, or remove configured persona source directories.
This is how you include personas installed into another checkout or repo.
See **[packages/cli/README.md](./packages/cli/README.md#sources)**.
Expand All@@ -96,6 +101,70 @@ export POSTHOG_API_KEY=phx_…
agentworkforce agent posthog@best
```

### Persona pack installs

Install a persona pack into the current project:

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

The command copies matching `*.json` persona files into
`./.agentworkforce/workforce/personas/`, flattening nested package paths to
plain filenames. Existing files are skipped and reported as conflicts by
default; pass `--overwrite` to replace them:

```bash
agentworkforce install @agentrelay/personas --overwrite
```

Persona packs use npm as the distribution mechanism. A package can point at
its persona directory with `package.json` metadata, or fall back to a top-level
`personas/` directory:

```json
{
"name": "@acme/personas",
"version": "1.0.0",
"files": ["personas"],
"keywords": ["agentworkforce-personas"],
"agentworkforce": {
"personas": "personas"
}
}
```

```text
@acme/personas/
├── package.json
└── personas/
├── reviewer.json
└── release-runner.json
```

`install` is a copy utility. Use it when a project should own and edit its
persona files. `sources add <dir>` is separate: it points the cascade at a live
directory and does not copy files.

Worked authoring flow:

```bash
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
git add .agentworkforce/workforce/personas/reviewer.json
```

### Local persona override

Project-local `./.agentworkforce/workforce/personas/my-posthog.json`:
Expand Down
152 changes: 152 additions & 0 deletions packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ source.
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce show <persona>[@<tier>]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -17,6 +18,8 @@ agentworkforce harness check
- `list` — print the persona catalog as a table (or JSON). See
[`## List`](#list) below for every flag.
- `show` — print the resolved spec for one persona.
- `install` — copy persona JSON files from an npm or local persona pack into
the current project's fixed cwd source directory.
- `sources` — list, add, or remove persona source directories.
- `harness check` — probe which harnesses (`claude`, `codex`, `opencode`)
are installed. See [`## Harness check`](#harness-check) below.
Expand DownExpand Up@@ -68,6 +71,150 @@ agentworkforce agent posthog@best
agentworkforce agent my-posthog@best
```

## Install persona packs

```text
agentworkforce install <pkg|path> [--persona <id> ...] [--overwrite]
```

`install` is a shadcn-style copy utility for persona JSON. It copies persona
files into the current project's fixed cwd layer:
`<cwd>/.agentworkforce/workforce/personas/`.

Once copied, files are project-owned. Edit them directly and commit them to
git. The CLI does not create an install ledger, lockfile, manifest, update
command, uninstall command, diff command, or central AgentWorkforce registry.

### Package and path forms

Npm package specs are resolved with `npm pack`, so npm auth, npm config,
private packages, tags, and versions work the same way they do for npm:

```sh
agentworkforce install @agentrelay/personas
agentworkforce install @agentrelay/personas@1.2.3
agentworkforce install @agentrelay/personas@latest
```

Local path installs read directly from the directory:

```sh
agentworkforce install ./local-personas
agentworkforce install /absolute/path/to/local-personas
```

### Selecting personas

By default, every `*.json` file in the pack's persona directory is copied.
Use repeated `--persona <id>` flags to install a subset by persona `id`:

```sh
agentworkforce install @agentrelay/personas --persona relay-orchestrator
agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer
```

If any requested id is missing, the command exits non-zero before copying
anything.

### Conflicts and overwrite

Target filenames are flattened into the cwd persona directory:

```text
package/personas/nested/code-reviewer.json
-> .agentworkforce/workforce/personas/code-reviewer.json
```

If the target file already exists, the installer reports a conflict, skips
that file, and exits non-zero. Non-conflicting files from the same run may
still be copied. Pass `--overwrite` to replace existing files unconditionally:

```sh
agentworkforce install @agentrelay/personas --overwrite
```

Filename collisions across packages use the same rule. The install layer does
not namespace files by package; avoid shipping two pack files with the same
basename if they are expected to be installed together.

### Persona pack format

A pack can contain multiple personas:

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

`package.json` may declare the persona directory:

```json
{
"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 use a top-level `personas/` directory.
3. Recursively copy every `*.json` file from that directory, flattening to
`<cwd>/.agentworkforce/workforce/personas/<basename>.json`.

Local path installs use the same metadata rules.

### Relationship to sources

Use `install` when this project should receive editable copies:

```sh
agentworkforce install @acme/personas
git add .agentworkforce/workforce/personas
```

Use `sources add` when you want the cascade to point at a live directory
without copying:

```sh
agentworkforce sources add ~/src/acme-personas/personas
```

Both feed the same cascade. `install` writes to the fixed cwd layer, while
`sources` changes the configured source directories in
`~/.agentworkforce/workforce/config.json`.

### Author and publish a persona pack

```sh
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
```

Then install it in a project:

```sh
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
agentworkforce list --filter-tag review
agentworkforce agent reviewer@best-value
```

## List

```
Expand DownExpand Up@@ -296,6 +443,11 @@ changes — `systemPrompt`, `harness`, and `harnessSettings` still come from the
base. Use top-level `systemPrompt` if you want to replace the prompt
uniformly across all tiers.

To define a standalone local persona that does not inherit from a lower layer,
include `intent` and a complete `tiers` object for `best`, `best-value`, and
`minimum`. This is the shape persona packs usually ship before `install`
copies them into the cwd layer.

## Env references & secrets

Any `env` value or `mcpServers.*.{headers,env,args,url,command}` value can be
Expand Down
19 changes: 19 additions & 0 deletions packages/cli/src/cli.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ import {
configureGitForMount,
decideCleanMode,
parseAgentArgs,
parseInstallArgs,
resolveSystemPromptPlaceholders,
stripAgentFlag
} from './cli.js';
Expand DownExpand Up@@ -94,6 +95,24 @@ test('parseAgentArgs: -- stops flag parsing, positional args after are preserved
assert.deepEqual(positional, ['--install-in-repo', 'posthog']);
});

test('parseInstallArgs: accepts package specs, repeatable persona flags, and overwrite', () => {
assert.deepEqual(
parseInstallArgs([
'@scope/pkg@1.2.3',
'--persona',
'relay-orchestrator',
'--persona',
'code-reviewer',
'--overwrite'
]),
{
source: '@scope/pkg@1.2.3',
personaIds: ['relay-orchestrator', 'code-reviewer'],
overwrite: true
}
);
});

test('decideCleanMode: claude defaults to mount (parity with opencode)', () => {
// claude and opencode both default to the sandbox mount; the includeGit
// path in relayfile 0.6 keeps `.git` in the mount so git operations work
Expand Down
Loading
Loading
, '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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,6 +56,7 @@ corepack pnpm --filter agentworkforce link --global
```
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -74,6 +75,10 @@ agentworkforce harness check
intent. Flags: `--all`, `--json`, `--filter-rating <tier>`,
`--filter-harness <harness>`, `--no-display-description`. See
**[packages/cli/README.md](./packages/cli/README.md#list)** for details.
- `install` — copy persona JSON files from an npm package or local package
directory into `./.agentworkforce/workforce/personas/`. Installed files are
project-owned and editable. There is no install manifest, lockfile, update
command, or registry beyond the npm package spec you pass.
- `sources` — list, add, or remove configured persona source directories.
This is how you include personas installed into another checkout or repo.
See **[packages/cli/README.md](./packages/cli/README.md#sources)**.
Expand All@@ -96,6 +101,70 @@ export POSTHOG_API_KEY=phx_…
agentworkforce agent posthog@best
```

### Persona pack installs

Install a persona pack into the current project:

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

The command copies matching `*.json` persona files into
`./.agentworkforce/workforce/personas/`, flattening nested package paths to
plain filenames. Existing files are skipped and reported as conflicts by
default; pass `--overwrite` to replace them:

```bash
agentworkforce install @agentrelay/personas --overwrite
```

Persona packs use npm as the distribution mechanism. A package can point at
its persona directory with `package.json` metadata, or fall back to a top-level
`personas/` directory:

```json
{
"name": "@acme/personas",
"version": "1.0.0",
"files": ["personas"],
"keywords": ["agentworkforce-personas"],
"agentworkforce": {
"personas": "personas"
}
}
```

```text
@acme/personas/
├── package.json
└── personas/
├── reviewer.json
└── release-runner.json
```

`install` is a copy utility. Use it when a project should own and edit its
persona files. `sources add <dir>` is separate: it points the cascade at a live
directory and does not copy files.

Worked authoring flow:

```bash
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
git add .agentworkforce/workforce/personas/reviewer.json
```

### Local persona override

Project-local `./.agentworkforce/workforce/personas/my-posthog.json`:
Expand Down
152 changes: 152 additions & 0 deletions packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ source.
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce show <persona>[@<tier>]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -17,6 +18,8 @@ agentworkforce harness check
- `list` — print the persona catalog as a table (or JSON). See
[`## List`](#list) below for every flag.
- `show` — print the resolved spec for one persona.
- `install` — copy persona JSON files from an npm or local persona pack into
the current project's fixed cwd source directory.
- `sources` — list, add, or remove persona source directories.
- `harness check` — probe which harnesses (`claude`, `codex`, `opencode`)
are installed. See [`## Harness check`](#harness-check) below.
Expand DownExpand Up@@ -68,6 +71,150 @@ agentworkforce agent posthog@best
agentworkforce agent my-posthog@best
```

## Install persona packs

```text
agentworkforce install <pkg|path> [--persona <id> ...] [--overwrite]
```

`install` is a shadcn-style copy utility for persona JSON. It copies persona
files into the current project's fixed cwd layer:
`<cwd>/.agentworkforce/workforce/personas/`.

Once copied, files are project-owned. Edit them directly and commit them to
git. The CLI does not create an install ledger, lockfile, manifest, update
command, uninstall command, diff command, or central AgentWorkforce registry.

### Package and path forms

Npm package specs are resolved with `npm pack`, so npm auth, npm config,
private packages, tags, and versions work the same way they do for npm:

```sh
agentworkforce install @agentrelay/personas
agentworkforce install @agentrelay/personas@1.2.3
agentworkforce install @agentrelay/personas@latest
```

Local path installs read directly from the directory:

```sh
agentworkforce install ./local-personas
agentworkforce install /absolute/path/to/local-personas
```

### Selecting personas

By default, every `*.json` file in the pack's persona directory is copied.
Use repeated `--persona <id>` flags to install a subset by persona `id`:

```sh
agentworkforce install @agentrelay/personas --persona relay-orchestrator
agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer
```

If any requested id is missing, the command exits non-zero before copying
anything.

### Conflicts and overwrite

Target filenames are flattened into the cwd persona directory:

```text
package/personas/nested/code-reviewer.json
-> .agentworkforce/workforce/personas/code-reviewer.json
```

If the target file already exists, the installer reports a conflict, skips
that file, and exits non-zero. Non-conflicting files from the same run may
still be copied. Pass `--overwrite` to replace existing files unconditionally:

```sh
agentworkforce install @agentrelay/personas --overwrite
```

Filename collisions across packages use the same rule. The install layer does
not namespace files by package; avoid shipping two pack files with the same
basename if they are expected to be installed together.

### Persona pack format

A pack can contain multiple personas:

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

`package.json` may declare the persona directory:

```json
{
"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 use a top-level `personas/` directory.
3. Recursively copy every `*.json` file from that directory, flattening to
`<cwd>/.agentworkforce/workforce/personas/<basename>.json`.

Local path installs use the same metadata rules.

### Relationship to sources

Use `install` when this project should receive editable copies:

```sh
agentworkforce install @acme/personas
git add .agentworkforce/workforce/personas
```

Use `sources add` when you want the cascade to point at a live directory
without copying:

```sh
agentworkforce sources add ~/src/acme-personas/personas
```

Both feed the same cascade. `install` writes to the fixed cwd layer, while
`sources` changes the configured source directories in
`~/.agentworkforce/workforce/config.json`.

### Author and publish a persona pack

```sh
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
```

Then install it in a project:

```sh
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
agentworkforce list --filter-tag review
agentworkforce agent reviewer@best-value
```

## List

```
Expand DownExpand Up@@ -296,6 +443,11 @@ changes — `systemPrompt`, `harness`, and `harnessSettings` still come from the
base. Use top-level `systemPrompt` if you want to replace the prompt
uniformly across all tiers.

To define a standalone local persona that does not inherit from a lower layer,
include `intent` and a complete `tiers` object for `best`, `best-value`, and
`minimum`. This is the shape persona packs usually ship before `install`
copies them into the cwd layer.

## Env references & secrets

Any `env` value or `mcpServers.*.{headers,env,args,url,command}` value can be
Expand Down
19 changes: 19 additions & 0 deletions packages/cli/src/cli.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ import {
configureGitForMount,
decideCleanMode,
parseAgentArgs,
parseInstallArgs,
resolveSystemPromptPlaceholders,
stripAgentFlag
} from './cli.js';
Expand DownExpand Up@@ -94,6 +95,24 @@ test('parseAgentArgs: -- stops flag parsing, positional args after are preserved
assert.deepEqual(positional, ['--install-in-repo', 'posthog']);
});

test('parseInstallArgs: accepts package specs, repeatable persona flags, and overwrite', () => {
assert.deepEqual(
parseInstallArgs([
'@scope/pkg@1.2.3',
'--persona',
'relay-orchestrator',
'--persona',
'code-reviewer',
'--overwrite'
]),
{
source: '@scope/pkg@1.2.3',
personaIds: ['relay-orchestrator', 'code-reviewer'],
overwrite: true
}
);
});

test('decideCleanMode: claude defaults to mount (parity with opencode)', () => {
// claude and opencode both default to the sandbox mount; the includeGit
// path in relayfile 0.6 keeps `.git` in the mount so git operations work
Expand Down
Loading
Loading
, '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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,6 +56,7 @@ corepack pnpm --filter agentworkforce link --global
```
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -74,6 +75,10 @@ agentworkforce harness check
intent. Flags: `--all`, `--json`, `--filter-rating <tier>`,
`--filter-harness <harness>`, `--no-display-description`. See
**[packages/cli/README.md](./packages/cli/README.md#list)** for details.
- `install` — copy persona JSON files from an npm package or local package
directory into `./.agentworkforce/workforce/personas/`. Installed files are
project-owned and editable. There is no install manifest, lockfile, update
command, or registry beyond the npm package spec you pass.
- `sources` — list, add, or remove configured persona source directories.
This is how you include personas installed into another checkout or repo.
See **[packages/cli/README.md](./packages/cli/README.md#sources)**.
Expand All@@ -96,6 +101,70 @@ export POSTHOG_API_KEY=phx_…
agentworkforce agent posthog@best
```

### Persona pack installs

Install a persona pack into the current project:

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

The command copies matching `*.json` persona files into
`./.agentworkforce/workforce/personas/`, flattening nested package paths to
plain filenames. Existing files are skipped and reported as conflicts by
default; pass `--overwrite` to replace them:

```bash
agentworkforce install @agentrelay/personas --overwrite
```

Persona packs use npm as the distribution mechanism. A package can point at
its persona directory with `package.json` metadata, or fall back to a top-level
`personas/` directory:

```json
{
"name": "@acme/personas",
"version": "1.0.0",
"files": ["personas"],
"keywords": ["agentworkforce-personas"],
"agentworkforce": {
"personas": "personas"
}
}
```

```text
@acme/personas/
├── package.json
└── personas/
├── reviewer.json
└── release-runner.json
```

`install` is a copy utility. Use it when a project should own and edit its
persona files. `sources add <dir>` is separate: it points the cascade at a live
directory and does not copy files.

Worked authoring flow:

```bash
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
git add .agentworkforce/workforce/personas/reviewer.json
```

### Local persona override

Project-local `./.agentworkforce/workforce/personas/my-posthog.json`:
Expand Down
152 changes: 152 additions & 0 deletions packages/cli/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ source.
agentworkforce agent <persona>[@<tier>]
agentworkforce list [flags]
agentworkforce show <persona>[@<tier>]
agentworkforce install [flags] <pkg|path>
agentworkforce sources <list|add|remove>
agentworkforce harness check
```
Expand All@@ -17,6 +18,8 @@ agentworkforce harness check
- `list` — print the persona catalog as a table (or JSON). See
[`## List`](#list) below for every flag.
- `show` — print the resolved spec for one persona.
- `install` — copy persona JSON files from an npm or local persona pack into
the current project's fixed cwd source directory.
- `sources` — list, add, or remove persona source directories.
- `harness check` — probe which harnesses (`claude`, `codex`, `opencode`)
are installed. See [`## Harness check`](#harness-check) below.
Expand DownExpand Up@@ -68,6 +71,150 @@ agentworkforce agent posthog@best
agentworkforce agent my-posthog@best
```

## Install persona packs

```text
agentworkforce install <pkg|path> [--persona <id> ...] [--overwrite]
```

`install` is a shadcn-style copy utility for persona JSON. It copies persona
files into the current project's fixed cwd layer:
`<cwd>/.agentworkforce/workforce/personas/`.

Once copied, files are project-owned. Edit them directly and commit them to
git. The CLI does not create an install ledger, lockfile, manifest, update
command, uninstall command, diff command, or central AgentWorkforce registry.

### Package and path forms

Npm package specs are resolved with `npm pack`, so npm auth, npm config,
private packages, tags, and versions work the same way they do for npm:

```sh
agentworkforce install @agentrelay/personas
agentworkforce install @agentrelay/personas@1.2.3
agentworkforce install @agentrelay/personas@latest
```

Local path installs read directly from the directory:

```sh
agentworkforce install ./local-personas
agentworkforce install /absolute/path/to/local-personas
```

### Selecting personas

By default, every `*.json` file in the pack's persona directory is copied.
Use repeated `--persona <id>` flags to install a subset by persona `id`:

```sh
agentworkforce install @agentrelay/personas --persona relay-orchestrator
agentworkforce install @agentrelay/personas --persona relay-orchestrator --persona code-reviewer
```

If any requested id is missing, the command exits non-zero before copying
anything.

### Conflicts and overwrite

Target filenames are flattened into the cwd persona directory:

```text
package/personas/nested/code-reviewer.json
-> .agentworkforce/workforce/personas/code-reviewer.json
```

If the target file already exists, the installer reports a conflict, skips
that file, and exits non-zero. Non-conflicting files from the same run may
still be copied. Pass `--overwrite` to replace existing files unconditionally:

```sh
agentworkforce install @agentrelay/personas --overwrite
```

Filename collisions across packages use the same rule. The install layer does
not namespace files by package; avoid shipping two pack files with the same
basename if they are expected to be installed together.

### Persona pack format

A pack can contain multiple personas:

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

`package.json` may declare the persona directory:

```json
{
"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 use a top-level `personas/` directory.
3. Recursively copy every `*.json` file from that directory, flattening to
`<cwd>/.agentworkforce/workforce/personas/<basename>.json`.

Local path installs use the same metadata rules.

### Relationship to sources

Use `install` when this project should receive editable copies:

```sh
agentworkforce install @acme/personas
git add .agentworkforce/workforce/personas
```

Use `sources add` when you want the cascade to point at a live directory
without copying:

```sh
agentworkforce sources add ~/src/acme-personas/personas
```

Both feed the same cascade. `install` writes to the fixed cwd layer, while
`sources` changes the configured source directories in
`~/.agentworkforce/workforce/config.json`.

### Author and publish a persona pack

```sh
mkdir -p acme-personas/personas
cd acme-personas
npm init -y
npm pkg set name=@acme/personas version=1.0.0
npm pkg set 'files[0]=personas' 'keywords[0]=agentworkforce-personas'
npm pkg set agentworkforce.personas=personas
$EDITOR personas/reviewer.json
npm publish --access public
```

Then install it in a project:

```sh
cd ../my-project
agentworkforce install @acme/personas --persona reviewer
agentworkforce list --filter-tag review
agentworkforce agent reviewer@best-value
```

## List

```
Expand DownExpand Up@@ -296,6 +443,11 @@ changes — `systemPrompt`, `harness`, and `harnessSettings` still come from the
base. Use top-level `systemPrompt` if you want to replace the prompt
uniformly across all tiers.

To define a standalone local persona that does not inherit from a lower layer,
include `intent` and a complete `tiers` object for `best`, `best-value`, and
`minimum`. This is the shape persona packs usually ship before `install`
copies them into the cwd layer.

## Env references & secrets

Any `env` value or `mcpServers.*.{headers,env,args,url,command}` value can be
Expand Down
19 changes: 19 additions & 0 deletions packages/cli/src/cli.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ import {
configureGitForMount,
decideCleanMode,
parseAgentArgs,
parseInstallArgs,
resolveSystemPromptPlaceholders,
stripAgentFlag
} from './cli.js';
Expand DownExpand Up@@ -94,6 +95,24 @@ test('parseAgentArgs: -- stops flag parsing, positional args after are preserved
assert.deepEqual(positional, ['--install-in-repo', 'posthog']);
});

test('parseInstallArgs: accepts package specs, repeatable persona flags, and overwrite', () => {
assert.deepEqual(
parseInstallArgs([
'@scope/pkg@1.2.3',
'--persona',
'relay-orchestrator',
'--persona',
'code-reviewer',
'--overwrite'
]),
{
source: '@scope/pkg@1.2.3',
personaIds: ['relay-orchestrator', 'code-reviewer'],
overwrite: true
}
);
});

test('decideCleanMode: claude defaults to mount (parity with opencode)', () => {
// claude and opencode both default to the sandbox mount; the includeGit
// path in relayfile 0.6 keeps `.git` in the mount so git operations work
Expand Down
Loading
Loading