Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
146556 stories
·
33 followers

Satya Nadella insists people are using Microsoft’s Copilot AI a lot

1 Share
With Microsoft spending many billions on data centers, and rumors that no one is using its AI, CEO Satya Nadella shared some usage numbers.
Read the whole story
alvinashcraft
46 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Gemini CLI gets its hooks into the agentic development loop

1 Share

Google has added hooks to Gemini CLI, its terminal-based competitor to Anthropic’s Claude Code.

Hooks ensure that Gemini CLI runs a given script or program inside of the agentic loop and bring a larger degree of control to the agentic development loop. These could be used, for example, to run security scanners or compliance checks, log tool interactions, inject relevant information into the context window, or even adjust the model’s parameters on the fly.

As the Gemini CLI team notes in the announcement, “efficiency in the age of agents isn’t just about writing code faster; it’s about building custom tools that adapt to your specific environment.”

Hooks in Gemini CLI (Credit: Google).

While a developer could try to instruct the agent to run a specific script at certain times within the loop in the prompt or AGENTS.md file, given the non-deterministic nature of those agent models, there’s no guarantee that this will actually happen or that the agent won’t forget about this instruction over time.

Claude Code did it first

If this sounds familiar, it’s likely because you already know about Claude Code Hooks, which first introduced this idea last September (though there is also a GitHub issue from July 2025 that proposes this feature). Google’s implementation is not quite a one-to-one match to Anthropic’s, but it should only take a few minutes to adapt an existing Claude hook to Gemini CLI.

Setting up hooks

Like with hooks in Claude Code, Gemini CLI also implements roughly a dozen lifecycle events where a hook can fire. That may be right at the session start, after the user submits a prompt but before the agent starts planning (to add context, for example), before tools are selected (to optimize the tool selection or filter available tools), and similar moments in the agent loop.

defining a google gemini cli hook in a JSON file.

Defining a Gemini CLI hook (Credit: Google).

The hooks are defined as JSON files that describe when they are invoked and which script they should run. Those scripts are standard Bash scripts and Google notes that it is essential to keep those hooks fast because they do run synchronously and delays in the script will also delay the agent response.

Google recommends that developers use parallel operations and caching when possible to keep the operations fast.

One interesting use case for hooks is to utilize the ‘AfterAgent’ hook, which fires when the agent loop ends, to force the agent into a continuous loop to work on a difficult task — while also refreshing the context between those runs to avoid context rot.

As for security, it’s important to stress that hooks will have the user’s privileges, and Google notes that developers should review the source code of any third-party hooks.

Hooks, which are now available as part of the Gemini CLI v0.26.0 update, can also be packaged inside Gemini CLI extensions. That’s Google’s format for packaging prompts, MCP servers, sub-agents, and agent skills — and now hooks — into a single sharable package.

The post Gemini CLI gets its hooks into the agentic development loop appeared first on The New Stack.

Read the whole story
alvinashcraft
47 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

PPP 494 | How to Stay Poised When Everything Starts to Slip, with author Andrew Wittman

1 Share

Summary

In this episode, Andy talks with Dr. Andrew Wittman, former Marine, police officer, federal agent, and leadership coach, about his new book Inner Armor: Perpetual Resilience. If you lead projects and teams, you already know pressure is coming. The real question is what you do when it arrives.

Andrew explains why the brain can work against you under stress, and how the questions you ask yourself shape the options you can see. You'll learn the Two Minute Rule and how it can help you shift from "we can't" thinking into problem-solving mode. Andy and Andrew also explore how filters and assumptions influence what leaders notice, why limitation can be more dangerous than fear, and what it looks like to build a First Responder Mindset so you can hold your poise when stakeholders push back.

They close with a powerful discussion on identity and a practical look at raising resilient kids. If you're looking for insights on leading with clarity and composure when the stakes are high, this episode is for you!

Sound Bites

  • "The first thing you have to understand about the brain is that it is the original search engine. Like it has to answer a question."
  • "The brain knows that you're a genius. Even if you don't consciously recognize that you're a genius, your brain knows it. It'll never go against your genius self. So if you say things like, I don't know how we could do this, your brain says, 'Oh, we don't know.' So it stops searching completely for any answer."
  • "Just for two minutes, pretend that you could do it. It's amazing that your brain will just go to work and find like 15 ways you actually could do it, whereas seconds ago, we thought we couldn't."
  • "When bad news happens, get happy. Whenever you hear bad news, you should get happy because this is your biggest opportunity to have the greatest comeback ever."
  • "My question is, no matter what the bad news is, I'm going to ask myself this: how can I use this to my greatest possible advantage?"
  • "I want to know what the holes in this project are. I don't want to hear rainbows and sunshine, right? Positive thinking will get you killed quicker than negative thinking."
  • "We take in 11 million bits of information per second. Every second we see, hear, feel, touch, 11 million bits. Only 126 bits go to our conscious mind for action, which means we're filtering out 99.9% of all that information."
  • "When you walk into a room, and you think no one supports you, you're going to see every cue that you could find to back that up. And you'll discard anything that would go against that."
  • "The world is always ready to define you if you don't define yourself."
  • "My identity: I'm a man of excellence who always keeps his word. I aspire to always keep my word. And so everything that I do is pre-decided by that identity."
  • "Excellence is if I give my best effort, I could sleep tonight."
  • "Welcome to Planet Earth, everybody has to deal with the externals. It's the great equalizer. We all have to deal with it. You're not special. I hate to tell you, CEO, you're not special."
  • "Those pressure situations, they don't create your habits. They actually reveal them."

Chapters

  • 00:00 Introduction
  • 01:40 Start of Interview
  • 02:07 Andrew's Backstory and Early Influences
  • 04:23 Unhelpful Questions Under Pressure and the Two Minute Rule
  • 07:27 Applying the Two Minute Rule When a Key Dependency Slips
  • 12:12 Training Practices to Make Resilience Automatic
  • 16:49 Recognizing When Your Filter Is the Real Problem
  • 18:33 Exposing Assumptions and Filters in Project Plans
  • 22:21 A Personal Example of Misreading a Situation
  • 25:10 How Beliefs Shape What You Notice in a Room
  • 27:35 Why Limitation Is More Dangerous Than Fear
  • 32:02 Building a First Responder Mindset and Holding Poise
  • 36:07 Identity and Defining Yourself
  • 40:37 Parenting Practices That Build Resilience in Kids
  • 43:17 End of Interview
  • 43:42 Andy Comments After the Interview
  • 47:47 Outtakes

Learn More

You can learn more about Andrew and his work at GetWarriorTough.com.

For more learning on this topic, check out:

  • Episode 448 with Marie-Helene Pelletier. It's an insightful discussion on resilience and burnout, and I think it would be a great follow-up to this discussion with Andrew.
  • Episode 477 with Jess Baker. She's a business psychologist and coach who offers a refreshing perspective on how to increase your resilience at work and in life.
  • Episode 398 with Dr. Neha Sangwan. It's an episode that will give you another perspective on avoiding burnout for you and your teams.

Level Up Your AI Skills

Join other listeners from around the world who are taking our AI Made Simple course to prepare for an AI-infused future.

Just go to ai.PeopleAndProjectsPodcast.com. Thanks!

Pass the PMP Exam This Year

If you or someone you know is thinking about getting PMP certified, we've put together a helpful guide called The 5 Best Resources to Help You Pass the PMP Exam on Your First Try. We've helped thousands of people earn their certification, and we'd love to help you too. It's totally free, and it's a great way to get a head start.

Just go to 5BestResources.PeopleAndProjectsPodcast.com to grab your copy. I'd love to help you get your PMP this year!

Join Us for LEAD52

I know you want to be a more confident leader–that's why you listen to this podcast. LEAD52 is a global community of people like you who are committed to transforming our ability to lead and deliver. It's 52 weeks of leadership learning, delivered right to your inbox, taking less than 5 minutes a week. And it's all for free. Learn more and sign up at GetLEAD52.com. Thanks!

Thank you for joining me for this episode of The People and Projects Podcast!

Talent Triangle: Power Skills

Topics: Leadership, Resilience, Stress Management, Decision Making, Mindset, Emotional Regulation, Stakeholder Management, Communication, Self-Leadership, Identity, Team Performance

The following music was used for this episode:

Music: Imagefilm 034 by Sascha Ende
License (CC BY 4.0): https://filmmusic.io/standard-license

Music: Synthiemania by Frank Schroeter
License (CC BY 4.0): https://filmmusic.io/standard-license





Download audio: https://traffic.libsyn.com/secure/peopleandprojectspodcast/494-AndrewWittman.mp3?dest-id=107017
Read the whole story
alvinashcraft
47 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Changing how ASP.NET generates OpenAPI schema names

1 Share
Preventing any naming conflicts in the OpenAPI documentation by ensuring that each schema name is uniquely identified by its full name.
Read the whole story
alvinashcraft
47 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

DHS is using Google and Adobe AI to make videos

1 Share

The US Department of Homeland Security is using AI video generators from Google and Adobe to make and edit content shared with the public, a new document reveals. It comes as immigration agencies have flooded social media with content to support President Trump’s mass deportation agenda—some of which appears to be made with AI—and as workers in tech have put pressure on their employers to denounce the agencies’ activities. 

The document, released on Wednesday, provides an inventory of which commercial AI tools DHS uses for tasks ranging from generating drafts of documents to managing cybersecurity. 

In a section about “editing images, videos or other public affairs materials using AI,” it reveals for the first time that DHS is using Google’s Veo 3 video generator and Adobe Firefly, estimating that the agency has between 100 and 1,000 licenses for the tools. It also discloses that DHS uses Microsoft Copilot Chat for generating first drafts of documents and summarizing long reports and Poolside software for coding tasks, in addition to tools from other companies.

Google, Adobe, and DHS did not immediately respond to requests for comment.

The news provides details about how agencies like Immigrations and Customs Enforcement, which is part of DHS, might be creating the large amounts of content they’ve shared on X and other channels as immigration operations have expanded across US cities. They’ve posted content celebrating “Christmas after mass deportations,” referenced Bible verses and Christ’s birth, showed faces of those the agency has arrested, and shared ads aimed at recruiting agents. The agencies have also repeatedly used music without permissions from artists in their videos.

Some of the content, particularly videos, has the appearance of being AI-generated, but it hasn’t been clear until now what AI models the agencies might be using. This marks the first concrete evidence such generators are being used by DHS to create content shared with the public.

It still remains impossible to verify which company helped create a specific piece of content, or indeed if it was AI-generated at all. Adobe offers options to “watermark” a video made with its tools to disclose that it is AI-generated, for example, but this disclosure does not always stay intact when the content is uploaded and shared across different sites. 

The document reveals that DHS has specifically been using Flow, a tool from Google that combines its Veo 3 video generator with a suite of filmmaking tools. Users can generate clips and assemble entire videos with AI, including videos that contain sound, dialogue, and background noise, making them hyperrealistic. Adobe launched its Firefly generator in 2023, promising that it does not use copyrighted content in its training or output. Like Google’s tools, Adobe’s can generate videos, images, soundtracks, and speech. The document does not reveal further details about how the agency is using these video generation tools.

Workers at large tech companies, including more than 140 current and former employees from Google and more than 30 from Adobe, have been putting pressure on their employers in recent weeks to take a stance against ICE and the shooting of Alex Pretti on January 24. Google’s leadership has not made statements in response. In October, Google and Apple removed apps on their app stores that were intended to track sightings of ICE, citing safety risks. 

An additional document released on Wednesday revealed new details about how the agency is using more niche AI products, including a facial recognition app used by ICE, as first reported by 404Media in June.

Read the whole story
alvinashcraft
47 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Building a Rich Text Editor in React

1 Share

Rich text editing is a common requirement in modern React applications, but rarely simple to implement. Allowing users to format text with headings, lists, and emphasis introduces challenges around state, content consistency, and maintainability.

Many applications rely on raw HTML strings or direct use of contenteditable. While this can work at first, it often leads to unpredictable behavior as the application grows. Content becomes harder to validate and version, and easy to break when multiple users or automated systems are involved.

A more reliable approach is to treat rich text as structured data instead of markup. Explicit content models give applications control over content creation, rendering, and extensibility, while aligning naturally with React’s declarative, state-driven model.
In this article, we will explore why rich text editing is hard in React, how structured content helps address these challenges, and how extension-based editors enable safe customization. We will also walk through a step-by-step example using Puck’s rich text editor to demonstrate these concepts in practice.

Why Rich Text Is Hard in React

Rich text editing conflicts with several core principles of how React applications are designed. Many traditional solutions rely on browser-level APIs rather than explicit React state, which makes them harder to control as complexity increases.

  • Many implementations depend on contentEditable and browser-managed HTML mutations. These operate outside React’s state model and make editor behavior difficult to reason about.

  • Rendering user-generated HTML without an explicit content model limits an application’s ability to validate, transform, or reason about content reliably over time, which in turn makes it difficult to diff, version, or audit, especially in collaborative or frequently edited environments.

  • Small markup changes can easily break layouts or violate design and accessibility rules without providing any clear signal to the application.

  • Raw HTML alone does not convey intent, which makes it unsafe for automated transformations, programmatic editing, or AI-driven workflows without an additional layer of structure and control.

In practice, many editors expose HTML as an interface while managing structured state internally. The core challenge is not the presence of HTML itself, but whether applications retain control and intent over how that HTML is produced and evolved.

Why Use Puck for Rich Text Editing

Puck

Puck is an open source visual editor for React that lets teams build custom page builders using their own components. The core of Puck is simply a React editor and a renderer, making it easy to integrate into any React application and define editing behavior through configuration.

  • Schema-driven fields: Rich text in Puck is defined through explicit field schemas, making the allowed structure and behavior clear and enforceable at the application level.

  • Built on TipTap: Puck’s rich text editor is powered by TipTap, a widely adopted editor engine known for its extensible and state-driven architecture.

  • Customizable: Formatting options, heading levels, and editor capabilities can be enabled or disabled.

  • Extensible by design: New formatting features and behaviors can be added using extensions, without modifying or forking the editor core.

  • Natural fit for React: Puck’s configuration model aligns with React’s component-driven approach, making rich text editing easier to reason about and maintain.

Step-by-Step Tutorial: Rich Text Editing with Puck

A complete working demo is available in this GitHub repository. You are encouraged to clone the repository and run the project locally to explore the full implementation, or follow the instructions below to set it up from scratch.

To run the demo locally, use the following commands:

git clone https://github.com/Studio1HQ/puck_demo_richtext.git
cd puck_demo_richtext
npm install
npm run dev

Then navigate to http://localhost:3000/edit and experiment with the rich text editor.

1. Setting Up Puck

First up, let’s install Puck. If you’re adding it to an existing project, install it directly via npm:

npm install @puckeditor/core

Alternatively, you can scaffold a new project using the official recipe. This sets up a working React and Next.js application with the editor and rendering pipeline already configured.

npx create-puck-app rich-text-demo
cd rich-text-demo
npm run dev

Once the development server is running, navigate to http://localhost:3000/edit to edit a page and http://localhost:3000 to view it.

Localhost

The Next.js Puck recipe includes the following:

  • Editor: A visual editor interface where content blocks can be added, configured, and edited.

  • Renderer: A rendering layer that takes saved editor data and outputs a live page using the same component configuration.

  • Configuration-driven setup: All editor behavior, available blocks, and field types are defined through a single configuration file, rather than custom editor logic.

For this article, we focus only on the editor configuration and how rich text behavior is defined. Routing, persistence, and deployment details are intentionally kept minimal to keep attention on the core concepts.

2. Adding a Rich Text Editor to Puck

Rich text editing in Puck is defined declaratively through configuration. Instead of manually wiring an editor, handling DOM updates, or managing selection state, rich text behavior is enabled by adding a dedicated field type to a component definition.

To set it up, replace the contents of /puck.config.tsx with the following Puck configuration object.

import type { Config } from "@puckeditor/core";

type Props = {
  HeadingBlock: { title: string };
  RichTextBlock: { content: string };
};

export const config: Config<Props> = {
  components: {
    // Simple heading block for comparison
    HeadingBlock: {
      fields: {
        title: { type: "text" },
      },
      defaultProps: {
        title: "Heading",
      },
      render: ({ title }) => (
        <div style={{ padding: 64 }}>
          <h1>{title}</h1>
        </div>
      ),
    },

    // Basic rich text editor block
    RichTextBlock: {
      label: "Rich Text",
      fields: {
        content: {
          type: "richtext",
        },
      },
      render: ({ content }) => (
        <div style={{ padding: 64, maxWidth: 700, margin: "0 auto" }}>
          {content}
        </div>
      ),
    },
  },
};

export default config;

This file serves as the baseline for all upcoming sections, where we incrementally add control and extensibility.

To enable inline editing in Puck, the [contentEditable](https://puckeditor.com/docs/api-reference/fields/richtext#contenteditable) option is added to the rich text field definition.

Add the following line to the content field of the RichTextBlock in puck.config.tsx:

RichTextBlock: {
  fields: {
    content: {
      type: "richtext",
      contentEditable: true,
    },
  },
  render: ({ content }) => (
    <div style={{ padding: 64, maxWidth: 700, margin: "0 auto" }}>
      {content}
    </div>
  ),
},

Editor

Inline editing works well for simple content updates, quick adjustments, and editorial workflows where users benefit from editing content in its final visual context.

3. Customizing Editor Behavior (Control)

Rich text editors are often expected to give users complete freedom, but in most real applications, this leads to inconsistent content and broken design systems. Teams usually need to restrict formatting options to ensure visual consistency, accessibility, and predictable rendering across the application.

Puck lets you selectively enable or disable formatting options based on the needs of the product or team.

Disabling a Formatting Option (Bold Example)

The example below shows how to disable the bold formatting option in a rich text field.

Add the following [options](https://puckeditor.com/docs/api-reference/fields/richtext#options) configuration to the content field of the RichTextBlock in puck.config.tsx:

RichTextBlock: {
  fields: {
    content: {
      type: "richtext",
      options: {
        bold: false,
      },
    },
  },
  render: ({ content }) => (
    <div style={{ padding: 64, maxWidth: 700, margin: "0 auto" }}>
      {content}
    </div>
  ),
},

This configuration removes the bold formatting capability from the editor.

Puckeditor

Restricting Heading Levels (Structure)

In rich text editing, allowing unrestricted heading levels often leads to inconsistent content hierarchy and poor accessibility. Most applications only need a small, well-defined set of heading levels to maintain clarity and visual consistency.

Puck also lets you constrain heading behavior through configuration, ensuring that content follows a predictable structure.

The example below restricts headings to H1 and H2 only.

Add the following heading configuration to the options object of the content field in puck.config.tsx:

RichTextBlock: {
  fields: {
    content: {
      type: "richtext",
      options: {
        heading: {
          levels: [1, 2],
        },
      },
    },
  },
  render: ({ content }) => (
    <div style={{ padding: 64, maxWidth: 700, margin: "0 auto" }}>
      {content}
    </div>
  ),
},

Once this is applied, the editor will only allow users to select H1 and H2. All other heading levels are removed from the editor interface and cannot be applied through shortcuts.

Basic Puck editor interface hiding heading levels other than H1 and H2

Customizing the Menu Bar (UI Control)

Default editor toolbars are designed to cover a wide range of use cases, but in real applications, they often expose more options than necessary. This can overwhelm users and lead to inconsistent content. Most teams benefit from presenting a simplified toolbar that reflects only the formatting options they want to support.

Puck lets you customize the rich text menu bar and decide which controls and components to render, making it possible to control the editor user experience without modifying the editor engine or writing custom UI code.

The example below shows how to define a custom menu bar that exposes only selected controls.

Add the renderMenu function to the content field of the RichTextBlock in puck.config.tsx:

import { RichTextMenu } from "@puckeditor/core";

content: {
  type: "richtext",
  renderMenu: () => (
    <RichTextMenu>
      <RichTextMenu.Group>
        <RichTextMenu.Bold />
      </RichTextMenu.Group>
    </RichTextMenu>
  ),
},

This configuration replaces the default toolbar with a minimal menu that includes only the bold control. All other formatting options are hidden from the interface.

Puck editor interface showing only the bold control in the rich text editor toolbar

4. Adding Custom Extensions (Extensibility)

Modern rich text editors are not monolithic systems. Instead of baking every feature into the core editor, advanced functionality is added by extending the editor engine itself. This approach keeps the editor lightweight while allowing applications to introduce new capabilities only when needed.

Puck’s rich text editor follows this model. It is built on TipTap, which allows new formatting behaviors to be added by registering extensions through configuration.

The example below adds support for superscript formatting by registering the Superscript extension.

First, install the Superscript extension:

npm install @tiptap/extension-superscript

Then, add the extension to the rich text field configuration in puck.config.tsx:

import Superscript from "@tiptap/extension-superscript";

content: {
  type: "richtext",
  tiptap: {
    extensions: [Superscript],
  },
},

This configuration enables superscript functionality at the editor engine level. The editor now understands superscript formatting and can apply it internally, but users do not yet see a toolbar button or control to trigger it.

Separating editor capability from editor UI is a key design principle. By adding functionality through extensions first, applications can control when and how features are exposed to users. This makes the editor easier to evolve, safer to customize, and better aligned with product requirements.

In the next step, this capability will be surfaced through a custom toolbar control.

Exposing the Extension via a Custom Control

To make the feature usable, the editor needs to expose this capability through the user interface.

This is done by connecting the editor state to the toolbar using a selector and rendering a custom control that responds to that state.

A selector allows the editor to expose information about its current state, such as whether a formatting option is active or whether it can be applied at a given cursor position. This state is then consumed by the menu bar to control button behavior.

The example below shows how to expose the Superscript extension through a custom toolbar button.

Update the content field in puck.config.tsx as follows:

    // Rich text block demonstrating structure, control, extensibility
    RichTextBlock: {
      label: "Rich Text",
      fields: {
        content: {
          type: "richtext",

          // Add custom TipTap extension
          tiptap: {
            extensions: [Superscript],
            selector: ({ editor }) => ({
              isSuperscript: editor?.isActive("superscript"),
              canSuperscript: editor
                ?.can()
                .chain()
                .toggleSuperscript()
                .run(),
            }),
          },

          // Custom toolbar with a Superscript control
          renderMenu: ({ children, editor, editorState }) => (
            <RichTextMenu>
              {children}

              <RichTextMenu.Group>
                <RichTextMenu.Control
                  title="Superscript"
                  icon={<SuperscriptIcon size={16} />}
                  onClick={() =>
                    editor?.chain().focus().toggleSuperscript().run()
                  }
                  active={editorState?.isSuperscript}
                  disabled={!editorState?.canSuperscript}
                />
              </RichTextMenu.Group>
            </RichTextMenu>
          ),
        },
      },
      render: ({ content }) => (
        <div style={{ padding: 64, maxWidth: 700, margin: "0 auto" }}>
          {content}
        </div>
      ),
    },
  },
};

export default config;

This configuration connects the Superscript extension to the editor interface

This configuration connects the Superscript extension to the editor interface. The selector exposes whether superscript is active and whether it can be applied, and the custom control uses that state to render an interactive toolbar button.

Further Exploration

You can extend this demo by:

Key Takeaways

Rich text editing works best when it is treated as a structured system rather than a free form input. By modeling content intentionally, enforcing clear rules, and extending behavior through configuration, teams can build editors that scale reliably with their applications.

Puck fits naturally into this model by combining a structured, rich text engine with a configuration-driven approach that aligns well with modern React development.

  • Structure over uncontrolled markup: Rich text should encode intent and hierarchy through explicit structure, not rely solely on browser-managed HTML.

  • Control over free-form editing: Editors should enforce design and content rules instead of relying on manual cleanup.

  • Extensibility through configuration: New capabilities can be added safely without modifying core editor logic.

  • Separation of concerns: Editing behavior, user interface, and rendering remain clearly decoupled.

Explore the full demo repository to see these concepts in action, experiment with editor constraints, and extend the rich text editor to fit your own use cases.

Read the whole story
alvinashcraft
48 minutes ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories