Skip to content
Closed
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
91 changes: 1 addition & 90 deletions .claude/commands/gm-doctor.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ test -d "$LOCAL_PROJECT_DIR/channel/node_modules" && echo "DEPS_INSTALLED" || ec
```
Report WARN: "Installed missing channel dependencies."

4. **If channel exists, check for drift** — compare deployed channel against the plugin template (same approach as nono drift detection in Check 9). If the template is newer, update the deployed file and report WARN.
4. **If channel exists, check for drift** — compare deployed channel against the plugin template. If the template is newer, update the deployed file and report WARN.

5. **Check the shell alias** includes `--dangerously-load-development-channels server:taskyou`. This is the one step that doesn't self-heal, so make it as close to one-click as possible:
```bash
Expand Down Expand Up @@ -431,94 +431,6 @@ ssh -o ConnectTimeout=5 "$SERVER_HOST" '$HOME/.local/bin/audit.sh' 2>/dev/null

---

## Check 9: Credential Isolation (nono)

This check verifies if nono is set up, and if not, strongly recommends it. Always run this check regardless of whether credentials are currently configured.

1. **Check if nono is set up on the server:**
- nono binary installed: `ssh "$SSH_TARGET" 'command -v nono'`
- Profile deployed: `ssh "$SSH_TARGET" 'test -f ~/.config/nono/profiles/taskyou-agent.json'`
- nono-exec exists: `ssh "$SSH_TARGET" 'test -x ~/.local/bin/nono-exec'`
- At least one executor stub in `~/bin/`: `ssh "$SSH_TARGET" 'test -x ~/bin/claude'`

2. **If nono IS set up**, verify health:
- Check nono version: `ssh "$SSH_TARGET" 'nono --version'`
- Verify profile exists
- Verify nono-exec exists (if missing, this is an old "fat wrapper" deployment — needs update)
- Verify at least one executor stub exists in `~/bin/`
- Check kernel supports Landlock: `ssh "$SSH_TARGET" 'uname -r'` (needs >= 5.13)
- Report PASS with nono version and number of wrapped executors

3. **Drift detection** — if nono IS set up, check whether deployed files match current templates:

a. Find the TaskYou-OS plugin directory (or repo checkout):
```bash
# Check if we're in the taskyou-os repo
TASKYOU_OS_DIR=""
if [ -f "./templates/nono-exec.sh.tmpl" ]; then
TASKYOU_OS_DIR="."
else
PLUGIN_DIR=$(python3 -c "import json; d=json.load(open('$HOME/.claude/plugins/installed_plugins.json')); entries=d.get('plugins',{}).get('taskyou-os@taskyou-os',[]); print(entries[0]['installPath'] if entries else '')" 2>/dev/null)
if [ -n "$PLUGIN_DIR" ] && [ -f "$PLUGIN_DIR/templates/nono-exec.sh.tmpl" ]; then
TASKYOU_OS_DIR="$PLUGIN_DIR"
fi
fi
```

b. If templates are available, render `nono-exec.sh.tmpl` and `nono-profile.json.tmpl` locally (using the user's config.env), then compare against the deployed versions on the server via SSH:
```bash
# Render locally to /tmp, then diff against remote
# For nono-exec:
ssh "$SSH_TARGET" 'cat ~/.local/bin/nono-exec' > /tmp/doctor-nono-exec-remote.sh
diff /tmp/doctor-nono-exec-local.sh /tmp/doctor-nono-exec-remote.sh

# For profile:
ssh "$SSH_TARGET" 'cat ~/.config/nono/profiles/taskyou-agent.json' > /tmp/doctor-nono-profile-remote.json
diff /tmp/doctor-nono-profile-local.json /tmp/doctor-nono-profile-remote.json
```

c. If either file differs:
- Show a brief summary of what changed (don't dump entire diffs — just note which file and whether it's a minor or structural change)
- Update automatically: scp the freshly rendered versions to the server
- Report WARN with "Updated nono-exec/profile to match current templates"

d. If nono-exec doesn't exist at all (old "fat wrapper" deployment):
- Report WARN: "nono-exec not found — this server has old fat wrappers that need migration"
- Explain: re-run `./setup.sh server` (or `./setup.sh exe`) to deploy the new nono-exec + thin stubs

4. **If nono is NOT set up**, strongly recommend it:
- Report WARN
- Explain clearly:
```
⚠ nono credential isolation is not configured.

nono is strongly recommended for all TaskYou deployments. It provides
kernel-enforced sandboxing so agents can USE credentials via a secure
proxy but can never SEE or extract the raw keys — even if compromised
via prompt injection.

To enable:
1. Add these to your config.env:
NONO_ENABLED="true"
NONO_CREDENTIALS="linear:LINEAR_API_KEY,github:GITHUB_TOKEN"
NONO_PROXY_HOSTS="api.linear.app,api.github.com"
2. Re-run: ./setup.sh server <your-project-dir>

Learn more: https://github.com/always-further/nono
```
- Ask: "Would you like me to help you configure nono now?"
- If yes:
- Read the user's config.env
- Detect which credential variables are set (LINEAR_API_KEY, GITHUB_TOKEN, etc.)
- Propose the appropriate NONO_CREDENTIALS and NONO_PROXY_HOSTS values
- Ask for confirmation before modifying config.env
- If confirmed, add the nono variables to config.env
- Tell the user to re-run `./setup.sh server` to apply

**Important:** Never print or display actual credential values. Only check for their existence.

---

## Summary

After all checks, present a summary table:
Expand All @@ -534,7 +446,6 @@ TaskYou-OS Doctor
GM templates PASS/WARN/FAIL
Task event channel PASS/WARN/FAIL
Security audit PASS/WARN/FAIL
Credential isolation PASS/WARN
─────────────────────────────────
```

Expand Down
2 changes: 0 additions & 2 deletions .claude/commands/launch.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ Have a conversation about what they're building. The goal is to understand their
Also ask:
5. **Do they need GitHub?** Only needed if agents will be pushing code to GitHub repositories. For research/analysis/content projects, the answer is usually no.
6. **Linear** (task escalation to humans) or **R2** (hosting generated files) — skip unless they know what these are or have a clear need.
7. **Credential isolation (nono):** If the agents will use external APIs (SaaS services, databases, etc.) now or in the future, recommend enabling nono. Explain it simply: "This keeps your API keys locked in a secure vault on the server. Your agents can use the APIs they need, but they never see the raw passwords or keys — they're injected automatically behind the scenes." Default to enabling it — it's safe to turn on even before any credentials are added. Set `NONO_ENABLED="true"` in config.env. Credentials and proxy hosts can be added later as integrations are set up.

Present your recommendations and get confirmation. Then move to Phase 2.

Expand Down Expand Up @@ -261,7 +260,6 @@ Use everything from Phase 1 (project name, workspaces, alias, etc.) and Phase 2
If Linear was chosen, collect: API key, team ID, team key, label ID, state ID, workspace URL.
If R2 was chosen, collect: bucket name, public URL.
If GitHub repos are needed, collect the `workspace:org/repo` mappings.
If nono was chosen (recommended), set `NONO_ENABLED="true"` in config.env. The `NONO_CREDENTIALS` and `NONO_PROXY_HOSTS` can be left commented out for now — they're added later when actual API integrations are configured.

### Create the project directory:
```bash
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.claude/settings.local.json
.worktrees/
.task-worktrees
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,14 @@ Run `/taskyou-os:doctor` from any directory. It checks and updates everything au
6. **CLAUDE.md drift** — detects new sections in the plugin template and offers to add them to your GM
7. **Task event channel** — deploys the push-notification channel to a GM that predates it (renders `channel/`, installs deps, writes `.mcp.json`) and offers to add the channel flag to your launch alias
8. **Security audit** — runs the server-side credential and permissions check
9. **Credential isolation** — verifies nono sandbox setup and detects template drift

If `/doctor` finds issues, it fixes what it can and tells you what to do for the rest.

> **Enabling push notifications on an existing GM:** task events now arrive automatically as `<channel>` messages instead of needing a polling agent. Update the plugin, then run `/taskyou-os:doctor` — it deploys the channel and offers to add the required flag to your launch alias. After the alias change, **restart the GM** so the channel loads. (Channels are in research preview: they need Claude Code 2.1.80+ and a claude.ai login.)

### Update the Server

If you need to re-deploy server-side files (hooks, scripts, nono config) after a plugin update:
If you need to re-deploy server-side files (hooks, scripts) after a plugin update:

```bash
./setup.sh server ~/Projects/gms/myproject
Expand All @@ -155,7 +154,6 @@ These are configured via flags in `config.env` during setup. They're part of the
- **Slack** (`SLACK_ENABLED=true`) — Manage TaskYou from Slack: task events pushed to Slack, `@mentions`/DMs drive `ty` ([details](modules/slack/README.md))
- **Cloudflare R2** (`R2_ENABLED=true`) — Public URLs for files and assets agents generate
- **GitHub** (`GITHUB_REPOS=workspace:org/repo`) — Push agent work to your repositories
- **nono** (`NONO_ENABLED=true`) — Credential isolation for agents via sandboxed executor wrappers

## Manual Setup

Expand Down
19 changes: 0 additions & 19 deletions config.example.env
Original file line number Diff line number Diff line change
Expand Up @@ -96,22 +96,3 @@ PROJECT_DESCRIPTION="My Project does X, Y, and Z."

# EXE_DEV_ENABLED="true"
# EXE_DEV_VM_NAME="myproject-gm"

# === Optional: Credential isolation (nono) ===
# Set NONO_ENABLED=true to sandbox agents and isolate credentials.
# Credentials are stored in the Linux Secret Service on the server.
# Agents access them via nono's phantom token proxy — raw keys never
# enter agent memory or the filesystem.
# Requires Linux kernel 5.13+ (Landlock support).

# NONO_ENABLED="true"

# Credentials to proxy (name:ENV_VAR pairs, comma-separated).
# On servers with D-Bus/Secret Service, credentials are stored securely there.
# On headless servers (e.g. exe.dev VMs), credentials fall back to
# ~/.config/nono/secrets.env (chmod 600), sourced by nono-exec before sandboxing.
# NONO_CREDENTIALS="linear:LINEAR_API_KEY,github:GITHUB_TOKEN"

# Hosts agents can reach through the credential proxy.
# Only these hosts receive injected credentials.
# NONO_PROXY_HOSTS="api.linear.app,api.github.com"
3 changes: 1 addition & 2 deletions modules/slack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@ GM's `config.env` yourself and run `./setup.sh server <gm>` (or `exe`).
- **Socket Mode** uses an authenticated WebSocket; there's no inbound HTTP
endpoint to expose or verify.
- **No code execution from chat** — the LLM only *classifies*; the bridge only
shells out to `ty`. Pair with `nono` (`NONO_ENABLED`) for executor credential
isolation.
shells out to `ty`.
- **Local secrets** — tokens live in `~/scripts/slack/.env` (chmod 600), never
sent to the LLM.

Expand Down
Loading