totopo 3.0.0 → 3.0.1-rc-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  <img src=".github/assets/logo.png" alt="totopo" width="100%" />
4
4
 
5
- Run AI coding agents in a secure local sandbox.
5
+ Local sandbox for AI agents.
6
6
 
7
7
  ![build](https://github.com/asafratzon/totopo/actions/workflows/build.yml/badge.svg)
8
8
  ![tests](https://github.com/asafratzon/totopo/actions/workflows/tests.yml/badge.svg)
@@ -10,28 +10,50 @@ Run AI coding agents in a secure local sandbox.
10
10
  ![npm downloads](https://img.shields.io/npm/dm/totopo)
11
11
  ![license](https://img.shields.io/npm/l/totopo)
12
12
 
13
- ## Why totopo?
13
+ ## Motivation
14
14
 
15
- AI agents are non-deterministic. They occasionally get things wrong. Most of the time they're fine — but "most of the time" isn't a great argument for giving an agent unrestricted access to your machine, your credentials, and your remote repositories.
15
+ Two fundamental issues with AI agents:
16
+ - They are non-deterministic — they will occasionally get things wrong.
17
+ - They are susceptible to prompt injection — they can get compromised and act against your interests without you knowing.
16
18
 
17
- totopo draws a clear boundary: agents get a full, capable environment to work in — they just can't touch anything outside the workspace, and they can't reach your remote. No domain whitelisting, no paranoia, no compromise on what the agent can actually do.
19
+ totopo addresses both with a dev container - when you run totopo in a given directory, the directory is mounted as a workspace where agents get a full, capable environment to work in — they just can't touch anything outside the workspace, and they can't reach remote git repositories.
20
+
21
+ If an agent makes a mistake, damage is contained to the workspace; your git remote is out of reach.<br>
22
+ If an agent gets compromised, it can't reach your host files — blast radius is limited to the workspace you chose to share.
23
+
24
+ > totopo's security approach is basic — it is about the minimal precautions I believe anyone running AI agents should have. If you need more robust protections, look somewhere else.
18
25
 
19
26
  ## Requirements
20
27
 
21
28
  - [Docker](https://www.docker.com/products/docker-desktop/) — builds and runs the dev container
22
29
  - [Node.js](https://nodejs.org/) — required to run `npx totopo`
23
30
 
24
- ## Getting Started
31
+ ## Quick Start
25
32
 
26
33
  ```bash
27
34
  cd your-project
28
35
  npx totopo
29
36
  ```
30
37
 
31
- `npx totopo` always runs the latest stable version — no install required. Alternatively, install globally to pin a specific version: `npm install -g totopo`.
38
+ `npx totopo` always runs the latest stable version. Alternatively, install globally to pin a specific version: `npm install -g totopo`.
32
39
 
33
40
  > **Do not install totopo as a local project dependency.** totopo stores all workspace state in `~/.totopo/`, shared across all your workspaces. A local install means different projects could run different versions, which can break schema compatibility with shared config. Use `npx` or a global install.
34
41
 
42
+ ### Basic Usage
43
+
44
+ Once set up, the flow is simple:
45
+
46
+ 1. Run `npx totopo` → **Open session**
47
+ 2. Run `claude`, `opencode`, or `codex` — pick an agent, start working
48
+
49
+ A few things happen automatically:
50
+
51
+ - **Agents stay up to date** — when you open a session, totopo ensures all AI CLIs are on their latest version.
52
+ - **Sessions are persistent** — agent memory and settings survive container restarts and rebuilds.
53
+ - **Your machine stays safe** — the container can't push to remote, can't read outside the workspace, and sensitive paths like `.env` can be hidden from agents entirely (see [Shadow Paths](#shadow-paths)).
54
+
55
+ For a deeper look at how totopo works and how to configure it, see the sections below.
56
+
35
57
  ## How totopo Works
36
58
 
37
59
  totopo organises work around **workspaces** — any directory containing a `totopo.yaml` file. Running `npx totopo` for the first time in a directory walks you through a short setup and creates `totopo.yaml` (a small, well-documented config file that lives at the workspace root).
@@ -51,7 +73,7 @@ On every run, totopo shows the workspace menu:
51
73
 
52
74
  ### Working directory
53
75
 
54
- The workspace is always mounted at `/workspace` inside the container. When you run totopo from a subdirectory, you get a quick prompt to start **here** or at the **Workspace root**. If you're already at the workspace root, the session starts directly at `/workspace`.
76
+ The workspace is always mounted at `/workspace` inside the container. When you run totopo from a subdirectory, you get a quick prompt to start **here** or at the **workspace root**. If you're already at the workspace root, the session starts directly at `/workspace`.
55
77
 
56
78
  ## Core Features
57
79
 
package/bin/totopo.js CHANGED
@@ -15,7 +15,7 @@ import { run as globalMenu } from "../dist/commands/global.js";
15
15
  import { run as menu } from "../dist/commands/menu.js";
16
16
  import { run as onboard } from "../dist/commands/onboard.js";
17
17
  import { resetImage, stop, run as workspaceMenu } from "../dist/commands/workspace.js";
18
- import { repairTotopoYaml } from "../dist/lib/totopo-yaml.js";
18
+ import { GITHUB_README_URL, repairTotopoYaml } from "../dist/lib/totopo-yaml.js";
19
19
  import { deriveContainerName, findTotopoYamlDir, listWorkspaceIds, resolveWorkspace } from "../dist/lib/workspace-identity.js";
20
20
 
21
21
  // --- Guard: inside container -------------------------------------------------------------------------------------------------------------
@@ -176,6 +176,9 @@ while (showMenu) {
176
176
  if (result === "back") showMenu = true;
177
177
  break;
178
178
  }
179
+ case "help":
180
+ log.info(`Check out the official docs at:\n ${GITHUB_README_URL}`);
181
+ break;
179
182
  default:
180
183
  break;
181
184
  }
@@ -9,7 +9,6 @@ import { cancel, confirm, isCancel, log, multiselect, outro, select, text } from
9
9
  import { AGENTS_DIR, CONTAINER_NAME_PREFIX, LABEL_MANAGED, TOTOPO_DIR, TOTOPO_YAML } from "../lib/constants.js";
10
10
  import { safeRmSync } from "../lib/safe-rm.js";
11
11
  import { listWorkspaces } from "../lib/workspace-identity.js";
12
- import { run as runDoctor } from "./doctor.js";
13
12
  // --- Helpers -----------------------------------------------------------------------------------------------------------------------------
14
13
  /** Remove workspace cache dir and optionally totopo.yaml from the workspace root. Exported for testing. */
15
14
  export function removeWorkspaceFiles(workspaceRoot, workspaceDir, removeTotopoYaml) {
@@ -249,7 +248,6 @@ export async function run(currentWorkspaceId) {
249
248
  { value: "stop-containers", label: "Stop containers", hint: "pick running containers" },
250
249
  { value: "clear-memory", label: "Clear agent memory", hint: "pick workspaces to clear" },
251
250
  { value: "remove-images", label: "Remove images", hint: "pick images to remove" },
252
- { value: "doctor", label: "Doctor", hint: "check Docker health" },
253
251
  { value: "uninstall-workspace", label: "Uninstall workspaces", hint: "pick workspaces to remove" },
254
252
  { value: "uninstall", label: "Uninstall totopo", hint: "wipe ~/.totopo/ and all containers/images" },
255
253
  { value: "back", label: "← Back" },
@@ -274,16 +272,9 @@ export async function run(currentWorkspaceId) {
274
272
  return undefined;
275
273
  break;
276
274
  }
277
- case "doctor":
278
- await runDoctor(null, true);
279
- await sleep(500);
280
- break;
281
275
  case "uninstall":
282
276
  await uninstallTotopo();
283
277
  return undefined;
284
278
  }
285
279
  }
286
280
  }
287
- function sleep(ms) {
288
- return new Promise((resolve) => setTimeout(resolve, ms));
289
- }
@@ -27,6 +27,7 @@ export async function run(args) {
27
27
  ...(workspaceRunning ? [{ value: "stop", label: "Stop container", hint: "stops this workspace's container" }] : []),
28
28
  { value: "settings", label: "Manage Workspace", hint: "profiles, shadow paths, rebuild" },
29
29
  { value: "manage-totopo", label: "Manage totopo →", hint: "stop, clear, remove, uninstall" },
30
+ { value: "help", label: "Help", hint: "official docs" },
30
31
  { value: "quit", label: "Quit" },
31
32
  ];
32
33
  const action = await select({ message: "Menu:", options });
@@ -79,6 +79,7 @@ export function readTotopoYaml(dir) {
79
79
  // We rely on that tag existing so these URLs resolve correctly for every installed version.
80
80
  const { version } = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"));
81
81
  const GITHUB_RAW_BASE = `https://raw.githubusercontent.com/asafratzon/totopo/v${version}`;
82
+ export const GITHUB_README_URL = `https://github.com/asafratzon/totopo/blob/v${version}/README.md`;
82
83
  const YAML_HEADER = `# yaml-language-server: $schema=${GITHUB_RAW_BASE}/schema/totopo.schema.json
83
84
  `;
84
85
  // Inline comments injected before specific YAML keys (preceded by a blank line)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "totopo",
3
- "version": "3.0.0",
3
+ "version": "3.0.1-rc-2",
4
4
  "description": "Run AI coding agents safely in your local codebase",
5
5
  "type": "module",
6
6
  "bin": {