resumime que es `personal-agent` en esta maquina


**Examining Personal-Agent**

I'm currently focused on the user's request, specifically the `personal-agent`. My immediate task is to gather data about it. I'm checking the provided URL, hoping to glean some insights into its current state. The initial focus is on the `personal-agent`'s status and any available documentation.

**Gathering Personal-Agent Data**

I've successfully accessed the status API endpoint, revealing the current state of the `personal-agent`. Simultaneously, I'm poring over the `SERVICES-ARCHITECTURE.md` file, which is proving to be a valuable resource for architectural details. My next move is to methodically search the filesystem, paying close attention to `/home/sebas` and `/mnt/rpi` for further clues about its configuration and function.

bash

curl -s http://100.116.176.16:8082/api/status | jq . || echo "Status API failed"


      "format": "md",
      "status": "active",
      "source_ref": "personal-agent:run:a1ad721a-bcbc-473e-806d-0793fbbfaac2",
      "created_at": "2026-03-24T14:26:24.158968+00:00",
      "updated_at": "2026-03-24T15:39:47.195210+00:00",
      "metadata": {
        "report_type": "feature-use-case-map",
        "run_id": "a1ad721a-bcbc-473e-806d-0793fbbfaac2",
        "topic": "matchable"
      },
      "task_title": "Matchable: mapa exhaustivo de features y use cases",
      "task_status": "done"
    },
    {
      "id": "art_smoke_markdown_file_links",
      "task_id": "task_smoke_markdown_file_links",
      "artifact_type": "report",
      "title": "smoke markdown file links",
      "content": "[tmp](personal-agent-markdown-link-test.md)",
      "format": "md",
      "status": "active",
      "source_ref": "personal-agent:smoke",
      "created_at": "2026-03-17T21:11:26.188844+00:00",
      "updated_at": "2026-03-17T21:11:26.188844+00:00",
      "metadata": {
        "cwd": "/tmp"
      },
      "task_title": "smoke markdown file links",
      "task_status": "completed"
    },
    {
      "id": "art_5e03c108db5345269e77d02e21d07dd9",
      "task_id": "task_84da4829fdea45728971df65c57ff33f",
      "artifact_type": "report",
      "title": "Codex result for Document the current Raycast-based fullscreen notification and reply implementation for Codex.",
      "content": "Hi Sebas. Kept it tight.\n\nDocumented current live flow in [docs/raycast-codex-notify.md](/Users/sebas/personal-agent/docs/raycast-codex-notify.md). It captures the actual implementation split between `~/.codex/hooks/notify_macos.sh` and `~/Code/raycast-codex-reply`, including:\n\n- notify hook decision path\n- rollout-message recovery from `~/.codex/state_5.sqlite`\n- Raycast reply bridge files + deeplinks\n- approval watcher flow\n- fallback AppleScript dialog\n- explicit note that `personal-agent`’s old blocker/reply path is removed, so this is not handled by the current runtime\n\nAdded a README pointer at [README.md](/Users/sebas/personal-agent/README.md).\n\nVerification: `./scripts/run-checks.sh` passed.",
      "format": "md",
      "status": "active",
      "source_ref": "personal-agent",
      "created_at": "2026-03-17T02:12:31.505135+00:00",
      "updated_at": "2026-03-17T02:12:31.505135+00:00",
      "metadata": {
        "classification": "deliverable",
        "cwd": "/Users/sebas/personal-agent",
        "output_refs": {
          "paths": [
            "./scripts/run-checks.sh",
            "~/.codex/hooks/notify_macos.sh",
            "~/.codex/state_5.sqlite",
            "~/Code/raycast-codex-reply"
          ]
        },
        "run_id": "run_9f50b4d09e5842498c055923a851c678"
      },
      "task_title": "Document the current Raycast-based fullscreen notification and reply implementation for Codex.",
      "task_status": "completed"
    },
    {
      "id": "art_d69dff710f97429882a05b0ec979ac5b",
      "task_id": "task_be1a1e514a7d43d1b59009ccca9fb57c",
      "artifact_type": "report",
      "title": "Codex result for Migrate remaining personal-agent legacy persistence/read paths to the shared task/runtime model",
      "content": "Hi. Legacy seam closed.\n\nCanonical shared-memory model now drives personal-agent surfaces from [shared_memory.py](/Users/sebas/personal-agent/personal_agent/shared_memory.py), with `personal-agent-memory-v1` and `personal-agent-task-v1` helpers, canonical kind detection, and an actual in-place migrator for old memory/task records plus legacy approval memories. [research_store.py](/Users/sebas/personal-agent/personal_agent/research_store.py) now reads/writes canonical run/source/claim/artifact/task records, drops the old bridge fallback for run inspection, uses native approvals rows for request/list/resolve, and includes approvals in search results. [router.py](/Users/sebas/personal-agent/personal_agent/router.py) now mirrors handoffs with canonical memory metadata, and [scripts/personal.py](/Users/sebas/personal-agent/scripts/personal.py) wires `approvals resolve` back into the CLI. [migration.py](/Users/sebas/personal-agent/personal_agent/migration.py) now runs real migration work instead of no-op, and [README.md](/Users/sebas/personal-agent/README.md) reflects the new model.\n\nCoverage added in [tests/test_personal.py](/Users/sebas/personal-agent/tests/test_personal.py) for canonical research records, native approval lifecycle, and legacy migration behavior. Verified with `./scripts/run-checks.sh` and `git diff --check`; both passed. No daemon/UI smoke run.",
      "format": "md",
      "status": "active",
      "source_ref": "personal-agent",
      "created_at": "2026-03-17T02:02:06.161088+00:00",
      "updated_at": "2026-03-17T02:02:06.161088+00:00",
      "metadata": {
        "classification": "deliverable",
        "cwd": "/Users/sebas/personal-agent",
        "output_refs": {
          "paths": [
            " helpers, canonical kind detection, and an actual in-place migrator for old memory/task records plus legacy approval memories. [research_store.py](/Users/sebas/personal-agent/personal_agent/research_store.py) now reads/writes canonical run/source/claim/artifact/task records, drops the old bridge fallback for run inspection, uses native approvals rows for request/list/resolve, and includes approvals in search results. [router.py](/Users/sebas/personal-agent/personal_agent/router.py) now mirrors handoffs with canonical memory metadata, and [scripts/personal.py](/Users/sebas/personal-agent/scripts/personal.py) wires ",
            "./scripts/run-checks.sh"
          ]
        },
        "run_id": "run_b694a238b532454bb547c056246a31fd"
      },
      "task_title": "Migrate remaining personal-agent legacy persistence/read paths to the shared task/runtime model",
      "task_status": "completed"
    },
    {
      "id": "art_b4f5386484794717b0ddc4c42c265319",
      "task_id": "task_871c609196b94132aa686188007f6dea",
      "artifact_type": "report",
      "title": "Codex result for Consolidate all Ballbox payment-system work from demo validation through production readiness and go-live certification.",
      "content": "Consolidated into one active workflow.\n\nCreated local repo mapping in [.agents/local-config.json](/Users/sebas/Code/ai-dev-workflow/.agents/local-config.json), set current feature in [.agents/current-feature](/Users/sebas/Code/ai-dev-workflow/.agents/current-feature), and wrote the active feature context in [.agents/feature-contexts/ballbox-payment-system-prod-readiness.json](/Users/sebas/Code/ai-dev-workflow/.agents/feature-contexts/ballbox-payment-system-prod-readiness.json). Added the execution brief/checklist in [docs/ballbox-payment-system-consolidation.md](/Users/sebas/Code/ai-dev-workflow/docs/ballbox-payment-system-consolidation.md).\n\nKey consolidation outcome: `ballbox` is stable/demo-facing only; `ballbox-payment-integration` is the real workstream. Demo validation exists now. Production hardening is partially drafted but unstaged in backend. Go-live certification is still blocked by two real gaps: missing TCN/Yunshu live adapter contract, and unvalidated MercadoPago real QR flow.\n\nVerification: JSON valid. Shared-memory sync failed because `shared_agent_memory` is not installed/importable in this environment. Control repo also remains behind `origin/main` by 1 commit: `111e974 Feat: accept shared memory run-task handoffs (#2)`. I did not pull because this branch is also 3 commits ahead.\n\nBest next move: review and commit the backend readiness slice in `~/Code/ballbox-payment-integration`, then `/status --current`.",
      "format": "md",
      "status": "active",
      "source_ref": "personal-agent",
      "created_at": "2026-03-17T01:55:28.432378+00:00",
      "updated_at": "2026-03-17T01:55:28.432378+00:00",
      "metadata": {
        "classification": "deliverable",
        "cwd": "/Users/sebas/Code/ai-dev-workflow",
        "output_refs": {
          "paths": [
            " is not installed/importable in this environment. Control repo also remains behind ",
            " is stable/demo-facing only; ",
            "~/Code/ballbox-payment-integration"
          ]
        },
        "run_id": "run_80140950f2c04d10bd3941d712ab0b25"
      },
      "task_title": "Take the Ballbox payment system from demo flow to production readiness",
      "task_status": "completed"
    },
    {
      "id": "art_a5cbdcb711234fd3b8306f379678523c",
      "task_id": "task_746e1a74f77b4cb0b8e3fd950fad90cb",
      "artifact_type": "report",
      "title": "link smoke",
      "content": "[tct](link) [txt](link.com)",
      "format": "md",
      "status": "active",
      "source_ref": "personal-agent",
      "created_at": "2026-03-16T20:42:13.176072+00:00",
      "updated_at": "2026-03-16T20:42:13.176072+00:00",
      "metadata": {},
      "task_title": "link smoke",
      "task_status": "completed"
    },
    {
      "id": "art_322e6f0e62724030b8d995053a5ec674",
      "task_id": "task_2f22e794212641c49d7f8a600ad3a4bd",
      "artifact_type": "report",
      "title": "Codex result for en personal-agent que el script que hace restart del daemon pause tareas corriendo (como sea, que...",
      "content": "## Summary\nImplementado en `personal-agent`: el restart del daemon ahora pausa runs activas, las deja en estado reiniciable, y al levantar de nuevo el runtime intenta relanzarlas solo. También blindé el watcher para que un run ya pausado no termine marcado como fallo cuando llega el `SIGTERM`.\n\n## Changes\n- [`/Users/sebas/personal-agent/personal_agent/runtime.py`](file:///Users/sebas/personal-agent/personal_agent/runtime.py)\n  - agregado `pause_running_tasks()`\n  - `stop()` ahora puede pausar antes de terminar procesos\n  - runs `running` recuperadas tras restart/crash pasan a `paused`, task vuelve a `draft`, metadata marca `auto_restart_on_daemon_start`\n  - en boot, `_restart_paused_runs()` relanza tasks pausadas con `cwd`/prompt guardados\n  - `_watch_run()` sale temprano si el run ya no está `running`, evita falso `failed`\n- [`/Users/sebas/personal-agent/scripts/personal.py`](file:///Users/sebas/personal-agent/scripts/personal.py)\n  - nuevo comando `pause-running --reason ...`\n- [`/Users/sebas/personal-agent/scripts/daemon-8082.sh`](file:///Users/sebas/personal-agent/scripts/daemon-8082.sh)\n  - `restart` ahora ejecuta `python3 scripts/personal.py pause-running ...` antes de `stop/start`\n- [`/Users/sebas/personal-agent/tests/test_personal.py`](file:///Users/sebas/personal-agent/tests/test_personal.py)\n  - actualizado recovery test para validar pause + auto-restart\n  - nuevo test para pause/shutdown race, sin false failure/artifact\n\n## Verification\n- `python3 -m unittest tests.test_personal` ✅\n- `./scripts/run-checks.sh` ✅\n- `./scripts/daemon-8082.sh restart`\n  - pause step ejecutó bien\n  - restart completo bloqueado por entorno actual: `\"foreign listener on 127.0.0.1:8082 (pid 18283); refusing to stop it\"`\n- `curl -fsS http://127.0.0.1:8082/api/status` ✅\n  - confirmó que la task activa quedó `draft` con latest run `paused`\n\n## Outputs\n- Branch: none\n- PR: none\n- Files changed:\n  - [`/Users/sebas/personal-agent/personal_agent/runtime.py`](file:///Users/sebas/personal-agent/personal_agent/runtime.py)\n  - [`/Users/sebas/personal-agent/scripts/personal.py`](file:///Users/sebas/personal-agent/scripts/personal.py)\n  - [`/Users/sebas/personal-agent/scripts/daemon-8082.sh`](file:///Users/sebas/personal-agent/scripts/daemon-8082.sh)\n  - [`/Users/sebas/personal-agent/tests/test_personal.py`](file:///Users/sebas/personal-agent/tests/test_personal.py)\n- Artifacts created: none",
      "format": "md",
      "status": "active",
      "source_ref": "personal-agent",
      "created_at": "2026-03-16T20:25:49.823843+00:00",
      "updated_at": "2026-03-16T20:25:49.823843+00:00",
      "metadata": {
        "classification": "deliverable",
        "cwd": "/Users/sebas/personal-agent",
        "output_refs": {
          "branches": [
            "none"
          ],
          "paths": [
            " recuperadas tras restart/crash pasan a ",
            "./scripts/daemon-8082.sh restart",
            "./scripts/run-checks.sh",
            "/Users/sebas/personal-agent/personal_agent/runtime.py",
            "/Users/sebas/personal-agent/scripts/daemon-8082.sh",
            "/Users/sebas/personal-agent/scripts/personal.py",
            "/Users/sebas/personal-agent/tests/test_personal.py",
            "curl -fsS http://127.0.0.1:8082/api/status",
            "python3 scripts/personal.py pause-running ...",
            "stop/start"
          ]
        },
        "run_id": "run_8ff645c9a9ad4d558df0265495267a41"
      },
      "task_title": "en personal-agent que el script que hace restart del daemon pause tareas corriendo (como sea, que...",
      "task_status": "completed"
    },
    {
      "id": "art_d7f2bb1c7a204e56834b97bc4e77989b",
      "task_id": "task_8a866bb8156441ff8cee2f0f9f28e0c5",
      "artifact_type": "report",
      "title": "Codex result for en un worktree nuevo en personal-agent, agregar soporte markdown para links (ej. aca http://127.0...",
      "content": "## Summary\nAgregado soporte markdown para links en artifacts/report renderizados por el daemon. `[USECASE.md](http://...)` ahora sale como `<a>` clickable, no literal. Hecho en worktree nuevo; además dejé un test existente compatible con worktrees.\n\n## Changes\n- Link markdown inline en [personal_agent/daemon.py](/Users/sebas/personal-agent-wt-markdown-links/personal_agent/daemon.py#L630)\n  - parse `[label](href)`\n  - `href` allowlist: `http`, `https`, `mailto`, `/`, `./`, `../`, `#`\n  - links no seguros quedan literales\n- Tests en [tests/test_personal.py](/Users/sebas/personal-agent-wt-markdown-links/tests/test_personal.py#L1653)\n  - cubre render de link local `http://127.0.0.1:8082/artifacts/...`\n  - cubre fallback seguro para `javascript:...`\n- Fix de test frágil para worktree en [tests/test_personal.py](/Users/sebas/personal-agent-wt-markdown-links/tests/test_personal.py#L1345)\n  - deja de asumir path absoluto fijo del repo principal\n\n## Verification\n- `./scripts/run-checks.sh`\n- Resultado: `Ran 36 tests ... OK`\n\n## Outputs\n- Worktree: `/Users/sebas/personal-agent-wt-markdown-links`\n- Branch: `fix-artifact-markdown-links`\n- Files changed:\n  - [personal_agent/daemon.py](/Users/sebas/personal-agent-wt-markdown-links/personal_agent/daemon.py)\n  - [tests/test_personal.py](/Users/sebas/personal-agent-wt-markdown-links/tests/test_personal.py)\n- PR: none\n- Artifacts: none",
      "format": "md",
      "status": "active",
      "source_ref": "personal-agent",
      "created_at": "2026-03-16T19:15:50.674755+00:00",
      "updated_at": "2026-03-16T19:15:50.674755+00:00",
      "metadata": {
        "classification": "deliverable",
        "cwd": "/Users/sebas/personal-agent",
        "output_refs": {
          "paths": [
            "./scripts/run-checks.sh",
            "/Users/sebas/personal-agent-wt-markdown-links",
            "[USECASE.md](http://...)"
          ]
        },
        "run_id": "run_cce5f6d82e0148f6a56c9c12d159711e"
      },
      "task_title": "en un worktree nuevo en personal-agent, agregar soporte markdown para links (ej. aca http://127.0...",
      "task_status": "completed"
    },
    {
      "id": "art_b418ed73b479471eb1a936388268b7e9",
      "task_id": "task_273752f696ea4b87b2dba4497bad37f7",
      "artifact_type": "report",
      "title": "Codex result for en personal-agent en el worktree actual /Users/sebas/Code/personal-agent-simple-codex-runner agre...",
      "content": "## Summary\n\nAgregué spacing estable en la UI del dashboard para evitar layout shifts en el resumen `\"drafts / running / failed / results\"` y en las cajas/listas de estados. El cambio quedó implementado en la UI inline del daemon.\n\n## Changes\n\n- En [personal_agent/daemon.py](/Users/sebas/Code/personal-agent-simple-codex-runner/personal_agent/daemon.py#L33) ajusté la grilla para alinear cards arriba y dar altura mínima a panels.\n- En [personal_agent/daemon.py](/Users/sebas/Code/personal-agent-simple-codex-runner/personal_agent/daemon.py#L52) reemplacé el summary textual por una `summary-grid` con 4 cards de ancho reservado, para que el cambio de números no mueva el layout.\n- En [personal_agent/daemon.py](/Users/sebas/Code/personal-agent-simple-codex-runner/personal_agent/daemon.py#L56) agregué `list-slot` y `empty-state` con altura mínima para estabilizar Drafts, Active Runs, Recent Results y Failed Runs.\n- En [personal_agent/daemon.py](/Users/sebas/Code/personal-agent-simple-codex-runner/personal_agent/daemon.py#L116) actualicé `renderList()` y sumé `renderSummary()` para render consistente durante refresh y estados vacíos.\n- En [personal_agent/daemon.py](/Users/sebas/Code/personal-agent-simple-codex-runner/personal_agent/daemon.py#L60) agregué ajuste responsive para mobile sin mantener alturas forzadas innecesarias.\n\n## Verification\n\n- `./scripts/run-checks.sh` ✅\n- Smoke UI en instancia temporal `127.0.0.1:8090` ✅\n- Verifiqué que el HTML servido incluye `summary-grid`, `summary-card`, `list-slot`, `empty-state` ✅\n- No pude reiniciar `127.0.0.1:8082`: el helper detectó listener ajeno `pid 81699` y se negó a pararlo. El `8082` actual seguía sirviendo HTML previo.\n\n## Outputs\n\n- Branch: sin cambios\n- PR: ninguno\n- Archivo modificado: [personal_agent/daemon.py](/Users/sebas/Code/personal-agent-simple-codex-runner/personal_agent/daemon.py)\n- Artifact temporal validado: dashboard smoke en `http://127.0.0.1:8090/` durante la verificación",
      "format": "md",
      "status": "active",
      "source_ref": "personal-agent",
      "created_at": "2026-03-16T18:55:10.658042+00:00",
      "updated_at": "2026-03-16T18:55:10.658042+00:00",
      "metadata": {
        "classification": "deliverable",
        "cwd": "/Users/sebas/Code/personal-agent-simple-codex-runner",
        "output_refs": {
          "branches": [
            "sin"
          ],
          "paths": [
            "\"drafts / running / failed / results\"",
            "./scripts/run-checks.sh"
          ]
        },
        "run_id": "run_382bb0979ec643e5b780c43c49f59103"
      },
      "task_title": "en personal-agent en el worktree actual /Users/sebas/Code/personal-agent-simple-codex-runner agre...",
      "task_status": "completed"
    },
    {
      "id": "art_b90cb99f638c45ecbb358d2f51cdad89",
      "task_id": "task_12b3a671a5d5494e9f0ed28ac8a16079",
      "artifact_type": "report",
      "title": "Codex result for quiero abrir un worktree nuevo para dejar un USECASE.md en ballbox-payment-integration que expliq...",
      "content": "## Summary\nAbrí un worktree nuevo para `ballbox-payment-integration`, agregué una guía `USECASE.md` en español explicando cómo se usa el producto end-to-end, la linkeé desde el `README.md`, hice commit, push y abrí PR.\n\n## Changes\n- Nuevo doc: [USECASE.md](/Users/sebas/Code/ballbox-payment-integration-usecase/USECASE.md)\n- Link de acceso rápido en [README.md](/Users/sebas/Code/ballbox-payment-integration-usecase/README.md)\n- Contenido cubre:\n  - qué resuelve el bridge\n  - actores\n  - flujo `/pay` -> QR -> webhook -> callback a máquina\n  - uso local/demo\n  - prerequisitos de producción\n  - límites actuales\n\n## Verification\n- `npm install`\n- `npm run typecheck`\n- `npm test`\n- Resultado: verde\n- Worktree limpio al final en branch publicada\n\n## Outputs\n- Branch: `docs/usecase-md`\n- PR: `#1` `Add product usage guide`\n- Worktree: `/Users/sebas/Code/ballbox-payment-integration-usecase`\n- Files:\n  - [USECASE.md](/Users/sebas/Code/ballbox-payment-integration-usecase/USECASE.md)\n  - [README.md](/Users/sebas/Code/ballbox-payment-integration-usecase/README.md)",
      "format": "md",
      "status": "active",
      "source_ref": "personal-agent",
      "created_at": "2026-03-16T18:52:19.557278+00:00",
      "updated_at": "2026-03-16T18:52:19.557278+00:00",
      "metadata": {
        "classification": "deliverable",
        "cwd": "/Users/sebas/Code/ai-dev-workflow",
        "output_refs": {
          "paths": [
            "/Users/sebas/Code/ballbox-payment-integration-usecase",
            "docs/usecase-md"
          ]
        },
        "run_id": "run_f6edf712c14d4153bde400000125024b"
      },
      "task_title": "quiero abrir un worktree nuevo para dejar un USECASE.md en ballbox-payment-integration que expliq...",
      "task_status": "completed"
    }
  ],
  "cwd_options": [
    {
      "name": "personal-agent",
      "path": "/mnt/rpi/repos/opencode-harness",
      "source": "known",
      "repo_id": "repo_personal_agent"
    },
    {
      "name": "ballbox-company-agent",
      "path": "/mnt/rpi/repos/ballbox-company-agent",
      "source": "known",
      "repo_id": "repo_ballbox_company_agent"
    },
    {
      "name": "ballbox",
      "path": "/mnt/rpi/repos/ballbox",
      "source": "workspace"
    },
    {
      "name": "browser-harness",
      "path": "/mnt/rpi/repos/browser-harness",
      "source": "workspace"
    },
    {
      "name": "FelipeVersion",
      "path": "/mnt/rpi/repos/FelipeVersion",
      "source": "workspace"
    }
  ],
  "summary": {
    "draft_count": 8,
    "running_count": 0,
    "failed_count": 3,
    "result_count": 12
  }
}

[Showing lines 601-876 of 876 (50.0KB limit). Full output: /tmp/pi-bash-82aaaf6928732755.log]


# Services Architecture

This file documents the local service shape on `ballbox-first`, with emphasis on terminal persistence for `pi` and tmux.

## Goal

Keep `pi` usable as an interactive TUI while making tmux only a persistence layer.

Desired properties:

- `pi` runs inside tmux.
- Closing a terminal client does not kill `pi`.
- tmux does not become the primary UI.
- Mouse scroll works for history without moving the `pi` cursor.
- Color rendering stays correct inside tmux.

## Current tmux model

### tmux config

`~/.tmux.conf` is intentionally persistence-first:

- `mouse on`
- `history-limit 100000`
- `set-clipboard on`
- custom prefix: `C-\\`
- status bar off
- dangerous interactive defaults unbound
- copy mode uses vi keys
- wheel scroll enters/uses copy mode
- explicit detach/reload bindings only

### Important tmux bindings

- Prefix: `Ctrl-\\`
- Detach: `Ctrl-\\` then `D`
- Reload config: `Ctrl-\\` then `r`
- Scroll/history:
  - wheel up enters copy mode or scrolls within it
  - wheel down scrolls or exits copy mode

### Why tmux stays minimal

tmux is not used for pane/window management here. It is only the durable PTY container for the running `pi` process.

That means:

- no pane splitting
- no tab/session UI workflow
- no mouse-driven tmux navigation
- no session picker dependency for normal `pi` use

## `pitmux`

`~/.bashrc` defines `pitmux()`.

Purpose:

- start `pi` inside a tmux session
- keep the session attachable later
- keep color output correct inside tmux

### Current launch behavior

`pitmux` forces these env values for the `pi` process:

- `TERM=tmux-256color`
- `COLORTERM=truecolor`
- `TERM_PROGRAM=`

This avoids the brown background / palette mismatch that appeared when `pi` ran inside tmux with the host terminal's `TERM_PROGRAM` leaking through.

### Usage

```bash
pitmux
pitmux pi-1
```

If no name is passed, `pitmux` creates a timestamped session name like:

```text
pi-20260421-165900
```

### Launch shape

`pitmux` runs:

```bash
env TERM=tmux-256color COLORTERM=truecolor TERM_PROGRAM= tmux new-session -A -s <session> pi
```

## `pi` resume helper

`~/.bashrc` also defines `piresume()`.

That wrapper is separate from tmux.

Purpose:

- run `pi` normally
- after exit, print the latest session id hint
- help resume with:

```bash
pi --session <id>
```

## Shell / web service history

### Removed

- `code-server` at `/cli`
- `ttyd`
- `dtach`
- `pi-dashboard`

Reason: they did not match the target shape or they introduced too much UI mismatch.

### Current direction

The current preferred path is:

- local terminal or SSH
- `pitmux` for persistence
- tmux only as a PTY container
- `pi` as the interactive TUI

## Operational rules

- Do not use tmux as the main UI.
- Do not depend on `Ctrl+D` as a detach action; it exits the shell and can kill the session.
- Use tmux detach explicitly.
- Keep browser/web exposure out of the loop unless a future tool actually needs it.

## Open questions

- Whether `pi` can eventually run with a better PTY/session wrapper than tmux.
- Whether a future tool can expose the same persistent TUI model without tmux.

## Relevant files

- `~/.bashrc`
- `~/.tmux.conf`
- `/mnt/rpi/pi-config/AGENTS.md`


**Considering API Insights**

I've just analyzed the JSON response from the status API. It confirms that the `personal-agent` service is indeed running on port 8082, as I suspected. The response provides critical context, highlighting its role in managing "tasks" and "runs." Furthermore, it hints at other APIs for interacting with artifacts, giving me a better understanding of the system's capabilities.

**Exploring Service Dependencies**

I've moved from the status API to considering the larger system architecture. The architecture document doesn't explicitly describe the `personal-agent`, but mentions related services. It seems the agent is a backend for running AI tasks. Now I'm examining its relationship with the dashboard and potentially `pitmux` and `pi`. I am exploring the files related to the artifact, seeing if I can find the restart of the daemon implementation details.

**Pinpointing Core Functionality**

The latest JSON response really solidified my understanding of the `personal-agent`. It's not just a service; it's the operational backbone. The key is in "tasks" and "runs," the foundation for its AI agent management. I see a dashboard and API, all on port 8082, with robust features like artifact storage and run control. The code lives at `/mnt/rpi/repos/opencode-harness`, the artifact content confirms it is the runtime and harness for all things AI agents. I see shared memory is being used for agents, with the agent database. The system design is now clear.

**Confirming Code Location**

The `personal-agent` is definitely the heart of this. The API's JSON output points directly to `/mnt/rpi/repos/opencode-harness` as the code's home, and my analysis of the artifact contents and the architecture document further solidifies this. This is the central repository for the runtime and harness for AI agent operations, responsible for tasks, runs, and artifacts. Now I am checking for a README to know how to interact with it.


AGENTS.md
ballbox-company-agent/
config/
data/
docs/
INSTALL.md
LICENSE
main.py*
personal_agent/
README.md
scripts/
systemd/
tests/


# opencode-harness

Successor to `second-brain`.

Personal research + memory runtime, kept separate from `ai-dev-workflow`.

See [INSTALL.md](INSTALL.md) for setup.

## Principles

- Repo-local ownership for personal capabilities
- Global skill discovery via `~/.agents/skills` (installer copies skills)
- Shared DB in sibling repo `~/agents-database` is the durable source of truth for new work
- Human approval required for outreach / external side effects
- `ai-dev-workflow` stays focused on project workflows

## V1 Front Door

`opencode-harness` now grows toward a front-door runtime:

- daemon + dashboard at `127.0.0.1:8082`
- shared-memory orchestration over `agents-database`
- direct task runner with `draft -> confirm cwd -> launch -> result`
- one runner process per task, launched from the selected repo root
- dashboard/CLI snapshot with drafts, active runs, failed runs, and recent results

System map and machine-recreation guide:

- [docs/system-v1.md](docs/system-v1.md)
- [docs/raycast-codex-notify.md](docs/raycast-codex-notify.md)

## What Exists Today

This repository now contains:

- shared-memory-backed persistence for research runs
- source, claim, task, and approval tracking
- memory search over stored runs, claims, and tasks
- Agent skill wrappers owned by this repo
- reusable utility skills for temporary file sharing and karaoke stem separation
- task intake persistence with parent tasks and subtasks
- request routing and specialist delegation across personal/company/code contexts
- internal command surface via `python3 scripts/personal.py`
- unit tests for the storage lifecycle

## Shared Memory Integration

Durable shared memory lives in the sibling project at `~/agents-database`.

- research, leisure, approvals, and task intake write directly to shared memory
- `memory-search` reads shared memory directly
- approvals use the native shared-memory approvals table
- `memory-migrate` rewrites legacy opencode-harness metadata into the canonical shared-memory schema
- `research status --run-id <id>` resolves runs from canonical shared-memory records only

Default shared-memory path discovery:

- tries `~/agents-database/src` first
- then falls back to sibling discovery heuristics if the direct path is unavailable
- database defaults to `<shared-memory-root>/data/shared-agent-memory.sqlite3`
- runner binary is configurable; choose the installed CLI that best fits the machine/runtime

These can be overridden with:

- `PERSONAL_AGENT_SHARED_MEMORY_ROOT`
- `PERSONAL_AGENT_SHARED_MEMORY_DB_PATH`
- `PERSONAL_AGENT_RUNNER_BIN`
- `PERSONAL_AGENT_RUNNER_ADD_DIRS`
- `PERSONAL_AGENT_CODEX_ADD_DIRS` remains legacy-compatible env input for add-dir lists

## What Is Still A Promise

These are goals for future work. They are not implemented in the main runner path yet.

- browser automation and live web execution
- email sending or contact workflows
- proactive background daemon / scheduler
- calendar or inbox integrations
- fully autonomous task execution

## Routing Model

`opencode-harness` is the intended front door.

- start here for general requests
- personal context stays here
- code-shaped requests default to `~/ai-dev-workflow` unless the draft cwd is changed before launch
- the main daemon path is now a direct code runner, not a multi-agent orchestrator

## Layout

```text
opencode-harness/
├── .agents/skills/
├── data/
├── personal_agent/
├── scripts/
└── tests/
```

## Internal Commands

Internal command surface only. Not intended as the primary UX for end users.

```bash
python3 scripts/personal.py research start --goal "Investigate X"
python3 scripts/personal.py research search-web --run-id <id> --query "best local-first assistants"
python3 scripts/personal.py research capture-url --run-id <id> --url https://example.com
python3 scripts/personal.py research add-source --run-id <id> --url https://example.com
python3 scripts/personal.py report --run-id <id> --format md
python3 scripts/personal.py memory-search --query "X"
python3 scripts/personal.py memory-migrate
python3 scripts/personal.py route --input "Ballbox necesita fix en repo de pagos" --execute
python3 scripts/personal.py --json status
python3 scripts/personal.py approvals list
python3 scripts/personal.py --json approvals resolve --approval-id <id> --status approved --note "safe to proceed"
python3 scripts/personal.py tasks next
python3 scripts/personal.py leisure add --title "Severance" --media-type series
python3 scripts/personal.py leisure list --media-type series
```

## Operator Note

- daemon is long-running
- this agent can start, stop, or restart it across sessions
- canonical UI endpoint: `http://127.0.0.1:8082/`
- canonical status JSON endpoint: `http://127.0.0.1:8082/api/status`
- helper script:
  - `./scripts/daemon-8082.sh start`
  - `./scripts/daemon-8082.sh stop`
  - `./scripts/daemon-8082.sh restart`
  - `./scripts/daemon-8082.sh status`
  - `./scripts/daemon-8082.sh logs`

## Intended Usage Model

- personal capabilities stay in this repo
- this repo should be the normal conversational entry point
- Skills from this repo can be installed globally into `~/.agents/skills`
- managed-skill backups are stored outside that directory in `~/.agents/skills-backups` to avoid skill discovery conflicts
- current utility skills also include `temporary-file-share` and `karaoke-stem-separation`
- `ai-dev-workflow` remains separate and keeps owning its own workflow skills
- specialist repos can be delegated to when the request clearly matches them
- risky external actions should go through the approval queue first

## Clone-Friendly Extras

- `scripts/install-opencode.sh` installs skills + OpenCode rules without cloning (see INSTALL.md)
- `scripts/install-skills.sh` links skills into `~/.agents/skills`
- GitHub Actions runs the unit test suite on push and pull request

## Tests

```bash
./scripts/run-checks.sh
```

## Push Gate

Install the local pre-push gate once per clone:

```bash
./scripts/install-git-hooks.sh
```

After that, `git push` is blocked unless `scripts/run-checks.sh` passes.


**Reviewing Architecture Design**

I'm confident in the overall architecture now, the `personal-agent` as the core runtime is clear. It's the central hub for task management on the Pi, operating as `opencode-harness`. Focus is now on the modular components running within, and how their interactions are handled.

**Clarifying the Core**

The `personal-agent` runtime is clearly defined, and the architecture is robust. Its roles as task manager, front door, and persistent memory hub, including the API running on `ballbox-first:8082`, are all well-understood. I am now focusing on the individual skills it manages, like `karaoke-stem-separation`, and the scripts that control its operation, such as `scripts/daemon-8082.sh`.

`personal-agent` (interno: `opencode-harness`) es el **runtime y dashboard central** para ejecutar y gestionar tareas agénticas en esta máquina.

### Puntos clave:
*   **Harness/Runtime**: Es el motor que gestiona el ciclo de vida de las tareas (`draft` -> `running` -> `result`/`failed`). Corre procesos independientes para cada tarea.
*   **Dashboard & API**: Corre en el puerto `:8082`. Podés ver el estado en `http://100.116.176.16:8082/` o vía JSON en `/api/status`.
*   **Memoria Durable**: Integrado con `agents-database`. Persiste investigación, fuentes, hallazgos y artefactos (como reportes MD o archivos generados).
*   **Skills**: Contiene habilidades personales como `karaoke-stem-separation`, `temporary-file-share`, y flujos de investigación avanzada.
*   **Ubicación**: El código está en `/mnt/rpi/repos/opencode-harness`.
*   **Control**: Se maneja con `scripts/daemon-8082.sh` (start/stop/restart) y tiene una CLI en `scripts/personal.py`.

Es tu "puerta de entrada" para pedidos generales y de contexto personal, separando lo administrativo/leisure del workflow puro de desarrollo (`ai-dev-workflow`).


localmente desmantelemoslo:
move skills a donde van los demas skills
agents-database queda accesible por el agente directo (read y write)
saquemos el dashboard y api (de nginx service y daemon y `personal.py` cli tambien)
borremos el repo local

la idea general es que pi agent va a reemplazarlo
dame el plan de accion en pasos y te apruebo a ver si me entendiste


Entendí así:

- `personal-agent` se desarma localmente.
- Los skills que valen se migran al lugar común de skills.
- `agents-database` queda como backend directo de lectura/escritura para el agente.
- Se sacan dashboard, API, daemon, `personal.py` y el servicio nginx asociado.
- Al final se borra el repo local.
- `pi agent` pasa a ser el reemplazo.

## Plan de acción

1. **Inventario corto**
   - Listar qué skills existen hoy en `personal-agent`.
   - Identificar qué artefactos/datos todavía hay que conservar.

2. **Migrar skills**
   - Copiar o instalar los skills que correspondan al directorio común de skills.
   - Verificar que queden visibles para el agente nuevo.

3. **Confirmar acceso directo a `agents-database`**
   - Probar lectura y escritura desde el agente directo.
   - Validar que no quede dependencia del runtime viejo para memoria o tareas.

4. **Retirar superficies de entrada**
   - Eliminar el dashboard web.
   - Quitar la API en `:8082`.
   - Sacar el servicio del daemon.
   - Remover el CLI `scripts/personal.py`.

5. **Limpiar integraciones**
   - Quitar cualquier config de nginx, systemd, tmux, scripts de arranque o hooks que apunten a `personal-agent`.

6. **Verificación final**
   - Confirmar que no haya procesos, puertos, servicios ni referencias activas.
   - Verificar que `pi agent` cubre lo que necesitás.

7. **Borrar repo local**
   - Una vez validado todo, borrar `/mnt/rpi/repos/opencode-harness` o el path real del repo.

Si querés, lo ejecuto con ese orden.
Respondeme solo con: **aprobado**.


skills que empiecen con personal* no las migres, el resto si
me gusta el plan, ejecutalo


**Planning skill management**

I need to execute a plan, ensuring that irreversible actions get explicit confirmation. The user has already approved this. I should start by checking the memory search first since the task relies on prior knowledge. I may also need to use the agents-database API. It’s important to move skills to a common location, ensuring I am careful when deleting anything. I need to verify where the skills are stored, likely in the /.agents/skills directory. Let's take a closer look at both the repo and skill directories.

Voy a hacer 3 cosas en orden: inventario, migración de skills no-`personal*`, y corte de superficies viejas. Después valido y borro el repo.

cd /mnt/rpi/repos/opencode-harness && find .agents/skills -maxdepth 2 -type f | sed 's#^./##' | sort && echo '---' && find .agents/skills -maxdepth 2 -mindepth 1 -type d | sed 's#^./##' | sort

cd /mnt/rpi/repos/opencode-harness && find . -maxdepth 2 \( -path './.git' -o -path './.venv' \) -prune -o -type f | sed 's#^./##' | sort | head -n 400


---
name: personal-memory-search
description: Search persisted research memory, claims, and tasks
---

# personal-memory-search

## Workflow

1. Execute:
   - `curl -fsSL "${AGENTS_DB_API:-http://100.116.176.16:8091}/api/search?q=<query>&scope=global&scope=project&limit=20"`
2. Return matching runs, claims, and tasks from the JSON response.
3. Prefer reuse of prior work before starting a new run.


.agents/skills/ballbox-company/SKILL.md
.agents/skills/karaoke-stem-separation/SKILL.md
.agents/skills/memory-write/memory-write
.agents/skills/memory-write/SKILL.md
.agents/skills/personal-memory-search/SKILL.md
.agents/skills/personal-research/SKILL.md
.agents/skills/personal-status/SKILL.md
.agents/skills/personal-task-intake/SKILL.md
.agents/skills/telegram-notify/.env.example
.agents/skills/telegram-notify/SKILL.md
.agents/skills/telegram-notify/telegram-notify
.agents/skills/temporary-file-share/SKILL.md
---
.agents/skills/ballbox-company
.agents/skills/karaoke-stem-separation
.agents/skills/memory-write
.agents/skills/personal-memory-search
.agents/skills/personal-research
.agents/skills/personal-status
.agents/skills/personal-task-intake
.agents/skills/telegram-notify
.agents/skills/temporary-file-share


AGENTS.md
ballbox-company-agent/AGENTS.md
ballbox-company-agent/index.md
ballbox-company-agent/README.md
ballbox-company-agent/what-goes-where.md
docs/raycast-codex-notify.md
docs/remote-ops.md
docs/services-architecture.md
docs/system-v1.md
.git
.githooks/pre-push
.gitignore
INSTALL.md
LICENSE
main.py
personal_agent/config.py
personal_agent/daemon.py
personal_agent/__init__.py
personal_agent/migration.py
personal_agent/planner.py
personal_agent/reporting.py
personal_agent/repo_targets.py
personal_agent/research.db
personal_agent/research_store.py
personal_agent/router.py
personal_agent/runtime.py
personal_agent/shared_memory.py
personal_agent/source_capture.py
personal_agent/web_search.py
README.md
scripts/daemon-8082.sh
scripts/install-git-hooks.sh
scripts/install-opencode.sh
scripts/install-skills.sh
scripts/launchd-8082.sh
scripts/personal.py
scripts/run-checks.sh
scripts/run-server-daemon.sh
tests/test_personal.py


**Considering skill management**

I'm thinking about common skills that might already be present. I want to inspect directory names and compare them with the target. I might need to use tools like `rsync` or `cp`. I should check if there's an AGENTS file or documentation that mentions skills. I might also search for `.agents/skills` references in the repository. Additionally, I need to think about removing scripts like `install-skills`, especially since the dashboard and API have been removed.

curl -fsSL 'http://100.116.176.16:8091/api/search?q=opencode-harness%20personal-agent%20deprecation%20skills%20daemon%208082&scope=global&scope=project&limit=10' | jq .

cd /mnt/rpi/repos/opencode-harness && rg -n "8082|daemon-8082|personal\.py|dashboard|api/status|opencode-harness|install-skills|install-opencode|personal_agent" -S .


Research run: Show open tasks in the personal-agent UI and let the operator promote them to draft

Goal: Show open tasks in the personal-agent UI and let the operator promote them to draft
Scope: personal-agent daemon UI, runtime, and task-state transition flow
Assumptions: Open is the backlog state; draft is the runtime-ready state; the UI should expose open parent tasks clearly and offer an explicit action to move selected tasks into draft without auto-starting them.
Summary: Show open tasks in the personal-agent UI and let the operator promote them to draft

Explanation: facets=0.00 lexical=0.33 semantic=0.95 confidence=0.90 freshness=0.85

Research run: Investigate personal assistant patterns

Goal: Investigate personal assistant patterns
Scope: recent setup patterns
Assumptions: v1 defaults
Summary: Seeded baseline run for personal-agent verification.

Explanation: facets=0.00 lexical=0.17 semantic=0.99 confidence=0.85 freshness=0.80

Capture Verification

Capture Verification
local verification capture
content_type=text/html
file:///tmp/personal-agent-capture.html

Explanation: facets=0.00 lexical=0.17 semantic=0.99 confidence=0.75 freshness=0.70

V1 legacy bridge policy

New durable work lives only in agents-database. Legacy personal-agent sqlite stays transition-only, with old-run inspection bridged through mirrored shared-memory records.

Summary: Legacy sqlite is transition-only; old-run inspection falls back to shared-memory mirrors.

Explanation: facets=0.00 lexical=0.17 semantic=0.99 confidence=0.96 freshness=0.95

Codex should launch with agents-database as writable extra dir

When personal-agent work needs sandboxed Codex access to the canonical shared DB, launch Codex with `--add-dir /Users/sebas/agents-database`. The real database stays inside the agents-database repo.

Summary: Use `--add-dir /Users/sebas/agents-database` for sandboxed Codex runs that need canonical shared DB write access.

Explanation: facets=0.00 lexical=0.17 semantic=0.98 confidence=0.98 freshness=0.98

Research run: Implement blocked-task workflow for dependent code and non-code work

Goal: Implement blocked-task workflow for dependent code and non-code work
Scope: personal-agent task system and runtime behavior
Assumptions: Use the current shared task model as canonical; keep dependency metadata minimal-first; support blocked-by-one-task initially; for code tasks use stacked worktree/branch workflow based on blocker branch until blocker merges.
Summary: Implement blocked-task workflow for dependent code and non-code work

Explanation: facets=0.00 lexical=0.17 semantic=0.98 confidence=0.90 freshness=0.85

Research step: Strengthen personal-agent code-task prompting for dependency context and PR outc

Explanation: facets=0.00 lexical=0.17 semantic=0.98 confidence=0.75 freshness=0.75

Research run: Strengthen personal-agent code-task prompting for dependency context and PR outcome handling

Goal: Strengthen personal-agent code-task prompting for dependency context and PR outcome handling
Scope: personal-agent runtime prompt construction and code-task execution conventions
Assumptions: Code tasks should carry explicit dependency/base-branch context into the prompt; runner should be instructed to work on top of blocker code when relevant; code-task outcomes should default to either opening a new PR or pushing to the existing dependent PR branch depending on task context and existing branch/PR state.
Summary: Strengthen personal-agent code-task prompting for dependency context and PR outcome handling

Capture: Pricing | Software automation tool for your business

Pricing | Software automation tool for your business Integrate your bookings with MATCHi Learn more Pricing Resources For clients Request demo English Spanish French Czech Create account Software that grows with your business Matchable is subscription-free for venues, independent trainers, and organizers. For business For freelancers For venues or academies Matchable takes as low as 1.8% to keep the engines running. Pay only when receiving a payment. No upfront fees, no hidden costs, not for you, not for your client. Accept payments in 36+ countries Keep track through the trainer application Add your availability and holidays Add your certifications, skills and more Instantly receive payments 1.8% / Per transaction Create account Request demo Features Private training service Unlimited services Classes and events Unlimited schedules Courses Coming soon Unlimited seasons Promotion tools Free Automated invoices Free Client CRM Unlimited clients Insights Coming soon Coming soon Recruitment Venue profile Manager Web-only manager to manage your everyday Trainer application Let your trainers manager their profile, bookings, availabilities and more. Free Multi-venue management Manage multiple venues from your manager Unlimited venues Manager seats Add multiple manager to your account Unlimited seats Payments Online payments You only pay when you get paid. Simple as that. We only take a small commission when you receive money through a booking. * Stripe or Mollie will also charge standard processing fees, which depend on the payment method selected. 1.8%* Subscription fee No monthly fee, no hidden costs Free Client fee Matchable doesn't monetise your clients, not now, not ever. Fair and square. Free Manual payment links Coming soon Coming soon In-person payments Coming soon Coming soon Manual bookings Free Matchable Marketplace (optional) No additional fee applied to new clients who discover your business via the marketplace. Free Optional add-ons Matchable Widget Show your services and activities on your own website through our widget. On request Google Calendar View your Matchable bookings in your own Apple or Google calendar. Free Stripe Receive payments Free Mollie Receive payments Free MATCHi Automate court bookings Free Coming soon Google Analytics Automate court bookings Coming soon Coming soon Meta Pixel Automate court bookings Coming soon Support Chat support Available through Manager Panel Email support Response within 24 hours Knowledge base Video Support Dedicated agent For freelancers or organisers Matchable takes as low as 1.8% to keep the engines running. Pay only when receiving a payment. No upfront fees, no hidden costs, not for you, not for your client. Accept payments in 36+ countries Manage your trainers and activities Automate your back-office Unlimited connected trainers Instantly receive payments 1.8% / Per transaction Create account Request demo Features Private training service Unlimited services Classes and events Unlimited schedules Courses Coming soon Unlimited seasons Promotion tools Free Automated invoices Free Client CRM Unlimited clients Insights Coming soon Coming soon Recruitment - Venue profile - Manager Web-only manager to manage your everyday Trainer application Let your trainers manager their profile, bookings, availabilities and more. Free Multi-venue management Manage multiple venues from your manager Unlimited venues Manager seats Add multiple manager to your account - Payments Online payments You only pay when you get paid. Simple as that. We only take a small commission when you receive money through a booking. * Stripe or Mollie will also charge standard processing fees, which depend on the payment method selected. 1.8%* Subscription fee No monthly fee, no hidden costs Free Client fee Matchable doesn't monetise your clients, not now, not ever. Fair and square. Free Manual payment links Coming soon Coming soon In-person payments Coming soon Coming soon Manual bookings Free Matchable Marketplace (optional) No additional fee applied to new clients who discover your business via the marketplace. Free Optional add-ons Matchable Widget Show your services and activities on your own website through our widget. Free Google Calendar View your Matchable bookings in your own Apple or Google calendar. Free Stripe Receive payments Free Mollie Receive payments Free MATCHi Automate court bookings Free Google Analytics Automate court bookings Coming soon Meta Pixel Automate court bookings Coming soon Support Chat support Available through Manager Panel Email support Response within 24 hours Knowledge base Video Support - Dedicated agent - Freelancer Business Pricing? Glad you asked Matchable takes as low as 1.8% to keep the engines running. Pay only when receiving a payment. No upfront fees, no hidden costs, not for you, not for your client. Accept payments in 36+ countries Keep track through the trainer application Add your availability and holidays Add your certifications, skills and more Instantly receive payments 1.8% / Per transaction Create account Request demo Manage your trainers and activities Automate your back-office Unlimited connected trainers Instantly receive payments 1.8% / Per transaction Create account Request demo Features Private training service Unlimited services Classes and events Unlimited schedules Courses Coming soon Unlimited seasons Promotion tools Free Automated invoices Free Client CRM Unlimited clients Insights Coming soon Coming soon Recruitment - Venue profile - Manager Web-only manager to manage your everyday Trainer application Let your trainers manager their profile, bookings, availabilities and more. Free Multi-venue management Manage multiple venues from your manager Unlimited venues Manager seats Add multiple manager to your account - Unlimited seats Payments Online payments You only pay when you get paid. Simple as that. We only take a small commission when you receive money through a booking. * Stripe or Mollie will also charge standard processing fees, which depend on the payment method selected. 1.8%* 1.8%* Subscription fee No monthly fee, no hidden costs Free Client fee Matchable doesn't monetise your clients, not now, not ever. Fair and square. Free Manual payment links Coming soon Coming soon In-person payments Coming soon Coming soon Manual bookings Free Matchable Marketplace (optional) No additional fee applied to new clients who discover your business via the marketplace. Free Optional add-ons Matchable Widget Show your services and activities on your own website through our widget. Free On request Google Calendar View your Matchable bookings in your own Apple or Google calendar. Free Stripe Receive payments Free Mollie Receive payments Free MATCHi Automate court bookings On request Coming soon Google Analytics Automate court bookings Coming soon Coming soon Meta Pixel Automate court bookings Coming soon Support Chat support Available through Manager Panel Email support Response within 24 hours Knowledge base Video Support - Dedicated agent - Frequently asked questions. Answered. What is Matchable? Matchable is an academy automation tool and a global marketplace in one. Trainers and venues can showcase themselves to clients and businesses to get booked instantly. You can automate lessons bookings, trainer schedules and court reservations. Players book and pay in Matchable and courts are auto-assigned in real time through MATCHi. How can I join Matchable as a venue or a trainer? We’d love to have you on the platform! Visit this page to register and we'll reach out to you as soon as possible. Is there a cost for using Matchable? Matchable takes as low as 1.8% to keep the engines running. Pay only when receiving a payment. No upfront fees, no hidden costs, not for you, not for your client. Can I still use MATCHi for my bookings? Yes, for sure! The integration is only visible in the back-office admin of the Matchable Manager. How do I offer private training as a service using Matchable and MATCHi? It’s very easy. The first step is to request your account, and from there, read this article for the step by step guide. How do I integrate with Matchable as a MATCHi club? You only have to register once, and we’ll guide you through the integration process, read the full article here for onboarding . How to contact you if I have any additional questions? We’re happy to hear from you, so you can contact us for an introduction call here or send us an email at info@getmatchable.com . Does Matchable have an App? Yes, we have a Trainer App and Client App that we recently launched. You can download them in the Apple Store or on Google Play . Marketplace Log in Create account List your business Report a bug Support Request demo Talk to sales Help Center Voucher balance Contact us Company Integrations Partnerships Company news Work with us Investor portal Tools Resource overview Talent interviews Press kit © 2025 Matchable Privacy Policy Terms of Service Cookies Settings Follow-us

Explanation: facets=0.00 lexical=0.17 semantic=0.97 confidence=0.75 freshness=0.75

Capture: How to book a training | Matchable

How to book a training | Matchable Help center Go to Matchable Czech English Spanish All collections For clients How to book a training How to book a training This article explains how to purchase a training. Open https://www.getmatchable.com/ and search for your preferred venue/trainer or sport using the search bar. Under ‘Trainers’ , you can find the trainer you’d like to book a training with. Select your trainer, or view their profile if you’d like to know more about their skills or read their reviews. Then select ‘Continue’ to proceed with the booking. As shown below, you can select the type of training. In this case, the trainer offers a ‘group lesson’ during peak and off-peak hours, as well as a ‘private 1-to-1 lesson’ . Select your preferred option. Select Number of Attendees After selecting your preference, choose the number of people who would like to attend the training. Select Training Duration Then, select the duration of the training session. Choose Your Package Select your ‘package’ . Many trainers offer discounts when you book more than one class. Review Your Purchase On the right, you’ll see a summary of your purchase. Apply Discount or Voucher Code If you have a discount or voucher code, you can apply it here. Click ‘Apply’ to activate your code. Continue to Planning Once you’re ready, click ‘Continue to planning’ to finalize your booking. You can plan your training session here, or choose to do it at a later stage. By clicking ‘Plan’ , you can check the trainer’s availability. Click your preferred date and time slot, then select ‘Confirm’ . You can log in to your existing account or create an account. Once you’ve done this, click ‘Pay’ to proceed with the payment. You will receive a confirmation email when you’ve purchased the training. Did this answer your question? 😞 😐 😁

How to book a training | Matchable

Summary: How to book a training | Matchable

Explanation: facets=0.00 lexical=0.17 semantic=0.96 confidence=0.75 freshness=0.75


./main.py:8:    daemon start   - Start the personal-agent daemon on port 8082
./AGENTS.md:28:- Codex launch convention for opencode-harness work that must write shared DB: add `--add-dir ~/agents-database` so sandboxed runs can edit the canonical DB in-repo
./AGENTS.md:33:- after changes to `personal_agent/daemon.py` or daemon-served routing/runtime code, restart `8082` before UI smoke tests; otherwise the dashboard may still serve stale behavior
./personal_agent/config.py:13:        "PERSONAL_AGENT_SHARED_MEMORY_ROOT",
./personal_agent/config.py:20:    os.environ.get("PERSONAL_AGENT_SHARED_MEMORY_DB_PATH", SHARED_MEMORY_DATA_DIR / "shared-agent-memory.sqlite3")
./personal_agent/config.py:25:        "PERSONAL_AGENT_RUNNER_ADD_DIRS",
./personal_agent/config.py:26:        os.environ.get("PERSONAL_AGENT_CODEX_ADD_DIRS", str(SHARED_MEMORY_ROOT)),
./personal_agent/config.py:31:    os.environ.get("PERSONAL_AGENT_RUNNER_BIN")
./personal_agent/config.py:32:    or os.environ.get("PERSONAL_AGENT_OPENCODE_BIN")
./personal_agent/config.py:34:    or os.environ.get("PERSONAL_AGENT_CODEX_BIN")
./personal_agent/runtime.py:16:PERSONAL_AGENT_ID = "personal-agent"
./personal_agent/runtime.py:17:PERSONAL_PROJECT_ID = "proj_personal_agent"
./personal_agent/runtime.py:69:            owner_agent=PERSONAL_AGENT_ID,
./personal_agent/runtime.py:100:            PERSONAL_AGENT_ID,
./personal_agent/runtime.py:158:    def dashboard_snapshot(self) -> dict[str, Any]:
./personal_agent/runtime.py:159:        tasks = self.service.list_tasks(owner_agent=PERSONAL_AGENT_ID, limit=200)
./personal_agent/runtime.py:271:                source_ref=PERSONAL_AGENT_ID,
./personal_agent/runtime.py:307:                source_ref=PERSONAL_AGENT_ID,
./personal_agent/runtime.py:361:        tasks = self.service.list_tasks(owner_agent=PERSONAL_AGENT_ID, status="draft", limit=200)
./INSTALL.md:30:git clone https://github.com/sebasfavaron/opencode-harness.git
./INSTALL.md:49:python3 scripts/personal.py research start --json   --goal "Investigate local-first personal assistant patterns"   --scope "starter implementation ideas"   --assumptions "foundation repo only"
./INSTALL.md:55:python3 scripts/personal.py research search-web --json   --run-id "<run-id>"   --query "local-first personal assistant patterns"   --max-results 5
./INSTALL.md:57:python3 scripts/personal.py research capture-url --json   --run-id "<run-id>"   --url "https://example.com"   --notes "why this source matters"
./INSTALL.md:59:python3 scripts/personal.py research add-source --json   --run-id "<run-id>"   --url "https://example.com"   --title "Example source"
./INSTALL.md:61:python3 scripts/personal.py research add-claim --json   --run-id "<run-id>"   --claim "Example finding"   --confidence 0.6   --status tentative   --source-url "https://example.com"
./INSTALL.md:67:python3 scripts/personal.py report --run-id "<run-id>" --format md
./INSTALL.md:83:export PERSONAL_AGENT_SHARED_MEMORY_DB_PATH=/absolute/path/to/shared-agent-memory.sqlite3
./INSTALL.md:91:curl -fsSL https://raw.githubusercontent.com/sebasfavaron/opencode-harness/main/scripts/install-opencode.sh | sh
./INSTALL.md:97:curl -fsSL https://raw.githubusercontent.com/sebasfavaron/opencode-harness/main/scripts/install-opencode.sh | sh -s -- restore
./INSTALL.md:111:./scripts/install-skills.sh
./INSTALL.md:122:python3 scripts/personal.py route --json   --input "Ballbox necesita fix en repo de pagos"   --execute
./scripts/daemon-8082.sh:5:PORT="8082"
./scripts/daemon-8082.sh:7:LOG_FILE="/tmp/personal-agent-daemon-8082.log"
./scripts/daemon-8082.sh:8:PID_FILE="/tmp/personal-agent-daemon-8082.pid"
./scripts/daemon-8082.sh:9:LAUNCHD_HELPER="${ROOT}/scripts/launchd-8082.sh"
./scripts/daemon-8082.sh:16:  curl -fsS "http://${HOST}:${PORT}/api/status" >/dev/null 2>&1
./scripts/daemon-8082.sh:23:  [[ "$command" == *"scripts/personal.py daemon"* ]]
./scripts/daemon-8082.sh:122:    setsid python3 scripts/personal.py daemon --host "$HOST" --port "$PORT" < /dev/null >"$LOG_FILE" 2>&1 &
./scripts/daemon-8082.sh:124:    nohup python3 scripts/personal.py daemon --host "$HOST" --port "$PORT" < /dev/null >"$LOG_FILE" 2>&1 &
./scripts/daemon-8082.sh:186:      echo "status http://${HOST}:${PORT}/api/status"
./scripts/daemon-8082.sh:213:  echo "status http://${HOST}:${PORT}/api/status"
./scripts/daemon-8082.sh:236:      python3 scripts/personal.py pause-running --reason "daemon-8082.sh restart on ${HOST}:${PORT}"
./scripts/daemon-8082.sh:243:    python3 scripts/personal.py pause-running --reason "daemon-8082.sh restart on ${HOST}:${PORT}"
./scripts/daemon-8082.sh:251:Usage: ./scripts/daemon-8082.sh {start|stop|restart|status|logs}
./scripts/launchd-8082.sh:6:PORT="8082"
./scripts/launchd-8082.sh:7:LABEL="com.sebas.personal-agent.daemon-8082"
./scripts/launchd-8082.sh:9:LOG_FILE="/tmp/personal-agent-daemon-8082.log"
./scripts/launchd-8082.sh:10:ERR_FILE="/tmp/personal-agent-daemon-8082.err.log"
./scripts/launchd-8082.sh:25:    <string>scripts/personal.py</string>
./scripts/launchd-8082.sh:89:Usage: ./scripts/launchd-8082.sh {install|uninstall|start|stop|restart|status|logs}
./scripts/install-opencode.sh:4:REPO_DEFAULT="sebasfavaron/opencode-harness"
./scripts/install-opencode.sh:7:REPO="${PERSONAL_AGENT_REPO:-$REPO_DEFAULT}"
./scripts/install-opencode.sh:8:REF="${PERSONAL_AGENT_REF:-$REF_DEFAULT}"
./scripts/install-opencode.sh:9:RAW_BASE="${PERSONAL_AGENT_RAW_BASE:-https://raw.githubusercontent.com/${REPO}/${REF}}"
./scripts/install-opencode.sh:11:LOCAL_PATH="${PERSONAL_AGENT_LOCAL_PATH:-}"
./scripts/install-opencode.sh:21:MANAGED_STATE_DIR="${HOME}/.agents/opencode-harness-install"
./ballbox-company-agent/what-goes-where.md:26:- dashboard
./personal_agent/repo_targets.py:12:        "repo_personal_agent": {
./personal_agent/repo_targets.py:13:            "id": "repo_personal_agent",
./personal_agent/research_store.py:15:PERSONAL_AGENT_ID = "personal-agent"
./personal_agent/research_store.py:16:PERSONAL_PROJECT_ID = "proj_personal_agent"
./personal_agent/research_store.py:223:        "owner_agent": PERSONAL_AGENT_ID,
./personal_agent/research_store.py:637:        owner_agent=PERSONAL_AGENT_ID,
./tests/test_personal.py:314:            "PERSONAL_AGENT_DATA_DIR": os.environ.get("PERSONAL_AGENT_DATA_DIR"),
./tests/test_personal.py:315:            "PERSONAL_AGENT_SHARED_MEMORY_ROOT": os.environ.get("PERSONAL_AGENT_SHARED_MEMORY_ROOT"),
./tests/test_personal.py:316:            "PERSONAL_AGENT_SHARED_MEMORY_DB_PATH": os.environ.get("PERSONAL_AGENT_SHARED_MEMORY_DB_PATH"),
./tests/test_personal.py:318:        os.environ["PERSONAL_AGENT_DATA_DIR"] = self.tmp.name
./tests/test_personal.py:319:        os.environ["PERSONAL_AGENT_SHARED_MEMORY_ROOT"] = str(self.agents_db_dir)
./tests/test_personal.py:320:        os.environ["PERSONAL_AGENT_SHARED_MEMORY_DB_PATH"] = str(Path(self.tmp.name) / "shared-agent-memory.sqlite3")
./tests/test_personal.py:322:        from personal_agent import config
./tests/test_personal.py:323:        from personal_agent import shared_memory
./tests/test_personal.py:343:        self.runtime_memory_patcher = patch("personal_agent.runtime.get_memory_service", return_value=self.fake_operational_memory)
./tests/test_personal.py:345:            "personal_agent.research_store.shared_memory.get_memory_service",
./tests/test_personal.py:352:        from personal_agent import config
./tests/test_personal.py:353:        from personal_agent import shared_memory
./tests/test_personal.py:385:        from personal_agent.runtime import PersonalAgentRuntime
./tests/test_personal.py:398:        from personal_agent import repo_targets
./tests/test_personal.py:424:        from personal_agent.research_store import add_structured_task
./tests/test_personal.py:434:        self.assertEqual(parent["project_id"], "proj_personal_agent")
./tests/test_personal.py:441:        from personal_agent.runtime import PersonalAgentRuntime
./tests/test_personal.py:475:        with patch("personal_agent.runtime.subprocess.Popen", FakePopen):
./tests/test_personal.py:489:        from personal_agent.runtime import PersonalAgentRuntime
./tests/test_personal.py:514:        with patch("personal_agent.runtime.subprocess.Popen", FakePopen):
./tests/test_personal.py:526:        from personal_agent.runtime import PersonalAgentRuntime
./tests/test_personal.py:535:        from personal_agent.runtime import PersonalAgentRuntime
./tests/test_personal.py:544:            project_id="proj_personal_agent",
./tests/test_personal.py:569:        with patch("personal_agent.runtime.subprocess.Popen", FakePopen):
./tests/test_personal.py:583:        from personal_agent.runtime import PersonalAgentRuntime
./tests/test_personal.py:610:        with patch("personal_agent.runtime.subprocess.Popen", FakePopen):
./tests/test_personal.py:625:    def test_dashboard_snapshot_groups_drafts_running_failed_and_results(self) -> None:
./tests/test_personal.py:626:        from personal_agent.runtime import PersonalAgentRuntime
./tests/test_personal.py:635:            project_id="proj_personal_agent",
./tests/test_personal.py:646:            project_id="proj_personal_agent",
./tests/test_personal.py:656:            project_id="proj_personal_agent",
./tests/test_personal.py:670:        payload = runtime.dashboard_snapshot()
./tests/test_personal.py:683:        from personal_agent.research_store import next_tasks
./tests/test_personal.py:706:        from personal_agent.research_store import add_claim, add_source, get_run, start_research
./tests/test_personal.py:707:        from personal_agent.shared_memory import PERSONAL_MEMORY_SCHEMA
./tests/test_personal.py:725:        from personal_agent.research_store import list_approvals, request_approval, resolve_approval
./tests/test_personal.py:740:        from personal_agent.migration import migrate_legacy_memory
./tests/test_personal.py:741:        from personal_agent.research_store import get_run, list_approvals
./tests/test_personal.py:810:        from personal_agent.daemon import PersonalAgentHandler
./tests/test_personal.py:811:        from personal_agent.runtime import PersonalAgentRuntime
./tests/test_personal.py:862:        with patch("personal_agent.runtime.subprocess.Popen", FakePopen):
./tests/test_personal.py:873:            status_handler = TestHandler("GET", "/api/status")
./tests/test_personal.py:889:        from personal_agent.daemon import PersonalAgentHandler
./tests/test_personal.py:893:            "Abrir [USECASE.md](http://127.0.0.1:8082/artifacts/art_b90cb99f638c45ecbb358d2f51cdad89) y `code`."
./tests/test_personal.py:915:                "content": '[safe](javascript:alert(1)) [ok](http://127.0.0.1:8082/artifacts/art-1)',
./tests/test_personal.py:925:        from personal_agent.runtime import PERSONAL_AGENT_ID, PersonalAgentRuntime
./tests/test_personal.py:931:            owner_agent=PERSONAL_AGENT_ID,
./tests/test_personal.py:956:        with patch("personal_agent.runtime.subprocess.Popen", FakePopen):
./tests/test_personal.py:970:        from personal_agent.daemon import PersonalAgentHandler
./tests/test_personal.py:983:        from personal_agent.daemon import PersonalAgentHandler
./systemd/user/personal-agent.service:10:Environment=PORT=8082
./personal_agent/daemon.py:148:        const response = await fetch('/api/status');
./personal_agent/daemon.py:289:        if parsed.path == "/api/status":
./personal_agent/daemon.py:290:            self._send_json(self.server.runtime.dashboard_snapshot())
./personal_agent/daemon.py:396:
Back to dashboard

./personal_agent/daemon.py:441:
Back to dashboard

./personal_agent/daemon.py:706:def run_server(host: str = "127.0.0.1", port: int = 8082, interval_seconds: float = 5.0) -> None:
./personal_agent/planner.py:191:            '  "target_repo_id": "repo_personal_agent|repo_ai_dev_workflow|repo_ballbox_company_agent|null",',
./personal_agent/planner.py:202:            "- Set target_repo_id when the request names a repo or clearly implies one; for 'this repo' use repo_personal_agent.",
./personal_agent/shared_memory.py:13:PERSONAL_AGENT_ID = "personal-agent"
./personal_agent/shared_memory.py:14:PERSONAL_PROJECT_ID = "proj_personal_agent"
./personal_agent/shared_memory.py:127:    if metadata.get("schema") != PERSONAL_MEMORY_SCHEMA and metadata.get("legacy_system") != PERSONAL_AGENT_ID:
./personal_agent/shared_memory.py:217:            owner_agent=PERSONAL_AGENT_ID,
./ballbox-company-agent/scripts/ballbox_company_agent.py:176:def cmd_dashboard(_: argparse.Namespace) -> int:
./ballbox-company-agent/scripts/ballbox_company_agent.py:275:    dashboard = sub.add_parser("dashboard")
./ballbox-company-agent/scripts/ballbox_company_agent.py:276:    dashboard.set_defaults(func=cmd_dashboard)
./scripts/personal.py:14:from personal_agent.daemon import run_server
./scripts/personal.py:15:from personal_agent.migration import migrate_legacy_memory
./scripts/personal.py:16:from personal_agent.reporting import build_report
./scripts/personal.py:17:from personal_agent.research_store import (
./scripts/personal.py:38:from personal_agent.router import route_request
./scripts/personal.py:39:from personal_agent.runtime import PersonalAgentRuntime
./scripts/personal.py:114:    daemon.add_argument("--port", type=int, default=8082)
./scripts/personal.py:289:        _print(runtime.dashboard_snapshot(), args.as_json)
./scripts/run-server-daemon.sh:6:PORT="${PORT:-8082}"
./scripts/run-server-daemon.sh:15:if [ -z "${PERSONAL_AGENT_RUNNER_BIN:-}" ]; then
./scripts/run-server-daemon.sh:16:  PERSONAL_AGENT_RUNNER_BIN="$(command -v opencode || true)"
./scripts/run-server-daemon.sh:19:if [ -z "${PERSONAL_AGENT_RUNNER_BIN}" ]; then
./scripts/run-server-daemon.sh:24:export PERSONAL_AGENT_RUNNER_BIN
./scripts/run-server-daemon.sh:26:exec python3 "${REPO_ROOT}/scripts/personal.py" daemon --host "${HOST}" --port "${PORT}"
./README.md:1:# opencode-harness
./README.md:19:`opencode-harness` now grows toward a front-door runtime:
./README.md:21:- daemon + dashboard at `127.0.0.1:8082`
./README.md:25:- dashboard/CLI snapshot with drafts, active runs, failed runs, and recent results
./README.md:43:- internal command surface via `python3 scripts/personal.py`
./README.md:53:- `memory-migrate` rewrites legacy opencode-harness metadata into the canonical shared-memory schema
./README.md:65:- `PERSONAL_AGENT_SHARED_MEMORY_ROOT`
./README.md:66:- `PERSONAL_AGENT_SHARED_MEMORY_DB_PATH`
./README.md:67:- `PERSONAL_AGENT_RUNNER_BIN`
./README.md:68:- `PERSONAL_AGENT_RUNNER_ADD_DIRS`
./README.md:69:- `PERSONAL_AGENT_CODEX_ADD_DIRS` remains legacy-compatible env input for add-dir lists
./README.md:83:`opencode-harness` is the intended front door.
./README.md:93:opencode-harness/
./README.md:96:├── personal_agent/
./README.md:106:python3 scripts/personal.py research start --goal "Investigate X"
./README.md:107:python3 scripts/personal.py research search-web --run-id <id> --query "best local-first assistants"
./README.md:108:python3 scripts/personal.py research capture-url --run-id <id> --url https://example.com
./README.md:109:python3 scripts/personal.py research add-source --run-id <id> --url https://example.com
./README.md:110:python3 scripts/personal.py report --run-id <id> --format md
./README.md:111:python3 scripts/personal.py memory-search --query "X"
./README.md:112:python3 scripts/personal.py memory-migrate
./README.md:113:python3 scripts/personal.py route --input "Ballbox necesita fix en repo de pagos" --execute
./README.md:114:python3 scripts/personal.py --json status
./README.md:115:python3 scripts/personal.py approvals list
./README.md:116:python3 scripts/personal.py --json approvals resolve --approval-id <id> --status approved --note "safe to proceed"
./README.md:117:python3 scripts/personal.py tasks next
./README.md:118:python3 scripts/personal.py leisure add --title "Severance" --media-type series
./README.md:119:python3 scripts/personal.py leisure list --media-type series
./README.md:126:- canonical UI endpoint: `http://127.0.0.1:8082/`
./README.md:127:- canonical status JSON endpoint: `http://127.0.0.1:8082/api/status`
./README.md:129:  - `./scripts/daemon-8082.sh start`
./README.md:130:  - `./scripts/daemon-8082.sh stop`
./README.md:131:  - `./scripts/daemon-8082.sh restart`
./README.md:132:  - `./scripts/daemon-8082.sh status`
./README.md:133:  - `./scripts/daemon-8082.sh logs`
./README.md:148:- `scripts/install-opencode.sh` installs skills + OpenCode rules without cloning (see INSTALL.md)
./README.md:149:- `scripts/install-skills.sh` links skills into `~/.agents/skills`
./ballbox-company-agent/README.md:11:- `index.md`: root dashboard
./ballbox-company-agent/README.md:22:- `scripts/ballbox_company_agent.py`: shared-memory + dashboard CLI
./ballbox-company-agent/README.md:48:python3 scripts/ballbox_company_agent.py dashboard
./docs/system-v1.md:9:  - dashboard at `127.0.0.1:8082`
./docs/system-v1.md:39:- orchestration code, daemon, dashboard, CLI: `personal-agent`
./docs/system-v1.md:89:   - run `~/personal-agent/scripts/install-opencode.sh`
./docs/system-v1.md:91:   - `python3 ~/personal-agent/scripts/personal.py status --json`
./docs/system-v1.md:93:   - `python3 ~/personal-agent/scripts/personal.py daemon`
./docs/system-v1.md:94:8. Open the dashboard.
./docs/system-v1.md:95:   - `http://127.0.0.1:8082`
./docs/system-v1.md:101:- canonical UI endpoint: `http://127.0.0.1:8082/`
./docs/system-v1.md:102:- canonical status endpoint: `http://127.0.0.1:8082/api/status`
./docs/system-v1.md:106:- `personal-agent` status command returns dashboard JSON
./docs/system-v1.md:107:- `personal.py` accepts `--json` before or after subcommands
./docs/system-v1.md:108:- dashboard loads at `:8082`
./docs/raycast-codex-notify.md:220:- `scripts/personal.py` still defines `blocker reply` args
./docs/raycast-codex-notify.md:222:- `personal_agent/runtime.py` direct runner has no live human-reply pause/resume path
./docs/raycast-codex-notify.md:229:- docs or future refactors should not assume replies route through `python3 scripts/personal.py blocker reply`
./docs/remote-ops.md:6:- server `personal-agent`: task runner API on `http://100.116.176.16:8082`
./docs/remote-ops.md:22:curl http://100.116.176.16:8082/api/status
./docs/remote-ops.md:23:curl http://100.116.176.16:8091/api/status
./docs/remote-ops.md:31:- `PERSONAL_AGENT_RUNNER_BIN` overrides the runner binary when needed.
./docs/services-architecture.md:13:| `http://100.116.176.16:8082/api/status` | `:8082` (personal-agent daemon) | Personal Agent API directa por Tailscale IP |
./docs/services-architecture.md:14:| `http://100.116.176.16:8091/api/status` | `:8091` (agents-database HTTP API) | Shared memory + tasks/artifacts API directa por Tailscale IP |
./docs/services-architecture.md:21:| `:8082` | personal-agent daemon | API del personal agent |
./docs/services-architecture.md:41:curl http://100.116.176.16:8082/api/status
./docs/services-architecture.md:44:curl http://100.116.176.16:8091/api/status
./docs/services-architecture.md:87:curl http://100.116.176.16:8082/api/status
./docs/services-architecture.md:88:curl http://100.116.176.16:8091/api/status
./config/opencode/AGENTS.md:33:- personal-agent API: http://100.116.176.16:8082/api/status
./config/opencode/AGENTS.md:34:- agents-database API: http://100.116.176.16:8091/api/status
./config/opencode/AGENTS.md:69:- Personal Agent API: `http://100.116.176.16:8082/api/status` -> `:8082`
./config/opencode/AGENTS.md:70:- Agents Database API: `http://100.116.176.16:8091/api/status` -> `:8091`
./ballbox-company-agent/SOP/morning-brief.md:3:1. Read [root dashboard](../index.md).


systemctl --user is-active personal-agent.service 2>/dev/null || true; systemctl --user status personal-agent.service --no-pager 2>/dev/null | sed -n '1,80p' || true

ls -la ~/.agents/skills && echo '---' && find ~/.agents/skills -maxdepth 2 -type f | sed 's#^/home/sebas/##' | sort

find /etc/nginx -maxdepth 3 -type f | xargs -r rg -n "8082|personal-agent|opencode-harness|daemon-8082|scripts/personal.py" -S


active
● personal-agent.service - Personal Agent daemon
     Loaded: loaded (/home/sebas/.config/systemd/user/personal-agent.service; enabled; preset: enabled)
     Active: active (running) since Tue 2026-04-21 01:19:35 -03; 22h ago
 Invocation: 8c8143fff0844d8da4cee5042981f188
   Main PID: 1908 (python3)
      Tasks: 1 (limit: 9571)
        CPU: 5.055s
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/personal-agent.service
             └─1908 python3 /home/sebas/personal-agent/scripts/personal.py daemon --host 0.0.0.0 --port 8082

Apr 21 23:32:26 ballbox-first run-server-daemon.sh[1908]:   File "/usr/lib/python3.13/http/server.py", line 424, in handle_one_request
Apr 21 23:32:26 ballbox-first run-server-daemon.sh[1908]:     method()
Apr 21 23:32:26 ballbox-first run-server-daemon.sh[1908]:     ~~~~~~^^
Apr 21 23:32:26 ballbox-first run-server-daemon.sh[1908]:   File "/mnt/rpi/repos/opencode-harness/personal_agent/daemon.py", line 306, in do_GET
Apr 21 23:32:26 ballbox-first run-server-daemon.sh[1908]:     self._send_html(self._artifact_page(self.server.runtime.service.get_artifact(artifact_id)))
Apr 21 23:32:26 ballbox-first run-server-daemon.sh[1908]:                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
Apr 21 23:32:26 ballbox-first run-server-daemon.sh[1908]:   File "/mnt/rpi/agents-database/src/shared_agent_memory/service.py", line 892, in get_artifact
Apr 21 23:32:26 ballbox-first run-server-daemon.sh[1908]:     raise KeyError(artifact_id)
Apr 21 23:32:26 ballbox-first run-server-daemon.sh[1908]: KeyError: '~'
Apr 21 23:32:26 ballbox-first run-server-daemon.sh[1908]: ----------------------------------------


lrwxrwxrwx 1 sebas sebas 46 Apr 11 16:22 /home/sebas/.agents/skills -> /mnt/rpi/repos/opencode-harness/.agents/skills
---


(no output)

Command exited with code 123


readlink -f /home/sebas/.agents/skills && echo '---' && ls -la /home/sebas/.agents/skills

find /home/sebas/.agents -maxdepth 2 -type d | sort


total 24
drwxr-xr-x   5 sebas sebas 4096 Apr 21 10:29 .
drwx--x---+ 35 sebas sebas 4096 Apr 21 23:36 ..
drwxr-xr-x   3 sebas sebas 4096 Apr 21 16:25 extensions
drwxrwxr-x   2 sebas sebas 4096 Apr 14 22:59 opencode-harness-install
-rw-r--r--   1 sebas sebas  420 Apr 14 11:07 .skill-lock.json
lrwxrwxrwx   1 sebas sebas   46 Apr 11 16:22 skills -> /mnt/rpi/repos/opencode-harness/.agents/skills
drwxr-xr-x   7 sebas sebas 4096 Apr 11 16:14 skills.bck


/mnt/rpi/repos/opencode-harness/.agents/skills
---
lrwxrwxrwx 1 sebas sebas 46 Apr 11 16:22 /home/sebas/.agents/skills -> /mnt/rpi/repos/opencode-harness/.agents/skills


/home/sebas/.agents
/home/sebas/.agents/extensions
/home/sebas/.agents/extensions/resume-hint
/home/sebas/.agents/opencode-harness-install
/home/sebas/.agents/skills.bck
/home/sebas/.agents/skills.bck/personal-memory-search
/home/sebas/.agents/skills.bck/personal-research
/home/sebas/.agents/skills.bck/personal-status
/home/sebas/.agents/skills.bck/personal-task-intake
/home/sebas/.agents/skills.bck/telegram-notify


**Managing skills backup**

I think the `skills.bck` backup might contain personal skills, possibly linked due to a symlink. I need to inspect this. I should keep anything labeled personal in the repo until it’s deleted, but if the repo goes, the symlink will break. I need to replace that with a new directory for non-personal skills and maybe restore the personal skills as backups. I feel like I need to verify which files are personal while ensuring non-personal skills are accessible. The user explicitly said not to migrate personal skills, but they might vanish without a proper plan!

**Considering skill management**

Maybe it’s intended for the personal skills to be replaced by the pi agent, so they can eventually be removed. I should inspect `skills.bck` to see if it can remain untouched as a backup. If the repo is deleted, the symlink will break, but personal skills might still exist in `.agents/skills.bck`. I’ll need to create a real directory for common skills and set up `/.agents/skills` for non-personal ones. It's important to preserve scripts and ensure everything works for skill discovery! I’ll manage moving non-personal skills out of the repo while leaving personal skills there before deletion.

**Managing personal and non-personal skills**

The user clearly stated not to migrate personal skills, so maybe I should just delete them with the repo. I need to check the non-personal skills to see if they reference any repo paths before deciding how to copy them. There’s a `memory-write` subfolder containing a script. Since `/.agents/skills` is currently linked to the repo, I could move everything into a real directory, including this memory-write section. I should also ensure the existing `skills.bck` is retained while reviewing its contents for any older skill copies.

Descubrí algo importante: `~/.agents/skills` hoy es un symlink al repo que vamos a borrar. Si no lo reemplazo, te rompo la discovery de skills. Voy a convertirlo en dir real primero y dejar ahí los skills migrados.

**Planning service modification**

I might need to inspect the .agents/skills.bck file as a target, but creating a fresh version is also an option. We could modify it with bash/cp and consider using rsync.

First, I’ll plan operational steps such as stopping and disabling the personal-agent service. I’ll check the systemd user unit file in /.config/systemd/user/personal-agent.service to remove it. It might be wise to back up, but I believe it’s okay to proceed with irreversible changes. I also need to look for any cron jobs or other references related to the service.

rg -n "personal-agent|8082|daemon-8082|scripts/personal\.py|opencode-harness" /home/sebas/.config /home/sebas/.local /etc/nginx /etc/systemd /etc/xdg 2>/dev/null | sed -n '1,200p'

find /home/sebas/.config/systemd/user -maxdepth 1 -type f -name '*personal*' -o -name '*opencode*' -o -name '*8082*' | sort


[Unit]
Description=Personal Agent daemon
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=/home/sebas/personal-agent
Environment=HOST=0.0.0.0
Environment=PORT=8082
Environment=PERSONAL_AGENT_SHARED_MEMORY_ROOT=/mnt/rpi/agents-database
ExecStart=/home/sebas/personal-agent/scripts/run-server-daemon.sh
Restart=always
RestartSec=10

[Install]
WantedBy=default.target


ls -ld /home/sebas/personal-agent /mnt/rpi/repos/opencode-harness

find /home/sebas -maxdepth 2 -type l -lname '*opencode-harness*' -o -lname '*personal-agent*' | sort

readlink -f /home/sebas/personal-agent || true


lrwxrwxrwx  1 sebas sebas   31 Apr 11 16:22 /home/sebas/personal-agent -> /mnt/rpi/repos/opencode-harness
drwxr-xr-x 14 sebas sebas 4096 Apr 16 16:28 /mnt/rpi/repos/opencode-harness


/home/sebas/AGENTS.md.bck
/home/sebas/.agents/skills
/home/sebas/opencode-harness
/home/sebas/personal-agent


ls -ld /home/sebas/opencode-harness /home/sebas/personal-agent

readlink -f /home/sebas/opencode-harness || true


lrwxrwxrwx 1 sebas sebas 31 Apr 11 16:22 /home/sebas/opencode-harness -> /mnt/rpi/repos/opencode-harness
lrwxrwxrwx 1 sebas sebas 31 Apr 11 16:22 /home/sebas/personal-agent -> /mnt/rpi/repos/opencode-harness


**Considering repo deletion cleanup**

If the repository is being deleted, it might not matter much, but maybe I should consider removing more items first. The user wants the repo deleted, so cleaning up within it might be unnecessary. However, before deletion, I think I'll disable the service and remove symlinks to ensure everything is tidy. Since the service file references `scripts/run-server-daemon.sh`, this might create issues if the repo is gone, so I'll focus on removing the service file and symlink first.

**Checking nginx and agents**

I’m considering using `nginx -T`, but maybe that’s unnecessary since I’m searching through `/etc/nginx` and not finding anything. It seems like there’s no file, so no nginx action will be needed. It's important to ensure that the `agents-database` can be read and written to directly by the agent. Since the personal-agent will be gone, perhaps the pi agent can take over. I should also check if `/.agents/skills.bck` has a backup of personal skills.

Voy a tratar esto como decommission real: primero saco el servicio vivo y las rutas que lo hacen arrancar; después hago la migración de skills y al final borro el árbol.

**Examining service management steps**

I need to stop the service and disable or uninstall it. First, I should check the systemctl --user daemon-reload, and also see if the service is currently active. My plan is to stop, disable, and then remove the unit. If necessary, I might have to kill the process and remove symlinks afterward. I guess tackling the service first makes the most sense!

systemctl --user disable --now personal-agent.service

rm -f /home/sebas/.config/systemd/user/personal-agent.service && systemctl --user daemon-reload


Removed '/home/sebas/.config/systemd/user/default.target.wants/personal-agent.service'.


(no output)


systemctl --user is-active personal-agent.service 2>/dev/null || true; systemctl --user status personal-agent.service --no-pager 2>/dev/null | sed -n '1,20p' || true


inactive


**Organizing skills migration**

I need to migrate skills by creating a real directory at `/home/sebas/.agents/skills`, considering if I should backup from the repository. The existing symlink might complicate things, so removing that first makes sense. I'll create the new directory and copy over non-personal skills from the repo while preserving any existing custom skills — although it looks like there aren’t any there. I’ll also need to ensure I'm copying only the right directories and potentially include `ballbox-company`.

**Inspecting ballbox-company skill**

I think that the `ballbox-company` skill might need a repo-local path, but it seems likely to be okay. I should check its content for any relative paths to the repo-local setup. If I'm transferring the skill from the repo to the common space, the instruction might remain intact, but I need to ensure that it doesn’t reference a repo-local path that will disappear. A quick inspection of the skill files should help clarify this.


---
name: ballbox-company
description: Load Ballbox company context and operating namespace
---

# ballbox-company

## Purpose

Load the Ballbox company operating context when the request is about Ballbox.

## Workflow

1. Use the Ballbox namespace at `/mnt/rpi/repos/personal-agent/ballbox-company-agent` as the working context root.
2. Read `/mnt/rpi/repos/personal-agent/ballbox-company-agent/AGENTS.md` and follow its rules.
3. Use `/mnt/rpi/repos/personal-agent/ballbox-company-agent/index.md` as the default dashboard entry point.
4. Prefer shared-memory search before assuming facts; avoid invented certainty.
5. If the work implies repo/code changes, delegate to `~/ai-dev-workflow`.


---
name: karaoke-stem-separation
description: Create a local karaoke or instrumental track from a user-provided audio file
---

# karaoke-stem-separation

## Use When

- the user provides a local audio file they already have
- they want a karaoke, instrumental, or vocal stem
- output quality matters more than speed

## Preferred Workflow

1. Confirm the source file exists and inspect it with `ffprobe`.
2. Prefer real stem separation with Demucs over simple stereo center cancellation.
3. **Default heavy work target is Sebas laptop** via Tailscale SSH host `sebastians-macbook-pro-2` when available.
4. Laptop-first flow:
   - copy source audio to `~/tmp/karaoke-share/` on the laptop
   - create/reuse venv at `~/.cache/demucs-venv`
   - install `demucs` there if missing
   - run Demucs on laptop CPU: `python -m demucs -n htdemucs --two-stems vocals --mp3 --mp3-bitrate 320 --mp3-preset 2 -d cpu -o "<output-dir>" "<input-file>"`
   - copy resulting `no_vocals.mp3` back to the original machine near the source, usually with suffix `_karaoke_demucs.mp3`
5. If laptop path is unavailable or fails, fall back to local Pi execution.
6. On local Pi fallback, use `/mnt/rpi/tmp` for temp files and caches and `/mnt/rpi/Music` or a nearby writable path for outputs.
7. If needed on local Pi, ensure the system packages exist:
   - `sudo apt-get install -y python3-torch python3-torchaudio python3-antlr4`
8. Create a local venv that reuses system packages:
   - `python3 -m venv --system-site-packages "/mnt/rpi/tmp/demucs-venv-sys"`
9. Install the lighter Python packages into that local venv:
   - `TMPDIR="/mnt/rpi/tmp" PIP_CACHE_DIR="/mnt/rpi/tmp/pip-cache" "/mnt/rpi/tmp/demucs-venv-sys/bin/pip" install --no-deps demucs dora-search einops julius lameenc openunmix omegaconf retrying submitit treetable`
10. Run local Demucs on CPU with vocals split out:
   - `TMPDIR="/mnt/rpi/tmp" XDG_CACHE_HOME="/mnt/rpi/tmp/.cache" "/mnt/rpi/tmp/demucs-venv-sys/bin/python" -m demucs -n htdemucs --two-stems vocals --mp3 --mp3-bitrate 320 --mp3-preset 2 -d cpu -o "<output-dir>" "<input-file>"`
11. The instrumental will be `no_vocals.mp3`; copy it to a clearly named final file near the source.
12. Verify the final file with `ffprobe` and share it if requested.

## Fallback

- if Demucs is unavailable, `ffmpeg` center cancellation can be used as a last resort, but call out that quality will often be worse and vocals may remain

## Rules

- never modify the original source file
- do not delete the original downloaded/reference track after making karaoke; keep it beside the derived output unless the user explicitly asks to remove it
- create a new output file with a clear suffix like `_karaoke_demucs.mp3`
- prefer Sebas laptop first for CPU-heavy separation work; if that fails, fall back local
- prefer CPU mode on this Raspberry Pi unless there is a known accelerator configured
- when using laptop, bring final output back to the original source directory or its nearby `karaoke/` subdir
- if root disk space is tight, clear only temporary caches you created and keep heavy caches under `/mnt/rpi/tmp`
- do not claim center cancellation is true stem separation


---
name: memory-write
description: Save a durable high-signal memory into agents-database
---

# memory-write

## Use When

- new information is likely useful beyond current chat or task
- saving a decision, preference, project fact, reusable source/artifact, or handoff summary
- user asks to remember something durable

## Do Not Use When

- content is trivial, redundant, ephemeral, or likely useless later
- content is secret unless user explicitly asked to store it

## Required Workflow

1. If useful context may already exist, optionally check first:
   - `curl -fsSL "${AGENTS_DB_API:-http://100.116.176.16:8091}/api/search?q=<query>&scope=global&scope=project&limit=10"`
2. Choose best memory type:
   - `profile`: stable user preference, priority, recurring constraint
   - `decision`: chosen approach or operating rule
   - `project`: durable project fact or invariant
   - `artifact`: reusable source, claim, reference, output
   - `episode`: concise session summary, blocked state, handoff context
3. Build a concise payload with:
   - required: `type`, `scope`, `title`, `content`
   - recommended when known: `subtype`, `project_id`, `repo_id`, `task_id`, `run_id`, `source_ref`, `origin_agent`, `url`, `domain`, `metadata`
4. Save it with the helper:
   - `~/.agents/skills/memory-write/memory-write --type <type> --scope <scope> --title "<title>" --content "<content>"`
5. Confirm the created memory id and what was stored.

## Quick Examples

```bash
~/.agents/skills/memory-write/memory-write \
  --type profile \
  --subtype working_preference \
  --scope global \
  --title "User prefers concise status updates" \
  --content "Sebas prefers short, direct updates with business impact first." \
  --source-ref "conversation:2026-04-17" \
  --origin-agent personal-agent

~/.agents/skills/memory-write/memory-write \
  --type decision \
  --subtype operating_rule \
  --scope global \
  --title "Agents should save durable high-signal memory opportunistically" \
  --content "Treat agents-database as shared durable memory, not only search." \
  --metadata '{"source":"conversation"}'
```

## Rules

- prefer one strong memory over many weak ones
- keep `title` short and searchable
- keep `content` factual and compact
- use `episode` for summaries, not for every chat turn
- include `url` and `domain` for web-derived artifacts when known
- include `project_id`, `repo_id`, `task_id`, and `run_id` when context exists


---
name: telegram-notify
description: Send Telegram notifications via bot
---

# telegram-notify

## Workflow

1. Ensure environment variables are set (or stored in `~/.agents/skills/telegram-notify/.env`):
   - `TELEGRAM_BOT_TOKEN`
   - `TELEGRAM_CHAT_ID`
2. Execute:
   - `~/.agents/skills/telegram-notify/telegram-notify "<message>"`
3. Confirm that the message was sent.

## Rules

- never print the token or chat id in outputs
- keep messages concise and action-oriented


---
name: temporary-file-share
description: Expose a local directory or file briefly over HTTP for same-network or Tailscale download
---

# temporary-file-share

## Use When

- you need to fetch a file from a phone or another device quickly
- the file already exists locally and should stay in place
- a short-lived HTTP server is enough

## Workflow

1. Prefer serving the smallest useful directory, not `/`.
2. Verify the parent directory exists and the target file is present.
3. Start a detached HTTP server:
   - `sh -c 'nohup python3 -m http.server 8000 --bind 0.0.0.0 --directory "<directory>" >/tmp/file_share_http.log 2>&1 </dev/null &'`
4. Verify it is listening:
   - `ss -ltnp | rg ":8000"`
5. Give the user one or two direct URLs:
   - `http://100.116.176.16:8000/`
   - `http://100.116.176.16:8000/<filename>`
   - if relevant, also provide `http://ballbox-first.emperor-ratio.ts.net:8000/`
6. When the user confirms the download is done, stop the server:
   - identify the pid from `ss -ltnp | rg ":8000"`
   - `kill <pid>`
7. Verify the port is no longer listening.

## Rules

- default to port `8000` unless it is already in use
- do not move or rename the user's file just to share it
- prefer Tailscale IP or hostname over opening public exposure
- keep the server temporary; close it when the transfer is complete
- if the directory contains unrelated sensitive files, serve a narrower directory instead


**Considering skill adjustments**

I need to inspect other skills for absolute paths. Memory write and related references seem okay. I'll copy skill directories and may need to adjust the ballbox-company skill path. Using `rsync` or `cp` could work. I'll consider using `rsync -a --delete` from `.agents/skills` to `/home/sebas/.agents/skills/`. Preserving the current symlink is important, so I'll remove it and create the needed directories. Some system configs might still point to `personal-agent`, so I'll think about removing certain symlinks after repo deletion.

set -euo pipefail
# Replace symlink with a real skill directory.
rm -f /home/sebas/.agents/skills
mkdir -p /home/sebas/.agents/skills
# Migrate non-personal skills only.
for skill in ballbox-company karaoke-stem-separation memory-write telegram-notify temporary-file-share; do
  rsync -a "/mnt/rpi/repos/opencode-harness/.agents/skills/${skill}/" "/home/sebas/.agents/skills/${skill}/"
done
# Fix ballbox-company skill to point at the actual repo.
python3 - <<'PY'
from pathlib import Path
p = Path('/home/sebas/.agents/skills/ballbox-company/SKILL.md')
text = p.read_text()
text = text.replace('/mnt/rpi/repos/personal-agent/ballbox-company-agent', '/mnt/rpi/repos/ballbox-company-agent')
p.write_text(text)
PY
# Show result.
find /home/sebas/.agents/skills -maxdepth 2 -type f | sed 's#^/home/sebas/##' | sort


.agents/skills/ballbox-company/SKILL.md
.agents/skills/karaoke-stem-separation/SKILL.md
.agents/skills/memory-write/memory-write
.agents/skills/memory-write/SKILL.md
.agents/skills/telegram-notify/.env.example
.agents/skills/telegram-notify/SKILL.md
.agents/skills/telegram-notify/telegram-notify
.agents/skills/temporary-file-share/SKILL.md


**Considering installation cleanup**

I think we might need to remove symlinks and clear `opencode-harness-install`, since the installation metadata could be unnecessary. The user asked about deleting the local repo, but maybe we can keep the `.agents/opencode-harness-install` since it’s not the repo itself but rather install metadata. I wonder if we should leave it alone unless it references the old repo, but it might become stale. I’ll inspect further for any external references.

rg -n "personal-agent|opencode-harness|8082|scripts/personal\.py|daemon-8082" /home/sebas/.config /home/sebas/.agents /home/sebas/.bashrc /home/sebas/.profile /etc/systemd /etc/nginx 2>/dev/null | sed -n '1,200p'

systemctl --user list-unit-files | rg 'personal-agent|opencode-harness|8082' || true


/home/sebas/.agents/skills.bck/personal-status/SKILL.md:3:description: Inspect a personal-agent research run and report current state
/home/sebas/.agents/skills/memory-write/SKILL.md:46:  --origin-agent personal-agent


**Considering installation metadata**

I'm looking at this installation metadata, but I wonder if it's useless if the repo has been deleted. It might still have value, though. Should I go ahead and clean it up to avoid any stale data? But then again, if it’s being managed for the opencode-harness install, maybe it shouldn’t be deleted. I need to weigh the options here carefully!

find /home/sebas/.agents/opencode-harness-install -maxdepth 2 -type f -o -type l | sort | xargs -r ls -l

ls -ld /home/sebas/opencode-harness /home/sebas/personal-agent /mnt/rpi/repos/opencode-harness


-rw-rw-r-- 1 sebas sebas 171 Apr 14 22:59 /home/sebas/.agents/opencode-harness-install/managed-skills.txt


lrwxrwxrwx  1 sebas sebas   31 Apr 11 16:22 /home/sebas/opencode-harness -> /mnt/rpi/repos/opencode-harness
lrwxrwxrwx  1 sebas sebas   31 Apr 11 16:22 /home/sebas/personal-agent -> /mnt/rpi/repos/opencode-harness
drwxr-xr-x 14 sebas sebas 4096 Apr 16 16:28 /mnt/rpi/repos/opencode-harness


**Considering repo cleanup**

I’m thinking about whether to remove opencode-harness-install since it might be stale after the repo deletion. I should look at the managed-skills file to check if it just lists skills. If the repo is gone, it might be good to delete it as part of the decommissioning process. However, since the user didn’t mention removing install metadata, perhaps I can keep it if it isn’t harmful. I’ll decide on deleting symlinks and confirm if they should go too. Let's finalize this cleanup.

Ahora corto el resto de ataduras locales: symlinks, repo y el estado de instalación viejo. Después verifico que no quede nada vivo ni referenciado.

set -euo pipefail
rm -f /home/sebas/opencode-harness /home/sebas/personal-agent
rm -rf /mnt/rpi/repos/opencode-harness
rm -rf /home/sebas/.agents/opencode-harness-install


(no output)