diff --git a/.claude/commands/gm-doctor.md b/.claude/commands/gm-doctor.md index 9cb4b97..7a773a9 100644 --- a/.claude/commands/gm-doctor.md +++ b/.claude/commands/gm-doctor.md @@ -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 @@ -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 - - 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: @@ -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 ───────────────────────────────── ``` diff --git a/.claude/commands/launch.md b/.claude/commands/launch.md index 661aa09..b8c44b3 100644 --- a/.claude/commands/launch.md +++ b/.claude/commands/launch.md @@ -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. @@ -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 diff --git a/.gitignore b/.gitignore index cb4f57e..4cc4cde 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .claude/settings.local.json .worktrees/ +.task-worktrees diff --git a/README.md b/README.md index aaff61b..0ac08cd 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,6 @@ 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. @@ -139,7 +138,7 @@ If `/doctor` finds issues, it fixes what it can and tells you what to do for the ### 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 @@ -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 diff --git a/config.example.env b/config.example.env index ef2469a..2878662 100644 --- a/config.example.env +++ b/config.example.env @@ -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" diff --git a/modules/slack/README.md b/modules/slack/README.md index cf2d5fe..28d6781 100644 --- a/modules/slack/README.md +++ b/modules/slack/README.md @@ -119,8 +119,7 @@ GM's `config.env` yourself and run `./setup.sh server ` (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. diff --git a/setup.sh b/setup.sh index ad0cc6c..b59a11c 100755 --- a/setup.sh +++ b/setup.sh @@ -254,9 +254,6 @@ export R2_PUBLIC_URL="${R2_PUBLIC_URL:-}" export GITHUB_REPOS="${GITHUB_REPOS:-}" export EXE_DEV_ENABLED="${EXE_DEV_ENABLED:-false}" export EXE_DEV_VM_NAME="${EXE_DEV_VM_NAME:-}" -export NONO_ENABLED="${NONO_ENABLED:-false}" -export NONO_CREDENTIALS="${NONO_CREDENTIALS:-}" -export NONO_PROXY_HOSTS="${NONO_PROXY_HOSTS:-}" export SLACK_ENABLED="${SLACK_ENABLED:-false}" export SLACK_BOT_TOKEN="${SLACK_BOT_TOKEN:-}" export SLACK_APP_TOKEN="${SLACK_APP_TOKEN:-}" @@ -266,24 +263,6 @@ export SLACK_PROJECT_MAP="${SLACK_PROJECT_MAP:-}" export SLACK_ANTHROPIC_API_KEY="${SLACK_ANTHROPIC_API_KEY:-}" export SLACK_CLASSIFIER_MODEL="${SLACK_CLASSIFIER_MODEL:-claude-haiku-4-5-20251001}" -# Generate nono proxy flags for wrapper scripts -if [[ "$NONO_ENABLED" == "true" && -n "$NONO_PROXY_HOSTS" ]]; then - NONO_PROXY_FLAGS="" - IFS=',' read -ra hosts <<< "$NONO_PROXY_HOSTS" - for host in "${hosts[@]}"; do - host=$(echo "$host" | xargs) - NONO_PROXY_FLAGS+="--proxy-allow $host " - done - IFS=',' read -ra creds <<< "$NONO_CREDENTIALS" - for cred in "${creds[@]}"; do - name=$(echo "$cred" | cut -d: -f1 | xargs) - NONO_PROXY_FLAGS+="--proxy-credential $name " - done - export NONO_PROXY_FLAGS -else - export NONO_PROXY_FLAGS="" -fi - # Generate dynamic table content export PROJECTS_TABLE PROJECTS_TABLE=$(generate_projects_table) @@ -380,159 +359,6 @@ setup_local() { } -# ── nono credential isolation ──────────────────────────────────────────────── - -setup_nono() { - local ssh_target="$1" - local remote_home="$2" - - log "Setting up nono credential isolation" - - # Install nono via .deb package (Ubuntu/Debian) - if ssh "$ssh_target" "command -v nono" >/dev/null 2>&1; then - ok "nono already installed" - else - log "Installing nono" - # Get latest version, download .deb, install - # The .deb filename varies between releases (with/without -1 suffix), so try both - ssh "$ssh_target" 'set -e - VERSION=$(curl -sI https://github.com/always-further/nono/releases/latest | grep -i location | grep -oP "v\K[0-9.]+") - echo "Installing nono v${VERSION}" - wget -q "https://github.com/always-further/nono/releases/download/v${VERSION}/nono-cli_${VERSION}-1_amd64.deb" -O /tmp/nono.deb 2>/dev/null \ - || wget -q "https://github.com/always-further/nono/releases/download/v${VERSION}/nono-cli_${VERSION}_amd64.deb" -O /tmp/nono.deb - sudo dpkg -i /tmp/nono.deb - rm -f /tmp/nono.deb' || { - warn "nono install failed. Install manually: https://nono.sh/docs/cli/getting_started/installation" - warn "Skipping credential isolation setup." - return 1 - } - ok "nono installed" - fi - - # Detect whether Secret Service (D-Bus) is available - # On headless servers (e.g. exe.dev VMs), secret-tool won't work - local has_secret_service=false - if ssh "$ssh_target" 'command -v secret-tool >/dev/null 2>&1 && secret-tool store --label="nono-test" service nono-test username test <<< "test" 2>/dev/null && secret-tool lookup service nono-test username test >/dev/null 2>&1' 2>/dev/null; then - has_secret_service=true - # Clean up test entry - ssh "$ssh_target" 'secret-tool clear service nono-test username test' 2>/dev/null || true - ok "Secret Service available" - else - warn "Secret Service not available (headless) — using secrets.env fallback" - fi - - # Store credentials - if [[ -n "$NONO_CREDENTIALS" ]]; then - if $has_secret_service; then - log "Storing credentials in Secret Service" - IFS=',' read -ra creds <<< "$NONO_CREDENTIALS" - for entry in "${creds[@]}"; do - local name env_var value - name=$(echo "$entry" | cut -d: -f1 | xargs) - env_var=$(echo "$entry" | cut -d: -f2 | xargs) - value="${!env_var:-}" - - if [[ -z "$value" ]]; then - warn "Skipping $name: $env_var is empty in config.env" - continue - fi - - # Pipe value via stdin to avoid credentials in process list - printf '%s' "$value" | ssh "$ssh_target" "secret-tool store --label='nono: $name' service nono username $name 2>/dev/null" || { - warn "Failed to store $name — secret-tool may need a D-Bus session" - continue - } - ok "credential: $name (from $env_var)" - done - else - log "Storing credentials in secrets.env (headless fallback)" - local secrets_content="" - IFS=',' read -ra creds <<< "$NONO_CREDENTIALS" - for entry in "${creds[@]}"; do - local name env_var value - name=$(echo "$entry" | cut -d: -f1 | xargs) - env_var=$(echo "$entry" | cut -d: -f2 | xargs) - value="${!env_var:-}" - - if [[ -z "$value" ]]; then - warn "Skipping $name: $env_var is empty in config.env" - continue - fi - - secrets_content+="${name}=${value}"$'\n' - ok "credential: $name (from $env_var)" - done - - # Write via stdin to avoid credentials in process list - printf '%s' "$secrets_content" | ssh "$ssh_target" "mkdir -p $remote_home/.config/nono && cat > $remote_home/.config/nono/secrets.env && chmod 600 $remote_home/.config/nono/secrets.env" - ok "secrets.env written (chmod 600)" - fi - fi - - # Git credential helper for sandboxed executors - log "Configuring git credential helper" - if ssh "$ssh_target" "test -x /usr/bin/gh" 2>/dev/null; then - ssh "$ssh_target" "git config --global credential.helper '!/usr/bin/gh auth git-credential'" - ok "git credential helper: gh (full path for sandbox)" - else - ssh "$ssh_target" "git config --global credential.helper store" - ok "git credential helper: store (gh not installed)" - fi - - # Deploy nono profile (JSON format required by nono) - log "Deploying nono profile" - ssh "$ssh_target" "mkdir -p $remote_home/.config/nono/profiles" - render_file "$TEMPLATES_DIR/nono-profile.json.tmpl" "/tmp/taskyou-nono-profile.json" - scp -q "/tmp/taskyou-nono-profile.json" "$ssh_target:$remote_home/.config/nono/profiles/taskyou-agent.json" - rm -f "/tmp/taskyou-nono-profile.json" - ok "profile: taskyou-agent" - - # Deploy nono-exec (shared sandbox launcher) - log "Deploying nono-exec" - ssh "$ssh_target" "mkdir -p $remote_home/.local/bin" - render_file "$TEMPLATES_DIR/nono-exec.sh.tmpl" "/tmp/nono-exec.sh" - scp -q "/tmp/nono-exec.sh" "$ssh_target:$remote_home/.local/bin/nono-exec" - ssh "$ssh_target" "chmod +x $remote_home/.local/bin/nono-exec" - rm -f "/tmp/nono-exec.sh" - ok "nono-exec" - - # Deploy thin executor stubs - log "Deploying executor stubs" - ssh "$ssh_target" "mkdir -p $remote_home/bin" - - for executor in claude codex gemini openclaw opencode pi; do - # Check if this executor is actually installed on the server - if ! ssh "$ssh_target" "PATH=\$(echo \"\$PATH\" | tr ':' '\\n' | grep -v \"^\$HOME/bin\$\" | tr '\\n' ':' | sed 's/:\$//') command -v $executor" >/dev/null 2>&1; then - continue # Skip executors that aren't installed - fi - - render_file "$TEMPLATES_DIR/nono-stub.sh.tmpl" "/tmp/nono-stub-$executor.sh" - scp -q "/tmp/nono-stub-$executor.sh" "$ssh_target:$remote_home/bin/$executor" - ssh "$ssh_target" "chmod +x $remote_home/bin/$executor" - rm -f "/tmp/nono-stub-$executor.sh" - ok "stub: ~/bin/$executor" - done - - # Ensure ~/bin and ~/.local/bin are in PATH - # Both are needed: ~/bin for nono wrappers, ~/.local/bin for ty and other user tools - if ! ssh "$ssh_target" "grep -q 'export PATH=\$HOME/bin:\$HOME/.local/bin:\$PATH' $remote_home/.bashrc" 2>/dev/null; then - # Remove any older partial PATH line we may have added before - ssh "$ssh_target" "sed -i '/^export PATH=\\\$HOME\/bin:\\\$PATH$/d' $remote_home/.bashrc" 2>/dev/null || true - ssh "$ssh_target" "echo 'export PATH=\$HOME/bin:\$HOME/.local/bin:\$PATH' >> $remote_home/.bashrc" - ok "PATH: ~/bin and ~/.local/bin prepended in .bashrc" - else - ok "PATH: ~/bin and ~/.local/bin already in .bashrc" - fi - - # Note: Plain-text .env files (e.g., linear-cli/.env) are NOT removed here. - # They are used by cron scripts (linear-poll.mjs) that run outside the nono - # sandbox. Agents cannot access these files because nono's Landlock sandbox - # restricts filesystem access to the paths defined in the profile. - # A future version could move cron scripts into the sandbox as well. - - log "nono credential isolation setup complete" -} - # ── Slack module ────────────────────────────────────────────────────────────── # Install the Slack bridge on a remote host as the ty-slack systemd user @@ -980,11 +806,6 @@ with open(cf, 'w') as f: json.dump(data, f, indent=2) remote "touch $SERVER_HOME/notifications.jsonl" ok "notifications.jsonl" - # nono credential isolation - if [[ "$NONO_ENABLED" == "true" ]]; then - setup_nono "$SERVER_HOST" "$SERVER_HOME" || warn "nono setup failed, continuing without credential isolation" - fi - # Linear module if [[ "$LINEAR_ENABLED" == "true" ]]; then log "Setting up Linear integration" @@ -1236,11 +1057,6 @@ with open(cf, 'w') as f: json.dump(data, f, indent=2) exe_remote "touch $EXE_HOME/notifications.jsonl" ok "notifications.jsonl" - # nono credential isolation - if [[ "$NONO_ENABLED" == "true" ]]; then - setup_nono "$EXE_HOST" "$EXE_HOME" || warn "nono setup failed, continuing without credential isolation" - fi - # GM launcher script log "Setting up GM launcher" exe_remote "mkdir -p $EXE_HOME/bin" diff --git a/templates/exe-dev/gm-launcher.tmpl b/templates/exe-dev/gm-launcher.tmpl index 6e3cce3..dd3209b 100644 --- a/templates/exe-dev/gm-launcher.tmpl +++ b/templates/exe-dev/gm-launcher.tmpl @@ -1,5 +1,5 @@ #!/bin/bash -# Ensure ty, nono wrappers, and other user tools are in PATH +# Ensure ty and other user tools are in PATH # (tmux/daemon sessions may not source .bashrc) export PATH="$HOME/bin:$HOME/.local/bin:$PATH" cd /home/exedev/projects/gm && exec claude --dangerously-skip-permissions "$@" diff --git a/templates/nono-exec.sh.tmpl b/templates/nono-exec.sh.tmpl deleted file mode 100644 index 49696be..0000000 --- a/templates/nono-exec.sh.tmpl +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash -# nono-exec — shared sandbox launcher for TaskYou-OS executors -# Deployed to ~/.local/bin/nono-exec by setup.sh — do not edit manually -# -# All sandbox logic lives here. Per-executor stubs in ~/bin/ delegate -# to this script, so routine fixes only require updating one file. - -set -euo pipefail - -EXECUTOR_BIN="$1" -shift - -# Ensure ~/.local/bin is in PATH (for ty, nono, etc.) -# Daemon-spawned tmux panes may have a minimal PATH that skips .bashrc -export PATH="$HOME/.local/bin:$PATH" - -# ── 1. Find real binary ────────────────────────────────────────────────────── -# Search PATH without ~/bin to find the actual binary (not our stub) -REAL_BIN=$(PATH=$(echo "$PATH" | tr ':' '\n' | grep -v "^$HOME/bin$" | tr '\n' ':' | sed 's/:$//') which "$EXECUTOR_BIN" 2>/dev/null) - -if [ -z "$REAL_BIN" ]; then - echo "Error: $EXECUTOR_BIN not found in PATH (excluding ~/bin)" >&2 - echo "Install $EXECUTOR_BIN or check your PATH." >&2 - exit 1 -fi - -# ── 2. Source secrets ───────────────────────────────────────────────────────── -# If headless credential fallback is in use, source the secrets file. -# This happens before the sandbox applies, so env vars are available to nono's -# credential proxy. -if [ -f "$HOME/.config/nono/secrets.env" ]; then - set -a - # shellcheck disable=SC1091 - . "$HOME/.config/nono/secrets.env" - set +a -fi - -# ── 3. Build nono flags ────────────────────────────────────────────────────── -NONO_FLAGS=(--profile taskyou-agent --allow-cwd) -{{#NONO_PROXY_HOSTS}} -read -ra _proxy_args <<< "{{NONO_PROXY_FLAGS}}" -NONO_FLAGS+=("${_proxy_args[@]}") -{{/NONO_PROXY_HOSTS}} - -# ── 4. Worktree .git resolution ────────────────────────────────────────────── -# If .git is a file (git worktree), the real .git dir is elsewhere. -# Parse the gitdir pointer and allow the parent repo's .git directory so -# git operations inside the sandbox work correctly. -if [ -f .git ]; then - GITDIR=$(sed -n 's/^gitdir: //p' .git) - if [ -n "$GITDIR" ]; then - # Resolve to absolute path - GITDIR=$(cd "$(dirname "$GITDIR")" && pwd)/$(basename "$GITDIR") - # Allow the parent .git dir (two levels up from worktrees/) - PARENT_GIT=$(dirname "$(dirname "$GITDIR")") - NONO_FLAGS+=(--allow "$PARENT_GIT") - fi -fi - -# ── 5. Rewrite --append-system-prompt ───────────────────────────────────────── -# Some executors accept inline prompt text via --append-system-prompt, but nono -# can't pass large inline strings through its arg proxy. Write the prompt text -# to a temp file and swap the flag. -ARGS=() -while [ $# -gt 0 ]; do - case "$1" in - --append-system-prompt) - shift - PROMPT_FILE=$(mktemp /tmp/nono-prompt-XXXXXX.txt) - printf '%s' "$1" > "$PROMPT_FILE" - ARGS+=(--append-system-prompt-file "$PROMPT_FILE") - shift - ;; - *) - ARGS+=("$1") - shift - ;; - esac -done - -# ── 6. Launch sandboxed executor ────────────────────────────────────────────── -exec nono run "${NONO_FLAGS[@]}" -- "$REAL_BIN" "${ARGS[@]}" diff --git a/templates/nono-profile.json.tmpl b/templates/nono-profile.json.tmpl deleted file mode 100644 index f1810b3..0000000 --- a/templates/nono-profile.json.tmpl +++ /dev/null @@ -1,21 +0,0 @@ -{ - "meta": { - "name": "taskyou-agent", - "version": "1.0.0", - "description": "TaskYou agent sandbox with credential isolation", - "extends": "claude-code" - }, - "workdir": { - "access": "readwrite" - }, - "filesystem": { - "read": [ - "$HOME/.config/task", - "$HOME/.claude", - "$HOME/.local/share/task" - ] - }, - "network": { - "block": false - } -} diff --git a/templates/nono-stub.sh.tmpl b/templates/nono-stub.sh.tmpl deleted file mode 100644 index 0d93896..0000000 --- a/templates/nono-stub.sh.tmpl +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -exec "$HOME/.local/bin/nono-exec" "$(basename "$0")" "$@" diff --git a/templates/project-claude-md.tmpl b/templates/project-claude-md.tmpl index 855ef9a..2af1162 100644 --- a/templates/project-claude-md.tmpl +++ b/templates/project-claude-md.tmpl @@ -22,20 +22,6 @@ When you complete a task: 2. Write a brief summary of what you did as your final message 3. Include any file paths, URLs, or assets the GM needs for delivery -{{#NONO}} -## Credentials - -You are running inside a nono sandbox. Credentials are injected automatically -via a localhost proxy — you do not need to read .env files or manage API keys. -If a tool or API call fails with an authentication error, create a blocked task -explaining what credential you need access to. - -Do NOT attempt to: -- Read .env files or credential files from the filesystem -- Store API keys in files, environment variables, or code -- Access the secret-tool or keyring directly -{{/NONO}} - ## Domain Knowledge