From 3028740f2ac6e6f045962d5f61d0eb2dcc8694f3 Mon Sep 17 00:00:00 2001
From: Harsha Vardhan <80092815+harshav167@users.noreply.github.com>
Date: Sat, 3 Jan 2026 15:34:12 +1100
Subject: [PATCH 1/2] feat(session): filter sessions by current directory
By default, Session.list() now returns only sessions created in the
current working directory. This provides better isolation when working
in different directories within the same git repository.
- Add ListOptions interface with 'all' boolean option
- Filter sessions by Instance.directory unless all=true
- Add --all/-a flag to 'oc session list' CLI command
- Add ?all=true query parameter to /session API endpoint
This behavior mirrors Codex and Claude Code, which scope session
visibility to the current working directory rather than showing all
sessions across the entire project/machine.
---
packages/console/app/.opencode/agent/css.md | 149 --------------------
packages/opencode/src/cli/cmd/session.ts | 8 +-
packages/opencode/src/server/server.ts | 8 +-
packages/opencode/src/session/index.ts | 17 ++-
4 files changed, 27 insertions(+), 155 deletions(-)
delete mode 100644 packages/console/app/.opencode/agent/css.md
diff --git a/packages/console/app/.opencode/agent/css.md b/packages/console/app/.opencode/agent/css.md
deleted file mode 100644
index d5e68c7bf6a4..000000000000
--- a/packages/console/app/.opencode/agent/css.md
+++ /dev/null
@@ -1,149 +0,0 @@
----
-description: use whenever you are styling a ui with css
----
-
-you are very good at writing clean maintainable css using modern techniques
-
-css is structured like this
-
-```css
-[data-page="home"] {
- [data-component="header"] {
- [data-slot="logo"] {
- }
- }
-}
-```
-
-top level pages are scoped using `data-page`
-
-pages can break down into components using `data-component`
-
-components can break down into slots using `data-slot`
-
-structure things so that this hierarchy is followed IN YOUR CSS - you should rarely need to
-nest components inside other components. you should NEVER nest components inside
-slots. you should NEVER nest slots inside other slots.
-
-**IMPORTANT: This hierarchy rule applies to CSS structure, NOT JSX/DOM structure.**
-
-The hierarchy in css file does NOT have to match the hierarchy in the dom - you
-can put components or slots at the same level in CSS even if one goes inside another in the DOM.
-
-Your JSX can nest however makes semantic sense - components can be inside slots,
-slots can contain components, etc. The DOM structure should be whatever makes the most
-semantic and functional sense.
-
-It is more important to follow the pages -> components -> slots structure IN YOUR CSS,
-while keeping your JSX/DOM structure logical and semantic.
-
-use data attributes to represent different states of the component
-
-```css
-[data-component="modal"] {
- opacity: 0;
-
- &[data-state="open"] {
- opacity: 1;
- }
-}
-```
-
-this will allow jsx to control the styling
-
-avoid selectors that just target an element type like `> span` you should assign
-it a slot name. it's ok to do this sometimes where it makes sense semantically
-like targeting `li` elements in a list
-
-in terms of file structure `./src/style/` contains all universal styling rules.
-these should not contain anything specific to a page
-
-`./src/style/token` contains all the tokens used in the project
-
-`./src/style/component` is for reusable components like buttons or inputs
-
-page specific styles should go next to the page they are styling so
-`./src/routes/about.tsx` should have its styles in `./src/routes/about.css`
-
-`about.css` should be scoped using `data-page="about"`
-
-## Example of correct implementation
-
-JSX can nest however makes sense semantically:
-
-```jsx
-
-
Section Title
-
Content here
-
-```
-
-CSS maintains clean hierarchy regardless of DOM nesting:
-
-```css
-[data-page="home"] {
- [data-component="screenshots"] {
- [data-slot="left"] {
- /* styles */
- }
- [data-slot="content"] {
- /* styles */
- }
- }
-
- [data-component="title"] {
- /* can be at same level even though nested in DOM */
- }
-}
-```
-
-## Reusable Components
-
-If a component is reused across multiple sections of the same page, define it at the page level:
-
-```jsx
-
-
-
-
-```
-
-```css
-[data-page="home"] {
- /* Reusable title component defined at page level since it's used in multiple components */
- [data-component="title"] {
- text-transform: uppercase;
- font-weight: 400;
- }
-
- [data-component="install"] {
- /* install-specific styles */
- }
-
- [data-component="screenshots"] {
- /* screenshots-specific styles */
- }
-}
-```
-
-This is correct because the `title` component has consistent styling and behavior across the page.
-
-## Key Clarifications
-
-1. **JSX Nesting is Flexible**: Components can be nested inside slots, slots can contain components - whatever makes semantic sense
-2. **CSS Hierarchy is Strict**: Follow pages → components → slots structure in CSS
-3. **Reusable Components**: Define at the appropriate level where they're shared (page level if used across the page, component level if only used within that component)
-4. **DOM vs CSS Structure**: These don't need to match - optimize each for its purpose
-
-See ./src/routes/index.css and ./src/routes/index.tsx for a complete example.
diff --git a/packages/opencode/src/cli/cmd/session.ts b/packages/opencode/src/cli/cmd/session.ts
index c6a1fd4138f2..042a8cb4aaad 100644
--- a/packages/opencode/src/cli/cmd/session.ts
+++ b/packages/opencode/src/cli/cmd/session.ts
@@ -52,6 +52,12 @@ export const SessionListCommand = cmd({
describe: "limit to N most recent sessions",
type: "number",
})
+ .option("all", {
+ alias: "a",
+ describe: "show sessions from all directories in the project",
+ type: "boolean",
+ default: false,
+ })
.option("format", {
describe: "output format",
type: "string",
@@ -62,7 +68,7 @@ export const SessionListCommand = cmd({
handler: async (args) => {
await bootstrap(process.cwd(), async () => {
const sessions = []
- for await (const session of Session.list()) {
+ for await (const session of Session.list({ all: args.all })) {
if (!session.parentID) {
sessions.push(session)
}
diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts
index bc727b02857a..e2d9f047c17e 100644
--- a/packages/opencode/src/server/server.ts
+++ b/packages/opencode/src/server/server.ts
@@ -688,7 +688,8 @@ export namespace Server {
"/session",
describeRoute({
summary: "List sessions",
- description: "Get a list of all OpenCode sessions, sorted by most recently updated.",
+ description:
+ "Get a list of OpenCode sessions. By default, returns sessions from the current directory. Use ?all=true to get all sessions in the project.",
operationId: "session.list",
responses: {
200: {
@@ -702,9 +703,10 @@ export namespace Server {
},
}),
async (c) => {
- const sessions = await Array.fromAsync(Session.list())
+ const all = c.req.query("all") === "true"
+ const sessions = await Array.fromAsync(Session.list({ all }))
pipe(
- await Array.fromAsync(Session.list()),
+ sessions,
filter((s) => !s.time.archived),
sortBy((s) => s.time.updated),
)
diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts
index 0776590d6a9a..43aca2f689f5 100644
--- a/packages/opencode/src/session/index.ts
+++ b/packages/opencode/src/session/index.ts
@@ -286,10 +286,23 @@ export namespace Session {
},
)
- export async function* list() {
+ export interface ListOptions {
+ /**
+ * When true, returns all sessions for the project regardless of directory.
+ * When false (default), only returns sessions created in the current directory.
+ */
+ all?: boolean
+ }
+
+ export async function* list(options?: ListOptions) {
const project = Instance.project
+ const currentDirectory = Instance.directory
for (const item of await Storage.list(["session", project.id])) {
- yield Storage.read(item)
+ const session = await Storage.read(item)
+ if (options?.all !== true && session.directory !== currentDirectory) {
+ continue
+ }
+ yield session
}
}
From abb3bd912512259883c1b08605608ba8e4e6c401 Mon Sep 17 00:00:00 2001
From: Harsha Vardhan <80092815+harshav167@users.noreply.github.com>
Date: Sat, 3 Jan 2026 17:19:25 +1100
Subject: [PATCH 2/2] fix(config): allow extra fields in Command schema for
SpecKit compatibility
Add .passthrough() to Command Zod schema to allow external tools like
SpecKit to include additional frontmatter fields (handoffs, scripts,
agent_scripts) without causing validation errors.
This enables OpenCode to work with SpecKit templates that include
workflow-specific metadata beyond the core command fields.
---
packages/opencode/src/config/config.ts | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index 077a9dd11352..5997736d1b06 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -419,13 +419,15 @@ export namespace Config {
})
export type Permission = z.infer
- export const Command = z.object({
- template: z.string(),
- description: z.string().optional(),
- agent: z.string().optional(),
- model: z.string().optional(),
- subtask: z.boolean().optional(),
- })
+ export const Command = z
+ .object({
+ template: z.string(),
+ description: z.string().optional(),
+ agent: z.string().optional(),
+ model: z.string().optional(),
+ subtask: z.boolean().optional(),
+ })
+ .passthrough()
export type Command = z.infer
export const Agent = z