Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# AGENTS.md

## Cursor Cloud specific instructions

This is a personal dotfiles/utilities monorepo with independent subprojects in Go, Java/Kotlin, JavaScript/TypeScript, and Python. There are no shared services or databases. Each subproject builds and runs independently.

### Subproject layout and build commands

| Subproject | Build | Test |
|---|---|---|
| `go/` (all Go packages) | `cd go && go build ./pkg/my-fuzzy-finder ./pkg/my-fuzzy-finder-lib ./pkg/my-java-launcher ./pkg/my-node-launcher` | `cd go && go test ./pkg/my-fuzzy-finder-lib/...` |
| `java/` (Gradle multi-project) | `cd java && PATH="$HOME/go/bin:$PATH" ./gradlew build` | `cd java && PATH="$HOME/go/bin:$PATH" ./gradlew test` |
| `javascript/mcp-rules` | `cd javascript/mcp-rules && npx tsc` | N/A (no test suite) |
| `javascript/my-obsidian-plugin` | `cd javascript/my-obsidian-plugin && npx tsc --noEmit` | N/A (no test suite) |
| `python/token-count` | `cd python/token-count && poetry install` | `echo "test" \| poetry run token-count` |

### Non-obvious caveats

- **Java build requires `my-java-launcher` on PATH.** The Gradle `findAndCopyMyLauncher` task searches PATH for the Go-built `my-java-launcher` binary. Before running `./gradlew build`, ensure `$HOME/go/bin` is on PATH (i.e. run `go install ./pkg/my-java-launcher` from the `go/` directory first).
- **`claude-sandboxed` Go package is macOS-only.** It uses macOS seatbelt sandbox APIs and will not compile on Linux. Exclude it when running `go test ./...` on Linux: use `go test ./pkg/my-fuzzy-finder-lib/...` or test individual packages.
- **`python/claude-proxy` requires Python ~3.13** which may not be available. The `python/token-count` project works with Python 3.12.
- **Poetry** is installed at `~/.local/bin/poetry`. Ensure `~/.local/bin` is on PATH.
- **The repo uses Nushell `do.nu` scripts** as the preferred build orchestration, but all builds work directly with the underlying tools (go, gradle, npm, poetry).
- **No linter configuration** is present at the repo level. TypeScript checking via `tsc --noEmit` serves as the lint step for JS projects.

### Nushell

Nushell (`nu`) is installed at `/usr/local/bin/nu` (v0.111.0, prebuilt musl binary). The user's config files from `nushell/` are installed into `~/.config/nushell/`:

- `config.nu` — adapted for Linux with nearly full parity to the original:
- Starship prompt (installed at `/usr/local/bin/starship`, autoload adapted for Linux path)
- zoxide (installed at `~/.local/bin/zoxide`)
- Atuin shell history (installed at `~/.atuin/bin/atuin`)
- LS_COLORS (vivid-generated, identical to repo)
- GRADLE_OPTS, external bash completions, clipboard (`xclip` standing in for `pbcopy`/`pbpaste`)
- All aliases: `ll`, `la`, `gs`, `gl`, `gw`, `fz`, `wt`, `da`, `c`/`p` (clipboard), `f`, etc.
- `scripts/*.nu` — all library scripts installed (zdu, lib, file-set, work-trees, subject, my-dir, node, open-jdk, postgres, bash-completer)
- `vendor/autoload/` — Starship, zoxide, and Atuin configs in `~/.local/share/nushell/vendor/autoload/` (also sourced explicitly from config.nu)
- `bash-completer.nu` adapted for Linux bash-completion paths (`/usr` instead of `/opt/homebrew`)
- `fd` is symlinked from `fdfind` → `/usr/local/bin/fd` so the `fd` wrapper in `lib.nu` works

**Not integrated** (macOS-only, no Linux equivalent):
- Homebrew keg activation for OpenJDK/Node.js (`advertise-installed-open-jdks`, `advertise-installed-nodes`)
- `code`, `cursor`, `xcode` commands (macOS `open -a` syntax)
- `explore-tart.nu` (Tart VM manager, macOS-only)
- `obsidian.nu` (depends on `~/repos/personal` directory structure)

To start Nushell: just run `nu`. The config loads automatically. To activate a project's `do.nu` overlay: `do activate` (or alias `da`).
328 changes: 328 additions & 0 deletions ENVIRONMENT_REPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
# Environment Report

Bill of materials for the development environment set up for the `my-software` repository.


## Base VM

| Property | Value |
|---|---|
| OS | Ubuntu 24.04.4 LTS (Noble Numbat) |
| Kernel | `6.1.147` x86_64 |
| CPUs | 4 |
| RAM | 16 GB |
| Disk | 126 GB (overlay filesystem) |
| User | `ubuntu` (home: `/home/ubuntu`) |
| Workspace | `/workspace` (git clone of `dgroomes/my-software`) |
| Runtime | Cursor Cloud Agent (Firecracker VM) |


## Pre-existing tools (came with the VM image)

These were already installed on the VM before any setup work. They are part of the base Cursor Cloud
Agent image and are not managed by this repository.

| Tool | Version | Location | Notes |
|---|---|---|---|
| Go | 1.22.2 | system | Matches `go.mod` requirement of 1.22.5 (toolchain auto-downloads) |
| OpenJDK | 21.0.10 | `/usr/lib/jvm/java-21-openjdk-amd64` | Ubuntu package; used by Gradle for the `java/` subprojects |
| Node.js | 22.22.1 | `~/.nvm/versions/node/v22.22.1/bin/node` | Managed by nvm |
| npm | 10.9.4 | via nvm | Used for `javascript/` subprojects |
| pnpm | 10.32.1 | via nvm | Not used by this repo (repo uses npm) |
| Python | 3.12.3 | `/usr/bin/python3` | System Python; used by `python/token-count` |
| Rust | 1.83.0 | `/usr/local/cargo/bin/rustc` | Not used by repo, but was useful for potential source builds |
| Cargo | 1.83.0 | `/usr/local/cargo/bin/cargo` | Same as above |
| Git | 2.43.0 | system | Used everywhere |
| Bash | 5.2.21 | `/usr/bin/bash` | Used by bash-completion integration |
| xclip | system | `/usr/bin/xclip` | Used as Linux substitute for macOS `pbcopy`/`pbpaste` |
| nvm | — | `~/.nvm` | Node version manager (pre-installed) |


## Installed tools (added during setup)

Everything below was installed by the agent during the setup session. Each entry explains what
was installed, where, why, and how to reproduce the installation.

### Nushell

| Property | Value |
|---|---|
| Version | 0.111.0 |
| Location | `/usr/local/bin/nu` |
| Binary type | Static-linked musl ELF (x86_64) |
| Why | The repo's preferred build orchestration uses Nushell `do.nu` scripts. The user's shell config, aliases, and custom commands are all written in Nushell. |

**How it was installed:**

```bash
curl -sL -o /tmp/nu.tar.gz \
https://github.com/nushell/nushell/releases/download/0.111.0/nu-0.111.0-x86_64-unknown-linux-musl.tar.gz
tar xzf /tmp/nu.tar.gz -C /tmp
sudo cp /tmp/nu-0.111.0-x86_64-unknown-linux-musl/nu /usr/local/bin/nu
sudo chmod +x /usr/local/bin/nu
```

**How to reproduce in the future:** Check the [Nushell releases page](https://github.com/nushell/nushell/releases)
for the latest `x86_64-unknown-linux-musl` tarball. The musl build is fully static and requires
no shared libraries.


### Starship (prompt)

| Property | Value |
|---|---|
| Version | 1.24.2 |
| Location | `/usr/local/bin/starship` |
| Why | The user's Nushell config integrates Starship for a rich prompt showing git branch, language versions, and directory context. |

**How it was installed:**

```bash
curl -sS https://starship.rs/install.sh | sudo sh -s -- --yes
```

**How to reproduce:** The official Starship installer auto-detects the platform. It places the
binary in `/usr/local/bin/`.


### zoxide (directory jumper)

| Property | Value |
|---|---|
| Version | 0.9.9 |
| Location | `~/.local/bin/zoxide` |
| Why | The user's Nushell config uses zoxide for frecency-based directory jumping (the `z` command in `vendor/autoload/zoxide.nu`). |

**How it was installed:**

```bash
curl -sSfL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh
```

**How to reproduce:** The official installer downloads the correct binary for the platform and
places it in `~/.local/bin/`. Make sure `~/.local/bin` is on PATH.


### Atuin (shell history)

| Property | Value |
|---|---|
| Version | 18.13.6 |
| Location | `~/.atuin/bin/atuin` |
| Why | The user's Nushell config integrates Atuin for enhanced shell history with Ctrl+R search (configured in `vendor/autoload/atuin.nu`). |

**How it was installed:**

```bash
curl -sSf https://setup.atuin.sh | sh -s -- --yes --disable-login
```

**How to reproduce:** The official installer places the binary in `~/.atuin/bin/`. The `--disable-login`
flag skips the cloud sync account setup (not needed for local dev).


### fd (fast file finder)

| Property | Value |
|---|---|
| Version | 9.0.0 |
| Location | `/usr/bin/fdfind` (symlinked to `/usr/local/bin/fd`) |
| Why | The user's `lib.nu` wraps `fd` for structured Nushell output. Commands like `word-counts-of-files` and `file-set add` depend on it. |

**How it was installed:**

```bash
sudo apt-get install -y fd-find
sudo ln -sf /usr/bin/fdfind /usr/local/bin/fd
```

**Note:** On Ubuntu/Debian, the package is `fd-find` and the binary is `fdfind` (to avoid a name
conflict with another package). The symlink at `/usr/local/bin/fd` makes the user's Nushell
scripts work without modification.


### bash-completion (v2)

| Property | Value |
|---|---|
| Version | 2.11-8 |
| Location | `/usr/share/bash-completion/` |
| Why | The user's `bash-completer.nu` script provides Nushell tab-completions by delegating to bash-completion functions. The `one-shot-bash-completion.bash` script sources this library. |

**How it was installed:**

```bash
sudo apt-get install -y bash-completion
```


### Poetry (Python package manager)

| Property | Value |
|---|---|
| Version | 2.3.2 |
| Location | `~/.local/bin/poetry` |
| Why | The `python/token-count` and `python/claude-proxy` subprojects use Poetry for dependency management (each has a `pyproject.toml` with `poetry-core` as the build backend). |

**How it was installed:**

```bash
pip install poetry
```

**Note:** `~/.local/bin` must be on PATH for `poetry` to be found.


### my-java-launcher (Go binary)

| Property | Value |
|---|---|
| Version | Built from source in this repo |
| Location | `~/go/bin/my-java-launcher` |
| Why | The Gradle build for `java/` subprojects has a `findAndCopyMyLauncher` task that searches PATH for this binary. Without it, `./gradlew build` fails. |

**How it was installed:**

```bash
cd /workspace/go && go install ./pkg/my-java-launcher
```

**This is a critical dependency.** The Java/Kotlin build will fail without this Go binary on PATH.
`~/go/bin` must be on PATH (it is by default in this environment).


## Nushell configuration

The user's Nushell configuration from the `nushell/` directory in the repo was installed into the
Nushell config locations. This is the most complex part of the setup because the original config
targets macOS with Homebrew, and adaptations were needed for Linux.

### Files installed

**`~/.config/nushell/config.nu`** — Main configuration file. This is an *adapted copy* of `nushell/config.nu`
from the repo. Changes from the original:

| Original (macOS) | Adapted (Linux) |
|---|---|
| PATH includes `/opt/homebrew/bin`, `~/Library/Application Support/JetBrains/...`, etc. | PATH includes `~/.atuin/bin`, `~/.local/bin`, `~/.cargo/bin`, `~/go/bin`, `~/.local/npm/bin` |
| `$env.HOMEBREW_PREFIX = "/opt/homebrew"` and related Homebrew env vars | Removed (no Homebrew on Linux) |
| `pbcopy` / `pbpaste` aliases (macOS clipboard) | Replaced with `xclip -selection clipboard` wrappers |
| `$env.config.buffer_editor = "subl"` | Changed to `"vim"` |
| `advertise-installed-open-jdks` / `advertise-installed-nodes` calls | Removed (depend on Homebrew keg layout) |
| `source` of autoload scripts via Nushell's `vendor/autoload/` mechanism | Explicit `source` statements in config.nu (more reliable in non-interactive contexts) |
| `code`, `cursor`, `xcode` commands (macOS `open -a` syntax) | Not included |
| Everything else | Preserved as-is (aliases, color config, LS_COLORS, GRADLE_OPTS, do activate, history settings, etc.) |

**`~/.config/nushell/scripts/`** — All library scripts copied from `nushell/scripts/`:

| File | Purpose | Linux compatibility |
|---|---|---|
| `zdu.nu` | Zero-dependency utilities (`repos`, `coalesce`, `whichx`, `err`, `file-name`, `compress-home`, `epoch-into-datetime`) | Full |
| `lib.nu` | Main command library (`gw`, `fz`, `fd`, `cat-with-frontmatter`, `dirty-git-projects`, `run-from-readme`, `dedupe`, `wikipedia`, `stash`, `comma-per-thousand`, `git-switch-default-pull`, `git-checkout-as-my`, etc.) | Full (except `code`/`cursor`/`xcode` which are macOS-only) |
| `file-set.nu` | LLM context bundling (`file-set init`, `file-set add`, `file-set validate`, `file-set summarize`) | Full |
| `work-trees.nu` | Git worktree management (`work-tree list`, `work-tree switch`, `work-tree add`) | Full |
| `subject.nu` | Subject/workspace creation (`new-subject`) | Full |
| `my-dir.nu` | `.my` directory scaffolding (`my-dir-init`) | Full |
| `bash-completer.nu` | External bash-completion integration | **Adapted**: changed `BASH_COMPLETION_INSTALLATION_DIR` from `/opt/homebrew/opt/bash-completion@2` to `/usr` and `XDG_DATA_DIRS` from `/opt/homebrew/share` to `/usr/share` |
| `node.nu` | Node.js keg management (`activate-my-node`, `advertise-installed-nodes`) | Loads but commands error (depends on Homebrew keg layout) |
| `open-jdk.nu` | OpenJDK keg management (`activate-my-open-jdk`, `advertise-installed-open-jdks`) | Loads but commands error (depends on Homebrew keg layout) |
| `postgres.nu` | Postgres keg activation | Loads but commands error (depends on Homebrew keg layout) |
| `explore-tart.nu` | Tart VM management | macOS-only; loads but all commands are non-functional |
| `obsidian.nu` | Obsidian vault creation | Depends on `~/repos/personal` directory; non-functional |

**`~/.config/nushell/one-shot-bash-completion.bash`** — Bash script for one-shot completion lookups,
copied as-is from `nushell/one-shot-bash-completion.bash`.

**`~/.local/share/nushell/vendor/autoload/`** — Autoload scripts:

| File | Source | Adaptation |
|---|---|---|
| `starship.nu` | `nushell/vendor/autoload/starship.nu` | All `/opt/homebrew/bin/starship` paths → `/usr/local/bin/starship` |
| `zoxide.nu` | `nushell/vendor/autoload/zoxide.nu` | None needed (uses `zoxide` command without hardcoded paths) |
| `atuin.nu` | `nushell/vendor/autoload/atuin.nu` | None needed (uses `atuin` command without hardcoded paths) |


## Project dependency state

These are per-subproject dependency installations, not system-level tools.

| Subproject | What was installed | Location | Command to refresh |
|---|---|---|---|
| `go/` | Go module cache | `~/go/pkg/mod/` | `cd go && go mod download` |
| `go/` | `my-java-launcher` binary | `~/go/bin/my-java-launcher` | `cd go && go install ./pkg/my-java-launcher` |
| `java/` | Gradle 8.5 distribution | `~/.gradle/wrapper/dists/gradle-8.5-bin/` | Auto-downloaded by `./gradlew` |
| `java/` | Kotlin compiler, IntelliJ SDK, etc. | `~/.gradle/caches/` | Auto-downloaded by `./gradlew build` |
| `javascript/mcp-rules` | 84 npm packages | `javascript/mcp-rules/node_modules/` | `cd javascript/mcp-rules && npm install` |
| `javascript/my-obsidian-plugin` | 12 npm packages | `javascript/my-obsidian-plugin/node_modules/` | `cd javascript/my-obsidian-plugin && npm install` |
| `python/token-count` | Poetry virtualenv with tiktoken | `~/.cache/pypoetry/virtualenvs/token-count-*` | `cd python/token-count && poetry install` |


## What was NOT installed (and why)

| Component | Reason |
|---|---|
| Homebrew | Linux environment; all tools installed via apt, official installers, or prebuilt binaries |
| Python 3.13 | Not available on Ubuntu 24.04; `python/claude-proxy` requires it but `python/token-count` works with 3.12 |
| Nushell plugins (`nu_plugin_*`) | The prebuilt release includes them but they weren't registered; not needed for the core workflow |
| Obsidian | Desktop app; the `obsidian.nu` script loads but its commands are non-functional without `~/repos/personal` |
| Docker | Already available in the VM environment; no installation needed |
| IntelliJ IDEA | The `my-intellij-plugin` subproject builds via Gradle (headless); no IDE needed |
| Tart (VM manager) | macOS-only tool; `explore-tart.nu` loads but is non-functional |


## Reproducibility: how to set up this environment from scratch

For a future orchestrator setting up a fresh Ubuntu 24.04 VM for this repository:

```bash
# 1. System packages
sudo apt-get update
sudo apt-get install -y fd-find bash-completion xclip
sudo ln -sf /usr/bin/fdfind /usr/local/bin/fd

# 2. Nushell (check https://github.com/nushell/nushell/releases for latest)
curl -sL -o /tmp/nu.tar.gz \
https://github.com/nushell/nushell/releases/download/0.111.0/nu-0.111.0-x86_64-unknown-linux-musl.tar.gz
tar xzf /tmp/nu.tar.gz -C /tmp
sudo cp /tmp/nu-0.111.0-x86_64-unknown-linux-musl/nu /usr/local/bin/nu

# 3. Starship prompt
curl -sS https://starship.rs/install.sh | sudo sh -s -- --yes

# 4. zoxide
curl -sSfL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh

# 5. Atuin
curl -sSf https://setup.atuin.sh | sh -s -- --yes --disable-login

# 6. Poetry
pip install poetry

# 7. Go binary needed by Java build
cd /workspace/go && go install ./pkg/my-java-launcher

# 8. Nushell config (copy from repo and adapt, or use the snapshot)
mkdir -p ~/.config/nushell/scripts ~/.local/share/nushell/vendor/autoload
cp /workspace/nushell/scripts/*.nu ~/.config/nushell/scripts/
cp /workspace/nushell/one-shot-bash-completion.bash ~/.config/nushell/
# config.nu, starship.nu, bash-completer.nu need path adaptations (see above)

# 9. Project dependencies
cd /workspace/javascript/mcp-rules && npm install
cd /workspace/javascript/my-obsidian-plugin && npm install
cd /workspace/python/token-count && PATH="$HOME/.local/bin:$PATH" poetry install
```


## Update script (runs on every VM startup)

The SetupVmEnvironment update script handles only dependency refresh, not system tool
installation (which is baked into the snapshot):

```bash
pip install --quiet poetry
cd go && go install ./pkg/my-java-launcher
cd javascript/mcp-rules && npm install
cd /workspace/javascript/my-obsidian-plugin && npm install
cd /workspace/python/token-count && PATH="$HOME/.local/bin:$PATH" poetry install --quiet
```