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.tsexportconstRef=Schema.Struct({directory: AbsolutePath,// primary CWDdirectories: optional(Schema.Array(AbsolutePath)),// all workspace rootsworkspaceID: 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

constcollectionUrl=newURL("/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):

ALTERTABLE 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

    , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
     blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
    }
    } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
    })();
    (function(){
    try {
    var __m = "github.com";
    var __re = new RegExp('^' + "github\\.com" + '
    
    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.tsexportconstRef=Schema.Struct({directory: AbsolutePath,// primary CWDdirectories: optional(Schema.Array(AbsolutePath)),// all workspace rootsworkspaceID: 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

    constcollectionUrl=newURL("/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):

    ALTERTABLE 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

      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
      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.tsexportconstRef=Schema.Struct({directory: AbsolutePath,// primary CWDdirectories: optional(Schema.Array(AbsolutePath)),// all workspace rootsworkspaceID: 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

      constcollectionUrl=newURL("/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):

      ALTERTABLE 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

        , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
        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.tsexportconstRef=Schema.Struct({directory: AbsolutePath,// primary CWDdirectories: optional(Schema.Array(AbsolutePath)),// all workspace rootsworkspaceID: 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

        constcollectionUrl=newURL("/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):

        ALTERTABLE 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

          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
          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.tsexportconstRef=Schema.Struct({directory: AbsolutePath,// primary CWDdirectories: optional(Schema.Array(AbsolutePath)),// all workspace rootsworkspaceID: 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

          constcollectionUrl=newURL("/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):

          ALTERTABLE 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

            , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
            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.tsexportconstRef=Schema.Struct({directory: AbsolutePath,// primary CWDdirectories: optional(Schema.Array(AbsolutePath)),// all workspace rootsworkspaceID: 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

            constcollectionUrl=newURL("/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):

            ALTERTABLE 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

              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
              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.tsexportconstRef=Schema.Struct({directory: AbsolutePath,// primary CWDdirectories: optional(Schema.Array(AbsolutePath)),// all workspace rootsworkspaceID: 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

              constcollectionUrl=newURL("/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):

              ALTERTABLE 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

                , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
                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.tsexportconstRef=Schema.Struct({directory: AbsolutePath,// primary CWDdirectories: optional(Schema.Array(AbsolutePath)),// all workspace rootsworkspaceID: 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

                constcollectionUrl=newURL("/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):

                ALTERTABLE 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