Skip to content
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ cargo test -p lineark-sdk --test online -- --test-threads=1
cargo test -p lineark --test online -- --test-threads=1
```

**Online tests must be self-contained.** Never assume resources (projects, issues, teams, etc.) already exist in the test workspace. Each test must create the resources it needs and clean them up afterwards using RAII guards (`TeamGuard`, `IssueGuard`, `ProjectGuard`). These guards auto-delete the resource on drop, ensuring cleanup even when the test panics. Use unique names for created resources (e.g. `format!("[test] my thing {}", &uuid::Uuid::new_v4().to_string()[..8])`) to avoid conflicts from zombie resources left by previously-failed runs. Use `retry_with_backoff` when querying recently-created resources, since the Linear API is eventually consistent. Always check `output.status.success()` and include stdout/stderr in assertion messages before parsing JSON output — a bare `.unwrap()` on JSON parsing hides the real error (e.g. auth failures).

## Updating the schema

`schema/schema.graphql` is a vendored copy of Linear's public GraphQL schema (SDL). It's checked in for reproducible builds and reviewable diffs. To update it:
Expand Down
12 changes: 12 additions & 0 deletions crates/lineark/src/commands/issues.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ pub enum IssuesAction {
/// Filter by team key, name, or UUID.
#[arg(long)]
team: Option<String>,
/// Filter by project name or UUID.
#[arg(long)]
project: Option<String>,
/// Show only issues assigned to the authenticated user.
#[arg(long, default_value = "false")]
mine: bool,
Expand Down Expand Up @@ -420,6 +423,7 @@ pub struct CommentsConnection {
#[graphql(full_type = Comment)]
#[serde(rename_all = "camelCase", default)]
pub struct CommentSummary {
pub id: Option<String>,
pub body: Option<String>,
#[graphql(nested)]
pub user: Option<UserRef>,
Expand All @@ -442,6 +446,7 @@ pub async fn run(cmd: IssuesCmd, client: &Client, format: Format) -> anyhow::Res
IssuesAction::List {
limit,
team,
project,
mine,
show_done,
} => {
Expand All @@ -459,6 +464,13 @@ pub async fn run(cmd: IssuesCmd, client: &Client, format: Format) -> anyhow::Res
serde_json::json!({ "id": { "eq": team_id } }),
);
}
if let Some(ref project_val) = project {
let project_id = resolve_project_id(client, project_val).await?;
filter_map.insert(
"project".into(),
serde_json::json!({ "id": { "eq": project_id } }),
);
}
if mine {
let viewer = client
.whoami::<User>()
Expand Down
1 change: 1 addition & 0 deletions crates/lineark/src/commands/usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ COMMANDS:
[--around-active N] Active ± N neighbors
lineark cycles read <ID> [--team KEY] Read cycle (UUID, name, or number)
lineark issues list [-l N] [--team KEY] Active issues (done/canceled hidden), newest first
[--project NAME-OR-ID] Filter by project
[--mine] Only issues assigned to me
[--show-done] Include done/canceled issues
lineark issues read <IDENTIFIER> Full issue detail incl. sub-issues, comments, relations
Expand Down
20 changes: 20 additions & 0 deletions crates/lineark/tests/offline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -887,3 +887,23 @@ fn usage_includes_comments_delete() {
.success()
.stdout(predicate::str::contains("comments delete"));
}

// ── Issues list --project filter ────────────────────────────────────────────

#[test]
fn issues_list_help_shows_project_flag() {
lineark()
.args(["issues", "list", "--help"])
.assert()
.success()
.stdout(predicate::str::contains("--project"));
}

#[test]
fn usage_includes_issues_list_project_filter() {
lineark()
.arg("usage")
.assert()
.success()
.stdout(predicate::str::contains("--project"));
}
Loading