Skip to content

Workspace-Aware Amicode: Multi-Directory Sessions + Workspace Sidebar #215

Description

@jeonghun-jj-lee

Workspace-Aware Amicode: Multi-Directory Sessions + Workspace Sidebar

Important

Decision Surface

Problem: Amicode sessions scope to a single workspace folder (workspaceFolders[0]).
In multi-root VS Code workspaces (Altissimo + DirectTrajOpt + Piccolo), the agent can
access other folders via absolute paths but (a) gets external-directory permission prompts,
(b) only loads instructions from the primary folder, and (c) the sidebar is a dead placeholder.

Approach: Extend the opencode engine's Location.Ref to carry multiple directories.
All workspace folders become "internal" to the session — no permission prompts, instructions
discovered from each, tools operate freely across all. The Amicode sidebar's "Armonia"
placeholder becomes a full "Workspace" file explorer mirroring the native VS Code Explorer.

Approaches Considered:

  • (A) Multi-directory Location.Ref (chosen) — engine natively multi-root, cleanest model
  • (B) Virtual worktree umbrella — additive worktrees[] field, smaller change but hacky
  • (C) Extension-only shim — no engine changes, brittle injection of instructions + allowlists

Scope: opencode engine (packages/schema, packages/core, packages/server,
packages/opencode) + Amicode VS Code extension (sidebar, session creation, package.json).
Removes the Catalog sidebar view.

Assumptions:

  • The V2 session system (packages/core) is the target; V1 gets compatibility propagation
  • Single-folder workspaces behave identically to today (no regression)
  • The directories field is optional/nullable — existing sessions remain valid

Acceptance Criteria

  1. Multi-directory session creation — when Amicode passes multiple workspace folders,
    the opencode session stores all of them and treats each as internal scope
  2. No external-directory prompts — Bash, Read, Edit, Glob, Grep operating on any
    workspace folder path do NOT trigger the external-directory approval flow
  3. Multi-root instruction discovery — CLAUDE.md / AGENTS.md / CONTEXT.md from each
    workspace folder are discovered via findUp and loaded into the system prompt (deduplicated by resolved path)
  4. System prompt reflects workspace — the env block lists all workspace folders with
    the primary marked
  5. Single-folder fallback — with one workspace folder, behavior is unchanged from current
  6. Workspace sidebar — the Amicode activity bar shows a "Workspace" tree view that:
    • Renders all workspace folders as collapsible root nodes
    • Expands into the filesystem (files + directories, recursively)
    • Uses VS Code theme icons (file/folder icons from the active icon theme)
    • Shows git status decorations (modified, untracked, etc.)
    • Opens files in the editor on click
    • Full context menus: New File, New Folder, Rename, Delete, Copy Path, Copy Relative Path, Reveal in Finder, Open in Terminal
    • Respects files.exclude and .gitignore
    • Live-updates on filesystem changes
  7. Catalog removed — the amicode.catalog tree view, SessionCatalogTree, and related commands are removed
  8. DB migration — existing sessions continue to work (nullable directories column)

Key Decisions

Engine: Location.Ref schema extension

// packages/schema/src/location.ts
export const Ref = Schema.Struct({
  directory: AbsolutePath,                              // primary CWD
  directories: optional(Schema.Array(AbsolutePath)),    // all workspace roots
  workspaceID: optional(WorkspaceID),
})
  • directory = primary folder (default CWD for Bash, relative path resolution)
  • directories = full set of workspace folders (including the primary)
  • When directories is absent/empty → single-root behavior (backward compat)

Engine: Boundary check expansion

The containsPath function (used by external-directory approval) expands:

  • Check directory (primary)
  • Check each entry in directories
  • Check worktree (git root of primary)

Any hit → internal, no approval needed.

Engine: Instruction stacking

findUp runs independently from each directory in directories:

  • Order: primary first, then remaining in workspace order
  • Each findUp walks from its directory up to its own git worktree root
  • Deduplicate by resolved absolute path
  • All discovered instruction files are loaded and concatenated in order

Extension: Session creation

const collectionUrl = new URL("/session", server.url);
collectionUrl.searchParams.set("directory", workspaceFolders[0].uri.fsPath);
if (workspaceFolders.length > 1) {
  collectionUrl.searchParams.set("directories", JSON.stringify(
    workspaceFolders.map(f => f.uri.fsPath)
  ));
}

Extension: Sidebar architecture

  • package.json: rename amicode.armoniaamicode.workspace, rename to "Workspace"
  • Remove amicode.catalog view entirely
  • New WorkspaceTreeProvider implements TreeDataProvider<WorkspaceItem>
  • WorkspaceItem = { uri: vscode.Uri, type: vscode.FileType, workspaceFolder?: vscode.WorkspaceFolder }
  • Root nodes = workspace folders; children = vscode.workspace.fs.readDirectory()
  • File watcher: vscode.workspace.createFileSystemWatcher("**/*") → refresh affected subtree
  • Git decorations: FileDecorationProvider reading from vscode.scm or the git extension API
  • Context menus: contributed via menus.view/item/context in package.json, keyed on viewItem

Data Contracts

Session create request (HTTP):

POST /session
  ?directory=/Users/jj/.julia/dev/Altissimo
  &directories=["/Users/jj/.julia/dev/Altissimo","/Users/jj/.julia/dev/DirectTrajOpt","/Users/jj/.julia/dev/Piccolo"]

Session DB row (new column):

ALTER TABLE sessions ADD COLUMN directories TEXT;  -- JSON array, nullable

System prompt env block:

Working directory: /Users/jj/.julia/dev/Altissimo
Workspace folders:
  - /Users/jj/.julia/dev/Altissimo (primary)
  - /Users/jj/.julia/dev/DirectTrajOpt
  - /Users/jj/.julia/dev/Piccolo
Is directory a git repo: yes
Platform: darwin

Constraints & Invariants

  • Backward compatibility — sessions created without directories work as before
  • No hot-reload — changing workspace folders mid-session does not update existing sessions (new sessions pick up the change)
  • Primary is always firstdirectories[0] === directory (the primary)
  • Permission model unchanged — paths outside ALL workspace folders still trigger external-directory approval
  • No cross-worktree git — each directory's findUp stops at its own git root, not at a shared ancestor

Prior Art

  • VS Code's native Explorer handles multi-root via workspaceFolders array
  • The existing MoveSession concept in opencode (relocating a session to a different directory) shows the engine already treats directory as mutable
  • The sandboxes: string[] field on Project is a precedent for tracking multiple related directories

Source

Brainstorming session, 2026-08-19. Resolved through collaborative design interview.


Notes

  • The Catalog view (SessionCatalogTree) is removed. If pulse catalog access is needed later, it can live in the chat panel or a dedicated webview.
  • The workspace sidebar is intentionally a mirror of VS Code's Explorer — same UX expectations, same keyboard shortcuts where possible.
  • This design targets the V2 session system (packages/core). V1 (packages/opencode) gets compatibility propagation but is not the primary implementation target.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions