This document describes the current SESS architecture at v0.3.1.
SESS is a Go CLI that manages developer work as explicit sessions tied to repositories, branches, optional GitHub issues, and pull requests.
+---------------------------+ +-----------------------------+
| User shell / working repo | | GitHub + origin remote |
| current branch, worktree | | issues, PRs, default branch |
+-------------+-------------+ +--------------+--------------+
| ^
v |
+-------------+------------------------------------------+---------+
| SESS binary |
| |
| +------------------+ |
| | cmd/sess | entrypoint |
| +--------+---------+ |
| | |
| +--------v---------+ |
| | internal/sess | Cobra/Fang command layer |
| +-----+-------+----+ |
| | | |
| | +------------------------+ |
| v v |
| +-----+-----------+ +---------+----------+ |
| | internal/tui | <------> | internal/session | |
| | Bubble Tea UX | | lifecycle rules | |
| +-----+-------+---+ +---------+----------+ |
| | | | |
| | +-------------+ | |
| v v v |
| +-----+----------+ +------+-------+ +----------------------+ |
| | internal/git | | internal/db | | SQLite | |
| | git / gh wraps | | persistence | | ~/.sess-cli/sess.db | |
| +-----+----------+ +------+-------+ +----------------------+ |
+--------+----------------------+-----------------------------------+
|
+--> `git` and `gh` commands run against the local repo and GitHub
The codebase is intentionally layered:
cmd/sess
-> internal/sess
-> internal/tui
-> internal/session
-> internal/db
-> internal/git
Each layer has a distinct responsibility:
cmd/sess: application entrypointinternal/sess: Cobra/Fang command wiring, current working directory lookup, and database bootstrapinternal/tui: interactive workflows and Bubble Tea models forstartandendinternal/session: lifecycle rules for projects and sessionsinternal/db: SQLite schema and persistenceinternal/git: wrappers aroundgitandgh
In practice:
- thin commands in
internal/sessusually open the database and then hand control to either:- a TUI flow in
internal/tui, or - a small command path that uses
internal/sessionandinternal/gitdirectly
- a TUI flow in
internal/tuiis orchestration-heavy: it coordinates prompts, git operations, and session persistenceinternal/sessionowns state transitions such asactive -> paused -> active -> ended
sess-cli/
├── cmd/sess/
│ └── main.go
├── internal/
│ ├── db/
│ │ ├── db.go
│ │ └── db_test.go
│ ├── git/
│ │ ├── gh.go
│ │ └── git.go
│ ├── sess/
│ │ ├── root.go
│ │ ├── start.go
│ │ ├── status.go
│ │ ├── pause.go
│ │ ├── resume.go
│ │ ├── end.go
│ │ └── projects.go
│ ├── session/
│ │ ├── session.go
│ │ └── session_test.go
│ └── tui/
│ ├── common.go
│ ├── end.go
│ ├── end_test.go
│ ├── issue_select.go
│ ├── start.go
│ └── styles.go
└── docs/
SESS tracks two core concepts:
Project: a tracked repository on diskSession: a unit of work inside a project
A tracked project stores:
- repository path
- base branch
- last-used timestamp
A session stores:
- branch and branch type
- optional issue metadata
- state
- elapsed-time bookkeeping
- optional PR metadata once ended
Session states:
activepausedended
Only one active or paused session may exist per project at a time.
- Command resolves the current working directory and opens SQLite.
- TUI validates that the directory is a git repository.
- TUI detects the project base branch from
origin/HEAD, with fallback to the current branch. - Session manager initializes or loads the tracked project.
- If the stored base branch is invalid, the TUI repairs it before continuing.
- TUI collects issue, branch name, branch type, and dirty-worktree choices.
- Git wrappers:
- check out the tracked base branch
- pull
origin/<baseBranch> - create the new session branch
- Session manager persists the new active session.
- Command loads the tracked project and paused session.
- Git wrapper checks the current branch.
- If needed, SESS checks out the saved session branch.
- Session manager resumes time tracking only after branch alignment succeeds.
- Command loads the tracked project and active or paused session.
- TUI aligns the shell to the saved session branch if necessary.
- TUI checks whether there is shippable work.
- If dirty, SESS prompts for a commit message and commits the work.
- SESS fetches, rebases, and pushes the branch.
- SESS reuses an existing PR or creates a new one through
gh. - SESS checks out the project base branch.
- Session manager marks the session ended and stores PR metadata.
Failure rule:
- if an end-workflow step fails before session completion, the session remains open
SESS stores state locally in SQLite at:
~/.sess-cli/sess.db
Main persisted data:
- tracked projects and base branches
- session state and elapsed time
- linked issue metadata
- PR number and PR URL for ended sessions
The current schema is centered on two tables:
projectssessions
sessions.total_elapsed and sessions.current_slice_start are used together so pause and resume can accumulate time accurately across multiple active slices.
The current design prefers:
- explicit state transitions over implicit magic
- shelling out to
gitandghinstead of reimplementing those tools - local persistence instead of a remote service
- failure-safe workflow handling over aggressive automation
Why:
- simple deployment
- no daemon or background service
- enough structure for projects, sessions, and history
Why:
- lets SESS reuse standard tooling users already trust
- keeps behavior close to what users would run manually
- reduces the amount of custom protocol logic in the codebase
Why:
- interactive session flows are stateful and easier to express in Bubble Tea
- command files stay thin
- lifecycle rules still live below the TUI in
internal/session - git and GitHub side effects stay concentrated in one orchestration layer
The main architectural follow-up after v0.3.1 is conflict and interrupted-workflow recovery for sess end.
See: