Files
PiCloud/crates/picloud-cli/src/cmds/projects.rs
MechaCat02 f673922d89 feat(cli): pic projects ls + §7 M3/track-complete docs
§7 M3 (part 3) — the ownership track becomes inspectable, completing M1–M3.

- server: GET /api/v1/admin/projects (projects_api) lists every project + its
  owned-group count (projects repo list_with_counts, one GROUP BY); behind the
  /admin middleware, like the groups list.
- CLI: pic projects ls (cmds/projects.rs + client projects_list); the
  apply_ownership plan-preview journey now also asserts projects ls (plat owns
  exactly 1 group; teamb listed).
- docs: design §7 + CLAUDE.md record M3 shipped and the whole §7 multi-repo
  ownership track (M1 claim · M2 attach ceiling · M3 preview + projects ls)
  COMPLETE; deferred = structural-divergence + declarative tree shape + per-env
  approval gating.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 21:26:10 +02:00

30 lines
972 B
Rust

//! `pic projects` — read-only view of §7 multi-repo ownership projects.
//!
//! A project is the repo-root that declaratively owns a slice of the group
//! tree. Ownership is CLAIMED by `pic apply` (first apply with a `[project]`
//! slug registers it); this command only lists what exists.
use anyhow::Result;
use crate::client::Client;
use crate::config;
use crate::output::{OutputMode, Table};
/// `pic projects ls` — every project + how many group nodes it owns.
pub async fn ls(mode: OutputMode) -> Result<()> {
let creds = config::resolve()?;
let client = Client::from_creds(&creds)?;
let projects = client.projects_list().await?;
let mut table = Table::new(["slug", "name", "owned_groups", "created_at"]);
for p in &projects {
table.row([
p.slug.clone(),
p.name.clone(),
p.owned_groups.to_string(),
p.created_at.to_rfc3339(),
]);
}
table.print(mode);
Ok(())
}