Skip to content

Add 'last' subcommand to resume most recent session - #117

Open
okarina-chaan wants to merge 2 commits into
mainfrom
41_ccsessio_last
Open

Add 'last' subcommand to resume most recent session#117
okarina-chaan wants to merge 2 commits into
mainfrom
41_ccsessio_last

Conversation

@okarina-chaan

Copy link
Copy Markdown
Collaborator

Summary

Implements ccsession last subcommand to resume the most recent session without launching the picker.

Related issue

#41

Type of change

  • Bug fix
  • New feature
  • Refactor (no behaviour change)
  • Documentation
  • CI / build / tooling

How was this tested?

Automated tests

  • TestRun_Basic: verifies the most recent session ID is returned
  • TestFilterOutByDir: verifies directory filtering behavior

Manual testing

# Basic usage
ccsession last -n           # returns most recent session ID
ccsession last              # resumes the session

# With options
csession last --here -n                  # scope to current directory
ccsession last --exclude-dir foobar -n    # exclude paths containing "foobar"

Checklist

  • gofmt -l . reports nothing
  • go vet ./... passes
  • go test ./... passes
  • Docs (README.md etc.) updated for any user-facing change
  • Commit messages follow the Conventional Commits style

@sorafujitani sorafujitani left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

実動作で再現する問題があるため、修正をお願いします。

Comment thread internal/last/last.go Outdated
return "", fmt.Errorf("no sessions found")
}
latest := sessions[0]
return latest.ID, nil

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDだけを返すと、同じIDのJSONLが複数ある場合に resume.Run が別のセッションを再検索してしまいます。source.LocatorFor(latest) も返し、resumeへ渡してください。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

分かりました!
こちら修正しました。

Comment thread internal/last/last.go
if len(sessions) == 0 {
return "", fmt.Errorf("no sessions found")
}
latest := sessions[0]

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue #41 の仕様どおり、cwdが消滅・不明なセッションはスキップして、次の再開可能なセッションを選んでください。現在は後段でエラーになります。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

読み飛ばし失礼しました。
こちら対応しました!

Comment thread cmd/ccsession/main.go
excludeDirFlag := fs.String("exclude-dir", os.Getenv(excludeDirEnv), "hide sessions whose cwd contains <s> (case-insensitive)")
nFlag := fs.Bool("n", false, "dry-run: print what would be resumed")

if err := fs.Parse(args); err != nil {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fs.NArg() == 0 を検証してください。ccsession last typo -n では -n が無視され、意図せずresumeが実行されます。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちら対応しました!
テストケースも追加しています。

Comment thread internal/last/last.go Outdated
return "", err
}
for i := len(sessions) - 1; i >= 0; i-- {
if sessions[i].CWD != currentDir && !strings.HasPrefix(sessions[i].CWD, currentDir+"/") {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

現在地が / だとprefixが // になり、--here が全件除外します。filepath.Rel などで配下判定してください。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

func isUnderOrEqual(base, target string) bool {
	rel, err := filepath.Rel(base, target)
	if err != nil {
		return false
	}
	if rel == "." {
		return true
	}
	prefix := ".." + string(os.PathSeparator)
	return rel != ".." && !strings.HasPrefix(rel, prefix)
}

こんな関数を作ってみました!

指摘のところで呼び出してチェックするように変えました。
また、テストでもこの関数の単体テストを追加しました。

  Implements `ccsession last` to resume the most recent session
  without launching the picker.

  - Support --here, --exclude-dir, and -n flags
  - Add internal/last package with Run() and tests

  Closes #41
@okarina-chaan

okarina-chaan commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator Author

レビューありがとうございます!

CI落ちているのですが、今回のスコープ外と判断しております。
一度レビューいただけますか?

--

やったこと

cmd/ccsession/main.go

  • cmdLast に引数チェックを追加した
    • ccsession last typo -n-n が無視される問題を防止するため
  • last.Run から locator を受け取り、resume.Run に渡すよう変更した
    • 同一IDが複数ある場合に別セッションが選ばれる問題を修正するため

internal/last/last.go

  • Run の返り値を (string, string, error) に変更した
    • ID に加えて locator も返すことで、resume時に一意特定できるようにした
  • CWD == "" または !CWDExists のセッションを除外した
    • 後段で cwd unknown エラーになる候補を事前にスキップするため
  • --here 判定を filepath.Rel ベースの isUnderOrEqual に変更した
    • 現在地が / のとき全件除外される問題を修正するため

internal/last/last_test.go

  • TestRun_SkipMissingCWD 追加した
    • cwd消滅セッションをスキップする動作を検証するため
  • TestIsUnderOrEqual 追加した
    • / を含む境界ケースをカバーするため

テスト

go test ./...

すべてパスしたのを確認しました

補足: CI落ちについて

lint stepの失敗は本PR内容とは関係ないかもしれないです。

What failed
In the lint step, CI is using Go 1.27.0 and golangci-lint v2.12, and type checking fails inside the Go stdlib:

crypto/internal/randutil/randutil.go cannot import math/rand/v2
method must have no type parameters
undefined: rand
This points to an incompatibility between the selected Go version (stable resolving to 1.27 in your run) and the linter/tooling stack.

golangci-lintのバージョンを上げるか、Goのバージョンを固定すると解消すると思います!
ここで対応するか迷ったので、とりあえず直さずにいますがどうしますか?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants