Company Messaging — Skill (Branch-Based v3)
SkillCommunicationUse when sending encrypted internal messages between organization members via Company Savia.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Company Messaging — Skill (Branch-Based v3) skill
What this skill tells your AI
The instructions your AI receives, as published by gonzalezpazmonica/pm-workspace in .claude/skills/company-messaging/SKILL.md and read by ahel’s review.
Overview
Company Savia enables async messaging between users across a company using orphan Git branches. Messages are plain markdown files with YAML frontmatter, stored in personal inboxes and a pub/sub exchange branch.
Branch Architecture
main (orphan)
├── company/identity.md, org-chart.md
├── pubkeys/user/{handle}.pem
└── .savia-index/users.idx
user/{handle} (orphan)
├── inbox/unread/ ← Personal messages (unread)
├── inbox/read/ ← Personal messages (archive)
└── outbox/ ← Sent message archive
exchange (orphan)
└── pub/sub/pending/
├── {msg_id}.md ← Pending delivery (temp)
└── .index ← Routing table by recipient
team/{name} (orphan)
└── (shared team resources)
Message Lifecycle
- Compose: Create message with YAML frontmatter
- Encrypt (optional): RSA-4096 + AES-256-CBC via
savia-crypto.sh - Deliver: Write to
exchange:pub/sub/pending/{msg_id}.md - Sync:
git add + commit + pushto exchange branch - Pull: Recipient syncs and fetches from
exchange:pub/sub/pending/ - Move: Transfer to
user/{handle}/inbox/unread/ - Read: User moves to
user/{handle}/inbox/read/ - Archive: Old messages can be purged per retention policy
Fetch-Messages Workflow
git show exchange:pub/sub/pending/{msg_id}.md | decrypt | move to user/{handle}/inbox/unread/
No need to checkout exchange branch — just git show.
@Handle Resolution
Handles are resolved from main:company/directory.md (admin-only):
| Handle | Name | Role | Status |
|--------|------|------|--------|
| @admin | Admin Name | Admin | active |
Pubkeys stored at main:pubkeys/user/{handle}.pem.
Encryption Protocol
Hybrid RSA-4096 + AES-256-CBC (openssl only, zero deps):
- Keygen:
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 - Encrypt: Random AES-256 key → encrypt body → encrypt AES key with recipient RSA pubkey
- Store: Base64-encoded
encrypted_key:::encrypted_bodyin frontmatter - Decrypt: RSA-decrypt AES key (private.pem: chmod 600) → AES-decrypt body
Public keys auto-published to main:pubkeys/user/{handle}.pem by admin script.
Privacy Rules
Before any git push:
- Layer 1:
validate_privacy()— PATs, tokens, IPs, connection strings - Layer 2: Scan YAML frontmatter and body for secrets
- Layer 3: Verify subject line has no sensitive data (see messaging-subject-safety.md)
Script: scripts/privacy-check-company.sh
Message Types
| Type | Location | Persist | Encrypted |
|---|---|---|---|
| Direct message | exchange:pending → user/{handle}/inbox/unread/ | 7 days | Optional |
| Reply | user/{handle}/inbox/ | Until archived | Optional |
| Broadcast | exchange:pending (deliver to each user/{handle}) | 7 days | Optional |
| Announcement | main:company/announcements/ | Permanent | Never |
Threading
Messages form threads via YAML frontmatter:
thread: ID of first messagereply_to: ID of message being replied to
Replies auto-inherit thread from parent.
Read Tracking
- Personal messages: moved from
unread/toread/on user branch - Announcements: tracked in
$HOME/.pm-workspace/company-inbox-read.log
Scripts
| Script | Purpose |
|---|---|
scripts/savia-branch.sh | Abstraction layer for branch operations |
scripts/savia-messaging.sh | Message CRUD (create, fetch, deliver, archive) |
scripts/savia-crypto.sh | E2E encryption (RSA+AES) |
scripts/privacy-check-company.sh | Privacy validation pre-push |
Worktree Pattern
Writes use temporary worktrees to avoid checkout pollution:
git worktree add .claude/worktrees/{temp} user/{handle}
# Write/edit files
git add && git commit && git push
git worktree remove .claude/worktrees/{temp}
Session-Init Integration
Unread count from user/{handle}/inbox/unread/ (local, no network):
📬 3 unread messages · 1 pending broadcast
Signals
- GitHub stars
- 50
- Forks
- 12
- Last commit
- Sep 2026
Others that do the same job
Advanced
- Catalog kind
- skill
- Gateway key
company-messaging- Source
- github.com/gonzalezpazmonica/pm-workspace