diff --git a/.github/ISSUE_TEMPLATE/onboarding_issue.yml b/.github/ISSUE_TEMPLATE/onboarding_issue.yml index 12cbd3efd..6d5fcc4b8 100644 --- a/.github/ISSUE_TEMPLATE/onboarding_issue.yml +++ b/.github/ISSUE_TEMPLATE/onboarding_issue.yml @@ -18,7 +18,7 @@ body: - Installation (Homebrew / cargo / binary download) - First run (`nono run` returned an error immediately) - Writing or loading a profile (JSON) - - Using a built-in profile (e.g. `--profile always-further/claude`) + - Using a built-in profile (e.g. `--profile nolabs-ai/claude`) - nono ran but didn't seem to enforce anything - Something else (describe below) validations: @@ -29,7 +29,7 @@ body: attributes: label: What happened? description: What did you try, and what went wrong? - placeholder: "I followed the quickstart and ran `nono run --profile always-further/claude -- claude` but got..." + placeholder: "I followed the quickstart and ran `nono run --profile nolabs-ai/claude -- claude` but got..." validations: required: true diff --git a/README.md b/README.md index 8a82b72fc..132beefcb 100644 --- a/README.md +++ b/README.md @@ -63,9 +63,9 @@ Search for an agent in the registry, then run it: ```bash $ nono search opencode -always-further/opencode - Official Opencode Plugin +nolabs-ai/opencode - Official Opencode Plugin -$ nono run --profile always-further/opencode -- opencode +$ nono run --profile nolabs-ai/opencode -- opencode ``` That's it. `opencode` now runs with read/write access to the current directory and **nothing else** — your SSH keys, your cloud credentials, the rest of your disk are invisible to it. @@ -77,7 +77,7 @@ Profiles for all the popular agents live at [registry.nono.sh](https://registry. Outgrow the defaults? Scaffold a profile and tweak it — same command you already know: ```bash -nono profile init opencode --extends always-further/opencode +nono profile init opencode --extends nolabs-ai/opencode nono run --profile opencode -- opencode ``` @@ -148,6 +148,19 @@ The policy lives in the profile, not in the prompt. The agent can ask for a tool Read more in [Sandboxed Tool Execution](https://nono.sh/docs/cli/features/tool-sandbox). +## Migrating from `always-further/` packs + +All official packs have moved from the `always-further` namespace to `nolabs-ai`. To migrate +cleanly, remove the old pack first so its wiring is torn down, then pull the new one: + +```bash +nono remove always-further/ +nono pull nolabs-ai/ +``` + +Pulling the new pack without removing the old one can leave stale wiring from the previous +namespace in place (symlinks, plugin registrations, etc.). + ## Ready to go deep? Head over to the [docs](https://nono.sh/docs) and discover nono's rich composable policy system, credentials injection, L7 filtering, supply chain security, rollback, multiplexing, audit and more. diff --git a/crates/nono-cli/README.md b/crates/nono-cli/README.md index 32fa9c4a7..316da1de8 100644 --- a/crates/nono-cli/README.md +++ b/crates/nono-cli/README.md @@ -39,14 +39,14 @@ nono run --allow ./project-a --allow ./project-b -- command # Block network access nono run --allow-cwd --block-net -- command -# Use a pack profile (requires: nono pull always-further/claude) -nono run --profile always-further/claude -- claude +# Use a pack profile (requires: nono pull nolabs-ai/claude) +nono run --profile nolabs-ai/claude -- claude # Use a built-in profile -nono run --profile always-further/opencode -- opencode +nono run --profile nolabs-ai/opencode -- opencode # Keep a profile but temporarily allow unrestricted network -nono run --profile always-further/claude --allow-net -- claude +nono run --profile nolabs-ai/claude --allow-net -- claude # Start an interactive shell inside the sandbox nono shell --allow . @@ -85,14 +85,24 @@ Precedence is: CLI flag, then `NONO_THEME`, then config file, then the default ` | Profile | Install | Command | |---------|---------|---------| -| Claude Code | `nono pull always-further/claude` | `nono run --profile always-further/claude -- claude` | -| Codex | `nono pull always-further/codex` | `nono run --profile always-further/codex -- codex` | +| Claude Code | `nono pull nolabs-ai/claude` | `nono run --profile nolabs-ai/claude -- claude` | +| Codex | `nono pull nolabs-ai/codex` | `nono run --profile nolabs-ai/codex -- codex` | + +> **Migrating from `always-further/` packs?** +> Packs were moved from the `always-further` namespace to `nolabs-ai`. To cleanly migrate, +> remove the old pack first so its wiring is torn down, then pull the new one: +> ```bash +> nono remove always-further/ +> nono pull nolabs-ai/ +> ``` +> Just pulling the new pack without removing the old one can leave stale wiring from the +> previous namespace in place. ### Built-in profiles | Profile | Command | |---------|---------| -| OpenCode | `nono run --profile always-further/opencode -- opencode` | +| OpenCode | `nono run --profile nolabs-ai/opencode -- opencode` | | OpenClaw | `nono run --profile openclaw -- openclaw gateway` | | Swival | `nono run --profile swival -- swival` | diff --git a/crates/nono-cli/src/cli.rs b/crates/nono-cli/src/cli.rs index 2e076f77e..4523766e2 100644 --- a/crates/nono-cli/src/cli.rs +++ b/crates/nono-cli/src/cli.rs @@ -134,8 +134,8 @@ pub enum Commands { {after-help}")] #[command(after_help = "\x1b[1mEXAMPLES\x1b[0m nono run --allow . claude # Read/write current dir, run claude - nono run --profile always-further/claude claude # Use a profile - nono run --profile always-further/claude --allow-domain api.openai.com claude + nono run --profile nolabs-ai/claude claude # Use a profile + nono run --profile nolabs-ai/claude --allow-domain api.openai.com claude # Restrict outbound access to listed domains nono run --read ./src --write ./output cargo build # Separate read/write permissions @@ -156,7 +156,7 @@ pub enum Commands { {after-help}")] #[command(after_help = "\x1b[1mEXAMPLES\x1b[0m nono shell --allow . # Shell with read/write to current dir - nono shell --profile always-further/claude # Use a named profile + nono shell --profile nolabs-ai/claude # Use a named profile nono shell --allow . --shell /bin/zsh # Override shell binary ")] Shell(Box), @@ -558,9 +558,9 @@ IN-BAND DETACH: {all-args} {after-help}")] #[command(after_help = "\x1b[1mEXAMPLES\x1b[0m - nono pull always-further/claude - nono pull always-further/claude@1.2.0 --registry http://localhost:3000 - nono pull always-further/claude --init + nono pull nolabs-ai/claude + nono pull nolabs-ai/claude@1.2.0 --registry http://localhost:3000 + nono pull nolabs-ai/claude --init ")] Pull(PullArgs), @@ -574,7 +574,7 @@ IN-BAND DETACH: {all-args} {after-help}")] #[command(after_help = "\x1b[1mEXAMPLES\x1b[0m - nono remove always-further/claude + nono remove nolabs-ai/claude ")] Remove(RemoveArgs), @@ -589,7 +589,7 @@ IN-BAND DETACH: {after-help}")] #[command(after_help = "\x1b[1mEXAMPLES\x1b[0m nono update - nono update always-further/claude + nono update nolabs-ai/claude nono update --dry-run nono update --force # also update pinned packs ")] @@ -635,7 +635,7 @@ IN-BAND DETACH: {all-args} {after-help}")] #[command(after_help = "\x1b[1mEXAMPLES\x1b[0m - nono pin always-further/claude + nono pin nolabs-ai/claude ")] Pin(PinArgs), @@ -649,7 +649,7 @@ IN-BAND DETACH: {all-args} {after-help}")] #[command(after_help = "\x1b[1mEXAMPLES\x1b[0m - nono unpin always-further/claude + nono unpin nolabs-ai/claude ")] Unpin(UnpinArgs), diff --git a/crates/nono-cli/src/legacy_cleanup.rs b/crates/nono-cli/src/legacy_cleanup.rs index d83ff9e40..34e0ae6d9 100644 --- a/crates/nono-cli/src/legacy_cleanup.rs +++ b/crates/nono-cli/src/legacy_cleanup.rs @@ -3,7 +3,7 @@ //! Pre-0.43 installs wrote `~/.claude/hooks/nono-hook.sh` and patched //! `~/.claude/settings.json::hooks` with one matching command entry. //! Post-0.43 the integration ships as a registry pack -//! (`always-further/claude`) with its own marketplace-based plugin +//! (`nolabs-ai/claude`) with its own marketplace-based plugin //! install. If the legacy state isn't removed, Claude Code runs both — //! duplicate hook execution at best, broken behaviour if the legacy //! `nono-hook.sh` references binaries the current nono no longer ships. diff --git a/crates/nono-cli/src/main.rs b/crates/nono-cli/src/main.rs index 0116ef452..3d0cde2ab 100644 --- a/crates/nono-cli/src/main.rs +++ b/crates/nono-cli/src/main.rs @@ -503,7 +503,7 @@ mod tests { let helper = Cli::parse_from([ "nono", "pack-update-hint-helper", - "always-further/claude", + "nolabs-ai/claude", "1.0.0", ]); assert!(!allows_pre_exec_update_check(&helper.command)); diff --git a/crates/nono-cli/src/migration.rs b/crates/nono-cli/src/migration.rs index 143b61f63..ef064eda8 100644 --- a/crates/nono-cli/src/migration.rs +++ b/crates/nono-cli/src/migration.rs @@ -43,7 +43,7 @@ const LEARN_MORE_URL: &str = "https://github.com/nolabs-ai/nono/discussions/780" const OFFICIAL_PACKS: &[OfficialPack] = &[ OfficialPack { profile_name: "claude", - namespace: "always-further", + namespace: "nolabs-ai", pack_name: "claude", description: Some("Anthropic Claude Code sandbox profile + plugin"), installs_summary: Some("sandbox profile + Claude Code plugin (hooks, skill)"), @@ -52,24 +52,24 @@ const OFFICIAL_PACKS: &[OfficialPack] = &[ // renamed to `claude` so it matches the pack name. Once the pack // is installed, the resolver also accepts `claude-code` via the // artifact's `aliases` field. This entry only matters for users - // who type `--profile always-further/claude` *before* the pack is installed. + // who type `--profile nolabs-ai/claude` *before* the pack is installed. OfficialPack { profile_name: "claude-code", - namespace: "always-further", + namespace: "nolabs-ai", pack_name: "claude", description: Some("Anthropic Claude Code (legacy profile name; canonical is `claude`)"), installs_summary: Some("sandbox profile + Claude Code plugin (hooks, skill)"), }, OfficialPack { profile_name: "codex", - namespace: "always-further", + namespace: "nolabs-ai", pack_name: "codex", description: Some("OpenAI Codex CLI sandbox profile + plugin"), installs_summary: Some("sandbox profile + Codex plugin (hooks, skill)"), }, OfficialPack { profile_name: "opencode", - namespace: "always-further", + namespace: "nolabs-ai", pack_name: "opencode", description: Some("OpenCode AI coding assistant sandbox profile + plugin"), installs_summary: Some("sandbox profile + OpenCode plugin (hooks, skill)"), @@ -166,7 +166,7 @@ pub fn check_and_run(profile_name: &str) -> Result { } fn is_claude_pack(provider: &ProfileProvider) -> bool { - provider.namespace == "always-further" && provider.name == "claude" + provider.namespace == "nolabs-ai" && provider.name == "claude" } fn official_pack_for(profile_name: &str) -> Option<&'static OfficialPack> { @@ -312,7 +312,7 @@ mod tests { #[test] fn registry_ref_skips_migration() { - assert!(is_path_or_registry_ref("always-further/claude")); + assert!(is_path_or_registry_ref("nolabs-ai/claude")); assert!(is_path_or_registry_ref("./local.json")); assert!(is_path_or_registry_ref("path/to/profile.json")); assert!(!is_path_or_registry_ref("claude-code")); @@ -345,7 +345,7 @@ mod tests { .expect("claude-code") .as_provider(); assert_eq!(canonical.pack_ref(), legacy.pack_ref()); - assert_eq!(canonical.pack_ref(), "always-further/claude"); + assert_eq!(canonical.pack_ref(), "nolabs-ai/claude"); } #[test] diff --git a/crates/nono-cli/src/pack_update_hint.rs b/crates/nono-cli/src/pack_update_hint.rs index cf9998f78..3c85c5250 100644 --- a/crates/nono-cli/src/pack_update_hint.rs +++ b/crates/nono-cli/src/pack_update_hint.rs @@ -331,8 +331,8 @@ mod tests { #[test] fn refresh_helper_args_round_trip() { let stale = vec![ - ("always-further/claude".to_string(), "1.0.0".to_string()), - ("always-further/codex".to_string(), "2.3.4".to_string()), + ("nolabs-ai/claude".to_string(), "1.0.0".to_string()), + ("nolabs-ai/codex".to_string(), "2.3.4".to_string()), ]; let args = refresh_helper_args(&stale); @@ -342,7 +342,7 @@ mod tests { #[test] fn refresh_helper_args_reject_odd_values() { - assert!(parse_refresh_helper_args(vec!["always-further/claude".to_string()]).is_none()); + assert!(parse_refresh_helper_args(vec!["nolabs-ai/claude".to_string()]).is_none()); } #[test] diff --git a/crates/nono-cli/src/package_cmd.rs b/crates/nono-cli/src/package_cmd.rs index f8084dcf2..5b51e7772 100644 --- a/crates/nono-cli/src/package_cmd.rs +++ b/crates/nono-cli/src/package_cmd.rs @@ -117,9 +117,9 @@ pub fn run_pull(args: PullArgs) -> Result<()> { // pack (here, not via `migration::check_and_run`), also offer to // strip pre-0.43 inbuilt-hook leftovers. Idempotent — silent no-op // on a clean install. Mirrors the cleanup hook in `check_and_run` - // so power users who skip `--profile always-further/claude` don't end up with + // so power users who skip `--profile nolabs-ai/claude` don't end up with // both legacy and pack hooks firing. - if package_ref.namespace == "always-further" && package_ref.name == "claude" { + if package_ref.namespace == "nolabs-ai" && package_ref.name == "claude" { crate::legacy_cleanup::check_and_offer_cleanup()?; } diff --git a/crates/nono-cli/src/package_status.rs b/crates/nono-cli/src/package_status.rs index 646211bcc..7f7e3a4cf 100644 --- a/crates/nono-cli/src/package_status.rs +++ b/crates/nono-cli/src/package_status.rs @@ -5,6 +5,9 @@ use crate::profile; use crate::registry_client::{RegistryClient, resolve_registry_url}; use nono::{NonoError, Result}; +const DEPRECATED_NAMESPACE: &str = "always-further"; +const REPLACEMENT_NAMESPACE: &str = "nolabs-ai"; + #[derive(Clone, Copy, Debug)] struct OfficialPackStatusTarget { namespace: &'static str, @@ -13,18 +16,25 @@ struct OfficialPackStatusTarget { } const CLAUDE_PACK: OfficialPackStatusTarget = OfficialPackStatusTarget { - namespace: "always-further", + namespace: "nolabs-ai", name: "claude", profiles: &["claude", "claude-code"], }; const CODEX_PACK: OfficialPackStatusTarget = OfficialPackStatusTarget { - namespace: "always-further", + namespace: "nolabs-ai", name: "codex", profiles: &["codex"], }; -const OFFICIAL_PACK_STATUS_TARGETS: &[OfficialPackStatusTarget] = &[CLAUDE_PACK, CODEX_PACK]; +const OPENCODE_PACK: OfficialPackStatusTarget = OfficialPackStatusTarget { + namespace: "nolabs-ai", + name: "opencode", + profiles: &["opencode"], +}; + +const OFFICIAL_PACK_STATUS_TARGETS: &[OfficialPackStatusTarget] = + &[CLAUDE_PACK, CODEX_PACK, OPENCODE_PACK]; impl OfficialPackStatusTarget { fn key(self) -> String { @@ -45,6 +55,8 @@ pub(crate) fn enforce_for_active_profile(profile_name: Option<&str>, silent: boo return Ok(()); }; + warn_deprecated_namespace(silent); + for target in OFFICIAL_PACK_STATUS_TARGETS { if depends_on_official_pack_profile(*target, profile_name) { enforce_official_pack_status(*target, silent)?; @@ -53,6 +65,31 @@ pub(crate) fn enforce_for_active_profile(profile_name: Option<&str>, silent: boo Ok(()) } +/// Warn once per invocation for every pack installed under the deprecated +/// `always-further` namespace. Runs unconditionally (not gated on the active +/// profile) so users are notified regardless of which profile they're using, +/// including custom profiles that extend old packs. +fn warn_deprecated_namespace(silent: bool) { + if silent { + return; + } + let lockfile = match package::read_lockfile() { + Ok(lf) => lf, + Err(_) => return, + }; + let prefix = format!("{DEPRECATED_NAMESPACE}/"); + for old_ref in lockfile.packages.keys().filter(|k| k.starts_with(&prefix)) { + let name = &old_ref[prefix.len()..]; + let new_ref = format!("{REPLACEMENT_NAMESPACE}/{name}"); + eprintln!( + "\n [nono] ⚠ {old_ref} has moved to {new_ref}\n \ + Migrate with:\n \ + nono remove {old_ref}\n \ + nono pull {new_ref}\n" + ); + } +} + fn enforce_official_pack_status(target: OfficialPackStatusTarget, silent: bool) -> Result<()> { let lockfile = package::read_lockfile()?; let key = target.key(); @@ -166,6 +203,19 @@ fn is_official_package_ref(target: OfficialPackStatusTarget, value: &str) -> boo mod tests { use super::*; + #[test] + fn deprecated_namespace_constants_are_correct() { + assert_eq!(DEPRECATED_NAMESPACE, "always-further"); + assert_eq!(REPLACEMENT_NAMESPACE, "nolabs-ai"); + // Verify the replacement logic produces the right ref for a sample pack. + let old_ref = format!("{DEPRECATED_NAMESPACE}/claude"); + let name = old_ref.trim_start_matches(&format!("{DEPRECATED_NAMESPACE}/")); + assert_eq!( + format!("{REPLACEMENT_NAMESPACE}/{name}"), + "nolabs-ai/claude" + ); + } + #[test] fn yanked_message_pins_latest_when_available() { let status = PackageStatusResponse { @@ -179,40 +229,41 @@ mod tests { }), }; - let message = yanked_message("always-further/claude", "1.2.2", &status); - assert!(message.contains("nono pull always-further/claude@1.2.3 --force")); + let message = yanked_message("nolabs-ai/claude", "1.2.2", &status); + assert!(message.contains("nono pull nolabs-ai/claude@1.2.3 --force")); assert!(message.contains("security")); assert!(message.contains("high - profile policy fix")); } #[test] - fn official_profile_names_include_claude_and_codex() { + fn official_profile_names_include_claude_codex_and_opencode() { assert!(is_official_profile_name(CLAUDE_PACK, "claude")); assert!(is_official_profile_name(CLAUDE_PACK, "claude-code")); assert!(is_official_profile_name(CODEX_PACK, "codex")); + assert!(is_official_profile_name(OPENCODE_PACK, "opencode")); assert!(!is_official_profile_name(CLAUDE_PACK, "codex")); assert!(!is_official_profile_name(CODEX_PACK, "claude")); + assert!(!is_official_profile_name(OPENCODE_PACK, "claude")); } #[test] fn canonical_package_refs_target_official_packs() { + assert!(is_official_package_ref(CLAUDE_PACK, "nolabs-ai/claude")); assert!(is_official_package_ref( CLAUDE_PACK, - "always-further/claude" + "nolabs-ai/claude@1.2.3" )); + assert!(is_official_package_ref(CODEX_PACK, "nolabs-ai/codex")); + assert!(is_official_package_ref(CODEX_PACK, "nolabs-ai/codex@1.2.3")); + assert!(is_official_package_ref(OPENCODE_PACK, "nolabs-ai/opencode")); assert!(is_official_package_ref( - CLAUDE_PACK, - "always-further/claude@1.2.3" - )); - assert!(is_official_package_ref(CODEX_PACK, "always-further/codex")); - assert!(is_official_package_ref( - CODEX_PACK, - "always-further/codex@1.2.3" + OPENCODE_PACK, + "nolabs-ai/opencode@1.0.0" )); assert!(!is_official_package_ref(CLAUDE_PACK, "someone/claude")); assert!(!is_official_package_ref( CODEX_PACK, - "always-further/codex-extra" + "nolabs-ai/codex-extra" )); } } diff --git a/crates/nono-cli/src/profile/builtin.rs b/crates/nono-cli/src/profile/builtin.rs index 158d17591..4a3b84ebb 100644 --- a/crates/nono-cli/src/profile/builtin.rs +++ b/crates/nono-cli/src/profile/builtin.rs @@ -23,7 +23,7 @@ mod tests { #[test] fn test_claude_code_no_longer_inbuilt() { // Removed in v0.43.0: claude-code is now shipped via the registry pack - // `always-further/claude` and resolved through the user-profile + // `nolabs-ai/claude` and resolved through the user-profile // symlink, not the embedded policy.json. assert!(get_builtin("claude-code").is_none()); assert!(get_builtin("claude-no-kc").is_none()); @@ -32,7 +32,7 @@ mod tests { #[test] fn test_opencode_no_longer_inbuilt() { // Removed: opencode is now shipped via the registry pack - // `always-further/opencode`, not embedded in policy.json. + // `nolabs-ai/opencode`, not embedded in policy.json. assert!(get_builtin("opencode").is_none()); } diff --git a/crates/nono-cli/src/profile/mod.rs b/crates/nono-cli/src/profile/mod.rs index fa889da6d..2fb7b1693 100644 --- a/crates/nono-cli/src/profile/mod.rs +++ b/crates/nono-cli/src/profile/mod.rs @@ -2462,7 +2462,7 @@ pub fn load_profile_extends(name_or_path: &str) -> Option> { /// `install_as` matches the requested name. Self-heals Claude Code plugin /// wiring (symlink + `enabledPlugins`) on every successful resolution. /// 3. Built-in profiles (compiled into binary). -/// 4. Auto-pull prompt for the registry pack `always-further/claude` when +/// 4. Auto-pull prompt for the registry pack `nolabs-ai/claude` when /// the requested profile is `claude-code` (or inherits from it). pub fn load_profile(name_or_path: &str) -> Result { load_profile_impl(name_or_path, &[]) @@ -2605,9 +2605,9 @@ fn load_profile_inner(name_or_path: &str, cli_extends: &[String]) -> Result Result/always-further/claude/`. +/// True when `profile_path` lives inside `/nolabs-ai/claude/`. /// Used to gate legacy-cleanup invocation on the canonical claude pack /// rather than any pack that happens to publish a profile named `claude` /// or `claude-code`. @@ -2641,7 +2641,7 @@ fn is_always_further_claude_pack(profile_path: &Path) -> bool { let Ok(store) = crate::package::package_store_dir() else { return false; }; - profile_path_is_in_pack(profile_path, &store, "always-further", "claude") + profile_path_is_in_pack(profile_path, &store, "nolabs-ai", "claude") } /// Pure path-component matcher: does `profile_path` live under @@ -3186,7 +3186,7 @@ enum ResolvedBase { /// This handles the v0.42 → v0.43 upgrade case where a user profile /// `extends: ["claude-code"]` and the inbuilt `claude-code` is gone: /// instead of an inscrutable "base profile not found" error, the user -/// sees the same install prompt that `--profile always-further/claude` would +/// sees the same install prompt that `--profile nolabs-ai/claude` would /// produce, with the chain still resolving cleanly on accept. fn load_base_profile_raw( name: &str, @@ -3872,7 +3872,7 @@ pub fn list_profiles() -> Vec { } // Add pack-store profiles — names exposed by installed packs via - // `install_as`. Without this, `--profile always-further/claude` works (the + // `install_as`. Without this, `--profile nolabs-ai/claude` works (the // resolver finds it) but `nono profile list` doesn't surface it, // confusing users who expect a one-stop catalogue. for (name, _pack_ref) in list_pack_store_profiles() { @@ -3958,11 +3958,11 @@ mod tests { #[test] fn profile_path_is_in_pack_matches_canonical_layout() { let store = Path::new("/store"); - let claude_profile = Path::new("/store/always-further/claude/profile/claude.json"); + let claude_profile = Path::new("/store/nolabs-ai/claude/profile/claude.json"); assert!(profile_path_is_in_pack( claude_profile, store, - "always-further", + "nolabs-ai", "claude" )); @@ -3973,25 +3973,25 @@ mod tests { assert!(!profile_path_is_in_pack( third_party, store, - "always-further", + "nolabs-ai", "claude" )); // Different pack name in the same namespace must not match. - let codex = Path::new("/store/always-further/codex/profile/codex.json"); + let codex = Path::new("/store/nolabs-ai/codex/profile/codex.json"); assert!(!profile_path_is_in_pack( codex, store, - "always-further", + "nolabs-ai", "claude" )); // Path outside the store entirely must not match. - let outside = Path::new("/elsewhere/always-further/claude/profile.json"); + let outside = Path::new("/elsewhere/nolabs-ai/claude/profile.json"); assert!(!profile_path_is_in_pack( outside, store, - "always-further", + "nolabs-ai", "claude" )); } diff --git a/crates/nono-cli/src/profile_cmd.rs b/crates/nono-cli/src/profile_cmd.rs index 73e7036cc..a7fd67158 100644 --- a/crates/nono-cli/src/profile_cmd.rs +++ b/crates/nono-cli/src/profile_cmd.rs @@ -802,7 +802,7 @@ pub(crate) fn cmd_list(args: ProfileListArgs) -> Result<()> { } /// Like `print_profile_line` but appends the providing pack ref so the -/// user sees `claude-code Anthropic Claude Code … always-further/claude`. +/// user sees `claude-code Anthropic Claude Code … nolabs-ai/claude`. fn print_pack_profile_line(name: &str, pack_ref: &str, result: &Result, t: &theme::Theme) { match result { Ok(p) => { diff --git a/crates/nono-cli/src/profile_save_runtime.rs b/crates/nono-cli/src/profile_save_runtime.rs index 9a64f2c4b..8b02463eb 100644 --- a/crates/nono-cli/src/profile_save_runtime.rs +++ b/crates/nono-cli/src/profile_save_runtime.rs @@ -2256,14 +2256,14 @@ mod tests { &patch, "claude", "claude-test", - Some("always-further/claude"), + Some("nolabs-ai/claude"), ) .expect("prepare"); assert!(matches!(prepared.action, SaveAction::Created)); assert_eq!( prepared.profile.extends, - Some(vec!["always-further/claude".to_string()]) + Some(vec!["nolabs-ai/claude".to_string()]) ); } @@ -2287,13 +2287,13 @@ mod tests { &patch, "claude", "claude-test", - Some("always-further/claude@1.2.0"), + Some("nolabs-ai/claude@1.2.0"), ) .expect("prepare"); assert_eq!( prepared.profile.extends, - Some(vec!["always-further/claude@1.2.0".to_string()]) + Some(vec!["nolabs-ai/claude@1.2.0".to_string()]) ); } diff --git a/crates/nono-cli/src/pull_ui.rs b/crates/nono-cli/src/pull_ui.rs index 7cff8bfb8..c8f9c15ba 100644 --- a/crates/nono-cli/src/pull_ui.rs +++ b/crates/nono-cli/src/pull_ui.rs @@ -1,7 +1,7 @@ //! Sleek TUI for `nono pull`. Streams per-file download progress as it //! happens, then renders the install summary. Same output for the //! explicit `nono pull ` command and the auto-pull path triggered -//! by `--profile always-further/claude`. +//! by `--profile nolabs-ai/claude`. //! //! Design rules (do not relax without thinking): //! - No spinners, no in-place line rewrites — output stays readable in diff --git a/crates/nono-cli/src/setup.rs b/crates/nono-cli/src/setup.rs index 1571d91d1..cbdebf82f 100644 --- a/crates/nono-cli/src/setup.rs +++ b/crates/nono-cli/src/setup.rs @@ -374,7 +374,7 @@ impl SetupRunner { println!(" You can add these aliases to {}:", shell_rc); println!(); - println!(" alias nono-claude='nono run --profile always-further/claude -- claude'"); + println!(" alias nono-claude='nono run --profile nolabs-ai/claude -- claude'"); println!(" alias nono-safe='nono run --allow-cwd --block-net --'"); println!(); } @@ -393,7 +393,7 @@ impl SetupRunner { println!("Quick start examples:"); println!(); println!(" # Run Claude Code with built-in profile (recommended)"); - println!(" nono run --profile always-further/claude -- claude"); + println!(" nono run --profile nolabs-ai/claude -- claude"); println!(); println!(" # Run any command with current directory access"); println!(" nono run --allow-cwd -- "); diff --git a/crates/nono-cli/src/wiring.rs b/crates/nono-cli/src/wiring.rs index 0fdb4f9d8..3895bf1f9 100644 --- a/crates/nono-cli/src/wiring.rs +++ b/crates/nono-cli/src/wiring.rs @@ -250,7 +250,7 @@ pub enum WiringRecord { /// Per-leaf record for `JsonMerge`. `path` is the chain of object /// keys from the document root to the leaf (e.g. -/// `["enabledPlugins", "nono@always-further"]`). `installed_value` is +/// `["enabledPlugins", "nono@nolabs-ai"]`). `installed_value` is /// what we wrote at that leaf; `prior_value` is what was there before /// (None when the leaf didn't exist pre-merge). #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] @@ -1510,7 +1510,7 @@ mod tests { let _ = home; // signature parity with test setup WiringContext { pack_dir, - namespace: "always-further".to_string(), + namespace: "nolabs-ai".to_string(), pack_name: "claude".to_string(), } } @@ -1567,8 +1567,8 @@ mod tests { "/h/.config/nono/profile-drafts" ); assert_eq!( - expand_vars("$NONO_PACKAGES/always-further/claude", &ctx).expect("expand"), - "/h/.config/nono/packages/always-further/claude" + expand_vars("$NONO_PACKAGES/nolabs-ai/claude", &ctx).expect("expand"), + "/h/.config/nono/packages/nolabs-ai/claude" ); } @@ -1584,12 +1584,12 @@ mod tests { let config_str = config.path().to_str().expect("config path"); let ctx = WiringContext { pack_dir: PathBuf::from("/p"), - namespace: "always-further".to_string(), + namespace: "nolabs-ai".to_string(), pack_name: "claude".to_string(), }; let _env = EnvVarGuard::set_all(&[("HOME", home_str), ("XDG_CONFIG_HOME", config_str)]); let expected_config = format!("{config_str}/nono/profile-drafts"); - let expected_packages = format!("{config_str}/nono/packages/always-further/claude"); + let expected_packages = format!("{config_str}/nono/packages/nolabs-ai/claude"); assert_eq!( nono::try_canonicalize(Path::new( &expand_vars("$NONO_CONFIG/profile-drafts", &ctx).expect("expand") @@ -1598,7 +1598,7 @@ mod tests { ); assert_eq!( nono::try_canonicalize(Path::new( - &expand_vars("$NONO_PACKAGES/always-further/claude", &ctx).expect("expand") + &expand_vars("$NONO_PACKAGES/nolabs-ai/claude", &ctx).expect("expand") )), nono::try_canonicalize(Path::new(&expected_packages)) ); diff --git a/crates/nono-cli/tests/deprecated_policy.rs b/crates/nono-cli/tests/deprecated_policy.rs index 8470f22a3..a923c0d10 100644 --- a/crates/nono-cli/tests/deprecated_policy.rs +++ b/crates/nono-cli/tests/deprecated_policy.rs @@ -64,7 +64,7 @@ fn policy_show_alias() { fn policy_diff_alias() { // Both profiles must be embedded so the test doesn't depend on a // registry pack being installed. `claude-code` was used here - // before it was moved to the always-further/claude pack. + // before it was moved to the nolabs-ai/claude pack. let (ok_old, stdout_old, stderr_old) = run(&["policy", "diff", "default", "node-dev", "--json"]); let (ok_new, stdout_new, _) = run(&["profile", "diff", "default", "node-dev", "--json"]); diff --git a/crates/nono-cli/tests/profile_cli.rs b/crates/nono-cli/tests/profile_cli.rs index 0df1ec79a..a456cc9d2 100644 --- a/crates/nono-cli/tests/profile_cli.rs +++ b/crates/nono-cli/tests/profile_cli.rs @@ -226,7 +226,7 @@ fn test_show_format_manifest_default_profile() { fn test_show_format_manifest_node_dev_profile() { // node-dev is an embedded profile with non-empty filesystem grants, // standing in for the claude-code coverage that moved to the - // always-further/claude registry pack. + // nolabs-ai/claude registry pack. let output = nono_bin() .args(["profile", "show", "node-dev", "--format", "manifest"]) .output()