totopo 0.9.0 → 1.0.0-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
@@ -1,127 +1,138 @@
1
1
  # totopo
2
2
 
3
- Spin up a secure, isolated AI coding environment in any git project — in one command.
3
+ <img src=".github/assets/logo.png" alt="totopo" width="100%" />
4
4
 
5
- ## Status
5
+ A simple CLI to spin up a sandboxed Docker environment for AI coding agents.
6
6
 
7
- ⚠️ **Early development (pre-1.0)** — experimental. API and behavior may change. Not yet recommended for production use.
7
+ ![npm version](https://img.shields.io/npm/v/totopo)
8
+ ![npm downloads](https://img.shields.io/npm/dm/totopo)
9
+ ![license](https://img.shields.io/npm/l/totopo)
8
10
 
9
- ## How It Works
11
+ ## What is totopo?
10
12
 
11
- `npx totopo` sets up a hardened Docker container in your project with AI coding assistants (OpenCode, Claude Code, Codex) pre-installed. Your code stays on your host machine. The AI tools run isolated inside the container.
13
+ `npx totopo` spins up a secure, isolated dev container for any git project with AI coding tools pre-installed in a single command.
12
14
 
13
- ```
14
- Host machine
15
- ├── your editor → edits files normally (bind-mounted from container)
16
- ├── terminal → connected to container via docker exec
17
- │ ├── opencode → AI tools run here, isolated
18
- │ ├── claude
19
- │ └── codex
20
- └── git push/pull → only possible from host, blocked inside container
21
- ```
15
+ There are other solutions that offer more hardened security setups, and others with a richer feature set. totopo is neither of those. It is my own take on what makes a good balance between excellent developer experience and a sensible basic sandboxing setup.
22
16
 
23
17
  ---
24
18
 
25
- ## Prerequisites
19
+ ## Features at a Glance
26
20
 
27
- - [Docker Desktop](https://www.docker.com/products/docker-desktop/)
21
+ - **Sandboxed Docker container** — your code runs in an isolated environment with strict filesystem and privilege boundaries
22
+ - **Agents can't reach remote** — push, pull, fetch, and clone are blocked inside the container, preventing agents from accidentally affecting your remote repositories
23
+ - **Scoped mounts** — expose only the files and directories the agent needs, nothing more
24
+ - **AI coding CLIs with persistent sessions** — Claude Code, OpenCode, and Codex pre-installed, with conversation history that survives restarts and rebuilds
25
+ - **Host-mirror or generic runtime** — use a standard dev container, or let totopo match the container environment to your host so the agent works in the exact same setup as your codebase
28
26
 
29
27
  ---
30
28
 
31
- ## Quick Start
29
+ ## Requirements
30
+
31
+ - [Docker](https://www.docker.com/products/docker-desktop/)
32
+ - [git](https://git-scm.com/)
32
33
 
33
- ### 1. Run totopo in your project directory
34
+ ---
35
+
36
+ ## Quick Start
34
37
 
35
38
  ```bash
36
39
  cd your-project
37
40
  npx totopo
38
41
  ```
39
42
 
40
- If `.totopo/` doesn't exist yet, the onboarding flow runs automatically it creates the container config, prompts for API keys, and updates `.gitignore`.
43
+ Select **Open session** from the menu. If `.totopo/` doesn't exist yet, a one-time onboarding flow runs first. The first run builds the Docker image. Subsequent starts are fast.
41
44
 
42
- ### 2. Start the container
45
+ <!-- VIDEO: First-time setup — running `npx totopo` in a fresh repo, selecting a runtime mode, and waiting for the Docker image to build for the first time.
46
+ ![First-time setup](.github/assets/demo-onboarding.gif)
47
+ -->
43
48
 
44
- Select **Start session** from the menu. The first run builds the Docker image (a few minutes). Subsequent starts are fast.
49
+ <!-- VIDEO: Starting a session once the container is already built opening a session, running an AI tool, exiting.
50
+ ![Quick start](.github/assets/demo-quickstart.gif)
51
+ -->
45
52
 
46
- ### 3. Verify
53
+ ---
47
54
 
48
- Security checks run automatically on every container start. Re-run anytime from inside the container:
55
+ ## Features
49
56
 
50
- ```bash
51
- status
52
- ```
57
+ ### Sandboxed dev container
53
58
 
54
- ### 4. Stop
59
+ Every session runs inside a Docker container. Your code is bind-mounted from the host — edits are immediately visible in your editor. The container enforces several isolation boundaries:
55
60
 
56
- Run `npx totopo` again and select **Stop**.
61
+ | Control | Implementation |
62
+ | --- | --- |
63
+ | Non-root user | All processes run as `devuser` (uid 1001) — cannot modify system-level config |
64
+ | Filesystem isolation | Only the repo is mounted — host filesystem is not visible |
65
+ | Git remote block | `protocol.allow = never` in `/etc/gitconfig` — push, pull, fetch, and clone are all refused; requires root to override |
66
+ | No host credentials forwarded | Host git credentials are never copied into the container |
67
+ | Secrets never in image | API keys loaded at runtime from `~/.totopo/.env` — never baked into the image, never mounted into the container |
68
+ | No privilege escalation | `no-new-privileges:true` prevents any process from gaining elevated permissions |
57
69
 
58
- ---
70
+ Remote git operations are blocked inside the container. Push from your host terminal instead.
59
71
 
60
- ## What gets created in your project
72
+ ### Scoped sandboxing
61
73
 
62
- ```
63
- your-project/
64
- └── .totopo/
65
- ├── .env # API keys — gitignored, never committed
66
- ├── Dockerfile # Container image definition
67
- └── post-start.mjs # Security + readiness check on every start
68
- ```
74
+ Mount only the files and directories you need into the container rather than the full repository. Two scoped modes are available: `cwd` (current directory only) and `selective` (hand-pick individual files and folders).
69
75
 
70
- ---
76
+ In both scoped modes, `.git` is intentionally not mounted. Mounting `.git` would expose the full commit history of every repository file — including files outside the mounted paths — which defeats the point of scoped access. As a result, git is unavailable inside a scoped session and the agent operates without repository history. The agent is instructed to surface these limitations at session start.
77
+
78
+ Scoped sessions are well-suited for focused tasks where you want to give the agent a narrow, explicit view of your codebase.
79
+
80
+ <!-- VIDEO: Using scoped mounts — selecting cwd and selective modes, showing what the agent can and can't see inside the container.
81
+ ![Scoped sandboxing](.github/assets/demo-scoped.gif)
82
+ -->
71
83
 
72
- ## AI Tools
84
+ ### AI tools pre-installed
73
85
 
74
- Run inside the container terminal:
86
+ The container comes with the major AI coding CLIs ready to use out of the box:
75
87
 
76
88
  ```bash
77
89
  opencode # OpenCode
78
90
  claude # Claude Code (Anthropic)
79
91
  codex # Codex (OpenAI)
80
- status # Re-run security + readiness check
81
92
  ```
82
93
 
83
- ---
94
+ ### Dev container runtime
84
95
 
85
- ## Security Model
96
+ Choose between two modes:
86
97
 
87
- | Control | Implementation |
88
- | ------------------------ | ------------------------------------------------------------------------------------------------- |
89
- | Non-root user | All processes run as `devuser` (uid 1001) |
90
- | Filesystem isolation | Only the repo is mounted — host is not visible |
91
- | Git remote block | `protocol.allow never` in `/etc/gitconfig` — enforced at the git layer, requires root to override |
92
- | No privilege escalation | `no-new-privileges:true` security opt |
93
- | Secrets never in image | API keys loaded at runtime from `~/.totopo/.env` — never baked into the image, never mounted into the container |
98
+ - **Host-mirror** — the container runtime matches your host Node.js version and selected tools, keeping the environment consistent with your local setup.
99
+ - **Generic** a full dev container with the latest stable versions of all tools. Good default if you don't need version parity with your host.
94
100
 
95
- Remote git operations are blocked inside the container. Push from your host terminal instead.
101
+ Either way, basic dev tools and all three AI CLIs are always included.
96
102
 
97
- See `docs/VISION.md` for full details on the security model.
103
+ <!-- VIDEO: Switching runtime modes in the settings menu, selecting tools, and triggering a container rebuild.
104
+ ![Runtime switching](.github/assets/demo-runtime.gif)
105
+ -->
98
106
 
99
107
  ---
100
108
 
101
- ## Git Workflow
102
-
103
- ```bash
104
- # Inside container — local operations ✅
105
- git add .
106
- git commit -m "message"
107
- git log / diff / branch
109
+ ## What gets created in your project
108
110
 
109
- # Remote operations — host terminal only 🚫 blocked inside container
110
- git push / pull / fetch
111
+ ```
112
+ your-project/
113
+ └── .totopo/
114
+ ├── Dockerfile # container image definition
115
+ ├── post-start.mjs # security checks + readiness summary on every start
116
+ ├── settings.json # runtime mode + selected tools (committed with project)
117
+ ├── README.md # .totopo reference
118
+ └── agents/ # agent session data — gitignored, created on first session start
119
+ ├── claude/ # mounted as ~/.claude/
120
+ ├── opencode/ # mounted as ~/.config/opencode/ + ~/.local/share/opencode/
121
+ └── codex/ # mounted as ~/.codex/
122
+
123
+ ~/.totopo/.env # API keys — global, outside all repos, never mounted into container
111
124
  ```
112
125
 
126
+ Agent session history and conversation data are persisted in `agents/` across container rebuilds and restarts. This directory is gitignored — session data stays local to your machine.
127
+
113
128
  ---
114
129
 
115
130
  ## Limitations
116
131
 
117
- **No audio / microphone support** — the container has no access to host audio devices. Features that require microphone input (e.g. Claude Code's `/voice` mode) will not work inside the container.
132
+ **Audio / microphone** — the image includes `sox` (required by Claude Code for voice mode), but audio passthrough from the host depends on your OS. macOS, Linux, and Windows each require different device configuration. If you need voice mode, set up audio passthrough manually for your platform.
118
133
 
119
134
  ---
120
135
 
121
- ## Troubleshooting
122
-
123
- **Container fails to start** — the startup check prints exactly which check failed and why.
124
-
125
- **API key warnings** — check `.totopo/.env` has the correct variable names, then use **Rebuild** from the totopo menu to rebuild the container.
136
+ ## Disclaimer
126
137
 
127
- **AI tool not found** use **Rebuild** from the totopo menu to rebuild the container image. Do not install tools manually inside a running container as changes won't persist.
138
+ totopo is MIT licensed and fully open source fork it, adapt it, build on it. Issues are welcome but response times aren't guaranteed. Use at your own risk.
package/bin/totopo.js CHANGED
@@ -40,9 +40,6 @@ try {
40
40
  process.exit(1);
41
41
  }
42
42
 
43
- process.env.TOTOPO_PACKAGE_DIR = packageDir;
44
- process.env.TOTOPO_REPO_ROOT = repoRoot;
45
-
46
43
  // ─── Guard: dist/ must exist ─────────────────────────────────────────────────
47
44
  if (!existsSync(new URL("../dist/commands/sync-dockerfile.js", import.meta.url))) {
48
45
  console.error("");
@@ -15,9 +15,12 @@ export async function run(packageDir, repoRoot) {
15
15
  const templatesDir = join(packageDir, "templates");
16
16
  const totopoDir = join(repoRoot, ".totopo");
17
17
  const projectName = basename(repoRoot);
18
+ const tildefy = (p) => (p.startsWith(homedir()) ? p.replace(homedir(), "~") : p);
18
19
  // ─── Intro ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
20
+ process.stdout.write("\n");
19
21
  intro("totopo — First-time setup");
20
- box(`project : ${projectName}\nlocation : ${totopoDir}`, "No .totopo/ config found — totopo will create it now.", {
22
+ log.message("");
23
+ box(`project : ${projectName}\nlocation : ${tildefy(totopoDir)}`, "", {
21
24
  contentAlign: "center",
22
25
  titleAlign: "center",
23
26
  width: "auto",
@@ -109,7 +112,7 @@ export async function run(packageDir, repoRoot) {
109
112
  writeFileSync(gitignorePath, content);
110
113
  }
111
114
  }
112
- log.info(`Optionally add API keys to ${globalEnvPath} — all keys are injected into every container at runtime.`);
115
+ log.info(`Optionally add API keys to ${tildefy(globalEnvPath)} — they are injected into every totopo container at runtime.`);
113
116
  outro("Setup complete.");
114
117
  return true;
115
118
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "totopo",
3
- "version": "0.9.0",
3
+ "version": "1.0.0-rc-2",
4
4
  "description": "Secure AI Box — isolated dev environments for AI coding assistants",
5
5
  "type": "module",
6
6
  "bin": {