Mount project root for main channel

- Main gets /workspace/project with full project access
- Main can query SQLite database and edit configs
- Updated main CLAUDE.md with container paths
- Added docs for configuring additional mounts per group

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gavrielc
2026-01-31 23:01:45 +02:00
parent ef24c45413
commit 0ccdaaac48
2 changed files with 88 additions and 39 deletions

View File

@@ -1,11 +1,20 @@
# Main Channel - Admin Context # Main Channel - Admin Context
You are running in the **main channel**, which has elevated privileges. You can: You are running in the **main channel**, which has elevated privileges.
- Manage registered groups (add, remove, list)
- Schedule tasks for any group ## Container Mounts
- View tasks from all groups
- Access all group folders Main has access to the entire project:
- **Run Bash commands** (only main has this access)
| Container Path | Host Path | Access |
|----------------|-----------|--------|
| `/workspace/project` | Project root | read-write |
| `/workspace/group` | `groups/main/` | read-write |
Key paths inside the container:
- `/workspace/project/store/messages.db` - SQLite database
- `/workspace/project/data/registered_groups.json` - Group config
- `/workspace/project/groups/` - All group folders
--- ---
@@ -13,25 +22,22 @@ You are running in the **main channel**, which has elevated privileges. You can:
### Finding Available Groups ### Finding Available Groups
Groups appear in the database when messages are received. Query the SQLite database to find groups: Groups appear in the database when messages are received. Query the SQLite database:
```sql ```bash
-- Find all group chats (JIDs ending in @g.us) sqlite3 /workspace/project/store/messages.db "
SELECT DISTINCT chat_jid, name FROM chats WHERE chat_jid LIKE '%@g.us'; SELECT DISTINCT chat_jid, MAX(timestamp) as last_message
-- Or find chats with recent messages
SELECT chat_jid, MAX(timestamp) as last_message
FROM messages FROM messages
WHERE chat_jid LIKE '%@g.us' WHERE chat_jid LIKE '%@g.us'
GROUP BY chat_jid GROUP BY chat_jid
ORDER BY last_message DESC; ORDER BY last_message DESC
LIMIT 10;
"
``` ```
Database location: `store/messages.db`
### Registered Groups Config ### Registered Groups Config
Groups are registered in `data/registered_groups.json`: Groups are registered in `/workspace/project/data/registered_groups.json`:
```json ```json
{ {
@@ -54,10 +60,10 @@ Fields:
### Adding a Group ### Adding a Group
1. Query the database to find the group's JID 1. Query the database to find the group's JID
2. Read the current `data/registered_groups.json` 2. Read `/workspace/project/data/registered_groups.json`
3. Add the new group entry 3. Add the new group entry with `containerConfig` if needed
4. Write the updated JSON back 4. Write the updated JSON back
5. Create the group folder: `groups/{folder-name}/` 5. Create the group folder: `/workspace/project/groups/{folder-name}/`
6. Optionally create an initial `CLAUDE.md` for the group 6. Optionally create an initial `CLAUDE.md` for the group
Example folder name conventions: Example folder name conventions:
@@ -65,22 +71,48 @@ Example folder name conventions:
- "Work Team" → `work-team` - "Work Team" → `work-team`
- Use lowercase, hyphens instead of spaces - Use lowercase, hyphens instead of spaces
#### Adding Additional Directories for a Group
Groups can have extra directories mounted. Add `containerConfig` to their entry:
```json
{
"1234567890@g.us": {
"name": "Dev Team",
"folder": "dev-team",
"trigger": "@Andy",
"added_at": "2026-01-31T12:00:00Z",
"containerConfig": {
"additionalMounts": [
{
"hostPath": "/Users/gavriel/projects/webapp",
"containerPath": "webapp",
"readonly": false
}
]
}
}
}
```
The directory will appear at `/workspace/extra/webapp` in that group's container.
### Removing a Group ### Removing a Group
1. Read `data/registered_groups.json` 1. Read `/workspace/project/data/registered_groups.json`
2. Remove the entry for that group 2. Remove the entry for that group
3. Write the updated JSON back 3. Write the updated JSON back
4. The group folder and its files remain (don't delete them) 4. The group folder and its files remain (don't delete them)
### Listing Groups ### Listing Groups
Read `data/registered_groups.json` and format it nicely for the user. Read `/workspace/project/data/registered_groups.json` and format it nicely.
--- ---
## Global Memory ## Global Memory
You can read and write to `groups/CLAUDE.md` (the parent directory) for facts that should apply to all groups. Only update global memory when explicitly asked to "remember this globally" or similar. You can read and write to `/workspace/project/groups/CLAUDE.md` for facts that should apply to all groups. Only update global memory when explicitly asked to "remember this globally" or similar.
--- ---

View File

@@ -44,23 +44,40 @@ interface VolumeMount {
function buildVolumeMounts(group: RegisteredGroup, isMain: boolean): VolumeMount[] { function buildVolumeMounts(group: RegisteredGroup, isMain: boolean): VolumeMount[] {
const mounts: VolumeMount[] = []; const mounts: VolumeMount[] = [];
const homeDir = process.env.HOME || '/Users/gavriel'; const homeDir = process.env.HOME || '/Users/gavriel';
const projectRoot = process.cwd();
// Group's working directory (read-write) if (isMain) {
// Main gets the entire project root mounted
mounts.push({
hostPath: projectRoot,
containerPath: '/workspace/project',
readonly: false
});
// Main also gets its group folder as the working directory
mounts.push({
hostPath: path.join(GROUPS_DIR, group.folder),
containerPath: '/workspace/group',
readonly: false
});
} else {
// Other groups only get their own folder
mounts.push({ mounts.push({
hostPath: path.join(GROUPS_DIR, group.folder), hostPath: path.join(GROUPS_DIR, group.folder),
containerPath: '/workspace/group', containerPath: '/workspace/group',
readonly: false readonly: false
}); });
// Global CLAUDE.md (read-only for non-main, read-write for main) // Global CLAUDE.md (read-only for non-main)
const globalClaudeMd = path.join(GROUPS_DIR, 'CLAUDE.md'); const globalClaudeMd = path.join(GROUPS_DIR, 'CLAUDE.md');
if (fs.existsSync(globalClaudeMd)) { if (fs.existsSync(globalClaudeMd)) {
mounts.push({ mounts.push({
hostPath: globalClaudeMd, hostPath: globalClaudeMd,
containerPath: '/workspace/global/CLAUDE.md', containerPath: '/workspace/global/CLAUDE.md',
readonly: !isMain readonly: true
}); });
} }
}
// Claude sessions directory (for session persistence) // Claude sessions directory (for session persistence)
const claudeDir = path.join(homeDir, '.claude'); const claudeDir = path.join(homeDir, '.claude');