Team Directory — shared skills, personas & prompts (local folder)¶
Nyia Keeper shares team resources through a team directory: a regular folder on disk that you keep in
sync however you like (git, Dropbox, NFS, a symlink — your choice). Nyia only reads it. It carries
skills, personas (agents), and prompt overlays — the resources the assistant uses. (It does not carry
config values: command-mode and the RAG model must never be silently inherited from a shared source.)
How to sync it is up to you, and that's the review gate. If you keep the folder in git, your own
git pull is where you see the diff before new team content reaches your assistants — a deliberate
human checkpoint.
Trust model (honest). Shared team content is a trust decision, the same as trusting any shared codebase you point an AI tool at: a teammate with write access can add content, and no tool can tell you in advance whether that content is well-intentioned — this is the git-shared-repo + AI threat model, not something specific to Nyia. What Nyia does protect against, today, is the propagation mechanism being abused: a shared item cannot smuggle a symlink or a traversal path to exfiltrate files from your host (see the Security model). Content-level review of shared skills/prompts is planned next (an on-device guard model).
Quick Start¶
- Create a shared directory with the expected structure:
- Configure Nyia Keeper to use it:
- Verify it works:
nyia status # Shows team directory info
nyia-claude --list-skills # Team skills appear under "Team skills"
nyia-claude --list-agents # Team agents appear under "Team agents"
Directory Structure¶
The team directory follows the same layout as .nyiakeeper/shared/:
/path/to/team-shared/
├── skills/ # Shared skills (each needs SKILL.md)
│ ├── code-review/
│ │ └── SKILL.md
│ └── pair-review/
│ └── SKILL.md
├── agents/ # Shared agent personas
│ ├── reviewer.md # Claude agent (Markdown)
│ └── architect.md
└── prompts/ # Shared prompt overlays
└── team-guidelines.md
Skills¶
Each skill is a subdirectory containing a SKILL.md file. Skills are automatically discovered and listed by
--list-skills. Project-shared skills and agents (.nyiakeeper/shared/) are staged for each session inside
the container and handed to the assistant there; nothing is copied into the project's .claude/,
.opencode/ or .vibe/ any more, so an edit to a shared skill reaches the next session of every teammate.
Team and user skills (team directory, ~/.config/nyiakeeper/skills/) are still copied into the assistant's
global skills directory at launch.
Precedence matrix per assistant¶
When two copies of a skill share a NAME, each assistant decides which one it shows. Measured on 2026-10-31 (claude 2.1.289, codex-cli 0.160.1, opencode 1.18.34: Plan 393 spike S1; vibe 3.0.4: Plan 393 follow-up, in a real session):
| Assistant | Built-in nyia-* and team/user copies (global skills dir) |
Project-shared (.nyiakeeper/shared/skills, staged) |
Project's own (.<cli>/skills, .agents/skills) |
Same name in several places |
|---|---|---|---|---|
| Claude | ~/.claude/skills — wins |
--add-dir session dir — loses to both others |
.claude/skills — beats project-shared (.agents/skills is not read) |
global > project's own > project-shared; one copy shown |
| Codex | ~/.codex/skills |
~/.agents/skills |
.agents/skills, .codex/skills |
every copy is listed (no de-duplication) |
| OpenCode | ~/.config/opencode/skills |
~/.agents/skills — loses to all others |
.opencode/skills — wins, then .agents/skills, then .claude/skills |
project's own > global > project-shared |
| Vibe | ~/.vibe/skills |
~/.agents/skills — loses to all others |
.vibe/skills — wins, then .agents/skills (trusted folders only) |
project's own > global > project-shared; one copy shown |
Overriding a built-in: put your version under the SAME name in the team directory or your user skills
(~/.config/nyiakeeper/skills/): that unmarked copy in the global skills directory is kept by the installer and
is what Claude, OpenCode and Vibe show. A project-shared skill cannot override a built-in on Claude, OpenCode or
Vibe.
Recommendation: give team and project-shared skills a different name from the built-in nyia-* ones
(for example team-review, not nyia-code-review). Then every assistant shows both, and nothing depends on
the per-assistant order above. Codex note: built-ins are installed in ~/.codex/skills, which current Codex
still reads but no longer documents; if a Codex update stops reading it, the built-ins disappear for Codex only.
Agents¶
Agent personas are assistant-specific files placed directly in the agents/ directory. File formats vary by assistant:
| Assistant | Format | Example |
|---|---|---|
| Claude | *.md |
reviewer.md |
| OpenCode | *.md, *.json |
architect.md |
| Vibe | *.toml |
debugger.toml |
| Codex | Config-based | (uses ~/.codex/config.toml sections) |
Project-shared agents reach Claude (*.md) and OpenCode (*.md, *.json) only:
vibe and codex get no shared agents (vibe agents are TOML profiles, codex agents live in its config).
A README.md is never an agent.
Prompts¶
Prompt overlays placed in prompts/ are propagated to each assistant at launch. Use these for team-wide coding guidelines, review checklists, or domain-specific instructions.
No
config/. A team directory does not carry config values (command-mode, RAG model). Those are deliberately excluded so a shared source can never silently change how much the agent is allowed to do — set them locally withnyia config.
Precedence¶
For agents and prompts, Nyia resolves the sources in this order (higher wins):
1. Project-local (the assistant's own project files, e.g. .claude/agents/)
2. Project-shared (.nyiakeeper/shared/, staged per session)
3. Team (team_dir/skills/, team_dir/agents/, etc.)
4. Global user (~/.config/nyiakeeper/skills/, etc.)
Team resources shadow global user resources (no-clobber copy). For SKILLS the assistant itself decides between same-name copies: see the precedence matrix above, and prefer distinct names.
Configuration¶
Setting the team directory¶
# Set for all projects (global config)
nyia config global team_dir=/path/to/team-shared
# View current configuration
nyia config global --list
The key is stored as NYIA_TEAM_DIR in ~/.config/nyiakeeper/config/nyia.conf.
Checking team status¶
This shows: - Whether a team directory is configured - Whether the directory exists on disk - Which subdirectories are present (skills, agents, prompts)
Security¶
- The team directory is read-only from Nyia Keeper's perspective -- it never writes to it.
- No secrets or credentials should be placed in the team directory.
- Propagation is guarded (see the Security model): a shared skill/agent/prompt that is a symlink, contains a nested symlink, or uses a traversal path is refused — it cannot be used to read files from your host. This is a structural guard, not content review.
- Content is a trust decision. The guard above stops the mechanism being abused; it does not judge whether a shared prompt's text is safe. Treat a shared source like any shared repo you'd point an AI tool at. On-device content review is planned next.
Sync Strategies¶
Nyia Keeper does not manage synchronization of the team directory. Common approaches:
| Strategy | Pros | Cons |
|---|---|---|
| Git repository | Version history, PR review | Requires git workflow |
| Dropbox/Google Drive | Automatic sync, no setup | No version control |
| NFS/SMB mount | Real-time access | Requires network infrastructure |
| Symlink to monorepo subdirectory | Zero-copy, always current | Ties to monorepo |
Team news (/nyia-whatsup)¶
/nyia-whatsup is a different class — news, not resources. The team directory (above) makes resources
available; /nyia-whatsup makes changes to them discoverable: when a teammate ships a new skill, edits a
prompt, or changes a convention, they publish a short news entry (committed to the project's git), and
everyone else sees it instead of finding out by accident.
"Nyia" (にゃ) is the cat that watches your code —
/nyia-whatsupis the cat telling you what changed.
Commands¶
| Command | What it does |
|---|---|
/nyia-whatsup |
Show news entries you haven't read yet, newest/most severe first |
/nyia-whatsup add |
Publish a news entry (draft → confirm → commit) |
/nyia-whatsup list |
List all entries with a read / unread / hidden marker |
/nyia-whatsup ack <id> |
Acknowledge an entry (dismisses a breaking warning) |
/nyia-whatsup hide <id> |
Permanently hide an entry ("not for me") |
How entries are stored¶
Each entry is a single markdown file with YAML frontmatter, committed to the project so the team shares it via git:
.nyiakeeper/whatsup/
├── entries/2026/06/2026-06-04-a3f-001.md # one file per entry (committed)
└── .seen.json # your per-machine read state (gitignored)
One file per entry means two people can publish at the same time without merge
conflicts. Your read state (.seen.json) is per-machine and never committed.
Outside a Nyia project (no .nyiakeeper/), /nyia-whatsup still works in standalone
mode, storing entries under .whatsup/ with manual invocation only.
Severity levels¶
- info — inline note, low priority.
- important — pulled to the top of the list.
- breaking — shown in a loud visual box and stays flagged on every read
until you run
/nyia-whatsup ack <id>. V1 is a visual warning only; it does not block.
Automatic news at session start (opt-in)¶
/nyia-whatsup integrates with the /nyia-kickoff and /nyia-checkpoint skills, but only when
enabled in config (default: off):
# Enable whatsup and surface unread news automatically at session start
nyia config global whatsup_enabled=true
nyia config global whatsup_auto_read=kickoff
| Config key | Values | Default | Effect |
|---|---|---|---|
whatsup_enabled (NYIA_WHATSUP_ENABLED) |
true | false |
false |
Master switch for lifecycle hooks |
whatsup_auto_read (NYIA_WHATSUP_AUTO_READ) |
kickoff | never |
never |
Show unread news during /nyia-kickoff |
When enabled, /nyia-checkpoint also detects when a session changed meta-files
(skills, prompts, shared config) and offers to publish a /nyia-whatsup entry.
Security¶
- No secrets in entries. Entries are committed and shared, so
/nyia-whatsup addsummarizes changes by file path and your own words only — it never dumps config, prompt, credential, or.envcontents into an entry. - Publishing stages only the new entry file (never
git add .), and shows you the staged diff before committing.
Troubleshooting¶
"Team dir configured but does not exist"¶
The path in your config does not exist on disk. Check:
"Team dir configured but has no content"¶
The directory exists but contains none of the expected subdirectories (skills/, agents/, prompts/). Create at least one:
Team skills/agents not appearing¶
- Verify the team directory is configured:
nyia config global --list - Check that skills have a
SKILL.mdfile in their subdirectory - Check that agent files use the correct format for your assistant
- Check precedence: a project-local resource with the same name takes priority
Testing team sharing (helper script)¶
A self-contained smoke test verifies the whole feature end-to-end without touching your
real config (it runs in an isolated temporary NYIAKEEPER_HOME).
File: scripts/test-team-sharing.sh
Run it (host or inside the Vagrant VM, from the repo root):
scripts/test-team-sharing.sh # dev edition (./bin)
NYIA_BIN_DIR=dist/runtime/bin scripts/test-team-sharing.sh # runtime edition
NYIA_ASSISTANT=codex scripts/test-team-sharing.sh # a different assistant (default: claude)
Exit code 0 = all checks passed.
What it checks:
1. nyia config global team_dir=… sets the team directory, and nyia config view shows it.
2. nyia status surfaces the team directory.
3. nyia-<assistant> --list-skills / --list-agents discover the sample team skill/agent.
4. A project-shared skill of the same name resolves (project-over-team precedence path).
In the Vagrant VM: the repo is mounted at /dockerized-assistants-src; run
/dockerized-assistants-src/scripts/test-team-sharing.sh (or cd there first). Use
NYIA_BIN_DIR=/dockerized-assistants-src/dist/runtime/bin to exercise the shipped (runtime) edition.
Note:
nyia config get <key>currently supports onlyhome/config/data, not the registered config keys — usenyia config viewto inspect key values. (Tracked for the config-dispatcher convergence work.)